From: Daniel Baston Date: Thu, 21 Jan 2016 23:03:31 +0000 (+0000) Subject: #75, Enhancement to PIP short circuit X-Git-Tag: 2.3.0beta1~275 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=be84723f10806ceaf6d63e34b650fcf11b0683dc;p=postgis #75, Enhancement to PIP short circuit git-svn-id: http://svn.osgeo.org/postgis/trunk@14613 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/postgis/lwgeom_geos.c b/postgis/lwgeom_geos.c index d4d7bea52..4e61cb9b4 100644 --- a/postgis/lwgeom_geos.c +++ b/postgis/lwgeom_geos.c @@ -119,6 +119,48 @@ Datum postgis_geos_version(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } +static char +is_poly(const GSERIALIZED* g) +{ + int type = gserialized_get_type(g); + return type == POLYGONTYPE || type == MULTIPOLYGONTYPE; +} + +static char +is_point(const GSERIALIZED* g) +{ + int type = gserialized_get_type(g); + return type == POINTTYPE || type == MULTIPOINTTYPE; +} + +/* utility function that checks a LWPOINT and a GSERIALIZED poly against + * a cache. Serialized poly may be a multipart. + */ +static int +pip_short_circuit(RTREE_POLY_CACHE* poly_cache, LWPOINT* point, GSERIALIZED* gpoly) +{ + int result; + + if ( poly_cache && poly_cache->ringIndices ) + { + result = point_in_multipolygon_rtree(poly_cache->ringIndices, poly_cache->polyCount, poly_cache->ringCounts, point); + } + else + { + LWGEOM* poly = lwgeom_from_gserialized(gpoly); + if ( lwgeom_get_type(poly) == POLYGONTYPE ) + { + result = point_in_polygon(lwgeom_as_lwpoly(poly), point); + } + else + { + result = point_in_multipolygon(lwgeom_as_lwmpoly(poly), point); + } + lwgeom_free(poly); + } + + return result; +} /** * @brief Compute the Hausdorff distance thanks to the corresponding GEOS function @@ -1663,10 +1705,6 @@ Datum contains(PG_FUNCTION_ARGS) GSERIALIZED *geom2; GEOSGeometry *g1, *g2; GBOX box1, box2; - int type1, type2; - LWGEOM *lwgeom; - LWPOINT *point; - RTREE_POLY_CACHE *poly_cache; int result; PrepGeomCache *prep_cache; @@ -1699,48 +1737,60 @@ Datum contains(PG_FUNCTION_ARGS) ** short-circuit 2: if geom2 is a point and geom1 is a polygon ** call the point-in-polygon function. */ - type1 = gserialized_get_type(geom1); - type2 = gserialized_get_type(geom2); - if ((type1 == POLYGONTYPE || type1 == MULTIPOLYGONTYPE) && type2 == POINTTYPE) + if (is_poly(geom1) && is_point(geom2)) { + GSERIALIZED* gpoly = is_poly(geom1) ? geom1 : geom2; + GSERIALIZED* gpoint = is_point(geom1) ? geom1 : geom2; + RTREE_POLY_CACHE* cache = GetRtreeCache(fcinfo, gpoly); + int retval; + POSTGIS_DEBUG(3, "Point in Polygon test requested...short-circuiting."); - lwgeom = lwgeom_from_gserialized(geom1); - point = lwgeom_as_lwpoint(lwgeom_from_gserialized(geom2)); - - POSTGIS_DEBUGF(3, "Precall point_in_multipolygon_rtree %p, %p", lwgeom, point); - - poly_cache = GetRtreeCache(fcinfo, geom1); - - if ( poly_cache && poly_cache->ringIndices ) + if (gserialized_get_type(gpoint) == POINTTYPE) { - result = point_in_multipolygon_rtree(poly_cache->ringIndices, poly_cache->polyCount, poly_cache->ringCounts, point); - } - else if ( type1 == POLYGONTYPE ) - { - result = point_in_polygon((LWPOLY*)lwgeom, point); + LWGEOM* point = lwgeom_from_gserialized(gpoint); + int pip_result = pip_short_circuit(cache, lwgeom_as_lwpoint(point), gpoly); + lwgeom_free(point); + + retval = (pip_result == 1); /* completely inside */ } - else if ( type1 == MULTIPOLYGONTYPE ) + else if (gserialized_get_type(gpoint) == MULTIPOINTTYPE) { - result = point_in_multipolygon((LWMPOLY*)lwgeom, point); + LWMPOINT* mpoint = lwgeom_as_lwmpoint(lwgeom_from_gserialized(gpoint)); + uint32_t i; + int found_completely_inside = LW_FALSE; + + retval = LW_TRUE; + for (i = 0; i < mpoint->ngeoms; i++) + { + /* We need to find at least one point that's completely inside the + * polygons (pip_result == 1). As long as we have one point that's + * completely inside, we can have as many as we want on the boundary + * itself. (pip_result == 0) + */ + int pip_result = pip_short_circuit(cache, mpoint->geoms[i], gpoly); + if (pip_result == 1) + found_completely_inside = LW_TRUE; + + if (pip_result == -1) /* completely outside */ + { + retval = LW_FALSE; + break; + } + } + + retval = retval && found_completely_inside; + lwmpoint_free(mpoint); } else { - /* Gulp! Should not be here... */ - elog(ERROR,"Type isn't poly or multipoly!"); + /* Never get here */ + elog(ERROR,"Type isn't point or multipoint!"); PG_RETURN_NULL(); } - lwgeom_free(lwgeom); - lwpoint_free(point); + PG_FREE_IF_COPY(geom1, 0); PG_FREE_IF_COPY(geom2, 1); - if ( result == 1 ) /* completely inside */ - { - PG_RETURN_BOOL(TRUE); - } - else - { - PG_RETURN_BOOL(FALSE); - } + PG_RETURN_BOOL(retval); } else { @@ -1888,10 +1938,6 @@ Datum covers(PG_FUNCTION_ARGS) GSERIALIZED *geom2; int result; GBOX box1, box2; - int type1, type2; - LWGEOM *lwgeom; - LWPOINT *point; - RTREE_POLY_CACHE *poly_cache; PrepGeomCache *prep_cache; geom1 = PG_GETARG_GSERIALIZED_P(0); @@ -1920,50 +1966,50 @@ Datum covers(PG_FUNCTION_ARGS) * short-circuit 2: if geom2 is a point and geom1 is a polygon * call the point-in-polygon function. */ - type1 = gserialized_get_type(geom1); - type2 = gserialized_get_type(geom2); - if ((type1 == POLYGONTYPE || type1 == MULTIPOLYGONTYPE) && type2 == POINTTYPE) + if (is_poly(geom1) && is_point(geom2)) { - POSTGIS_DEBUG(3, "Point in Polygon test requested...short-circuiting."); - - lwgeom = lwgeom_from_gserialized(geom1); - point = lwgeom_as_lwpoint(lwgeom_from_gserialized(geom2)); + GSERIALIZED* gpoly = is_poly(geom1) ? geom1 : geom2; + GSERIALIZED* gpoint = is_point(geom1) ? geom1 : geom2; + RTREE_POLY_CACHE* cache = GetRtreeCache(fcinfo, gpoly); + int retval; - POSTGIS_DEBUGF(3, "Precall point_in_multipolygon_rtree %p, %p", lwgeom, point); - - poly_cache = GetRtreeCache(fcinfo, geom1); - - if ( poly_cache && poly_cache->ringIndices ) - { - result = point_in_multipolygon_rtree(poly_cache->ringIndices, poly_cache->polyCount, poly_cache->ringCounts, point); - } - else if ( type1 == POLYGONTYPE ) + POSTGIS_DEBUG(3, "Point in Polygon test requested...short-circuiting."); + if (gserialized_get_type(gpoint) == POINTTYPE) { - result = point_in_polygon((LWPOLY*)lwgeom, point); + LWGEOM* point = lwgeom_from_gserialized(gpoint); + int pip_result = pip_short_circuit(cache, lwgeom_as_lwpoint(point), gpoly); + lwgeom_free(point); + + retval = (pip_result != -1); /* not outside */ } - else if ( type1 == MULTIPOLYGONTYPE ) + else if (gserialized_get_type(gpoint) == MULTIPOINTTYPE) { - result = point_in_multipolygon((LWMPOLY*)lwgeom, point); + LWMPOINT* mpoint = lwgeom_as_lwmpoint(lwgeom_from_gserialized(gpoint)); + uint32_t i; + + retval = LW_TRUE; + for (i = 0; i < mpoint->ngeoms; i++) + { + int pip_result = pip_short_circuit(cache, mpoint->geoms[i], gpoly); + if (pip_result == -1) + { + retval = LW_FALSE; + break; + } + } + + lwmpoint_free(mpoint); } else { - /* Gulp! Should not be here... */ - elog(ERROR,"Type isn't poly or multipoly!"); + /* Never get here */ + elog(ERROR,"Type isn't point or multipoint!"); PG_RETURN_NULL(); } - lwgeom_free(lwgeom); - lwpoint_free(point); PG_FREE_IF_COPY(geom1, 0); PG_FREE_IF_COPY(geom2, 1); - if ( result != -1 ) /* not outside */ - { - PG_RETURN_BOOL(TRUE); - } - else - { - PG_RETURN_BOOL(FALSE); - } + PG_RETURN_BOOL(retval); } else { @@ -2041,10 +2087,6 @@ Datum coveredby(PG_FUNCTION_ARGS) GEOSGeometry *g1, *g2; int result; GBOX box1, box2; - LWGEOM *lwgeom; - LWPOINT *point; - int type1, type2; - RTREE_POLY_CACHE *poly_cache; char *patt = "**F**F***"; geom1 = PG_GETARG_GSERIALIZED_P(0); @@ -2075,48 +2117,54 @@ Datum coveredby(PG_FUNCTION_ARGS) * short-circuit 2: if geom1 is a point and geom2 is a polygon * call the point-in-polygon function. */ - type1 = gserialized_get_type(geom1); - type2 = gserialized_get_type(geom2); - if ((type2 == POLYGONTYPE || type2 == MULTIPOLYGONTYPE) && type1 == POINTTYPE) + if (is_point(geom1) && is_poly(geom2)) { - POSTGIS_DEBUG(3, "Point in Polygon test requested...short-circuiting."); + GSERIALIZED* gpoly = is_poly(geom1) ? geom1 : geom2; + GSERIALIZED* gpoint = is_point(geom1) ? geom1 : geom2; + RTREE_POLY_CACHE* cache = GetRtreeCache(fcinfo, gpoly); + int retval; - point = lwgeom_as_lwpoint(lwgeom_from_gserialized(geom1)); - lwgeom = lwgeom_from_gserialized(geom2); - - poly_cache = GetRtreeCache(fcinfo, geom2); - - if ( poly_cache && poly_cache->ringIndices ) - { - result = point_in_multipolygon_rtree(poly_cache->ringIndices, poly_cache->polyCount, poly_cache->ringCounts, point); - } - else if ( type2 == POLYGONTYPE ) + POSTGIS_DEBUG(3, "Point in Polygon test requested...short-circuiting."); + if (gserialized_get_type(gpoint) == POINTTYPE) { - result = point_in_polygon((LWPOLY*)lwgeom, point); + LWGEOM* point = lwgeom_from_gserialized(gpoint); + int pip_result = pip_short_circuit(cache, lwgeom_as_lwpoint(point), gpoly); + lwgeom_free(point); + + retval = (pip_result != -1); /* not outside */ } - else if ( type2 == MULTIPOLYGONTYPE ) + else if (gserialized_get_type(gpoint) == MULTIPOINTTYPE) { - result = point_in_multipolygon((LWMPOLY*)lwgeom, point); + LWMPOINT* mpoint = lwgeom_as_lwmpoint(lwgeom_from_gserialized(gpoint)); + uint32_t i; + + retval = LW_TRUE; + for (i = 0; i < mpoint->ngeoms; i++) + { + int pip_result = pip_short_circuit(cache, mpoint->geoms[i], gpoly); + if (pip_result == -1) + { + retval = LW_FALSE; + break; + } + } + + lwmpoint_free(mpoint); } else { - /* Gulp! Should not be here... */ - elog(ERROR,"Type isn't poly or multipoly!"); + /* Never get here */ + elog(ERROR,"Type isn't point or multipoint!"); PG_RETURN_NULL(); } - lwgeom_free(lwgeom); - lwpoint_free(point); PG_FREE_IF_COPY(geom1, 0); PG_FREE_IF_COPY(geom2, 1); - if ( result != -1 ) /* not outside */ - { - PG_RETURN_BOOL(TRUE); - } - else - { - PG_RETURN_BOOL(FALSE); - } + PG_RETURN_BOOL(retval); + } + else + { + POSTGIS_DEBUGF(3, "CoveredBy: type1: %d, type2: %d", type1, type2); } initGEOS(lwpgnotice, lwgeom_geos_error); @@ -2223,19 +2271,13 @@ Datum crosses(PG_FUNCTION_ARGS) PG_RETURN_BOOL(result); } - PG_FUNCTION_INFO_V1(geos_intersects); Datum geos_intersects(PG_FUNCTION_ARGS) { GSERIALIZED *geom1; GSERIALIZED *geom2; - GSERIALIZED *serialized_poly; int result; GBOX box1, box2; - int type1, type2, polytype; - LWPOINT *point; - LWGEOM *lwgeom; - RTREE_POLY_CACHE *poly_cache; PrepGeomCache *prep_cache; geom1 = PG_GETARG_GSERIALIZED_P(0); @@ -2265,61 +2307,50 @@ Datum geos_intersects(PG_FUNCTION_ARGS) * short-circuit 2: if the geoms are a point and a polygon, * call the point_outside_polygon function. */ - type1 = gserialized_get_type(geom1); - type2 = gserialized_get_type(geom2); - if ( (type1 == POINTTYPE && (type2 == POLYGONTYPE || type2 == MULTIPOLYGONTYPE)) || - (type2 == POINTTYPE && (type1 == POLYGONTYPE || type1 == MULTIPOLYGONTYPE))) + if ((is_point(geom1) && is_poly(geom2)) || (is_poly(geom1) && is_point(geom2))) { - POSTGIS_DEBUG(3, "Point in Polygon test requested...short-circuiting."); + GSERIALIZED* gpoly = is_poly(geom1) ? geom1 : geom2; + GSERIALIZED* gpoint = is_point(geom1) ? geom1 : geom2; + RTREE_POLY_CACHE* cache = GetRtreeCache(fcinfo, gpoly); + int retval; - if ( type1 == POINTTYPE ) + POSTGIS_DEBUG(3, "Point in Polygon test requested...short-circuiting."); + if (gserialized_get_type(gpoint) == POINTTYPE) { - point = lwgeom_as_lwpoint(lwgeom_from_gserialized(geom1)); - lwgeom = lwgeom_from_gserialized(geom2); - serialized_poly = geom2; - polytype = type2; + LWGEOM* point = lwgeom_from_gserialized(gpoint); + int pip_result = pip_short_circuit(cache, lwgeom_as_lwpoint(point), gpoly); + lwgeom_free(point); + + retval = (pip_result != -1); /* not outside */ } - else + else if (gserialized_get_type(gpoint) == MULTIPOINTTYPE) { - point = lwgeom_as_lwpoint(lwgeom_from_gserialized(geom2)); - lwgeom = lwgeom_from_gserialized(geom1); - serialized_poly = geom1; - polytype = type1; - } + LWMPOINT* mpoint = lwgeom_as_lwmpoint(lwgeom_from_gserialized(gpoint)); + uint32_t i; - poly_cache = GetRtreeCache(fcinfo, serialized_poly); + retval = LW_FALSE; + for (i = 0; i < mpoint->ngeoms; i++) + { + int pip_result = pip_short_circuit(cache, mpoint->geoms[i], gpoly); + if (pip_result != -1) /* not outside */ + { + retval = LW_TRUE; + break; + } + } - if ( poly_cache && poly_cache->ringIndices ) - { - result = point_in_multipolygon_rtree(poly_cache->ringIndices, poly_cache->polyCount, poly_cache->ringCounts, point); - } - else if ( polytype == POLYGONTYPE ) - { - result = point_in_polygon((LWPOLY*)lwgeom, point); - } - else if ( polytype == MULTIPOLYGONTYPE ) - { - result = point_in_multipolygon((LWMPOLY*)lwgeom, point); + lwmpoint_free(mpoint); } else { - /* Gulp! Should not be here... */ - elog(ERROR,"Type isn't poly or multipoly!"); + /* Never get here */ + elog(ERROR,"Type isn't point or multipoint!"); PG_RETURN_NULL(); } - lwgeom_free(lwgeom); - lwpoint_free(point); PG_FREE_IF_COPY(geom1, 0); PG_FREE_IF_COPY(geom2, 1); - if ( result != -1 ) /* not outside */ - { - PG_RETURN_BOOL(TRUE); - } - else - { - PG_RETURN_BOOL(FALSE); - } + PG_RETURN_BOOL(retval); } initGEOS(lwpgnotice, lwgeom_geos_error); @@ -2409,7 +2440,7 @@ Datum touches(PG_FUNCTION_ARGS) * geom1 bounding box we can prematurely return FALSE. */ if ( gserialized_get_gbox_p(geom1, &box1) && - gserialized_get_gbox_p(geom2, &box2) ) + gserialized_get_gbox_p(geom2, &box2) ) { if ( gbox_overlaps_2d(&box1, &box2) == LW_FALSE ) { diff --git a/regress/regress_ogc.sql b/regress/regress_ogc.sql index 00c173730..98608a069 100644 --- a/regress/regress_ogc.sql +++ b/regress/regress_ogc.sql @@ -30,6 +30,15 @@ SELECT 'within104', ST_within('POINT(0 12)'::geometry, 'POLYGON((0 0, 0 10, 10 1 SELECT 'within105', ST_within(ST_GeomFromText('POINT(521513 5377804)', 32631), ST_GeomFromText('POLYGON((521526 5377783, 521481 5377811, 521494 5377832, 521539 5377804, 521526 5377783))', 32631)); -- PIP - repeated vertex SELECT 'within106', ST_within(ST_GeomFromText('POINT(521513 5377804)', 32631), ST_GeomFromText('POLYGON((521526 5377783, 521482 5377811, 521481 5377811, 521494 5377832, 521539 5377804, 521526 5377783))', 32631)); +-- PIP - multipoint within polygon +SELECT 'within107', ST_within('MULTIPOINT(5 5)'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); +SELECT 'within108', ST_within('MULTIPOINT(5 5, 5 7)'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); +-- PIP - multipoint on vertices of polygon +SELECT 'within109', ST_within('MULTIPOINT(0 0, 10 10)'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); +-- PIP - multipoint partly outside of polygon +SELECT 'within110', ST_within('MULTIPOINT(5 5, 15 7)'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); +-- PIP - multipoint not fully within polygon (but at least one point still fully within, so "within" passes) +SELECT 'within111', ST_within('MULTIPOINT(5 5, 10 10)'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); -- PIP - point within polygon SELECT 'disjoint100', ST_disjoint('POINT(5 5)'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); -- PIP - point on polygon vertex @@ -72,6 +81,25 @@ SELECT 'intersects104', ST_intersects('POINT(0 12)'::geometry, 'POLYGON((0 0, 0 SELECT 'intersects105', ST_intersects(ST_GeomFromText('POINT(521513 5377804)', 32631), ST_GeomFromText('POLYGON((521526 5377783, 521481 5377811, 521494 5377832, 521539 5377804, 521526 5377783))', 32631)); -- PIP - repeated vertex SELECT 'intersects106', ST_intersects(ST_GeomFromText('POINT(521543 5377804)', 32631), ST_GeomFromText('POLYGON((521526 5377783, 521482 5377811, 521494 5377832, 521539 5377804, 521526 5377783))', 32631)); +-- PIP - multipoint on polygon vertex +SELECT 'intersects111', ST_Intersects('MULTIPOINT ((0 0))'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); +-- PIP - multipoint outside polygon +SELECT 'intersects112', ST_intersects('MULTIPOINT ((-1 0))'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); +-- PIP - multipoint on polygon edge +SELECT 'intersects113', ST_intersects('MULTIPOINT ((0 5))'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); +SELECT 'intersects114', ST_intersects('MULTIPOINT ((0 5), (0 8))'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); +-- PIP - multipoint in line with polygon edge +SELECT 'intersects115', ST_intersects('MULTIPOINT ((0 12))'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); +-- PIP - multipoint vertically aligned with polygon vertex +SELECT 'intersects116', ST_intersects(ST_GeomFromText('MULTIPOINT ((521513 5377804))', 32631), ST_GeomFromText('POLYGON((521526 5377783, 521481 5377811, 521494 5377832, 521539 5377804, 521526 5377783))', 32631)); +-- PIP - repeated vertex +SELECT 'intersects117', ST_intersects(ST_GeomFromText('MULTIPOINT ((521543 5377804))', 32631), ST_GeomFromText('POLYGON((521526 5377783, 521482 5377811, 521494 5377832, 521539 5377804, 521526 5377783))', 32631)); +-- PIP - multipoint within polygon +SELECT 'intersects118', ST_intersects('MULTIPOINT ((5 5))'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); +SELECT 'intersects119', ST_intersects('MULTIPOINT ((5 5), (7 7))'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); +-- PIP - multipoint partially within polygon +SELECT 'intersects120', ST_intersects('MULTIPOINT ((5 5), (15 5))'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); +SELECT 'intersects121', ST_intersects('MULTIPOINT ((15 5), (5 5))'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); -- PIP - point within polygon SELECT 'intersects150', ST_intersects('POINT(5 5)'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); -- PIP - point on polygon vertex @@ -100,11 +128,29 @@ SELECT 'contains104', ST_contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geom SELECT 'contains105', ST_contains(ST_GeomFromText('POLYGON((521526 5377783, 521481 5377811, 521494 5377832, 521539 5377804, 521526 5377783))', 32631), ST_GeomFromText('POINT(521513 5377804)', 32631)); -- PIP - repeated vertex SELECT 'contains106', ST_contains(ST_GeomFromText('POLYGON((521526 5377783, 521482 5377811, 521481 5377811, 521494 5377832, 521539 5377804, 521526 5377783))', 32631), ST_GeomFromText('POINT(521513 5377804)', 32631)); +-- PIP - multipoint within polygon +SELECT 'contains110', ST_contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'MULTIPOINT ((5 5))'::geometry); +-- PIP - multipoint on vertex of polygon +SELECT 'contains111', ST_contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'MULTIPOINT ((0 0))'::geometry); +SELECT 'contains112', ST_contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'MULTIPOINT ((0 0), (10 0))'::geometry); +-- PIP - multipoint outside polygon +SELECT 'contains113', ST_contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'MULTIPOINT ((-1 0))'::geometry); +-- PIP - multipoint partially outside polygon +SELECT 'contains114', ST_contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'MULTIPOINT ((-1 0), (5 5))'::geometry); +SELECT 'contains115', ST_contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'MULTIPOINT ((5 5), (-1 0))'::geometry); +-- PIP - point on edge of polygon +SELECT 'contains116', ST_contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'MULTIPOINT ((0 5))'::geometry); +-- PIP - point in line with polygon edge +SELECT 'contains117', ST_contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'MULTIPOINT ((0 12))'::geometry); +-- PIP - multipoint within polygon +SELECT 'contains118', ST_contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'MULTIPOINT ((5 5), (7 7))'::geometry); +-- PIP - point on edge of polygon and within +SELECT 'contains119', ST_contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'MULTIPOINT ((0 5), (5 5))'::geometry); -- moved here from regress.sql select 'within119', ST_within('LINESTRING(-1 -1, -1 101, 101 101, 101 -1)'::GEOMETRY,'BOX3D(0 0, 100 100)'::BOX3D); select 'within120', ST_within('LINESTRING(-1 -1, -1 100, 101 100, 101 -1)'::GEOMETRY,'BOX3D(0 0, 100 100)'::BOX3D); -SELECT 'contains110', ST_Contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'LINESTRING(1 10, 9 10, 9 8)'::geometry); -SELECT 'contains111', ST_Contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'LINESTRING(1 10, 10 10, 10 8)'::geometry); +SELECT 'contains120', ST_Contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'LINESTRING(1 10, 9 10, 9 8)'::geometry); +SELECT 'contains121', ST_Contains('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry, 'LINESTRING(1 10, 10 10, 10 8)'::geometry); SELECT 'within130', ST_Within('LINESTRING(1 10, 9 10, 9 8)'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); SELECT 'within131', ST_Within('LINESTRING(1 10, 10 10, 10 8)'::geometry, 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry); SELECT 'overlaps', ST_overlaps('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'::geometry,'POINT(5 5)'::geometry); diff --git a/regress/regress_ogc_expected b/regress/regress_ogc_expected index 5488b62f9..83231a2e9 100644 --- a/regress/regress_ogc_expected +++ b/regress/regress_ogc_expected @@ -16,6 +16,11 @@ within103|f within104|f within105|t within106|t +within107|t +within108|t +within109|f +within110|f +within111|t disjoint100|f disjoint101|f disjoint102|t @@ -37,6 +42,17 @@ intersects103|t intersects104|f intersects105|t intersects106|f +intersects111|t +intersects112|f +intersects113|t +intersects114|t +intersects115|f +intersects116|t +intersects117|f +intersects118|t +intersects119|t +intersects120|t +intersects121|t intersects150|t intersects151|t intersects152|f @@ -51,10 +67,20 @@ contains103|f contains104|f contains105|t contains106|t -within119|f -within120|f contains110|t contains111|f +contains112|f +contains113|f +contains114|f +contains115|f +contains116|f +contains117|f +contains118|t +contains119|t +within119|f +within120|f +contains120|t +contains121|f within130|t within131|f overlaps|f