From 80fc36a22b83d78cf0e53a03b76b2c0b0f184930 Mon Sep 17 00:00:00 2001 From: Paul Ramsey Date: Wed, 5 Nov 2008 20:49:11 +0000 Subject: [PATCH] Fix for case where the p-i-p shortcut case and the GEOS shortcut case interleave and use the same cache area. git-svn-id: http://svn.osgeo.org/postgis/branches/1.3@3260 b70326c6-7e19-0410-871a-916f4a2858ee --- lwgeom/lwgeom_geos_c.c | 31 +++++++++++++++++++++++++------ lwgeom/lwgeom_rtree.c | 4 ++++ lwgeom/lwgeom_rtree.h | 1 + regress/regress_ogc_prep.sql | 26 ++++++++++++++++++++++++++ regress/regress_ogc_prep_expected | 15 +++++++++++++++ 5 files changed, 71 insertions(+), 6 deletions(-) diff --git a/lwgeom/lwgeom_geos_c.c b/lwgeom/lwgeom_geos_c.c index 8d1e545ff..643e37dda 100644 --- a/lwgeom/lwgeom_geos_c.c +++ b/lwgeom/lwgeom_geos_c.c @@ -55,6 +55,7 @@ #ifdef PREPARED_GEOM typedef struct { + char type; PG_LWGEOM* pg_geom1; PG_LWGEOM* pg_geom2; size_t pg_geom1_size; @@ -1506,6 +1507,10 @@ Datum contains(PG_FUNCTION_ARGS) errorIfGeometryCollection(geom1,geom2); errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); +#ifdef PGIS_DEBUG + lwnotice("Contains: entered", type1, type2); +#endif + /* * short-circuit 1: if geom2 bounding box is not completely inside * geom1 bounding box we can prematurely return FALSE. @@ -1517,6 +1522,9 @@ Datum contains(PG_FUNCTION_ARGS) if ( ( box2.xmin < box1.xmin ) || ( box2.xmax > box1.xmax ) || ( box2.ymin < box1.ymin ) || ( box2.ymax > box1.ymax ) ) { +#ifdef PGIS_DEBUG + lwnotice("Contains: bbox short circuit", type1, type2); +#endif PG_RETURN_BOOL(FALSE); } } @@ -1526,6 +1534,9 @@ Datum contains(PG_FUNCTION_ARGS) */ type1 = lwgeom_getType((uchar)SERIALIZED_FORM(geom1)[0]); type2 = lwgeom_getType((uchar)SERIALIZED_FORM(geom2)[0]); +#ifdef PGIS_DEBUG + lwnotice("Contains: type1: %d, type2: %d", type1, type2); +#endif if((type1 == POLYGONTYPE || type1 == MULTIPOLYGONTYPE) && type2 == POINTTYPE) { #ifdef PGIS_DEBUG @@ -1534,9 +1545,6 @@ Datum contains(PG_FUNCTION_ARGS) lwgeom = lwgeom_deserialize(SERIALIZED_FORM(geom1)); point = lwpoint_deserialize(SERIALIZED_FORM(geom2)); -#ifdef PGIS_DEBUG - lwnotice("Precall point_in_polygon %p, %p", lwgeom, point); -#endif /* * Switch the context to the function-scope context, @@ -1550,14 +1558,24 @@ Datum contains(PG_FUNCTION_ARGS) if( poly_cache->ringIndices ) { +#ifdef PGIS_DEBUG + lwnotice("R-Tree Point in Polygon test."); +#endif + result = point_in_multipolygon_rtree(poly_cache->ringIndices, poly_cache->polyCount, poly_cache->ringCount, point); } else if ( type1 == POLYGONTYPE ) { +#ifdef PGIS_DEBUG + lwnotice("Brute force Point in Polygon test."); +#endif result = point_in_polygon((LWPOLY*)lwgeom, point); } else if ( type1 == MULTIPOLYGONTYPE ) { +#ifdef PGIS_DEBUG + lwnotice("Brute force Point in Polygon test."); +#endif result = point_in_multipolygon((LWMPOLY*)lwgeom, point); } else { @@ -1580,9 +1598,6 @@ Datum contains(PG_FUNCTION_ARGS) } else { -#ifdef PGIS_DEBUG - lwnotice("Contains: type1: %d, type2: %d", type1, type2); -#endif } initGEOS(lwnotice, lwnotice); @@ -3880,6 +3895,9 @@ GetPrepGeomCache(FunctionCallInfoData *fcinfo, PG_LWGEOM *pg_geom1, PG_LWGEOM *p size_t pg_geom1_size = 0; size_t pg_geom2_size = 0; + /* Make sure this isn't someone else's cache object. */ + if( cache && cache->type != 2 ) cache = NULL; + if (!PrepGeomHash) CreatePrepGeomHash(); @@ -3903,6 +3921,7 @@ GetPrepGeomCache(FunctionCallInfoData *fcinfo, PG_LWGEOM *pg_geom1, PG_LWGEOM *p cache = palloc(sizeof(PrepGeomCache)); MemoryContextSwitchTo(old_context); + cache->type = 2; cache->prepared_geom = 0; cache->geom = 0; cache->argnum = 0; diff --git a/lwgeom/lwgeom_rtree.c b/lwgeom/lwgeom_rtree.c index 2ceb573b5..91969abe5 100644 --- a/lwgeom/lwgeom_rtree.c +++ b/lwgeom/lwgeom_rtree.c @@ -421,6 +421,7 @@ RTREE_POLY_CACHE * createCache() result->ringCount = 0; result->ringIndices = 0; result->poly = 0; + result->type = 1; return result; } @@ -519,6 +520,9 @@ RTREE_POLY_CACHE *retrieveCache(LWGEOM *lwgeom, uchar *serializedPoly, { int length; + /* Make sure this isn't someone else's cache object. */ + if( currentCache && currentCache->type != 1 ) currentCache = NULL; + #ifdef PGIS_DEBUG_CALLS lwnotice("retrieveCache called with %p %p %p", lwgeom, serializedPoly, currentCache); #endif diff --git a/lwgeom/lwgeom_rtree.h b/lwgeom/lwgeom_rtree.h index cc694cfb2..0f9c7b81c 100644 --- a/lwgeom/lwgeom_rtree.h +++ b/lwgeom/lwgeom_rtree.h @@ -45,6 +45,7 @@ LWMLINE *mergeMultiLines(LWMLINE *line1, LWMLINE *line2); typedef struct { + char type; RTREE_NODE **ringIndices; int ringCount; int polyCount; diff --git a/regress/regress_ogc_prep.sql b/regress/regress_ogc_prep.sql index 1b3acd11a..e4c64839f 100644 --- a/regress/regress_ogc_prep.sql +++ b/regress/regress_ogc_prep.sql @@ -242,6 +242,32 @@ SELECT c, ST_Covers(p1, p2) AS covers_p1p2, ST_Covers(p2, p1) AS covers_p2p1 FRO ('covers209', 'POLYGON((0 0, 0 10, 10 10, 11 0, 0 0))', 'POLYGON((-2 -2, -2 -3, -3 -3, -3 -2, -2 -2))') ) AS v(c,p1,p2); +-- UNEXPECTED GEOMETRY TYPES -- + +SELECT c, ST_Contains(p1, p2) AS contains_p1p2, ST_Contains(p2, p1) AS contains_p2p1, + ST_Covers(p1, p2) AS covers_p1p2, ST_Covers(p2, p1) AS covers_p2p1, + ST_Intersects(p1, p2) AS intersects_p1p2, ST_Intersects(p2, p1) AS intersects_p2p1, + ST_ContainsProperly(p1, p2) AS containsproper_p1p2, ST_ContainsProperly(p2, p1) AS containsproper_p2p1 + FROM +( VALUES +('types100', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(5 5)'), +('types101', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(5 5)'), +('types102', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POINT(5 5)'), +('types103', 'LINESTRING(0 0, 0 10, 10 10, 10 0)', 'POINT(5 5)'), +('types104', 'LINESTRING(0 0, 0 10, 10 10, 10 0)', 'POINT(5 5)'), +('types105', 'LINESTRING(0 0, 0 10, 10 10, 10 0)', 'POINT(5 5)'), +('types106', 'POINT(5 5)', 'POINT(5 5)'), +('types107', 'POINT(5 5)', 'POINT(5 5)'), +('types108', 'POINT(5 5)', 'POINT(5 5)'), +('types109', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'), +('types110', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'), +('types111', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'), +('types112', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'LINESTRING(0 0, 0 10, 10 10, 10 0)'), +('types113', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'LINESTRING(0 0, 0 10, 10 10, 10 0)'), +('types114', 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 'LINESTRING(0 0, 0 10, 10 10, 10 0)') +) AS v(c,p1,p2); + + SELECT 'intersects310', ST_intersects('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', p) FROM ( VALUES ('LINESTRING(1 10, 9 10, 9 8)'),('LINESTRING(1 10, 9 10, 9 8)'),('LINESTRING(1 10, 9 10, 9 8)') ) AS v(p); diff --git a/regress/regress_ogc_prep_expected b/regress/regress_ogc_prep_expected index 72ecd6883..4600388de 100644 --- a/regress/regress_ogc_prep_expected +++ b/regress/regress_ogc_prep_expected @@ -110,6 +110,21 @@ covers206|t|f covers207|t|f covers208|f|f covers209|f|f +types100|t|f|t|f|t|t|t|f +types101|t|f|t|f|t|t|t|f +types102|t|f|t|f|t|t|t|f +types103|f|f|f|f|f|f|f|f +types104|f|f|f|f|f|f|f|f +types105|f|f|f|f|f|f|f|f +types106|t|t|t|t|t|t|t|t +types107|t|t|t|t|t|t|t|t +types108|t|t|t|t|t|t|t|t +types109|t|t|t|t|t|t|f|f +types110|t|t|t|t|t|t|f|f +types111|t|t|t|t|t|t|f|f +types112|f|f|t|f|t|t|f|f +types113|f|f|t|f|t|t|f|f +types114|f|f|t|f|t|t|f|f intersects310|t intersects310|t intersects310|t -- 2.50.0