int geography_tree_distance(const GSERIALIZED* g1, const GSERIALIZED* g2, const SPHEROID* s, double tolerance, double* distance) { CIRC_NODE* circ_tree1 = NULL; CIRC_NODE* circ_tree2 = NULL; LWGEOM* lwgeom1 = NULL; LWGEOM* lwgeom2 = NULL; POINT4D pt1, pt2; lwgeom1 = lwgeom_from_gserialized(g1); lwgeom2 = lwgeom_from_gserialized(g2); circ_tree1 = lwgeom_calculate_circ_tree(lwgeom1); circ_tree2 = lwgeom_calculate_circ_tree(lwgeom2); lwgeom_startpoint(lwgeom1, &pt1); lwgeom_startpoint(lwgeom2, &pt2); if ( CircTreePIP(circ_tree1, g1, &pt2) || CircTreePIP(circ_tree2, g2, &pt1) ) { *distance = 0.0; } else { /* Calculate tree/tree distance */ *distance = circ_tree_distance_tree(circ_tree1, circ_tree2, s, tolerance); } circ_tree_free(circ_tree1); circ_tree_free(circ_tree2); lwgeom_free(lwgeom1); lwgeom_free(lwgeom2); return LW_SUCCESS; }
int lwcollection_startpoint(const LWCOLLECTION* col, POINT4D* pt) { if ( col->ngeoms < 1 ) return LW_FAILURE; return lwgeom_startpoint(col->geoms[0], pt); }
static int geography_distance_cache_tolerance(FunctionCallInfoData* fcinfo, const GSERIALIZED* g1, const GSERIALIZED* g2, const SPHEROID* s, double tolerance, double* distance) { CircTreeGeomCache* tree_cache = NULL; int type1 = gserialized_get_type(g1); int type2 = gserialized_get_type(g2); Assert(distance); /* Two points? Get outa here... */ if ( type1 == POINTTYPE && type2 == POINTTYPE ) return LW_FAILURE; /* Fetch/build our cache, if appropriate, etc... */ tree_cache = GetCircTreeGeomCache(fcinfo, g1, g2); /* OK, we have an index at the ready! Use it for the one tree argument and */ /* fill in the other tree argument */ if ( tree_cache && tree_cache->argnum && tree_cache->index ) { CIRC_NODE* circtree_cached = tree_cache->index; CIRC_NODE* circtree = NULL; const GSERIALIZED* g_cached; const GSERIALIZED* g; LWGEOM* lwgeom = NULL; int geomtype_cached; int geomtype; POINT4D p4d; /* We need to dynamically build a tree for the uncached side of the function call */ if ( tree_cache->argnum == 1 ) { g_cached = g1; g = g2; geomtype_cached = type1; geomtype = type2; } else if ( tree_cache->argnum == 2 ) { g_cached = g2; g = g1; geomtype_cached = type2; geomtype = type1; } else { lwpgerror("geography_distance_cache this cannot happen!"); return LW_FAILURE; } lwgeom = lwgeom_from_gserialized(g); if ( geomtype_cached == POLYGONTYPE || geomtype_cached == MULTIPOLYGONTYPE ) { lwgeom_startpoint(lwgeom, &p4d); if ( CircTreePIP(circtree_cached, g_cached, &p4d) ) { *distance = 0.0; lwgeom_free(lwgeom); return LW_SUCCESS; } } circtree = lwgeom_calculate_circ_tree(lwgeom); if ( geomtype == POLYGONTYPE || geomtype == MULTIPOLYGONTYPE ) { POINT2D p2d; circ_tree_get_point(circtree_cached, &p2d); p4d.x = p2d.x; p4d.y = p2d.y; if ( CircTreePIP(circtree, g, &p4d) ) { *distance = 0.0; circ_tree_free(circtree); lwgeom_free(lwgeom); return LW_SUCCESS; } } *distance = circ_tree_distance_tree(circtree_cached, circtree, s, tolerance); circ_tree_free(circtree); lwgeom_free(lwgeom); return LW_SUCCESS; } else { return LW_FAILURE; } }