From a038a8cb104d87e1c31356817b056ff38fcf6d8b Mon Sep 17 00:00:00 2001 From: Paul Ramsey Date: Thu, 5 Jul 2012 19:15:28 +0000 Subject: [PATCH] Fix issue where the cached object is a point and the uncached one is a polygon. (#1796) git-svn-id: http://svn.osgeo.org/postgis/trunk@10037 b70326c6-7e19-0410-871a-916f4a2858ee --- liblwgeom/lwgeodetic_tree.c | 5 +++ postgis/geography_measurement.c | 4 +- postgis/geography_measurement_trees.c | 55 ++++++++++++++++----------- 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/liblwgeom/lwgeodetic_tree.c b/liblwgeom/lwgeodetic_tree.c index 9074a3e20..7b840264e 100644 --- a/liblwgeom/lwgeodetic_tree.c +++ b/liblwgeom/lwgeodetic_tree.c @@ -113,6 +113,9 @@ circ_center_spherical(const GEOGRAPHIC_POINT* c1, const GEOGRAPHIC_POINT* c2, do { /* Direction from c1 to c2 */ double dir = sphere_direction(c1, c2, distance); + + LWDEBUGF(4,"calculating spherical center", dir); + LWDEBUGF(4,"dir is %g", dir); /* Catch sphere_direction when it barfs */ @@ -139,6 +142,8 @@ circ_center_cartesian(const GEOGRAPHIC_POINT* c1, const GEOGRAPHIC_POINT* c2, do POINT3D p1p2, pc; double proportion = offset/distance; + LWDEBUG(4,"calculating cartesian center"); + geog2cart(c1, &p1); geog2cart(c2, &p2); diff --git a/postgis/geography_measurement.c b/postgis/geography_measurement.c index c224a9b76..fec3e49e4 100644 --- a/postgis/geography_measurement.c +++ b/postgis/geography_measurement.c @@ -148,7 +148,7 @@ Datum geography_distance_cached(PG_FUNCTION_ARGS) { LWGEOM* lwgeom1 = lwgeom_from_gserialized(g1); LWGEOM* lwgeom2 = lwgeom_from_gserialized(g2); - distance = lwgeom_distance_spheroid(lwgeom1, lwgeom2, &s, FP_TOLERANCE); + distance = lwgeom_distance_spheroid(lwgeom1, lwgeom2, &s, tolerance); lwgeom_free(lwgeom1); lwgeom_free(lwgeom2); } @@ -281,7 +281,7 @@ Datum geography_distance_tree(PG_FUNCTION_ARGS) if ( CircTreePIP(circ_tree1, g1, lwgeom2) || CircTreePIP(circ_tree2, g2, lwgeom1) ) { - PG_RETURN_BOOL(FALSE); + PG_RETURN_FLOAT8(0.0); } /* Calculate tree/tree distance */ diff --git a/postgis/geography_measurement_trees.c b/postgis/geography_measurement_trees.c index 93b7c706c..892af0460 100644 --- a/postgis/geography_measurement_trees.c +++ b/postgis/geography_measurement_trees.c @@ -77,52 +77,63 @@ GetCircTreeGeomCache(FunctionCallInfoData* fcinfo, const GSERIALIZED* g1, const } int -CircTreePIP(const CIRC_NODE* tree, const GSERIALIZED* g, const LWGEOM* lwgeom) +CircTreePIP(const CIRC_NODE* tree1, const GSERIALIZED* g1, const LWGEOM* lwgeom2) { - int tree_type = gserialized_get_type(g); - GBOX gbox; - GEOGRAPHIC_POINT gp; - POINT3D gp3; - POINT4D pt; + int tree1_type = gserialized_get_type(g1); + GBOX gbox1; + GEOGRAPHIC_POINT in_gpoint; + POINT3D in_point3d; + POINT4D in_point; - if ( tree_type == POLYGONTYPE || tree_type == MULTIPOLYGONTYPE ) + /* If the tree'ed argument is a polygon, do the P-i-P using the tree-based P-i-P */ + if ( tree1_type == POLYGONTYPE || tree1_type == MULTIPOLYGONTYPE ) { /* Need a gbox to calculate an outside point */ - if ( LW_FAILURE == gserialized_get_gbox_p(g, &gbox) ) + if ( LW_FAILURE == gserialized_get_gbox_p(g1, &gbox1) ) { - LWGEOM* lwgeom_cached = lwgeom_from_gserialized(g); - lwgeom_calculate_gbox_geodetic(lwgeom_cached, &gbox); - lwgeom_free(lwgeom_cached); + LWGEOM* lwgeom1 = lwgeom_from_gserialized(g1); + lwgeom_calculate_gbox_geodetic(lwgeom1, &gbox1); + lwgeom_free(lwgeom1); } /* Need one point from the candidate geometry */ - if ( LW_FAILURE == lwgeom_startpoint(lwgeom, &pt) ) + if ( LW_FAILURE == lwgeom_startpoint(lwgeom2, &in_point) ) { - lwerror("CircTreePIP unable to generate start point for lwgeom %p", lwgeom); + lwerror("CircTreePIP unable to generate start point for lwgeom %p", lwgeom2); return LW_FALSE; } /* Flip the candidate point into geographics */ - geographic_point_init(pt.x, pt.y, &gp); - geog2cart(&gp, &gp3); + geographic_point_init(in_point.x, in_point.y, &in_gpoint); + geog2cart(&in_gpoint, &in_point3d); /* If the candidate isn't in the tree box, it's not in the tree area */ - if ( ! gbox_contains_point3d(&gbox, &gp3) ) + if ( ! gbox_contains_point3d(&gbox1, &in_point3d) ) { return LW_FALSE; } /* The candidate point is in the box, so it *might* be inside the tree */ else { - POINT2D pt_outside; /* latlon */ - POINT2D pt_inside; - pt_inside.x = pt.x; pt_inside.y = pt.y; + POINT2D pt2d_outside; /* latlon */ + POINT2D pt2d_inside; + pt2d_inside.x = in_point.x; + pt2d_inside.y = in_point.y; /* Calculate a definitive outside point */ - gbox_pt_outside(&gbox, &pt_outside); + gbox_pt_outside(&gbox1, &pt2d_outside); /* Test the candidate point for strict containment */ - return circ_tree_contains_point(tree, &pt_inside, &pt_outside, NULL); + return circ_tree_contains_point(tree1, &pt2d_inside, &pt2d_outside, NULL); } - + } + /* If the un-tree'd argument is a polygon and the tree'd argument isn't, we need to do a */ + /* standard P-i-P on the un-tree'd side. */ + else if ( lwgeom2->type == POLYGONTYPE || lwgeom2->type == MULTIPOLYGONTYPE ) + { + int result; + LWGEOM* lwgeom1 = lwgeom_from_gserialized(g1); + result = lwgeom_covers_lwgeom_sphere(lwgeom2, lwgeom1); + lwfree(lwgeom1); + return result; } else { -- 2.50.1