28 #include "../postgis_config.h"
33 #include "utils/array.h"
34 #include "utils/builtins.h"
35 #include "utils/lsyscache.h"
36 #include "utils/numeric.h"
38 #include "access/htup_details.h"
56 #define HANDLE_GEOS_ERROR(label) \
58 if (strstr(lwgeom_geos_errmsg, "InterruptedException")) \
60 (errcode(ERRCODE_QUERY_CANCELED), errmsg("canceling statement due to user request"))); \
62 lwpgerror("%s: %s", (label), lwgeom_geos_errmsg); \
72 Datum
touches(PG_FUNCTION_ARGS);
74 Datum
crosses(PG_FUNCTION_ARGS);
77 Datum
covers(PG_FUNCTION_ARGS);
79 Datum
isvalid(PG_FUNCTION_ARGS);
82 Datum
buffer(PG_FUNCTION_ARGS);
91 Datum
isring(PG_FUNCTION_ARGS);
120 text *result = cstring_to_text(ver);
121 PG_RETURN_POINTER(result);
184 geom1 = PG_GETARG_GSERIALIZED_P(0);
185 geom2 = PG_GETARG_GSERIALIZED_P(1);
199 GEOSGeom_destroy(g1);
203 retcode = GEOSHausdorffDistance(g1, g2, &result);
204 GEOSGeom_destroy(g1);
205 GEOSGeom_destroy(g2);
209 PG_FREE_IF_COPY(geom1, 0);
210 PG_FREE_IF_COPY(geom2, 1);
212 PG_RETURN_FLOAT8(result);
234 geom1 = PG_GETARG_GSERIALIZED_P(0);
235 geom2 = PG_GETARG_GSERIALIZED_P(1);
236 densifyFrac = PG_GETARG_FLOAT8(2);
250 GEOSGeom_destroy(g1);
254 retcode = GEOSHausdorffDistanceDensify(g1, g2, densifyFrac, &result);
255 GEOSGeom_destroy(g1);
256 GEOSGeom_destroy(g2);
260 PG_FREE_IF_COPY(geom1, 0);
261 PG_FREE_IF_COPY(geom2, 1);
263 PG_RETURN_FLOAT8(result);
276 #if POSTGIS_GEOS_VERSION < 37
278 lwpgerror(
"The GEOS version this PostGIS binary "
279 "was compiled against (%d) doesn't support "
280 "'GEOSFechetDistance' function (3.7.0+ required)",
293 geom1 = PG_GETARG_GSERIALIZED_P(0);
294 geom2 = PG_GETARG_GSERIALIZED_P(1);
295 densifyFrac = PG_GETARG_FLOAT8(2);
309 GEOSGeom_destroy(g1);
313 if (densifyFrac <= 0.0)
315 retcode = GEOSFrechetDistance(g1, g2, &result);
319 retcode = GEOSFrechetDistanceDensify(g1, g2, densifyFrac, &result);
322 GEOSGeom_destroy(g1);
323 GEOSGeom_destroy(g2);
327 PG_FREE_IF_COPY(geom1, 0);
328 PG_FREE_IF_COPY(geom2, 1);
330 PG_RETURN_FLOAT8(result);
347 ArrayIterator iterator;
352 int nelems = 0, geoms_size = 0, curgeom = 0,
count = 0;
356 GEOSGeometry *g = NULL;
357 GEOSGeometry *g_union = NULL;
358 GEOSGeometry **geoms = NULL;
365 if ( PG_ARGISNULL(0) )
368 array = PG_GETARG_ARRAYTYPE_P(0);
369 nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
372 if ( nelems == 0 ) PG_RETURN_NULL();
375 #if POSTGIS_PGSQL_VERSION >= 95
376 iterator = array_create_iterator(array, 0, NULL);
378 iterator = array_create_iterator(array, 0);
380 while( array_iterate(iterator, &
value, &isnull) )
383 if (isnull)
continue;
386 array_free_iterator(iterator);
394 if (
count == 1 && nelems == 1 )
396 #pragma GCC diagnostic push
397 #pragma GCC diagnostic ignored "-Wsign-compare"
398 PG_RETURN_POINTER((
GSERIALIZED *)(ARR_DATA_PTR(array)));
399 #pragma GCC diagnostic pop
409 geoms = palloc(
sizeof(GEOSGeometry*) * geoms_size);
415 #if POSTGIS_PGSQL_VERSION >= 95
416 iterator = array_create_iterator(array, 0, NULL);
418 iterator = array_create_iterator(array, 0);
420 while( array_iterate(iterator, &
value, &isnull) )
425 if (isnull)
continue;
445 if (gser_type > empty_type)
447 empty_type = gser_type;
448 POSTGIS_DEBUGF(4,
"empty_type = %d gser_type = %d", empty_type, gser_type);
459 "One of the geometries in the set "
460 "could not be converted to GEOS");
464 if ( curgeom == geoms_size )
467 geoms = repalloc( geoms,
sizeof(GEOSGeometry*) * geoms_size );
475 array_free_iterator(iterator);
483 g = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, geoms, curgeom);
484 if (!g)
HANDLE_GEOS_ERROR(
"Could not create GEOS COLLECTION from geometry array");
486 g_union = GEOSUnaryUnion(g);
490 GEOSSetSRID(g_union, srid);
492 GEOSGeom_destroy(g_union);
498 if ( empty_type > 0 )
515 PG_RETURN_POINTER(gser_out);
529 LWGEOM *lwgeom1, *lwresult ;
531 geom1 = PG_GETARG_GSERIALIZED_P(0);
541 PG_FREE_IF_COPY(geom1, 0);
543 PG_RETURN_POINTER(result);
559 LWGEOM *lwgeom1, *lwgeom2, *lwresult ;
561 geom1 = PG_GETARG_GSERIALIZED_P(0);
562 geom2 = PG_GETARG_GSERIALIZED_P(1);
574 PG_FREE_IF_COPY(geom1, 0);
575 PG_FREE_IF_COPY(geom2, 1);
577 PG_RETURN_POINTER(result);
591 LWGEOM *lwgeom1, *lwgeom2, *lwresult ;
593 geom1 = PG_GETARG_GSERIALIZED_P(0);
594 geom2 = PG_GETARG_GSERIALIZED_P(1);
606 PG_FREE_IF_COPY(geom1, 0);
607 PG_FREE_IF_COPY(geom2, 1);
609 PG_RETURN_POINTER(result);
617 GEOSGeometry *g1, *g3;
622 geom1 = PG_GETARG_GSERIALIZED_P(0);
626 PG_RETURN_POINTER(geom1);
632 lwpgerror(
"POSTGIS2GEOS: unable to deserialize input");
642 PG_RETURN_POINTER(result);
653 g3 = GEOSBoundary(g1);
657 GEOSGeom_destroy(g1);
661 POSTGIS_DEBUGF(3,
"result: %s", GEOSGeomToWKT(g3));
663 GEOSSetSRID(g3, srid);
669 GEOSGeom_destroy(g1);
670 GEOSGeom_destroy(g3);
672 "GEOS2POSTGIS threw an error (result postgis geometry "
677 GEOSGeom_destroy(g1);
678 GEOSGeom_destroy(g3);
680 PG_FREE_IF_COPY(geom1, 0);
682 PG_RETURN_POINTER(result);
689 GEOSGeometry *g1, *g3;
695 geom1 = PG_GETARG_GSERIALIZED_P(0);
699 PG_RETURN_POINTER(geom1);
710 g3 = GEOSConvexHull(g1);
711 GEOSGeom_destroy(g1);
715 POSTGIS_DEBUGF(3,
"result: %s", GEOSGeomToWKT(g3));
717 GEOSSetSRID(g3, srid);
720 GEOSGeom_destroy(g3);
725 "convexhull() failed to convert GEOS geometry to LWGEOM");
742 elog(ERROR,
"GEOS convexhull() threw an error (result postgis geometry formation)!");
746 PG_FREE_IF_COPY(geom1, 0);
747 PG_RETURN_POINTER(result);
755 GEOSGeometry *g1, *g3;
759 geom1 = PG_GETARG_GSERIALIZED_P(0);
760 tolerance = PG_GETARG_FLOAT8(1);
765 PG_RETURN_POINTER(geom1);
773 g3 = GEOSTopologyPreserveSimplify(g1,tolerance);
774 GEOSGeom_destroy(g1);
778 POSTGIS_DEBUGF(3,
"result: %s", GEOSGeomToWKT(g3));
783 GEOSGeom_destroy(g3);
787 elog(ERROR,
"GEOS topologypreservesimplify() threw an error (result postgis geometry formation)!");
791 PG_FREE_IF_COPY(geom1, 0);
792 PG_RETURN_POINTER(result);
800 GEOSBufferParams *bufferparams;
801 GEOSGeometry *g1, *g3 = NULL;
818 static const double DEFAULT_MITRE_LIMIT = 5.0;
819 static const int DEFAULT_ENDCAP_STYLE = ENDCAP_ROUND;
820 static const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
822 double mitreLimit = DEFAULT_MITRE_LIMIT;
823 int endCapStyle = DEFAULT_ENDCAP_STYLE;
824 int joinStyle = DEFAULT_JOIN_STYLE;
829 geom1 = PG_GETARG_GSERIALIZED_P(0);
830 size = PG_GETARG_FLOAT8(1);
852 params = pstrdup(PG_GETARG_CSTRING(2));
854 POSTGIS_DEBUGF(3,
"Params: %s", params);
856 for (param=params; ; param=NULL)
859 param = strtok(param,
" ");
861 POSTGIS_DEBUGF(3,
"Param: %s", param);
864 val = strchr(key,
'=');
865 if (!val || *(val + 1) ==
'\0')
867 lwpgerror(
"Missing value for buffer parameter %s", key);
873 POSTGIS_DEBUGF(3,
"Param: %s : %s", key, val);
875 if ( !strcmp(key,
"endcap") )
880 if ( !strcmp(val,
"round") )
882 endCapStyle = ENDCAP_ROUND;
884 else if ( !strcmp(val,
"flat") ||
885 !strcmp(val,
"butt") )
887 endCapStyle = ENDCAP_FLAT;
889 else if ( !strcmp(val,
"square") )
891 endCapStyle = ENDCAP_SQUARE;
895 lwpgerror(
"Invalid buffer end cap "
896 "style: %s (accept: "
897 "'round', 'flat', 'butt' "
904 else if ( !strcmp(key,
"join") )
906 if ( !strcmp(val,
"round") )
908 joinStyle = JOIN_ROUND;
910 else if ( !strcmp(val,
"mitre") ||
911 !strcmp(val,
"miter") )
913 joinStyle = JOIN_MITRE;
915 else if ( !strcmp(val,
"bevel") )
917 joinStyle = JOIN_BEVEL;
921 lwpgerror(
"Invalid buffer end cap "
922 "style: %s (accept: "
923 "'round', 'mitre', 'miter' "
929 else if ( !strcmp(key,
"mitre_limit") ||
930 !strcmp(key,
"miter_limit") )
933 mitreLimit = atof(val);
935 else if ( !strcmp(key,
"quad_segs") )
938 quadsegs = atoi(val);
940 else if ( !strcmp(key,
"side") ||
941 !strcmp(key,
"side") )
943 if ( !strcmp(val,
"both") )
947 else if ( !strcmp(val,
"left") )
951 else if ( !strcmp(val,
"right") )
958 lwpgerror(
"Invalid side parameter: %s (accept: 'right', 'left', 'both')", val);
965 "Invalid buffer parameter: %s (accept: 'endcap', 'join', 'mitre_limit', 'miter_limit', 'quad_segs' and 'side')",
973 POSTGIS_DEBUGF(3,
"endCap:%d joinStyle:%d mitreLimit:%g",
974 endCapStyle, joinStyle, mitreLimit);
978 bufferparams = GEOSBufferParams_create();
981 if (GEOSBufferParams_setEndCapStyle(bufferparams, endCapStyle) &&
982 GEOSBufferParams_setJoinStyle(bufferparams, joinStyle) &&
983 GEOSBufferParams_setMitreLimit(bufferparams, mitreLimit) &&
984 GEOSBufferParams_setQuadrantSegments(bufferparams, quadsegs) &&
985 GEOSBufferParams_setSingleSided(bufferparams, singleside))
987 g3 = GEOSBufferWithParams(g1, bufferparams, size);
991 lwpgerror(
"Error setting buffer parameters.");
993 GEOSBufferParams_destroy(bufferparams);
997 lwpgerror(
"Error setting buffer parameters.");
1000 GEOSGeom_destroy(g1);
1004 POSTGIS_DEBUGF(3,
"result: %s", GEOSGeomToWKT(g3));
1009 GEOSGeom_destroy(g3);
1013 elog(ERROR,
"GEOS buffer() threw an error (result postgis geometry formation)!");
1017 PG_FREE_IF_COPY(geom1, 0);
1018 PG_RETURN_POINTER(result);
1036 gser_input = PG_GETARG_GSERIALIZED_P(0);
1037 npoints = DatumGetInt32(DirectFunctionCall1(numeric_int4, PG_GETARG_DATUM(1)));
1046 PG_FREE_IF_COPY(gser_input, 0);
1055 PG_RETURN_POINTER(gser_result);
1081 static const double DEFAULT_MITRE_LIMIT = 5.0;
1082 static const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
1083 double mitreLimit = DEFAULT_MITRE_LIMIT;
1084 int joinStyle = DEFAULT_JOIN_STYLE;
1086 char *paramstr = NULL;
1090 gser_input = PG_GETARG_GSERIALIZED_P(0);
1091 size = PG_GETARG_FLOAT8(1);
1094 if (size == 0) PG_RETURN_POINTER(gser_input);
1098 if ( ! lwgeom_input )
1099 lwpgerror(
"ST_OffsetCurve: lwgeom_from_gserialized returned NULL");
1103 PG_RETURN_POINTER(gser_input);
1108 text *wkttext = PG_GETARG_TEXT_P(2);
1111 POSTGIS_DEBUGF(3,
"paramstr: %s", paramstr);
1113 for ( param=paramstr; ; param=NULL )
1116 param = strtok(param,
" ");
1118 POSTGIS_DEBUGF(3,
"Param: %s", param);
1121 val = strchr(key,
'=');
1122 if (!val || *(val + 1) ==
'\0')
1124 lwpgerror(
"ST_OffsetCurve: Missing value for buffer parameter %s", key);
1130 POSTGIS_DEBUGF(3,
"Param: %s : %s", key, val);
1132 if ( !strcmp(key,
"join") )
1134 if ( !strcmp(val,
"round") )
1136 joinStyle = JOIN_ROUND;
1138 else if ( !(strcmp(val,
"mitre") && strcmp(val,
"miter")) )
1140 joinStyle = JOIN_MITRE;
1142 else if ( ! strcmp(val,
"bevel") )
1144 joinStyle = JOIN_BEVEL;
1149 "Invalid buffer end cap style: %s (accept: 'round', 'mitre', 'miter' or 'bevel')",
1154 else if ( !strcmp(key,
"mitre_limit") ||
1155 !strcmp(key,
"miter_limit") )
1158 mitreLimit = atof(val);
1160 else if ( !strcmp(key,
"quad_segs") )
1163 quadsegs = atoi(val);
1168 "Invalid buffer parameter: %s (accept: 'join', 'mitre_limit', 'miter_limit and 'quad_segs')",
1173 POSTGIS_DEBUGF(3,
"joinStyle:%d mitreLimit:%g", joinStyle, mitreLimit);
1177 lwgeom_result =
lwgeom_offsetcurve(lwgeom_input, size, quadsegs, joinStyle, mitreLimit);
1180 lwpgerror(
"ST_OffsetCurve: lwgeom_offsetcurve returned NULL");
1185 PG_RETURN_POINTER(gser_result);
1195 LWGEOM *lwgeom1, *lwgeom2, *lwresult ;
1197 geom1 = PG_GETARG_GSERIALIZED_P(0);
1198 geom2 = PG_GETARG_GSERIALIZED_P(1);
1210 PG_FREE_IF_COPY(geom1, 0);
1211 PG_FREE_IF_COPY(geom2, 1);
1213 PG_RETURN_POINTER(result);
1227 LWGEOM *lwgeom1, *lwgeom2, *lwresult ;
1229 geom1 = PG_GETARG_GSERIALIZED_P(0);
1230 geom2 = PG_GETARG_GSERIALIZED_P(1);
1242 PG_FREE_IF_COPY(geom1, 0);
1243 PG_FREE_IF_COPY(geom2, 1);
1245 PG_RETURN_POINTER(result);
1256 LWGEOM *lwgeom, *lwresult;
1258 geom = PG_GETARG_GSERIALIZED_P(0);
1263 PG_FREE_IF_COPY(geom, 0);
1265 if (!lwresult) PG_RETURN_NULL();
1269 PG_RETURN_POINTER(result);
1276 LWGEOM *lwgeom, *lwresult;
1278 geom = PG_GETARG_GSERIALIZED_P(0);
1283 PG_FREE_IF_COPY(geom, 0);
1285 if (!lwresult) PG_RETURN_NULL();
1289 PG_RETURN_POINTER(result);
1298 LWGEOM *lwgeom1, *lwresult ;
1302 geom1 = PG_GETARG_GSERIALIZED_P(0);
1310 PG_RETURN_POINTER(geom1);
1314 bbox2 = (
GBOX *)PG_GETARG_POINTER(1);
1322 PG_FREE_IF_COPY(geom1, 0);
1325 PG_RETURN_POINTER(result);
1332 PG_RETURN_POINTER(geom1);
1339 PG_FREE_IF_COPY(geom1, 0);
1341 if (!lwresult) PG_RETURN_NULL();
1345 PG_RETURN_POINTER(result);
1374 (errmsg(
"Relate Operation called with a LWGEOMCOLLECTION type. This is unsupported."),
1375 errhint(
"Change argument 1: '%s'", hintmsg))
1387 (errmsg(
"Relate Operation called with a LWGEOMCOLLECTION type. This is unsupported."),
1388 errhint(
"Change argument 2: '%s'", hintmsg))
1403 geom1 = PG_GETARG_GSERIALIZED_P(0);
1407 PG_RETURN_BOOL(
true);
1414 lwpgerror(
"unable to deserialize input");
1425 PG_RETURN_BOOL(
false);
1428 result = GEOSisValid(g1);
1429 GEOSGeom_destroy(g1);
1433 elog(ERROR,
"GEOS isvalid() threw an error!");
1437 PG_FREE_IF_COPY(geom1, 0);
1438 PG_RETURN_BOOL(result);
1445 char *reason_str = NULL;
1446 text *result = NULL;
1447 const GEOSGeometry *g1 = NULL;
1449 geom = PG_GETARG_GSERIALIZED_P(0);
1456 reason_str = GEOSisValidReason(g1);
1457 GEOSGeom_destroy((GEOSGeometry *)g1);
1459 result = cstring_to_text(reason_str);
1460 GEOSFree(reason_str);
1467 PG_FREE_IF_COPY(geom, 0);
1468 PG_RETURN_POINTER(result);
1475 const GEOSGeometry *g1 = NULL;
1477 char *geos_reason = NULL;
1478 char *reason = NULL;
1479 GEOSGeometry *geos_location = NULL;
1482 HeapTupleHeader result;
1485 AttInMetadata *attinmeta;
1492 get_call_result_type(fcinfo, 0, &tupdesc);
1493 BlessTupleDesc(tupdesc);
1499 attinmeta = TupleDescGetAttInMetadata(tupdesc);
1501 geom = PG_GETARG_GSERIALIZED_P(0);
1503 if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
1505 flags = PG_GETARG_INT32(1);
1514 valid = GEOSisValidDetail(g1, flags, &geos_reason, &geos_location);
1515 GEOSGeom_destroy((GEOSGeometry *)g1);
1518 reason = pstrdup(geos_reason);
1519 GEOSFree(geos_reason);
1521 if ( geos_location )
1523 location =
GEOS2LWGEOM(geos_location, GEOSHasZ(geos_location));
1524 GEOSGeom_destroy(geos_location);
1530 lwpgerror(
"GEOS isvaliddetail() threw an exception!");
1541 values[0] = valid ?
"t" :
"f";
1549 tuple = BuildTupleFromCStrings(attinmeta, values);
1550 result = (HeapTupleHeader) palloc(tuple->t_len);
1551 memcpy(result, tuple->t_data, tuple->t_len);
1552 heap_freetuple(tuple);
1554 PG_RETURN_HEAPTUPLEHEADER(result);
1569 GEOSGeometry *g1, *g2;
1573 geom1 = PG_GETARG_GSERIALIZED_P(0);
1574 geom2 = PG_GETARG_GSERIALIZED_P(1);
1581 PG_RETURN_BOOL(
false);
1592 PG_RETURN_BOOL(
false);
1606 GEOSGeom_destroy(g1);
1610 result = GEOSOverlaps(g1,g2);
1612 GEOSGeom_destroy(g1);
1613 GEOSGeom_destroy(g2);
1616 PG_FREE_IF_COPY(geom1, 0);
1617 PG_FREE_IF_COPY(geom2, 1);
1619 PG_RETURN_BOOL(result);
1628 GEOSGeometry *g1, *g2;
1633 geom1 = PG_GETARG_GSERIALIZED_P(0);
1634 geom2 = PG_GETARG_GSERIALIZED_P(1);
1641 PG_RETURN_BOOL(
false);
1643 POSTGIS_DEBUG(3,
"contains called.");
1666 POSTGIS_DEBUG(3,
"Point in Polygon test requested...short-circuiting.");
1673 retval = (pip_result == 1);
1679 int found_completely_inside =
LW_FALSE;
1682 for (i = 0; i < mpoint->
ngeoms; i++)
1690 if (pip_result == 1)
1691 found_completely_inside =
LW_TRUE;
1693 if (pip_result == -1)
1700 retval = retval && found_completely_inside;
1706 elog(ERROR,
"Type isn't point or multipoint!");
1710 PG_FREE_IF_COPY(geom1, 0);
1711 PG_FREE_IF_COPY(geom2, 1);
1712 PG_RETURN_BOOL(retval);
1729 POSTGIS_DEBUG(4,
"containsPrepared: cache is live, running preparedcontains");
1730 result = GEOSPreparedContains( prep_cache->
prepared_geom, g1);
1731 GEOSGeom_destroy(g1);
1736 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
1741 GEOSGeom_destroy(g1);
1743 POSTGIS_DEBUG(4,
"containsPrepared: cache is not ready, running standard contains");
1744 result = GEOSContains( g1, g2);
1745 GEOSGeom_destroy(g1);
1746 GEOSGeom_destroy(g2);
1751 PG_FREE_IF_COPY(geom1, 0);
1752 PG_FREE_IF_COPY(geom2, 1);
1754 PG_RETURN_BOOL(result);
1767 geom1 = PG_GETARG_GSERIALIZED_P(0);
1768 geom2 = PG_GETARG_GSERIALIZED_P(1);
1775 PG_RETURN_BOOL(
false);
1785 PG_RETURN_BOOL(
false);
1795 if (!g)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
1796 result = GEOSPreparedContainsProperly( prep_cache->
prepared_geom, g);
1797 GEOSGeom_destroy(g);
1805 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
1809 GEOSGeom_destroy(g1);
1812 result = GEOSRelatePattern( g1, g2,
"T**FF*FF*" );
1813 GEOSGeom_destroy(g1);
1814 GEOSGeom_destroy(g2);
1819 PG_FREE_IF_COPY(geom1, 0);
1820 PG_FREE_IF_COPY(geom2, 1);
1822 PG_RETURN_BOOL(result);
1838 geom1 = PG_GETARG_GSERIALIZED_P(0);
1839 geom2 = PG_GETARG_GSERIALIZED_P(1);
1843 PG_RETURN_BOOL(
false);
1857 PG_RETURN_BOOL(
false);
1871 POSTGIS_DEBUG(3,
"Point in Polygon test requested...short-circuiting.");
1878 retval = (pip_result != -1);
1886 for (i = 0; i < mpoint->
ngeoms; i++)
1889 if (pip_result == -1)
1901 elog(ERROR,
"Type isn't point or multipoint!");
1905 PG_FREE_IF_COPY(geom1, 0);
1906 PG_FREE_IF_COPY(geom2, 1);
1907 PG_RETURN_BOOL(retval);
1921 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
1922 result = GEOSPreparedCovers( prep_cache->
prepared_geom, g1);
1923 GEOSGeom_destroy(g1);
1931 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
1935 GEOSGeom_destroy(g1);
1938 result = GEOSRelatePattern( g1, g2,
"******FF*" );
1939 GEOSGeom_destroy(g1);
1940 GEOSGeom_destroy(g2);
1945 PG_FREE_IF_COPY(geom1, 0);
1946 PG_FREE_IF_COPY(geom2, 1);
1948 PG_RETURN_BOOL(result);
1969 GEOSGeometry *g1, *g2;
1972 char *patt =
"**F**F***";
1974 geom1 = PG_GETARG_GSERIALIZED_P(0);
1975 geom2 = PG_GETARG_GSERIALIZED_P(1);
1982 PG_RETURN_BOOL(
false);
1993 PG_RETURN_BOOL(
false);
1996 POSTGIS_DEBUG(3,
"bounding box short-circuit missed.");
2009 POSTGIS_DEBUG(3,
"Point in Polygon test requested...short-circuiting.");
2016 retval = (pip_result != -1);
2024 for (i = 0; i < mpoint->
ngeoms; i++)
2027 if (pip_result == -1)
2039 elog(ERROR,
"Type isn't point or multipoint!");
2043 PG_FREE_IF_COPY(geom1, 0);
2044 PG_FREE_IF_COPY(geom2, 1);
2045 PG_RETURN_BOOL(retval);
2063 GEOSGeom_destroy(g1);
2067 result = GEOSRelatePattern(g1,g2,patt);
2069 GEOSGeom_destroy(g1);
2070 GEOSGeom_destroy(g2);
2074 PG_FREE_IF_COPY(geom1, 0);
2075 PG_FREE_IF_COPY(geom2, 1);
2077 PG_RETURN_BOOL(result);
2085 GEOSGeometry *g1, *g2;
2089 geom1 = PG_GETARG_GSERIALIZED_P(0);
2090 geom2 = PG_GETARG_GSERIALIZED_P(1);
2097 PG_RETURN_BOOL(
false);
2108 PG_RETURN_BOOL(
false);
2121 GEOSGeom_destroy(g1);
2125 result = GEOSCrosses(g1,g2);
2127 GEOSGeom_destroy(g1);
2128 GEOSGeom_destroy(g2);
2132 PG_FREE_IF_COPY(geom1, 0);
2133 PG_FREE_IF_COPY(geom2, 1);
2135 PG_RETURN_BOOL(result);
2147 geom1 = PG_GETARG_GSERIALIZED_P(0);
2148 geom2 = PG_GETARG_GSERIALIZED_P(1);
2154 PG_RETURN_BOOL(
false);
2165 PG_RETURN_BOOL(
false);
2180 POSTGIS_DEBUG(3,
"Point in Polygon test requested...short-circuiting.");
2187 retval = (pip_result != -1);
2195 for (i = 0; i < mpoint->
ngeoms; i++)
2198 if (pip_result != -1)
2210 elog(ERROR,
"Type isn't point or multipoint!");
2214 PG_FREE_IF_COPY(geom1, 0);
2215 PG_FREE_IF_COPY(geom2, 1);
2216 PG_RETURN_BOOL(retval);
2224 if ( prep_cache->
gcache.argnum == 1 )
2228 result = GEOSPreparedIntersects( prep_cache->
prepared_geom, g);
2229 GEOSGeom_destroy(g);
2236 result = GEOSPreparedIntersects( prep_cache->
prepared_geom, g);
2237 GEOSGeom_destroy(g);
2245 if (!g1)
HANDLE_GEOS_ERROR(
"First argument geometry could not be converted to GEOS");
2249 GEOSGeom_destroy(g1);
2252 result = GEOSIntersects( g1, g2);
2253 GEOSGeom_destroy(g1);
2254 GEOSGeom_destroy(g2);
2259 PG_FREE_IF_COPY(geom1, 0);
2260 PG_FREE_IF_COPY(geom2, 1);
2262 PG_RETURN_BOOL(result);
2271 GEOSGeometry *g1, *g2;
2275 geom1 = PG_GETARG_GSERIALIZED_P(0);
2276 geom2 = PG_GETARG_GSERIALIZED_P(1);
2283 PG_RETURN_BOOL(
false);
2294 PG_RETURN_BOOL(
false);
2307 GEOSGeom_destroy(g1);
2311 result = GEOSTouches(g1,g2);
2313 GEOSGeom_destroy(g1);
2314 GEOSGeom_destroy(g2);
2318 PG_FREE_IF_COPY(geom1, 0);
2319 PG_FREE_IF_COPY(geom2, 1);
2321 PG_RETURN_BOOL(result);
2330 GEOSGeometry *g1, *g2;
2334 geom1 = PG_GETARG_GSERIALIZED_P(0);
2335 geom2 = PG_GETARG_GSERIALIZED_P(1);
2342 PG_RETURN_BOOL(
true);
2353 PG_RETURN_BOOL(
true);
2366 GEOSGeom_destroy(g1);
2370 result = GEOSDisjoint(g1,g2);
2372 GEOSGeom_destroy(g1);
2373 GEOSGeom_destroy(g2);
2377 PG_FREE_IF_COPY(geom1, 0);
2378 PG_FREE_IF_COPY(geom2, 1);
2380 PG_RETURN_BOOL(result);
2391 GEOSGeometry *g1, *g2;
2394 geom1 = PG_GETARG_GSERIALIZED_P(0);
2395 geom2 = PG_GETARG_GSERIALIZED_P(1);
2410 GEOSGeom_destroy(g1);
2414 patt = DatumGetCString(DirectFunctionCall1(textout,
2415 PointerGetDatum(PG_GETARG_DATUM(2))));
2420 for ( i = 0; i < strlen(patt); i++ )
2422 if ( patt[i] ==
't' ) patt[i] =
'T';
2423 if ( patt[i] ==
'f' ) patt[i] =
'F';
2426 result = GEOSRelatePattern(g1,g2,patt);
2427 GEOSGeom_destroy(g1);
2428 GEOSGeom_destroy(g2);
2433 PG_FREE_IF_COPY(geom1, 0);
2434 PG_FREE_IF_COPY(geom2, 1);
2436 PG_RETURN_BOOL(result);
2446 GEOSGeometry *g1, *g2;
2449 int bnr = GEOSRELATE_BNR_OGC;
2451 POSTGIS_DEBUG(2,
"in relate_full()");
2455 geom1 = PG_GETARG_GSERIALIZED_P(0);
2456 geom2 = PG_GETARG_GSERIALIZED_P(1);
2458 if ( PG_NARGS() > 2 )
2460 bnr = PG_GETARG_INT32(2);
2474 GEOSGeom_destroy(g1);
2478 POSTGIS_DEBUG(3,
"constructed geometries ");
2480 POSTGIS_DEBUGF(3,
"%s", GEOSGeomToWKT(g1));
2481 POSTGIS_DEBUGF(3,
"%s", GEOSGeomToWKT(g2));
2483 relate_str = GEOSRelateBoundaryNodeRule(g1, g2, bnr);
2485 GEOSGeom_destroy(g1);
2486 GEOSGeom_destroy(g2);
2490 result = cstring_to_text(relate_str);
2491 GEOSFree(relate_str);
2493 PG_FREE_IF_COPY(geom1, 0);
2494 PG_FREE_IF_COPY(geom2, 1);
2496 PG_RETURN_TEXT_P(result);
2505 GEOSGeometry *g1, *g2;
2509 geom1 = PG_GETARG_GSERIALIZED_P(0);
2510 geom2 = PG_GETARG_GSERIALIZED_P(1);
2517 PG_RETURN_BOOL(
true);
2528 PG_RETURN_BOOL(
false);
2536 if (VARSIZE(geom1) == VARSIZE(geom2) && !memcmp(geom1, geom2, VARSIZE(geom1))) {
2537 PG_RETURN_BOOL(
true);
2551 GEOSGeom_destroy(g1);
2555 result = GEOSEquals(g1,g2);
2557 GEOSGeom_destroy(g1);
2558 GEOSGeom_destroy(g2);
2562 PG_FREE_IF_COPY(geom1, 0);
2563 PG_FREE_IF_COPY(geom2, 1);
2565 PG_RETURN_BOOL(result);
2575 POSTGIS_DEBUG(2,
"issimple called");
2577 geom = PG_GETARG_GSERIALIZED_P(0);
2580 PG_RETURN_BOOL(
true);
2585 PG_FREE_IF_COPY(geom, 0);
2591 PG_RETURN_BOOL(result);
2601 geom = PG_GETARG_GSERIALIZED_P(0);
2605 PG_RETURN_BOOL(
false);
2613 if ( GEOSGeomTypeId(g1) != GEOS_LINESTRING )
2615 GEOSGeom_destroy(g1);
2616 elog(ERROR,
"ST_IsRing() should only be called on a linear feature");
2619 result = GEOSisRing(g1);
2620 GEOSGeom_destroy(g1);
2624 PG_FREE_IF_COPY(geom, 0);
2625 PG_RETURN_BOOL(result);
2637 lwpgerror(
"%s: GEOS2LWGEOM returned NULL", __func__);
2641 POSTGIS_DEBUGF(4,
"%s: GEOS2LWGEOM returned a %s", __func__,
lwgeom_summary(lwgeom, 0));
2661 lwpgerror(
"POSTGIS2GEOS: unable to deserialize input");
2671 ArrayIterator iterator;
2676 #if POSTGIS_PGSQL_VERSION >= 95
2677 iterator = array_create_iterator(array, 0, NULL);
2679 iterator = array_create_iterator(array, 0);
2681 while(array_iterate(iterator, &
value, &isnull) )
2688 array_free_iterator(iterator);
2690 return nelems_not_null;
2696 ArrayIterator iterator;
2699 bool gotsrid =
false;
2704 #if POSTGIS_PGSQL_VERSION >= 95
2705 iterator = array_create_iterator(array, 0, NULL);
2707 iterator = array_create_iterator(array, 0);
2710 while(array_iterate(iterator, &
value, &isnull))
2724 lwpgerror(
"Geometry deserializing geometry");
2747 ArrayIterator iterator;
2750 bool gotsrid =
false;
2753 GEOSGeometry** geos_geoms = palloc(nelems *
sizeof(GEOSGeometry*));
2755 #if POSTGIS_PGSQL_VERSION >= 95
2756 iterator = array_create_iterator(array, 0, NULL);
2758 iterator = array_create_iterator(array, 0);
2761 while(array_iterate(iterator, &
value, &isnull))
2776 lwpgerror(
"Geometry could not be converted to GEOS");
2778 for (j = 0; j < i; j++) {
2779 GEOSGeom_destroy(geos_geoms[j]);
2794 for (j = 0; j <= i; j++) {
2795 GEOSGeom_destroy(geos_geoms[j]);
2803 array_free_iterator(iterator);
2811 GEOSGeometry *geosgeom;
2816 geom = PG_GETARG_GSERIALIZED_P(0);
2818 if ( ! geosgeom ) PG_RETURN_NULL();
2821 GEOSGeom_destroy(geosgeom);
2823 PG_FREE_IF_COPY(geom, 0);
2825 PG_RETURN_POINTER(lwgeom_result);
2835 GEOSGeometry *geos_result;
2836 const GEOSGeometry **vgeoms;
2838 #if POSTGIS_DEBUG_LEVEL >= 3
2842 #if POSTGIS_DEBUG_LEVEL >= 3
2846 if (PG_ARGISNULL(0))
2849 array = PG_GETARG_ARRAYTYPE_P(0);
2855 POSTGIS_DEBUGF(3,
"polygonize_garray: number of non-null elements: %d", nelems);
2860 vgeoms = (
const GEOSGeometry**)
ARRAY2GEOS(array, nelems, &is3d, &srid);
2862 POSTGIS_DEBUG(3,
"polygonize_garray: invoking GEOSpolygonize");
2864 geos_result = GEOSPolygonize(vgeoms, nelems);
2866 POSTGIS_DEBUG(3,
"polygonize_garray: GEOSpolygonize returned");
2868 for (i=0; i<nelems; ++i) GEOSGeom_destroy((GEOSGeometry *)vgeoms[i]);
2871 if ( ! geos_result ) PG_RETURN_NULL();
2873 GEOSSetSRID(geos_result, srid);
2875 GEOSGeom_destroy(geos_result);
2878 elog(ERROR,
"%s returned an error", __func__);
2882 PG_RETURN_POINTER(result);
2889 Datum* result_array_data;
2890 ArrayType *array, *result;
2892 uint32 nelems, nclusters, i;
2893 GEOSGeometry **geos_inputs, **geos_results;
2902 if (PG_ARGISNULL(0))
2905 array = PG_GETARG_ARRAYTYPE_P(0);
2908 POSTGIS_DEBUGF(3,
"clusterintersecting_garray: number of non-null elements: %d", nelems);
2910 if ( nelems == 0 ) PG_RETURN_NULL();
2917 geos_inputs =
ARRAY2GEOS(array, nelems, &is3d, &srid);
2925 elog(ERROR,
"clusterintersecting: Error performing clustering");
2930 if (!geos_results) PG_RETURN_NULL();
2932 result_array_data = palloc(nclusters *
sizeof(Datum));
2933 for (i=0; i<nclusters; ++i)
2935 result_array_data[i] = PointerGetDatum(
GEOS2POSTGIS(geos_results[i], is3d));
2936 GEOSGeom_destroy(geos_results[i]);
2938 pfree(geos_results);
2940 get_typlenbyvalalign(array->elemtype, &elmlen, &elmbyval, &elmalign);
2941 result = construct_array(result_array_data, nclusters, array->elemtype, elmlen, elmbyval, elmalign);
2945 elog(ERROR,
"clusterintersecting: Error constructing return-array");
2949 PG_RETURN_POINTER(result);
2955 Datum* result_array_data;
2956 ArrayType *array, *result;
2958 uint32 nelems, nclusters, i;
2970 if (PG_ARGISNULL(0))
2973 array = PG_GETARG_ARRAYTYPE_P(0);
2975 tolerance = PG_GETARG_FLOAT8(1);
2978 lwpgerror(
"Tolerance must be a positive number.");
2984 POSTGIS_DEBUGF(3,
"cluster_within_distance_garray: number of non-null elements: %d", nelems);
2986 if ( nelems == 0 ) PG_RETURN_NULL();
3001 elog(ERROR,
"cluster_within: Error performing clustering");
3006 if (!lw_results) PG_RETURN_NULL();
3008 result_array_data = palloc(nclusters *
sizeof(Datum));
3009 for (i=0; i<nclusters; ++i)
3016 get_typlenbyvalalign(array->elemtype, &elmlen, &elmbyval, &elmalign);
3017 result = construct_array(result_array_data, nclusters, array->elemtype, elmlen, elmbyval, elmalign);
3021 elog(ERROR,
"clusterwithin: Error constructing return-array");
3025 PG_RETURN_POINTER(result);
3033 LWGEOM *lwgeom1, *lwresult ;
3035 geom1 = PG_GETARG_GSERIALIZED_P(0);
3046 PG_FREE_IF_COPY(geom1, 0);
3048 PG_RETURN_POINTER(result);
3063 LWGEOM *lwgeom_in, *lwgeom_out;
3065 geom = PG_GETARG_GSERIALIZED_P(0);
3073 PG_FREE_IF_COPY(geom, 0);
3080 PG_FREE_IF_COPY(geom, 0);
3081 PG_RETURN_POINTER(result);
3093 LWGEOM *lwgeom_in, *lwgeom_out;
3094 double tolerance = 0.0;
3097 geom = PG_GETARG_GSERIALIZED_P(0);
3098 tolerance = PG_GETARG_FLOAT8(1);
3099 flags = PG_GETARG_INT32(2);
3107 PG_FREE_IF_COPY(geom, 0);
3114 PG_FREE_IF_COPY(geom, 0);
3115 PG_RETURN_POINTER(result);
3123 Datum
ST_Snap(PG_FUNCTION_ARGS);
3128 LWGEOM *lwgeom1, *lwgeom2, *lwresult;
3131 geom1 = PG_GETARG_GSERIALIZED_P(0);
3132 geom2 = PG_GETARG_GSERIALIZED_P(1);
3133 tolerance = PG_GETARG_FLOAT8(2);
3138 lwresult =
lwgeom_snap(lwgeom1, lwgeom2, tolerance);
3141 PG_FREE_IF_COPY(geom1, 0);
3142 PG_FREE_IF_COPY(geom2, 1);
3147 PG_RETURN_POINTER(result);
3179 LWGEOM *lwgeom_in, *lwblade_in, *lwgeom_out;
3181 in = PG_GETARG_GSERIALIZED_P(0);
3184 blade_in = PG_GETARG_GSERIALIZED_P(1);
3195 PG_FREE_IF_COPY(in, 0);
3196 PG_FREE_IF_COPY(blade_in, 1);
3202 PG_FREE_IF_COPY(in, 0);
3203 PG_FREE_IF_COPY(blade_in, 1);
3205 PG_RETURN_POINTER(out);
3228 LWGEOM *g1, *g2, *lwgeom_out;
3230 geom1 = PG_GETARG_GSERIALIZED_P(0);
3231 geom2 = PG_GETARG_GSERIALIZED_P(1);
3242 PG_FREE_IF_COPY(geom1, 0);
3243 PG_FREE_IF_COPY(geom2, 1);
3250 PG_FREE_IF_COPY(geom1, 0);
3251 PG_FREE_IF_COPY(geom2, 1);
3252 PG_RETURN_POINTER(out);
3264 Datum
ST_Node(PG_FUNCTION_ARGS);
3271 geom1 = PG_GETARG_GSERIALIZED_P(0);
3280 PG_FREE_IF_COPY(geom1, 0);
3287 PG_FREE_IF_COPY(geom1, 0);
3288 PG_RETURN_POINTER(out);
3310 int custom_clip_envelope;
3311 int return_polygons;
3314 if (PG_ARGISNULL(0))
3318 if (PG_ARGISNULL(2))
3320 lwpgerror(
"Tolerance must be a positive number.");
3324 tolerance = PG_GETARG_FLOAT8(2);
3328 lwpgerror(
"Tolerance must be a positive number.");
3333 if (PG_ARGISNULL(3))
3335 lwpgerror(
"return_polygons must be true or false.");
3338 return_polygons = PG_GETARG_BOOL(3);
3341 custom_clip_envelope = !PG_ARGISNULL(1);
3342 if (custom_clip_envelope) {
3343 clip = PG_GETARG_GSERIALIZED_P(1);
3346 lwpgerror(
"Could not determine envelope of clipping geometry.");
3347 PG_FREE_IF_COPY(clip, 1);
3350 PG_FREE_IF_COPY(clip, 1);
3354 input = PG_GETARG_GSERIALIZED_P(0);
3360 lwpgerror(
"Could not read input geometry.");
3361 PG_FREE_IF_COPY(input, 0);
3365 lwgeom_result =
lwgeom_voronoi_diagram(lwgeom_input, custom_clip_envelope ? &clip_envelope : NULL, tolerance, !return_polygons);
3370 lwpgerror(
"Error computing Voronoi diagram.");
3371 PG_FREE_IF_COPY(input, 0);
3378 PG_FREE_IF_COPY(input, 0);
3379 PG_RETURN_POINTER(result);
3393 #if POSTGIS_GEOS_VERSION < 36
3394 lwpgerror(
"The GEOS version this PostGIS binary "
3395 "was compiled against (%d) doesn't support "
3396 "'ST_MinimumClearance' function (3.6.0+ required)",
3401 GEOSGeometry* input_geos;
3407 input = PG_GETARG_GSERIALIZED_P(0);
3412 error = GEOSMinimumClearance(input_geos, &result);
3413 GEOSGeom_destroy(input_geos);
3416 PG_FREE_IF_COPY(input, 0);
3417 PG_RETURN_FLOAT8(result);
3432 #if POSTGIS_GEOS_VERSION < 36
3433 lwpgerror(
"The GEOS version this PostGIS binary "
3434 "was compiled against (%d) doesn't support "
3435 "'ST_MinimumClearanceLine' function (3.6.0+ required)",
3441 GEOSGeometry* input_geos;
3442 GEOSGeometry* result_geos;
3447 input = PG_GETARG_GSERIALIZED_P(0);
3453 result_geos = GEOSMinimumClearanceLine(input_geos);
3454 GEOSGeom_destroy(input_geos);
3458 GEOSSetSRID(result_geos, srid);
3460 GEOSGeom_destroy(result_geos);
3462 PG_FREE_IF_COPY(input, 0);
3463 PG_RETURN_POINTER(result);
3476 #if POSTGIS_GEOS_VERSION < 36
3477 lwpgerror(
"The GEOS version this PostGIS binary "
3478 "was compiled against (%d) doesn't support "
3479 "'ST_OrientedEnvelope' function (3.6.0+ required)",
3485 GEOSGeometry* input_geos;
3486 GEOSGeometry* result_geos;
3491 input = PG_GETARG_GSERIALIZED_P(0);
3497 result_geos = GEOSMinimumRotatedRectangle(input_geos);
3498 GEOSGeom_destroy(input_geos);
3502 GEOSSetSRID(result_geos, srid);
3504 GEOSGeom_destroy(result_geos);
3506 PG_FREE_IF_COPY(input, 0);
3507 PG_RETURN_POINTER(result);
int gbox_overlaps_2d(const GBOX *g1, const GBOX *g2)
Return LW_TRUE if the GBOX overlaps on the 2d plane, LW_FALSE otherwise.
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
int gbox_same_2d_float(const GBOX *g1, const GBOX *g2)
Check if two given GBOX are the same in x and y, or would round to the same GBOX in x and if serializ...
int gbox_contains_2d(const GBOX *g1, const GBOX *g2)
Return LW_TRUE if the first GBOX contains the second on the 2d plane, LW_FALSE otherwise.
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
int gserialized_has_z(const GSERIALIZED *gser)
Check if a GSERIALIZED has a Z ordinate.
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *box)
Read the bounding box off a serialization and calculate one if it is not already there.
uint32_t gserialized_get_type(const GSERIALIZED *s)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
GSERIALIZED * gserialized_from_lwgeom(LWGEOM *geom, size_t *size)
Allocate a new GSERIALIZED from an LWGEOM.
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, uint8_t want3d)
void lwgeom_geos_error(const char *fmt,...)
int cluster_within_distance(LWGEOM **geoms, uint32_t num_geoms, double tolerance, LWGEOM ***clusterGeoms, uint32_t *num_clusters)
Takes an array of LWGEOM* and constructs an array of LWGEOM*, where each element in the constructed a...
int cluster_intersecting(GEOSGeometry **geoms, uint32_t num_geoms, GEOSGeometry ***clusterGeoms, uint32_t *num_clusters)
Takes an array of GEOSGeometry* and constructs an array of GEOSGeometry*, where each element in the c...
LWGEOM * lwgeom_centroid(const LWGEOM *geom)
LWGEOM * lwgeom_delaunay_triangulation(const LWGEOM *geom, double tolerance, int32_t edgeOnly)
Take vertices of a geometry and build a delaunay triangulation on them.
LWGEOM * lwgeom_node(const LWGEOM *lwgeom_in)
void lwmpoint_free(LWMPOINT *mpt)
LWGEOM * lwgeom_symdifference(const LWGEOM *geom1, const LWGEOM *geom2)
LWMPOINT * lwgeom_as_lwmpoint(const LWGEOM *lwgeom)
void lwgeom_free(LWGEOM *geom)
LWGEOM * lwgeom_split(const LWGEOM *lwgeom_in, const LWGEOM *blade_in)
LWGEOM * lwgeom_intersection(const LWGEOM *geom1, const LWGEOM *geom2)
LWGEOM * lwgeom_offsetcurve(const LWGEOM *geom, double size, int quadsegs, int joinStyle, double mitreLimit)
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
char * lwmessage_truncate(char *str, int startpos, int endpos, int maxlength, int truncdirection)
int lwgeom_is_simple(const LWGEOM *lwgeom)
LWGEOM * lwgeom_snap(const LWGEOM *geom1, const LWGEOM *geom2, double tolerance)
Snap vertices and segments of a geometry to another using a given tolerance.
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
LWGEOM * lwgeom_difference(const LWGEOM *geom1, const LWGEOM *geom2)
const char * lwgeom_geos_version(void)
Return GEOS version string (not to be freed)
LWMPOLY * lwgeom_as_lwmpoly(const LWGEOM *lwgeom)
int lwgeom_needs_bbox(const LWGEOM *geom)
Check whether or not a lwgeom is big enough to warrant a bounding box.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
char * lwgeom_summary(const LWGEOM *lwgeom, int offset)
LWGEOM * lwgeom_pointonsurface(const LWGEOM *geom)
LWGEOM * lwgeom_sharedpaths(const LWGEOM *geom1, const LWGEOM *geom2)
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
LWGEOM * lwgeom_voronoi_diagram(const LWGEOM *g, const GBOX *env, double tolerance, int output_edges)
Take vertices of a geometry and build the Voronoi diagram.
LWMPOINT * lwgeom_to_points(const LWGEOM *lwgeom, uint32_t npoints)
LWGEOM * lwgeom_unaryunion(const LWGEOM *geom1)
LWGEOM * lwgeom_buildarea(const LWGEOM *geom)
Take a geometry and return an areal geometry (Polygon or MultiPolygon).
char * lwgeom_to_hexwkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
LWGEOM * lwgeom_linemerge(const LWGEOM *geom1)
LWGEOM * lwgeom_clip_by_rect(const LWGEOM *geom1, double x0, double y0, double x1, double y1)
void error_if_srid_mismatch(int srid1, int srid2)
#define LW_TRUE
Return types for functions with status returns.
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
#define SRID_UNKNOWN
Unknown SRID value.
LWGEOM * lwgeom_construct_empty(uint8_t type, int srid, char hasz, char hasm)
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
LWGEOM * lwgeom_union(const LWGEOM *geom1, const LWGEOM *geom2)
This library is the generic geometry handling section of PostGIS.
int point_in_multipolygon(LWMPOLY *mpolygon, LWPOINT *point)
int point_in_multipolygon_rtree(RTREE_NODE **root, int polyCount, int *ringCounts, LWPOINT *point)
int point_in_polygon(LWPOLY *polygon, LWPOINT *point)
PrepGeomCache * GetPrepGeomCache(FunctionCallInfo fcinfo, GSERIALIZED *g1, GSERIALIZED *g2)
Given a couple potential geometries and a function call context, return a prepared structure for one ...
RTREE_POLY_CACHE * GetRtreeCache(FunctionCallInfo fcinfo, GSERIALIZED *g1)
Checks for a cache hit against the provided geometry and returns a pre-built index structure (RTREE_P...
uint32_t array_nelems_not_null(ArrayType *array)
Datum polygonize_garray(PG_FUNCTION_ARGS)
static int pip_short_circuit(RTREE_POLY_CACHE *poly_cache, LWPOINT *point, GSERIALIZED *gpoly)
Datum contains(PG_FUNCTION_ARGS)
Datum coveredby(PG_FUNCTION_ARGS)
Datum isvaliddetail(PG_FUNCTION_ARGS)
Datum geos_geomunion(PG_FUNCTION_ARGS)
#define HANDLE_GEOS_ERROR(label)
Datum isvalid(PG_FUNCTION_ARGS)
static char is_point(const GSERIALIZED *g)
Datum ST_Snap(PG_FUNCTION_ARGS)
Datum ST_BuildArea(PG_FUNCTION_ARGS)
void errorIfGeometryCollection(GSERIALIZED *g1, GSERIALIZED *g2)
Throws an ereport ERROR if either geometry is a COLLECTIONTYPE.
Datum ST_Split(PG_FUNCTION_ARGS)
Datum covers(PG_FUNCTION_ARGS)
Datum ST_Node(PG_FUNCTION_ARGS)
Datum ST_GeneratePoints(PG_FUNCTION_ARGS)
Datum hausdorffdistancedensify(PG_FUNCTION_ARGS)
Datum ST_OffsetCurve(PG_FUNCTION_ARGS)
Datum cluster_within_distance_garray(PG_FUNCTION_ARGS)
Datum centroid(PG_FUNCTION_ARGS)
Datum touches(PG_FUNCTION_ARGS)
Datum disjoint(PG_FUNCTION_ARGS)
Datum geos_intersects(PG_FUNCTION_ARGS)
Datum ST_MinimumClearance(PG_FUNCTION_ARGS)
Datum GEOSnoop(PG_FUNCTION_ARGS)
Datum ST_FrechetDistance(PG_FUNCTION_ARGS)
Datum buffer(PG_FUNCTION_ARGS)
Datum convexhull(PG_FUNCTION_ARGS)
GEOSGeometry * POSTGIS2GEOS(GSERIALIZED *pglwgeom)
Datum ST_ClipByBox2d(PG_FUNCTION_ARGS)
Datum crosses(PG_FUNCTION_ARGS)
Datum relate_full(PG_FUNCTION_ARGS)
Datum relate_pattern(PG_FUNCTION_ARGS)
Datum issimple(PG_FUNCTION_ARGS)
Datum symdifference(PG_FUNCTION_ARGS)
Datum geos_difference(PG_FUNCTION_ARGS)
LWGEOM ** ARRAY2LWGEOM(ArrayType *array, uint32_t nelems, int *is3d, int *srid)
Datum topologypreservesimplify(PG_FUNCTION_ARGS)
Datum geos_intersection(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(postgis_geos_version)
GSERIALIZED * GEOS2POSTGIS(GEOSGeom geom, char want3d)
Datum ST_DelaunayTriangles(PG_FUNCTION_ARGS)
static char is_poly(const GSERIALIZED *g)
Datum boundary(PG_FUNCTION_ARGS)
Datum postgis_geos_version(PG_FUNCTION_ARGS)
Datum ST_UnaryUnion(PG_FUNCTION_ARGS)
Datum overlaps(PG_FUNCTION_ARGS)
Datum ST_Equals(PG_FUNCTION_ARGS)
Datum ST_OrientedEnvelope(PG_FUNCTION_ARGS)
Datum ST_SharedPaths(PG_FUNCTION_ARGS)
Datum ST_MinimumClearanceLine(PG_FUNCTION_ARGS)
Datum ST_Voronoi(PG_FUNCTION_ARGS)
Datum clusterintersecting_garray(PG_FUNCTION_ARGS)
GEOSGeometry ** ARRAY2GEOS(ArrayType *array, uint32_t nelems, int *is3d, int *srid)
Datum pgis_union_geometry_array(PG_FUNCTION_ARGS)
Datum hausdorffdistance(PG_FUNCTION_ARGS)
Datum isvalidreason(PG_FUNCTION_ARGS)
Datum isring(PG_FUNCTION_ARGS)
Datum linemerge(PG_FUNCTION_ARGS)
Datum pointonsurface(PG_FUNCTION_ARGS)
Datum containsproperly(PG_FUNCTION_ARGS)
char * text_to_cstring(const text *textptr)
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
#define POSTGIS_GEOS_VERSION
const GEOSPreparedGeometry * prepared_geom
RTREE_NODE ** ringIndices
The tree structure used for fast P-i-P tests by point_in_multipolygon_rtree()