]> granicus.if.org Git - postgis/commitdiff
#75, Enhancement to PIP short circuit
authorDaniel Baston <dbaston@gmail.com>
Thu, 21 Jan 2016 23:03:31 +0000 (23:03 +0000)
committerDaniel Baston <dbaston@gmail.com>
Thu, 21 Jan 2016 23:03:31 +0000 (23:03 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@14613 b70326c6-7e19-0410-871a-916f4a2858ee

postgis/lwgeom_geos.c
regress/regress_ogc.sql
regress/regress_ogc_expected

index d4d7bea52f6c72249b34507c6d6429eab99dbef1..4e61cb9b4b13d756911bfd7a58aeab86338b0b0f 100644 (file)
@@ -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 )
                {
index 00c173730219cb50f97f71f30753785c2bc367fe..98608a0697fef16aa59970b27b33182949460db2 100644 (file)
@@ -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);
index 5488b62f9c95e882421346be2b57b02c1ca7439f..83231a2e9ee85502314564cca4a83f653c0cc636 100644 (file)
@@ -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