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
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;
** 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
{
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);
* 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
{
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);
* 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);
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);
* 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);
* 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 )
{
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
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
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);