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) { \ 57 if (strstr(lwgeom_geos_errmsg, "InterruptedException")) \ 58 ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED), errmsg("canceling statement due to user request"))); \ 60 lwpgerror(label ": %s", lwgeom_geos_errmsg); \ 70 Datum
touches(PG_FUNCTION_ARGS);
72 Datum
crosses(PG_FUNCTION_ARGS);
75 Datum
covers(PG_FUNCTION_ARGS);
77 Datum
isvalid(PG_FUNCTION_ARGS);
80 Datum
buffer(PG_FUNCTION_ARGS);
89 Datum
isring(PG_FUNCTION_ARGS);
118 text *result = cstring2text(ver);
119 PG_RETURN_POINTER(result);
182 POSTGIS_DEBUG(2,
"hausdorff_distance called");
184 geom1 = PG_GETARG_GSERIALIZED_P(0);
185 geom2 = PG_GETARG_GSERIALIZED_P(1);
203 GEOSGeom_destroy(g1);
207 retcode = GEOSHausdorffDistance(g1, g2, &result);
208 GEOSGeom_destroy(g1);
209 GEOSGeom_destroy(g2);
217 PG_FREE_IF_COPY(geom1, 0);
218 PG_FREE_IF_COPY(geom2, 1);
220 PG_RETURN_FLOAT8(result);
242 geom1 = PG_GETARG_GSERIALIZED_P(0);
243 geom2 = PG_GETARG_GSERIALIZED_P(1);
244 densifyFrac = PG_GETARG_FLOAT8(2);
262 GEOSGeom_destroy(g1);
266 retcode = GEOSHausdorffDistanceDensify(g1, g2, densifyFrac, &result);
267 GEOSGeom_destroy(g1);
268 GEOSGeom_destroy(g2);
276 PG_FREE_IF_COPY(geom1, 0);
277 PG_FREE_IF_COPY(geom2, 1);
279 PG_RETURN_FLOAT8(result);
292 #if POSTGIS_GEOS_VERSION < 37 294 lwpgerror(
"The GEOS version this PostGIS binary " 295 "was compiled against (%d) doesn't support " 296 "'GEOSFechetDistance' function (3.7.0+ required)",
309 geom1 = PG_GETARG_GSERIALIZED_P(0);
310 geom2 = PG_GETARG_GSERIALIZED_P(1);
311 densifyFrac = PG_GETARG_FLOAT8(2);
329 GEOSGeom_destroy(g1);
333 if (densifyFrac <= 0.0)
335 retcode = GEOSFrechetDistance(g1, g2, &result);
339 retcode = GEOSFrechetDistanceDensify(g1, g2, densifyFrac, &result);
342 GEOSGeom_destroy(g1);
343 GEOSGeom_destroy(g2);
351 PG_FREE_IF_COPY(geom1, 0);
352 PG_FREE_IF_COPY(geom2, 1);
354 PG_RETURN_FLOAT8(result);
375 ArrayIterator iterator;
380 int nelems = 0, geoms_size = 0, curgeom = 0,
count = 0;
384 GEOSGeometry *g = NULL;
385 GEOSGeometry *g_union = NULL;
386 GEOSGeometry **geoms = NULL;
393 if ( PG_ARGISNULL(0) )
396 array = PG_GETARG_ARRAYTYPE_P(0);
397 nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
400 if ( nelems == 0 ) PG_RETURN_NULL();
403 #if POSTGIS_PGSQL_VERSION >= 95 404 iterator = array_create_iterator(array, 0, NULL);
406 iterator = array_create_iterator(array, 0);
408 while( array_iterate(iterator, &value, &isnull) )
416 array_free_iterator(iterator);
424 if (
count == 1 && nelems == 1 )
425 PG_RETURN_POINTER((
GSERIALIZED *)(ARR_DATA_PTR(array)));
434 geoms = palloc(
sizeof(GEOSGeometry*) * geoms_size);
440 #if POSTGIS_PGSQL_VERSION >= 95 441 iterator = array_create_iterator(array, 0, NULL);
443 iterator = array_create_iterator(array, 0);
445 while( array_iterate(iterator, &value, &isnull) )
472 if (gser_type > empty_type)
474 empty_type = gser_type;
475 POSTGIS_DEBUGF(4,
"empty_type = %d gser_type = %d", empty_type, gser_type);
486 "could not be converted to GEOS");
491 if ( curgeom == geoms_size )
494 geoms = repalloc( geoms,
sizeof(GEOSGeometry*) * geoms_size );
502 array_free_iterator(iterator);
510 g = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, geoms, curgeom);
517 g_union = GEOSUnaryUnion(g);
525 GEOSSetSRID(g_union, srid);
527 GEOSGeom_destroy(g_union);
533 if ( empty_type > 0 )
550 PG_RETURN_POINTER(gser_out);
564 LWGEOM *lwgeom1, *lwresult ;
566 geom1 = PG_GETARG_GSERIALIZED_P(0);
577 PG_FREE_IF_COPY(geom1, 0);
579 PG_RETURN_POINTER(result);
596 LWGEOM *lwgeom1, *lwgeom2, *lwresult ;
598 geom1 = PG_GETARG_GSERIALIZED_P(0);
599 geom2 = PG_GETARG_GSERIALIZED_P(1);
611 PG_FREE_IF_COPY(geom1, 0);
612 PG_FREE_IF_COPY(geom2, 1);
614 PG_RETURN_POINTER(result);
629 LWGEOM *lwgeom1, *lwgeom2, *lwresult ;
631 geom1 = PG_GETARG_GSERIALIZED_P(0);
632 geom2 = PG_GETARG_GSERIALIZED_P(1);
644 PG_FREE_IF_COPY(geom1, 0);
645 PG_FREE_IF_COPY(geom2, 1);
647 PG_RETURN_POINTER(result);
655 GEOSGeometry *g1, *g3;
661 geom1 = PG_GETARG_GSERIALIZED_P(0);
665 PG_RETURN_POINTER(geom1);
671 lwpgerror(
"POSTGIS2GEOS: unable to deserialize input");
681 PG_RETURN_POINTER(result);
695 g3 = (GEOSGeometry *)GEOSBoundary(g1);
699 GEOSGeom_destroy(g1);
704 POSTGIS_DEBUGF(3,
"result: %s", GEOSGeomToWKT(g3));
706 GEOSSetSRID(g3, srid);
712 GEOSGeom_destroy(g1);
714 GEOSGeom_destroy(g3);
715 elog(NOTICE,
"GEOS2POSTGIS threw an error (result postgis geometry formation)!");
719 GEOSGeom_destroy(g1);
720 GEOSGeom_destroy(g3);
722 PG_FREE_IF_COPY(geom1, 0);
724 PG_RETURN_POINTER(result);
731 GEOSGeometry *g1, *g3;
737 geom1 = PG_GETARG_GSERIALIZED_P(0);
741 PG_RETURN_POINTER(geom1);
755 g3 = (GEOSGeometry *)GEOSConvexHull(g1);
756 GEOSGeom_destroy(g1);
764 POSTGIS_DEBUGF(3,
"result: %s", GEOSGeomToWKT(g3));
766 GEOSSetSRID(g3, srid);
769 GEOSGeom_destroy(g3);
773 elog(ERROR,
"convexhull() failed to convert GEOS geometry to LWGEOM");
790 elog(ERROR,
"GEOS convexhull() threw an error (result postgis geometry formation)!");
794 PG_FREE_IF_COPY(geom1, 0);
795 PG_RETURN_POINTER(result);
803 GEOSGeometry *g1, *g3;
806 geom1 = PG_GETARG_GSERIALIZED_P(0);
807 tolerance = PG_GETARG_FLOAT8(1);
811 PG_RETURN_POINTER(geom1);
822 g3 = GEOSTopologyPreserveSimplify(g1,tolerance);
823 GEOSGeom_destroy(g1);
831 POSTGIS_DEBUGF(3,
"result: %s", GEOSGeomToWKT(g3));
836 GEOSGeom_destroy(g3);
840 elog(ERROR,
"GEOS topologypreservesimplify() threw an error (result postgis geometry formation)!");
844 PG_FREE_IF_COPY(geom1, 0);
845 PG_RETURN_POINTER(result);
853 GEOSGeometry *g1, *g3;
869 static const double DEFAULT_MITRE_LIMIT = 5.0;
870 static const int DEFAULT_ENDCAP_STYLE = ENDCAP_ROUND;
871 static const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
873 double mitreLimit = DEFAULT_MITRE_LIMIT;
874 int endCapStyle = DEFAULT_ENDCAP_STYLE;
875 int joinStyle = DEFAULT_JOIN_STYLE;
880 geom1 = PG_GETARG_GSERIALIZED_P(0);
881 size = PG_GETARG_FLOAT8(1);
906 params = pstrdup(PG_GETARG_CSTRING(2));
908 POSTGIS_DEBUGF(3,
"Params: %s", params);
910 for (param=params; ; param=NULL)
913 param = strtok(param,
" ");
914 if ( param == NULL )
break;
915 POSTGIS_DEBUGF(3,
"Param: %s", param);
918 val = strchr(key,
'=');
919 if ( val == NULL || *(val+1) ==
'\0' )
921 lwpgerror(
"Missing value for buffer " 922 "parameter %s", key);
928 POSTGIS_DEBUGF(3,
"Param: %s : %s", key, val);
930 if ( !strcmp(key,
"endcap") )
935 if ( !strcmp(val,
"round") )
937 endCapStyle = ENDCAP_ROUND;
939 else if ( !strcmp(val,
"flat") ||
940 !strcmp(val,
"butt") )
942 endCapStyle = ENDCAP_FLAT;
944 else if ( !strcmp(val,
"square") )
946 endCapStyle = ENDCAP_SQUARE;
950 lwpgerror(
"Invalid buffer end cap " 951 "style: %s (accept: " 952 "'round', 'flat', 'butt' " 959 else if ( !strcmp(key,
"join") )
961 if ( !strcmp(val,
"round") )
963 joinStyle = JOIN_ROUND;
965 else if ( !strcmp(val,
"mitre") ||
966 !strcmp(val,
"miter") )
968 joinStyle = JOIN_MITRE;
970 else if ( !strcmp(val,
"bevel") )
972 joinStyle = JOIN_BEVEL;
976 lwpgerror(
"Invalid buffer end cap " 977 "style: %s (accept: " 978 "'round', 'mitre', 'miter' " 984 else if ( !strcmp(key,
"mitre_limit") ||
985 !strcmp(key,
"miter_limit") )
988 mitreLimit = atof(val);
990 else if ( !strcmp(key,
"quad_segs") )
993 quadsegs = atoi(val);
997 lwpgerror(
"Invalid buffer parameter: %s (accept: " 998 "'endcap', 'join', 'mitre_limit', " 1000 "'quad_segs')", key);
1007 POSTGIS_DEBUGF(3,
"endCap:%d joinStyle:%d mitreLimit:%g",
1008 endCapStyle, joinStyle, mitreLimit);
1012 g3 = GEOSBufferWithStyle(g1, size, quadsegs, endCapStyle, joinStyle, mitreLimit);
1013 GEOSGeom_destroy(g1);
1021 POSTGIS_DEBUGF(3,
"result: %s", GEOSGeomToWKT(g3));
1026 GEOSGeom_destroy(g3);
1030 elog(ERROR,
"GEOS buffer() threw an error (result postgis geometry formation)!");
1034 PG_FREE_IF_COPY(geom1, 0);
1035 PG_RETURN_POINTER(result);
1055 gser_input = PG_GETARG_GSERIALIZED_P(0);
1056 npoints = DatumGetInt32(DirectFunctionCall1(numeric_int4, PG_GETARG_DATUM(1)));
1066 PG_FREE_IF_COPY(gser_input, 0);
1075 PG_RETURN_POINTER(gser_result);
1101 static const double DEFAULT_MITRE_LIMIT = 5.0;
1102 static const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
1103 double mitreLimit = DEFAULT_MITRE_LIMIT;
1104 int joinStyle = DEFAULT_JOIN_STYLE;
1106 char *paramstr = NULL;
1110 gser_input = PG_GETARG_GSERIALIZED_P(0);
1111 size = PG_GETARG_FLOAT8(1);
1116 lwpgerror(
"ST_OffsetCurve only works with LineStrings");
1126 PG_RETURN_POINTER(gser_input);
1130 if ( ! lwgeom_input )
1131 lwpgerror(
"ST_OffsetCurve: lwgeom_from_gserialized returned NULL");
1135 PG_RETURN_POINTER(gser_input);
1140 text *wkttext = PG_GETARG_TEXT_P(2);
1143 POSTGIS_DEBUGF(3,
"paramstr: %s", paramstr);
1145 for ( param=paramstr; ; param=NULL )
1148 param = strtok(param,
" ");
1149 if ( param == NULL )
break;
1150 POSTGIS_DEBUGF(3,
"Param: %s", param);
1153 val = strchr(key,
'=');
1154 if ( val == NULL || *(val+1) ==
'\0' )
1156 lwpgerror(
"ST_OffsetCurve: Missing value for buffer parameter %s", key);
1162 POSTGIS_DEBUGF(3,
"Param: %s : %s", key, val);
1164 if ( !strcmp(key,
"join") )
1166 if ( !strcmp(val,
"round") )
1168 joinStyle = JOIN_ROUND;
1170 else if ( !(strcmp(val,
"mitre") && strcmp(val,
"miter")) )
1172 joinStyle = JOIN_MITRE;
1174 else if ( ! strcmp(val,
"bevel") )
1176 joinStyle = JOIN_BEVEL;
1180 lwpgerror(
"Invalid buffer end cap style: %s (accept: " 1181 "'round', 'mitre', 'miter' or 'bevel')", val);
1185 else if ( !strcmp(key,
"mitre_limit") ||
1186 !strcmp(key,
"miter_limit") )
1189 mitreLimit = atof(val);
1191 else if ( !strcmp(key,
"quad_segs") )
1194 quadsegs = atoi(val);
1198 lwpgerror(
"Invalid buffer parameter: %s (accept: " 1199 "'join', 'mitre_limit', 'miter_limit and " 1200 "'quad_segs')", key);
1204 POSTGIS_DEBUGF(3,
"joinStyle:%d mitreLimit:%g", joinStyle, mitreLimit);
1210 if (lwgeom_result == NULL)
1211 lwpgerror(
"ST_OffsetCurve: lwgeom_offsetcurve returned NULL");
1216 PG_RETURN_POINTER(gser_result);
1226 LWGEOM *lwgeom1, *lwgeom2, *lwresult ;
1228 geom1 = PG_GETARG_GSERIALIZED_P(0);
1229 geom2 = PG_GETARG_GSERIALIZED_P(1);
1241 PG_FREE_IF_COPY(geom1, 0);
1242 PG_FREE_IF_COPY(geom2, 1);
1244 PG_RETURN_POINTER(result);
1258 LWGEOM *lwgeom1, *lwgeom2, *lwresult ;
1260 geom1 = PG_GETARG_GSERIALIZED_P(0);
1261 geom2 = PG_GETARG_GSERIALIZED_P(1);
1273 PG_FREE_IF_COPY(geom1, 0);
1274 PG_FREE_IF_COPY(geom2, 1);
1276 PG_RETURN_POINTER(result);
1287 GEOSGeometry *g1, *g3;
1290 geom = PG_GETARG_GSERIALIZED_P(0);
1301 PG_RETURN_POINTER(result);
1316 g3 = GEOSPointOnSurface(g1);
1320 GEOSGeom_destroy(g1);
1325 POSTGIS_DEBUGF(3,
"result: %s", GEOSGeomToWKT(g3) ) ;
1333 GEOSGeom_destroy(g1);
1334 GEOSGeom_destroy(g3);
1335 elog(ERROR,
"GEOS pointonsurface() threw an error (result postgis geometry formation)!");
1339 GEOSGeom_destroy(g1);
1340 GEOSGeom_destroy(g3);
1342 PG_FREE_IF_COPY(geom, 0);
1344 PG_RETURN_POINTER(result);
1351 GEOSGeometry *geosgeom, *geosresult;
1352 LWGEOM *igeom = NULL, *linear_geom = NULL;
1355 geom = PG_GETARG_GSERIALIZED_P(0);
1366 PG_RETURN_POINTER(result);
1374 PG_FREE_IF_COPY(geom, 0);
1377 if (linear_geom == NULL)
1388 if ( 0 == geosgeom )
1394 geosresult = GEOSGetCentroid(geosgeom);
1396 if ( geosresult == NULL )
1398 GEOSGeom_destroy(geosgeom);
1409 GEOSGeom_destroy(geosgeom);
1410 GEOSGeom_destroy(geosresult);
1411 elog(ERROR,
"Error in GEOS-PGIS conversion");
1414 GEOSGeom_destroy(geosgeom);
1415 GEOSGeom_destroy(geosresult);
1417 PG_FREE_IF_COPY(geom, 0);
1419 PG_RETURN_POINTER(result);
1426 #if POSTGIS_GEOS_VERSION < 35 1428 lwpgerror(
"The GEOS version this PostGIS binary " 1429 "was compiled against (%d) doesn't support " 1430 "'GEOSClipByRect' function (3.5.0+ required)",
1438 LWGEOM *lwgeom1, *lwresult ;
1442 geom1 = PG_GETARG_GSERIALIZED_P(0);
1450 PG_RETURN_POINTER(geom1);
1454 bbox2 = (
GBOX *)PG_GETARG_POINTER(1);
1462 PG_FREE_IF_COPY(geom1, 0);
1465 PG_RETURN_POINTER(result);
1472 PG_RETURN_POINTER(geom1);
1479 PG_FREE_IF_COPY(geom1, 0);
1481 if ( lwresult == NULL )
1486 PG_RETURN_POINTER(result);
1519 (errmsg(
"Relate Operation called with a LWGEOMCOLLECTION type. This is unsupported."),
1520 errhint(
"Change argument 1: '%s'", hintmsg))
1532 (errmsg(
"Relate Operation called with a LWGEOMCOLLECTION type. This is unsupported."),
1533 errhint(
"Change argument 2: '%s'", hintmsg))
1548 geom1 = PG_GETARG_GSERIALIZED_P(0);
1552 PG_RETURN_BOOL(
true);
1559 lwpgerror(
"unable to deserialize input");
1570 PG_RETURN_BOOL(
FALSE);
1573 result = GEOSisValid(g1);
1574 GEOSGeom_destroy(g1);
1578 elog(ERROR,
"GEOS isvalid() threw an error!");
1582 PG_FREE_IF_COPY(geom1, 0);
1583 PG_RETURN_BOOL(result);
1594 char *reason_str = NULL;
1595 text *result = NULL;
1596 const GEOSGeometry *g1 = NULL;
1598 geom = PG_GETARG_GSERIALIZED_P(0);
1605 reason_str = GEOSisValidReason(g1);
1606 GEOSGeom_destroy((GEOSGeometry *)g1);
1607 if (reason_str == NULL)
1612 result = cstring2text(reason_str);
1613 GEOSFree(reason_str);
1620 PG_FREE_IF_COPY(geom, 0);
1621 PG_RETURN_POINTER(result);
1632 const GEOSGeometry *g1 = NULL;
1634 char *geos_reason = NULL;
1635 char *reason = NULL;
1636 GEOSGeometry *geos_location = NULL;
1639 HeapTupleHeader result;
1642 AttInMetadata *attinmeta;
1649 get_call_result_type(fcinfo, 0, &tupdesc);
1650 BlessTupleDesc(tupdesc);
1656 attinmeta = TupleDescGetAttInMetadata(tupdesc);
1658 geom = PG_GETARG_GSERIALIZED_P(0);
1660 if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
1662 flags = PG_GETARG_INT32(1);
1671 valid = GEOSisValidDetail(g1, flags,
1672 &geos_reason, &geos_location);
1673 GEOSGeom_destroy((GEOSGeometry *)g1);
1676 reason = pstrdup(geos_reason);
1677 GEOSFree(geos_reason);
1679 if ( geos_location )
1681 location =
GEOS2LWGEOM(geos_location, GEOSHasZ(geos_location));
1682 GEOSGeom_destroy((GEOSGeometry *)geos_location);
1688 lwpgerror(
"GEOS isvaliddetail() threw an exception!");
1699 values[0] = valid ?
"t" :
"f";
1707 tuple = BuildTupleFromCStrings(attinmeta, values);
1708 result = (HeapTupleHeader) palloc(tuple->t_len);
1709 memcpy(result, tuple->t_data, tuple->t_len);
1710 heap_freetuple(tuple);
1712 PG_RETURN_HEAPTUPLEHEADER(result);
1727 GEOSGeometry *g1, *g2;
1731 geom1 = PG_GETARG_GSERIALIZED_P(0);
1732 geom2 = PG_GETARG_GSERIALIZED_P(1);
1739 PG_RETURN_BOOL(
false);
1750 PG_RETURN_BOOL(
FALSE);
1767 GEOSGeom_destroy(g1);
1772 result = GEOSOverlaps(g1,g2);
1774 GEOSGeom_destroy(g1);
1775 GEOSGeom_destroy(g2);
1782 PG_FREE_IF_COPY(geom1, 0);
1783 PG_FREE_IF_COPY(geom2, 1);
1785 PG_RETURN_BOOL(result);
1794 GEOSGeometry *g1, *g2;
1799 geom1 = PG_GETARG_GSERIALIZED_P(0);
1800 geom2 = PG_GETARG_GSERIALIZED_P(1);
1807 PG_RETURN_BOOL(
false);
1809 POSTGIS_DEBUG(3,
"contains called.");
1820 PG_RETURN_BOOL(
FALSE);
1835 POSTGIS_DEBUG(3,
"Point in Polygon test requested...short-circuiting.");
1842 retval = (pip_result == 1);
1848 int found_completely_inside =
LW_FALSE;
1851 for (i = 0; i < mpoint->
ngeoms; i++)
1859 if (pip_result == 1)
1860 found_completely_inside =
LW_TRUE;
1862 if (pip_result == -1)
1869 retval = retval && found_completely_inside;
1875 elog(ERROR,
"Type isn't point or multipoint!");
1879 PG_FREE_IF_COPY(geom1, 0);
1880 PG_FREE_IF_COPY(geom2, 1);
1881 PG_RETURN_BOOL(retval);
1900 POSTGIS_DEBUG(4,
"containsPrepared: cache is live, running preparedcontains");
1901 result = GEOSPreparedContains( prep_cache->
prepared_geom, g1);
1902 GEOSGeom_destroy(g1);
1916 GEOSGeom_destroy(g1);
1919 POSTGIS_DEBUG(4,
"containsPrepared: cache is not ready, running standard contains");
1920 result = GEOSContains( g1, g2);
1921 GEOSGeom_destroy(g1);
1922 GEOSGeom_destroy(g2);
1931 PG_FREE_IF_COPY(geom1, 0);
1932 PG_FREE_IF_COPY(geom2, 1);
1934 PG_RETURN_BOOL(result);
1947 geom1 = PG_GETARG_GSERIALIZED_P(0);
1948 geom2 = PG_GETARG_GSERIALIZED_P(1);
1955 PG_RETURN_BOOL(
false);
1965 PG_RETURN_BOOL(
FALSE);
1980 result = GEOSPreparedContainsProperly( prep_cache->
prepared_geom, g);
1981 GEOSGeom_destroy(g);
1998 GEOSGeom_destroy(g1);
2001 result = GEOSRelatePattern( g1, g2,
"T**FF*FF*" );
2002 GEOSGeom_destroy(g1);
2003 GEOSGeom_destroy(g2);
2012 PG_FREE_IF_COPY(geom1, 0);
2013 PG_FREE_IF_COPY(geom2, 1);
2015 PG_RETURN_BOOL(result);
2031 geom1 = PG_GETARG_GSERIALIZED_P(0);
2032 geom2 = PG_GETARG_GSERIALIZED_P(1);
2036 PG_RETURN_BOOL(
false);
2050 PG_RETURN_BOOL(
FALSE);
2064 POSTGIS_DEBUG(3,
"Point in Polygon test requested...short-circuiting.");
2071 retval = (pip_result != -1);
2079 for (i = 0; i < mpoint->
ngeoms; i++)
2082 if (pip_result == -1)
2094 elog(ERROR,
"Type isn't point or multipoint!");
2098 PG_FREE_IF_COPY(geom1, 0);
2099 PG_FREE_IF_COPY(geom2, 1);
2100 PG_RETURN_BOOL(retval);
2113 GEOSGeometry *g1 = (GEOSGeometry *)
POSTGIS2GEOS(geom2);
2119 result = GEOSPreparedCovers( prep_cache->
prepared_geom, g1);
2120 GEOSGeom_destroy(g1);
2137 GEOSGeom_destroy(g1);
2140 result = GEOSRelatePattern( g1, g2,
"******FF*" );
2141 GEOSGeom_destroy(g1);
2142 GEOSGeom_destroy(g2);
2151 PG_FREE_IF_COPY(geom1, 0);
2152 PG_FREE_IF_COPY(geom2, 1);
2154 PG_RETURN_BOOL(result);
2175 GEOSGeometry *g1, *g2;
2178 char *patt =
"**F**F***";
2180 geom1 = PG_GETARG_GSERIALIZED_P(0);
2181 geom2 = PG_GETARG_GSERIALIZED_P(1);
2188 PG_RETURN_BOOL(
false);
2199 PG_RETURN_BOOL(
FALSE);
2202 POSTGIS_DEBUG(3,
"bounding box short-circuit missed.");
2215 POSTGIS_DEBUG(3,
"Point in Polygon test requested...short-circuiting.");
2222 retval = (pip_result != -1);
2230 for (i = 0; i < mpoint->
ngeoms; i++)
2233 if (pip_result == -1)
2245 elog(ERROR,
"Type isn't point or multipoint!");
2249 PG_FREE_IF_COPY(geom1, 0);
2250 PG_FREE_IF_COPY(geom2, 1);
2251 PG_RETURN_BOOL(retval);
2273 GEOSGeom_destroy(g1);
2277 result = GEOSRelatePattern(g1,g2,patt);
2279 GEOSGeom_destroy(g1);
2280 GEOSGeom_destroy(g2);
2288 PG_FREE_IF_COPY(geom1, 0);
2289 PG_FREE_IF_COPY(geom2, 1);
2291 PG_RETURN_BOOL(result);
2301 GEOSGeometry *g1, *g2;
2305 geom1 = PG_GETARG_GSERIALIZED_P(0);
2306 geom2 = PG_GETARG_GSERIALIZED_P(1);
2313 PG_RETURN_BOOL(
false);
2324 PG_RETURN_BOOL(
FALSE);
2341 GEOSGeom_destroy(g1);
2345 result = GEOSCrosses(g1,g2);
2347 GEOSGeom_destroy(g1);
2348 GEOSGeom_destroy(g2);
2356 PG_FREE_IF_COPY(geom1, 0);
2357 PG_FREE_IF_COPY(geom2, 1);
2359 PG_RETURN_BOOL(result);
2371 geom1 = PG_GETARG_GSERIALIZED_P(0);
2372 geom2 = PG_GETARG_GSERIALIZED_P(1);
2379 PG_RETURN_BOOL(
false);
2390 PG_RETURN_BOOL(
FALSE);
2405 POSTGIS_DEBUG(3,
"Point in Polygon test requested...short-circuiting.");
2412 retval = (pip_result != -1);
2420 for (i = 0; i < mpoint->
ngeoms; i++)
2423 if (pip_result != -1)
2435 elog(ERROR,
"Type isn't point or multipoint!");
2439 PG_FREE_IF_COPY(geom1, 0);
2440 PG_FREE_IF_COPY(geom2, 1);
2441 PG_RETURN_BOOL(retval);
2449 if ( prep_cache->
argnum == 1 )
2457 result = GEOSPreparedIntersects( prep_cache->
prepared_geom, g);
2458 GEOSGeom_destroy(g);
2468 result = GEOSPreparedIntersects( prep_cache->
prepared_geom, g);
2469 GEOSGeom_destroy(g);
2486 GEOSGeom_destroy(g1);
2489 result = GEOSIntersects( g1, g2);
2490 GEOSGeom_destroy(g1);
2491 GEOSGeom_destroy(g2);
2500 PG_FREE_IF_COPY(geom1, 0);
2501 PG_FREE_IF_COPY(geom2, 1);
2503 PG_RETURN_BOOL(result);
2512 GEOSGeometry *g1, *g2;
2516 geom1 = PG_GETARG_GSERIALIZED_P(0);
2517 geom2 = PG_GETARG_GSERIALIZED_P(1);
2524 PG_RETURN_BOOL(
false);
2535 PG_RETURN_BOOL(
FALSE);
2552 GEOSGeom_destroy(g1);
2556 result = GEOSTouches(g1,g2);
2558 GEOSGeom_destroy(g1);
2559 GEOSGeom_destroy(g2);
2567 PG_FREE_IF_COPY(geom1, 0);
2568 PG_FREE_IF_COPY(geom2, 1);
2570 PG_RETURN_BOOL(result);
2579 GEOSGeometry *g1, *g2;
2583 geom1 = PG_GETARG_GSERIALIZED_P(0);
2584 geom2 = PG_GETARG_GSERIALIZED_P(1);
2591 PG_RETURN_BOOL(
true);
2602 PG_RETURN_BOOL(
TRUE);
2619 GEOSGeom_destroy(g1);
2623 result = GEOSDisjoint(g1,g2);
2625 GEOSGeom_destroy(g1);
2626 GEOSGeom_destroy(g2);
2634 PG_FREE_IF_COPY(geom1, 0);
2635 PG_FREE_IF_COPY(geom2, 1);
2637 PG_RETURN_BOOL(result);
2648 GEOSGeometry *g1, *g2;
2651 geom1 = PG_GETARG_GSERIALIZED_P(0);
2652 geom2 = PG_GETARG_GSERIALIZED_P(1);
2672 GEOSGeom_destroy(g1);
2676 patt = DatumGetCString(DirectFunctionCall1(textout,
2677 PointerGetDatum(PG_GETARG_DATUM(2))));
2682 for ( i = 0; i < strlen(patt); i++ )
2684 if ( patt[i] ==
't' ) patt[i] =
'T';
2685 if ( patt[i] ==
'f' ) patt[i] =
'F';
2688 result = GEOSRelatePattern(g1,g2,patt);
2689 GEOSGeom_destroy(g1);
2690 GEOSGeom_destroy(g2);
2699 PG_FREE_IF_COPY(geom1, 0);
2700 PG_FREE_IF_COPY(geom2, 1);
2702 PG_RETURN_BOOL(result);
2712 GEOSGeometry *g1, *g2;
2715 int bnr = GEOSRELATE_BNR_OGC;
2717 POSTGIS_DEBUG(2,
"in relate_full()");
2721 geom1 = PG_GETARG_GSERIALIZED_P(0);
2722 geom2 = PG_GETARG_GSERIALIZED_P(1);
2724 if ( PG_NARGS() > 2 )
2726 bnr = PG_GETARG_INT32(2);
2744 GEOSGeom_destroy(g1);
2748 POSTGIS_DEBUG(3,
"constructed geometries ");
2750 if ((g1==NULL) || (g2 == NULL))
2751 elog(NOTICE,
"g1 or g2 are null");
2753 POSTGIS_DEBUGF(3,
"%s", GEOSGeomToWKT(g1));
2754 POSTGIS_DEBUGF(3,
"%s", GEOSGeomToWKT(g2));
2756 relate_str = GEOSRelateBoundaryNodeRule(g1, g2, bnr);
2758 GEOSGeom_destroy(g1);
2759 GEOSGeom_destroy(g2);
2761 if (relate_str == NULL)
2767 result = cstring2text(relate_str);
2768 GEOSFree(relate_str);
2770 PG_FREE_IF_COPY(geom1, 0);
2771 PG_FREE_IF_COPY(geom2, 1);
2773 PG_RETURN_TEXT_P(result);
2782 GEOSGeometry *g1, *g2;
2786 geom1 = PG_GETARG_GSERIALIZED_P(0);
2787 geom2 = PG_GETARG_GSERIALIZED_P(1);
2794 PG_RETURN_BOOL(
TRUE);
2805 PG_RETURN_BOOL(
FALSE);
2813 if (VARSIZE(geom1) == VARSIZE(geom2) && !memcmp(geom1, geom2, VARSIZE(geom1))) {
2814 PG_RETURN_BOOL(
TRUE);
2832 GEOSGeom_destroy(g1);
2836 result = GEOSEquals(g1,g2);
2838 GEOSGeom_destroy(g1);
2839 GEOSGeom_destroy(g2);
2847 PG_FREE_IF_COPY(geom1, 0);
2848 PG_FREE_IF_COPY(geom2, 1);
2850 PG_RETURN_BOOL(result);
2860 POSTGIS_DEBUG(2,
"issimple called");
2862 geom = PG_GETARG_GSERIALIZED_P(0);
2865 PG_RETURN_BOOL(
TRUE);
2870 PG_FREE_IF_COPY(geom, 0);
2876 PG_RETURN_BOOL(result);
2886 geom = PG_GETARG_GSERIALIZED_P(0);
2890 PG_RETURN_BOOL(
FALSE);
2901 if ( GEOSGeomTypeId(g1) != GEOS_LINESTRING )
2903 GEOSGeom_destroy(g1);
2904 elog(ERROR,
"ST_IsRing() should only be called on a linear feature");
2907 result = GEOSisRing(g1);
2908 GEOSGeom_destroy(g1);
2916 PG_FREE_IF_COPY(geom, 0);
2917 PG_RETURN_BOOL(result);
2933 lwpgerror(
"%s: GEOS2LWGEOM returned NULL", __func__);
2937 POSTGIS_DEBUGF(4,
"%s: GEOS2LWGEOM returned a %s", __func__,
lwgeom_summary(lwgeom, 0));
2960 lwpgerror(
"POSTGIS2GEOS: unable to deserialize input");
2974 ArrayIterator iterator;
2979 #if POSTGIS_PGSQL_VERSION >= 95 2980 iterator = array_create_iterator(array, 0, NULL);
2982 iterator = array_create_iterator(array, 0);
2984 while(array_iterate(iterator, &value, &isnull) )
2991 array_free_iterator(iterator);
2993 return nelems_not_null;
2999 ArrayIterator iterator;
3002 bool gotsrid =
false;
3007 #if POSTGIS_PGSQL_VERSION >= 95 3008 iterator = array_create_iterator(array, 0, NULL);
3010 iterator = array_create_iterator(array, 0);
3013 while(array_iterate(iterator, &value, &isnull))
3027 lwpgerror(
"Geometry deserializing geometry");
3050 ArrayIterator iterator;
3053 bool gotsrid =
false;
3056 GEOSGeometry** geos_geoms = palloc(nelems *
sizeof(GEOSGeometry*));
3058 #if POSTGIS_PGSQL_VERSION >= 95 3059 iterator = array_create_iterator(array, 0, NULL);
3061 iterator = array_create_iterator(array, 0);
3064 while(array_iterate(iterator, &value, &isnull))
3079 lwpgerror(
"Geometry could not be converted to GEOS");
3081 for (j = 0; j < i; j++) {
3082 GEOSGeom_destroy(geos_geoms[j]);
3097 for (j = 0; j <= i; j++) {
3098 GEOSGeom_destroy(geos_geoms[j]);
3106 array_free_iterator(iterator);
3114 GEOSGeometry *geosgeom;
3119 geom = PG_GETARG_GSERIALIZED_P(0);
3121 if ( ! geosgeom ) PG_RETURN_NULL();
3124 GEOSGeom_destroy(geosgeom);
3126 PG_FREE_IF_COPY(geom, 0);
3128 PG_RETURN_POINTER(lwgeom_result);
3138 GEOSGeometry *geos_result;
3139 const GEOSGeometry **vgeoms;
3141 #if POSTGIS_DEBUG_LEVEL >= 3 3145 #if POSTGIS_DEBUG_LEVEL >= 3 3149 if (PG_ARGISNULL(0))
3152 array = PG_GETARG_ARRAYTYPE_P(0);
3158 POSTGIS_DEBUGF(3,
"polygonize_garray: number of non-null elements: %d", nelems);
3163 vgeoms = (
const GEOSGeometry**)
ARRAY2GEOS(array, nelems, &is3d, &srid);
3165 POSTGIS_DEBUG(3,
"polygonize_garray: invoking GEOSpolygonize");
3167 geos_result = GEOSPolygonize(vgeoms, nelems);
3169 POSTGIS_DEBUG(3,
"polygonize_garray: GEOSpolygonize returned");
3171 for (i=0; i<nelems; ++i) GEOSGeom_destroy((GEOSGeometry *)vgeoms[i]);
3174 if ( ! geos_result ) PG_RETURN_NULL();
3176 GEOSSetSRID(geos_result, srid);
3178 GEOSGeom_destroy(geos_result);
3179 if ( result == NULL )
3181 elog(ERROR,
"%s returned an error", __func__);
3185 PG_RETURN_POINTER(result);
3192 Datum* result_array_data;
3193 ArrayType *array, *result;
3195 uint32 nelems, nclusters, i;
3196 GEOSGeometry **geos_inputs, **geos_results;
3205 if (PG_ARGISNULL(0))
3208 array = PG_GETARG_ARRAYTYPE_P(0);
3211 POSTGIS_DEBUGF(3,
"clusterintersecting_garray: number of non-null elements: %d", nelems);
3213 if ( nelems == 0 ) PG_RETURN_NULL();
3220 geos_inputs =
ARRAY2GEOS(array, nelems, &is3d, &srid);
3228 elog(ERROR,
"clusterintersecting: Error performing clustering");
3233 if (!geos_results) PG_RETURN_NULL();
3235 result_array_data = palloc(nclusters *
sizeof(Datum));
3236 for (i=0; i<nclusters; ++i)
3238 result_array_data[i] = PointerGetDatum(
GEOS2POSTGIS(geos_results[i], is3d));
3239 GEOSGeom_destroy(geos_results[i]);
3241 pfree(geos_results);
3243 get_typlenbyvalalign(array->elemtype, &elmlen, &elmbyval, &elmalign);
3244 result = (ArrayType*) construct_array(result_array_data, nclusters, array->elemtype, elmlen, elmbyval, elmalign);
3248 elog(ERROR,
"clusterintersecting: Error constructing return-array");
3252 PG_RETURN_POINTER(result);
3258 Datum* result_array_data;
3259 ArrayType *array, *result;
3261 uint32 nelems, nclusters, i;
3273 if (PG_ARGISNULL(0))
3276 array = PG_GETARG_ARRAYTYPE_P(0);
3278 tolerance = PG_GETARG_FLOAT8(1);
3281 lwpgerror(
"Tolerance must be a positive number.");
3287 POSTGIS_DEBUGF(3,
"cluster_within_distance_garray: number of non-null elements: %d", nelems);
3289 if ( nelems == 0 ) PG_RETURN_NULL();
3304 elog(ERROR,
"cluster_within: Error performing clustering");
3309 if (!lw_results) PG_RETURN_NULL();
3311 result_array_data = palloc(nclusters *
sizeof(Datum));
3312 for (i=0; i<nclusters; ++i)
3319 get_typlenbyvalalign(array->elemtype, &elmlen, &elmbyval, &elmalign);
3320 result = (ArrayType*) construct_array(result_array_data, nclusters, array->elemtype, elmlen, elmbyval, elmalign);
3324 elog(ERROR,
"clusterwithin: Error constructing return-array");
3328 PG_RETURN_POINTER(result);
3336 LWGEOM *lwgeom1, *lwresult ;
3338 geom1 = PG_GETARG_GSERIALIZED_P(0);
3349 PG_FREE_IF_COPY(geom1, 0);
3351 PG_RETURN_POINTER(result);
3366 LWGEOM *lwgeom_in, *lwgeom_out;
3368 geom = PG_GETARG_GSERIALIZED_P(0);
3376 PG_FREE_IF_COPY(geom, 0);
3383 PG_FREE_IF_COPY(geom, 0);
3384 PG_RETURN_POINTER(result);
3396 LWGEOM *lwgeom_in, *lwgeom_out;
3397 double tolerance = 0.0;
3400 geom = PG_GETARG_GSERIALIZED_P(0);
3401 tolerance = PG_GETARG_FLOAT8(1);
3402 flags = PG_GETARG_INT32(2);
3410 PG_FREE_IF_COPY(geom, 0);
3417 PG_FREE_IF_COPY(geom, 0);
3418 PG_RETURN_POINTER(result);
3426 Datum
ST_Snap(PG_FUNCTION_ARGS);
3431 LWGEOM *lwgeom1, *lwgeom2, *lwresult;
3434 geom1 = PG_GETARG_GSERIALIZED_P(0);
3435 geom2 = PG_GETARG_GSERIALIZED_P(1);
3436 tolerance = PG_GETARG_FLOAT8(2);
3441 lwresult =
lwgeom_snap(lwgeom1, lwgeom2, tolerance);
3444 PG_FREE_IF_COPY(geom1, 0);
3445 PG_FREE_IF_COPY(geom2, 1);
3450 PG_RETURN_POINTER(result);
3482 LWGEOM *lwgeom_in, *lwblade_in, *lwgeom_out;
3484 in = PG_GETARG_GSERIALIZED_P(0);
3487 blade_in = PG_GETARG_GSERIALIZED_P(1);
3498 PG_FREE_IF_COPY(in, 0);
3499 PG_FREE_IF_COPY(blade_in, 1);
3505 PG_FREE_IF_COPY(in, 0);
3506 PG_FREE_IF_COPY(blade_in, 1);
3508 PG_RETURN_POINTER(out);
3531 LWGEOM *g1, *g2, *lwgeom_out;
3533 geom1 = PG_GETARG_GSERIALIZED_P(0);
3534 geom2 = PG_GETARG_GSERIALIZED_P(1);
3545 PG_FREE_IF_COPY(geom1, 0);
3546 PG_FREE_IF_COPY(geom2, 1);
3553 PG_FREE_IF_COPY(geom1, 0);
3554 PG_FREE_IF_COPY(geom2, 1);
3555 PG_RETURN_POINTER(out);
3567 Datum
ST_Node(PG_FUNCTION_ARGS);
3574 geom1 = PG_GETARG_GSERIALIZED_P(0);
3583 PG_FREE_IF_COPY(geom1, 0);
3590 PG_FREE_IF_COPY(geom1, 0);
3591 PG_RETURN_POINTER(out);
3606 #if POSTGIS_GEOS_VERSION < 35 3607 lwpgerror(
"The GEOS version this PostGIS binary " 3608 "was compiled against (%d) doesn't support " 3609 "'ST_Voronoi' function (3.5.0+ required)",
3620 int custom_clip_envelope;
3621 int return_polygons;
3624 if (PG_ARGISNULL(0))
3628 if (PG_ARGISNULL(2))
3630 lwpgerror(
"Tolerance must be a positive number.");
3634 tolerance = PG_GETARG_FLOAT8(2);
3638 lwpgerror(
"Tolerance must be a positive number.");
3643 if (PG_ARGISNULL(3))
3645 lwpgerror(
"return_polygons must be true or false.");
3648 return_polygons = PG_GETARG_BOOL(3);
3651 custom_clip_envelope = !PG_ARGISNULL(1);
3652 if (custom_clip_envelope) {
3653 clip = PG_GETARG_GSERIALIZED_P(1);
3656 lwpgerror(
"Could not determine envelope of clipping geometry.");
3657 PG_FREE_IF_COPY(clip, 1);
3660 PG_FREE_IF_COPY(clip, 1);
3664 input = PG_GETARG_GSERIALIZED_P(0);
3670 lwpgerror(
"Could not read input geometry.");
3671 PG_FREE_IF_COPY(input, 0);
3675 lwgeom_result =
lwgeom_voronoi_diagram(lwgeom_input, custom_clip_envelope ? &clip_envelope : NULL, tolerance, !return_polygons);
3680 lwpgerror(
"Error computing Voronoi diagram.");
3681 PG_FREE_IF_COPY(input, 0);
3688 PG_FREE_IF_COPY(input, 0);
3689 PG_RETURN_POINTER(result);
3705 #if POSTGIS_GEOS_VERSION < 36 3706 lwpgerror(
"The GEOS version this PostGIS binary " 3707 "was compiled against (%d) doesn't support " 3708 "'ST_MinimumClearance' function (3.6.0+ required)",
3713 GEOSGeometry* input_geos;
3719 input = PG_GETARG_GSERIALIZED_P(0);
3727 error = GEOSMinimumClearance(input_geos, &result);
3728 GEOSGeom_destroy(input_geos);
3735 PG_FREE_IF_COPY(input, 0);
3736 PG_RETURN_FLOAT8(result);
3751 #if POSTGIS_GEOS_VERSION < 36 3752 lwpgerror(
"The GEOS version this PostGIS binary " 3753 "was compiled against (%d) doesn't support " 3754 "'ST_MinimumClearanceLine' function (3.6.0+ required)",
3760 GEOSGeometry* input_geos;
3761 GEOSGeometry* result_geos;
3766 input = PG_GETARG_GSERIALIZED_P(0);
3775 result_geos = GEOSMinimumClearanceLine(input_geos);
3776 GEOSGeom_destroy(input_geos);
3783 GEOSSetSRID(result_geos, srid);
3785 GEOSGeom_destroy(result_geos);
3787 PG_FREE_IF_COPY(input, 0);
3788 PG_RETURN_POINTER(result);
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.
GEOSGeometry ** ARRAY2GEOS(ArrayType *array, uint32_t nelems, int *is3d, int *srid)
Datum coveredby(PG_FUNCTION_ARGS)
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
Datum isring(PG_FUNCTION_ARGS)
uint32_t gserialized_get_type(const GSERIALIZED *s)
Extract the geometry type from the serialized form (it hides in the anonymous data area...
char * lwgeom_to_hexwkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
uint32_t array_nelems_not_null(ArrayType *array)
LWGEOM * lwgeom_stroke(const LWGEOM *geom, uint32_t perQuad)
#define POSTGIS_GEOS_VERSION
PrepGeomCache * GetPrepGeomCache(FunctionCallInfo fcinfo, GSERIALIZED *g1, GSERIALIZED *g2)
Given a couple potential geometries and a function call context, return a prepared structure for one ...
Datum covers(PG_FUNCTION_ARGS)
const GEOSPreparedGeometry * prepared_geom
LWGEOM * lwgeom_sharedpaths(const LWGEOM *geom1, const LWGEOM *geom2)
Datum topologypreservesimplify(PG_FUNCTION_ARGS)
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Datum ST_Node(PG_FUNCTION_ARGS)
Datum boundary(PG_FUNCTION_ARGS)
Datum hausdorffdistancedensify(PG_FUNCTION_ARGS)
static char is_poly(const GSERIALIZED *g)
Datum pointonsurface(PG_FUNCTION_ARGS)
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
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...
Datum hausdorffdistance(PG_FUNCTION_ARGS)
int gserialized_has_m(const GSERIALIZED *gser)
Check if a GSERIALIZED has an M ordinate.
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Datum ST_SharedPaths(PG_FUNCTION_ARGS)
Datum ST_Equals(PG_FUNCTION_ARGS)
Datum postgis_geos_version(PG_FUNCTION_ARGS)
Datum ST_UnaryUnion(PG_FUNCTION_ARGS)
void lwpoint_free(LWPOINT *pt)
void lwgeom_free(LWGEOM *geom)
Datum ST_DelaunayTriangles(PG_FUNCTION_ARGS)
LWGEOM * lwgeom_clip_by_rect(const LWGEOM *geom1, double x0, double y0, double x1, double y1)
The tree structure used for fast P-i-P tests by point_in_multipolygon_rtree()
Datum isvalid(PG_FUNCTION_ARGS)
LWGEOM * lwgeom_offsetcurve(const LWLINE *lwline, double size, int quadsegs, int joinStyle, double mitreLimit)
Datum clusterintersecting_garray(PG_FUNCTION_ARGS)
Datum contains(PG_FUNCTION_ARGS)
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
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...
Datum ST_MinimumClearanceLine(PG_FUNCTION_ARGS)
Datum centroid(PG_FUNCTION_ARGS)
Datum ST_FrechetDistance(PG_FUNCTION_ARGS)
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.
Datum ST_BuildArea(PG_FUNCTION_ARGS)
int point_in_multipolygon_rtree(RTREE_NODE **root, int polyCount, int *ringCounts, LWPOINT *point)
Datum symdifference(PG_FUNCTION_ARGS)
Datum cluster_within_distance_garray(PG_FUNCTION_ARGS)
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
void error_if_srid_mismatch(int srid1, int srid2)
LWGEOM ** ARRAY2LWGEOM(ArrayType *array, uint32_t nelems, int *is3d, int *srid)
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Datum overlaps(PG_FUNCTION_ARGS)
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
int gserialized_has_z(const GSERIALIZED *gser)
Check if a GSERIALIZED has a Z ordinate.
int point_in_multipolygon(LWMPOLY *mpolygon, LWPOINT *point)
static char is_point(const GSERIALIZED *g)
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Datum geos_geomunion(PG_FUNCTION_ARGS)
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Datum touches(PG_FUNCTION_ARGS)
LWMPOLY * lwgeom_as_lwmpoly(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.
Datum linemerge(PG_FUNCTION_ARGS)
void lwmpoint_free(LWMPOINT *mpt)
Datum buffer(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(postgis_geos_version)
void lwgeom_geos_error(const char *fmt,...)
LWGEOM * lwgeom_node(const LWGEOM *lwgeom_in)
Datum ST_MinimumClearance(PG_FUNCTION_ARGS)
#define LW_TRUE
Return types for functions with status returns.
char * lwmessage_truncate(char *str, int startpos, int endpos, int maxlength, int truncdirection)
LWGEOM * lwgeom_delaunay_triangulation(const LWGEOM *geom, double tolerance, int edgeOnly)
Take vertices of a geometry and build a delaunay triangulation on them.
#define SRID_UNKNOWN
Unknown SRID value.
LWGEOM * lwgeom_intersection(const LWGEOM *geom1, const LWGEOM *geom2)
char * text2cstring(const text *textptr)
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_difference(const LWGEOM *geom1, const LWGEOM *geom2)
Datum ST_OffsetCurve(PG_FUNCTION_ARGS)
Datum convexhull(PG_FUNCTION_ARGS)
Datum containsproperly(PG_FUNCTION_ARGS)
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, int autofix)
LWGEOM * lwgeom_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Datum disjoint(PG_FUNCTION_ARGS)
Datum ST_ClipByBox2d(PG_FUNCTION_ARGS)
LWLINE * lwgeom_as_lwline(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.
int point_in_polygon(LWPOLY *polygon, LWPOINT *point)
int gbox_overlaps_2d(const GBOX *g1, const GBOX *g2)
Return LW_TRUE if the GBOX overlaps on the 2d plane, LW_FALSE otherwise.
LWGEOM * lwgeom_buildarea(const LWGEOM *geom)
Take a geometry and return an areal geometry (Polygon or MultiPolygon).
const char * lwgeom_geos_version(void)
Return GEOS version string (not to be freed)
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
Datum relate_full(PG_FUNCTION_ARGS)
Datum ST_Split(PG_FUNCTION_ARGS)
LWGEOM * lwgeom_unaryunion(const LWGEOM *geom1)
Datum geos_intersects(PG_FUNCTION_ARGS)
int lwgeom_is_simple(const LWGEOM *lwgeom)
LWGEOM * lwgeom_symdifference(const LWGEOM *geom1, const LWGEOM *geom2)
GEOSGeometry * POSTGIS2GEOS(GSERIALIZED *pglwgeom)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
LWMPOINT * lwgeom_as_lwmpoint(const LWGEOM *lwgeom)
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
LWMPOINT * lwgeom_to_points(const LWGEOM *lwgeom, int npoints)
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, char want3d)
Datum ST_GeneratePoints(PG_FUNCTION_ARGS)
Datum geos_difference(PG_FUNCTION_ARGS)
GSERIALIZED * GEOS2POSTGIS(GEOSGeom geom, char want3d)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Datum isvaliddetail(PG_FUNCTION_ARGS)
#define HANDLE_GEOS_ERROR(label)
LWGEOM * lwgeom_union(const LWGEOM *geom1, const LWGEOM *geom2)
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...
RTREE_NODE ** ringIndices
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
GSERIALIZED * gserialized_from_lwgeom(LWGEOM *geom, size_t *size)
Allocate a new GSERIALIZED from an LWGEOM.
Datum GEOSnoop(PG_FUNCTION_ARGS)
Datum polygonize_garray(PG_FUNCTION_ARGS)
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...
Datum ST_Voronoi(PG_FUNCTION_ARGS)
Datum relate_pattern(PG_FUNCTION_ARGS)
char * lwgeom_summary(const LWGEOM *lwgeom, int offset)
Datum isvalidreason(PG_FUNCTION_ARGS)
int lwgeom_needs_bbox(const LWGEOM *geom)
Check whether or not a lwgeom is big enough to warrant a bounding box.
Datum pgis_union_geometry_array(PG_FUNCTION_ARGS)
Datum geos_intersection(PG_FUNCTION_ARGS)
Datum crosses(PG_FUNCTION_ARGS)
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)...
This library is the generic geometry handling section of PostGIS.
LWGEOM * lwgeom_linemerge(const LWGEOM *geom1)
Datum issimple(PG_FUNCTION_ARGS)
LWGEOM * lwgeom_split(const LWGEOM *lwgeom_in, const LWGEOM *blade_in)
static int pip_short_circuit(RTREE_POLY_CACHE *poly_cache, LWPOINT *point, GSERIALIZED *gpoly)
Datum ST_Snap(PG_FUNCTION_ARGS)
void errorIfGeometryCollection(GSERIALIZED *g1, GSERIALIZED *g2)
Throws an ereport ERROR if either geometry is a COLLECTIONTYPE.