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"
37 #include "access/htup_details.h"
53 Datum
isvalid(PG_FUNCTION_ARGS);
56 Datum
buffer(PG_FUNCTION_ARGS);
65 Datum
isring(PG_FUNCTION_ARGS);
95 text *
result = cstring_to_text(ver);
103 text *
result = cstring_to_text(ver);
104 PG_RETURN_POINTER(
result);
123 geom1 = PG_GETARG_GSERIALIZED_P(0);
124 geom2 = PG_GETARG_GSERIALIZED_P(1);
138 GEOSGeom_destroy(g1);
142 retcode = GEOSHausdorffDistance(g1, g2, &
result);
143 GEOSGeom_destroy(g1);
144 GEOSGeom_destroy(g2);
148 PG_FREE_IF_COPY(geom1, 0);
149 PG_FREE_IF_COPY(geom2, 1);
173 geom1 = PG_GETARG_GSERIALIZED_P(0);
174 geom2 = PG_GETARG_GSERIALIZED_P(1);
175 densifyFrac = PG_GETARG_FLOAT8(2);
189 GEOSGeom_destroy(g1);
193 retcode = GEOSHausdorffDistanceDensify(g1, g2, densifyFrac, &
result);
194 GEOSGeom_destroy(g1);
195 GEOSGeom_destroy(g2);
199 PG_FREE_IF_COPY(geom1, 0);
200 PG_FREE_IF_COPY(geom2, 1);
223 geom1 = PG_GETARG_GSERIALIZED_P(0);
224 geom2 = PG_GETARG_GSERIALIZED_P(1);
225 densifyFrac = PG_GETARG_FLOAT8(2);
239 GEOSGeom_destroy(g1);
243 if (densifyFrac <= 0.0)
245 retcode = GEOSFrechetDistance(g1, g2, &
result);
249 retcode = GEOSFrechetDistanceDensify(g1, g2, densifyFrac, &
result);
252 GEOSGeom_destroy(g1);
253 GEOSGeom_destroy(g2);
257 PG_FREE_IF_COPY(geom1, 0);
258 PG_FREE_IF_COPY(geom2, 1);
268 #if POSTGIS_GEOS_VERSION < 30900
270 lwpgerror(
"The GEOS version this PostGIS binary "
271 "was compiled against (%d) doesn't support "
272 "'GEOSMaximumInscribedCircle' function (3.9.0+ required)",
280 TupleDesc resultTupleDesc;
281 HeapTuple resultTuple;
283 Datum result_values[3];
284 bool result_is_null[3];
292 geom = PG_GETARG_GSERIALIZED_P(0);
301 center = geometry_serialize(lwcenter);
302 nearest = geometry_serialize(lwnearest);
307 GEOSGeometry *ginput, *gcircle, *gcenter, *gnearest;
308 double width, height, size, tolerance;
315 lwpgerror(
"Geometry contains invalid coordinates");
325 size = width > height ? width : height;
326 tolerance = size / 1000.0;
337 gcircle = GEOSMaximumInscribedCircle(ginput, tolerance);
340 lwpgerror(
"Error calculating GEOSMaximumInscribedCircle.");
341 GEOSGeom_destroy(ginput);
347 gcircle = GEOSLargestEmptyCircle(ginput, NULL, tolerance);
350 lwpgerror(
"Error calculating GEOSLargestEmptyCircle.");
351 GEOSGeom_destroy(ginput);
356 gcenter = GEOSGeomGetStartPoint(gcircle);
357 gnearest = GEOSGeomGetEndPoint(gcircle);
358 GEOSDistance(gcenter, gnearest, &radius);
359 GEOSSetSRID(gcenter, srid);
360 GEOSSetSRID(gnearest, srid);
364 GEOSGeom_destroy(gcenter);
365 GEOSGeom_destroy(gnearest);
366 GEOSGeom_destroy(gcircle);
367 GEOSGeom_destroy(ginput);
370 get_call_result_type(fcinfo, NULL, &resultTupleDesc);
371 BlessTupleDesc(resultTupleDesc);
373 result_values[0] = PointerGetDatum(center);
374 result_is_null[0] =
false;
375 result_values[1] = PointerGetDatum(nearest);
376 result_is_null[1] =
false;
377 result_values[2] = Float8GetDatum(radius);
378 result_is_null[2] =
false;
379 resultTuple = heap_form_tuple(resultTupleDesc, result_values, result_is_null);
381 result = HeapTupleGetDatum(resultTuple);
393 #if POSTGIS_GEOS_VERSION < 30900
395 lwpgerror(
"The GEOS version this PostGIS binary "
396 "was compiled against (%d) doesn't support "
397 "'GEOSMaximumInscribedCircle' function (3.9.0+ required)",
406 TupleDesc resultTupleDesc;
407 HeapTuple resultTuple;
409 Datum result_values[3];
410 bool result_is_null[3];
411 double radius = 0.0, tolerance = 0.0;
413 bool is3d =
false, hasBoundary =
false;
418 geom = PG_GETARG_GSERIALIZED_P(0);
419 tolerance = PG_GETARG_FLOAT8(1);
420 boundary = PG_GETARG_GSERIALIZED_P(2);
432 center = geometry_serialize(lwcenter);
433 nearest = geometry_serialize(lwnearest);
438 GEOSGeometry *ginput, *gcircle, *gcenter, *gnearest;
439 GEOSGeometry *gboundary = NULL;
440 double width, height, size;
446 lwpgerror(
"Geometry contains invalid coordinates");
459 size = width > height ? width : height;
460 tolerance = size / 1000.0;
476 gcircle = GEOSLargestEmptyCircle(ginput, gboundary, tolerance);
479 lwpgerror(
"Error calculating GEOSLargestEmptyCircle.");
480 GEOSGeom_destroy(ginput);
484 gcenter = GEOSGeomGetStartPoint(gcircle);
485 gnearest = GEOSGeomGetEndPoint(gcircle);
486 GEOSDistance(gcenter, gnearest, &radius);
487 GEOSSetSRID(gcenter, srid);
488 GEOSSetSRID(gnearest, srid);
492 GEOSGeom_destroy(gcenter);
493 GEOSGeom_destroy(gnearest);
494 GEOSGeom_destroy(gcircle);
495 GEOSGeom_destroy(ginput);
496 if (gboundary) GEOSGeom_destroy(gboundary);
499 get_call_result_type(fcinfo, NULL, &resultTupleDesc);
500 BlessTupleDesc(resultTupleDesc);
502 result_values[0] = PointerGetDatum(center);
503 result_is_null[0] =
false;
504 result_values[1] = PointerGetDatum(nearest);
505 result_is_null[1] =
false;
506 result_values[2] = Float8GetDatum(radius);
507 result_is_null[2] =
false;
508 resultTuple = heap_form_tuple(resultTupleDesc, result_values, result_is_null);
510 result = HeapTupleGetDatum(resultTuple);
531 ArrayIterator iterator;
536 int nelems = 0, geoms_size = 0, curgeom = 0,
count = 0;
540 GEOSGeometry *g = NULL;
541 GEOSGeometry *g_union = NULL;
542 GEOSGeometry **geoms = NULL;
549 if ( PG_ARGISNULL(0) )
552 array = PG_GETARG_ARRAYTYPE_P(0);
553 nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
556 if ( nelems == 0 ) PG_RETURN_NULL();
559 iterator = array_create_iterator(array, 0, NULL);
560 while (array_iterate(iterator, &
value, &isnull))
563 if (isnull)
continue;
566 array_free_iterator(iterator);
577 if (
count == 1 && nelems == 1 )
579 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
580 #pragma GCC diagnostic push
581 #pragma GCC diagnostic ignored "-Wsign-compare"
584 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
585 #pragma GCC diagnostic pop
587 srid = GEOSGetSRID(g);
588 g_union = GEOSUnaryUnion(g);
591 GEOSSetSRID(g_union, srid);
593 GEOSGeom_destroy(g_union);
594 PG_RETURN_POINTER(gser_out);
601 geoms = palloc(
sizeof(GEOSGeometry*) * geoms_size);
607 iterator = array_create_iterator(array, 0, NULL);
608 while (array_iterate(iterator, &
value, &isnull))
613 if (isnull)
continue;
631 if (gser_type > empty_type)
633 empty_type = gser_type;
634 POSTGIS_DEBUGF(4,
"empty_type = %d gser_type = %d", empty_type, gser_type);
645 "One of the geometries in the set "
646 "could not be converted to GEOS");
650 if ( curgeom == geoms_size )
653 geoms = repalloc( geoms,
sizeof(GEOSGeometry*) * geoms_size );
661 array_free_iterator(iterator);
669 g = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, geoms, curgeom);
670 if (!g)
HANDLE_GEOS_ERROR(
"Could not create GEOS COLLECTION from geometry array");
672 g_union = GEOSUnaryUnion(g);
676 GEOSSetSRID(g_union, srid);
678 GEOSGeom_destroy(g_union);
684 if ( empty_type > 0 )
701 PG_RETURN_POINTER(gser_out);
716 LWGEOM *lwgeom1, *lwresult ;
719 geom1 = PG_GETARG_GSERIALIZED_P(0);
720 if (PG_NARGS() > 1 && ! PG_ARGISNULL(1))
721 prec = PG_GETARG_FLOAT8(1);
726 result = geometry_serialize(lwresult) ;
731 PG_FREE_IF_COPY(geom1, 0);
733 PG_RETURN_POINTER(
result);
742 LWGEOM *lwgeom1, *lwgeom2, *lwresult;
743 double gridSize = -1;
745 geom1 = PG_GETARG_GSERIALIZED_P(0);
746 geom2 = PG_GETARG_GSERIALIZED_P(1);
747 if (PG_NARGS() > 2 && ! PG_ARGISNULL(2))
748 gridSize = PG_GETARG_FLOAT8(2);
754 result = geometry_serialize(lwresult);
760 PG_FREE_IF_COPY(geom1, 0);
761 PG_FREE_IF_COPY(geom2, 1);
763 PG_RETURN_POINTER(
result);
771 PG_RETURN_DATUM(DirectFunctionCall2(
773 PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)
788 LWGEOM *lwgeom1, *lwgeom2, *lwresult ;
791 geom1 = PG_GETARG_GSERIALIZED_P(0);
792 geom2 = PG_GETARG_GSERIALIZED_P(1);
793 if (PG_NARGS() > 2 && ! PG_ARGISNULL(2))
794 prec = PG_GETARG_FLOAT8(2);
800 result = geometry_serialize(lwresult) ;
806 PG_FREE_IF_COPY(geom1, 0);
807 PG_FREE_IF_COPY(geom2, 1);
809 PG_RETURN_POINTER(
result);
816 GEOSGeometry *g1, *g3;
822 geom1 = PG_GETARG_GSERIALIZED_P(0);
826 PG_RETURN_POINTER(geom1);
837 g3 = GEOSConvexHull(g1);
838 GEOSGeom_destroy(g1);
842 POSTGIS_DEBUGF(3,
"result: %s", GEOSGeomToWKT(g3));
844 GEOSSetSRID(g3, srid);
847 GEOSGeom_destroy(g3);
852 "convexhull() failed to convert GEOS geometry to LWGEOM");
864 result = geometry_serialize(lwout);
869 elog(ERROR,
"GEOS convexhull() threw an error (result postgis geometry formation)!");
873 PG_FREE_IF_COPY(geom1, 0);
874 PG_RETURN_POINTER(
result);
881 #if POSTGIS_GEOS_VERSION < 31100
883 lwpgerror(
"The GEOS version this PostGIS binary "
884 "was compiled against (%d) doesn't support "
885 "'GEOSConcaveHull' function (3.11.0+ required)",
891 double ratio = PG_GETARG_FLOAT8(1);
892 bool allow_holes = PG_GETARG_BOOL(2);
900 PG_FREE_IF_COPY(geom, 0);
901 PG_RETURN_POINTER(
result);
909 #if POSTGIS_GEOS_VERSION < 31100
911 lwpgerror(
"The GEOS version this PostGIS binary "
912 "was compiled against (%d) doesn't support "
913 "'ST_SimplifyPolygonHull' function (3.11.0+ required)",
919 double vertex_fraction = PG_GETARG_FLOAT8(1);
920 uint32_t is_outer = PG_GETARG_BOOL(2);
928 PG_FREE_IF_COPY(geom, 0);
929 PG_RETURN_POINTER(
result);
940 GEOSGeometry *g1, *g3;
944 gs1 = PG_GETARG_GSERIALIZED_P(0);
945 tolerance = PG_GETARG_FLOAT8(1);
951 PG_RETURN_POINTER(gs1);
955 lwpgerror(
"Geometry contains invalid coordinates");
966 g3 = GEOSTopologyPreserveSimplify(g1,tolerance);
967 GEOSGeom_destroy(g1);
971 POSTGIS_DEBUGF(3,
"result: %s", GEOSGeomToWKT(g3));
976 GEOSGeom_destroy(g3);
980 elog(ERROR,
"GEOS topologypreservesimplify() threw an error (result postgis geometry formation)!");
984 PG_FREE_IF_COPY(gs1, 0);
985 PG_RETURN_POINTER(
result);
991 GEOSBufferParams *bufferparams;
992 GEOSGeometry *g1, *g3 = NULL;
1009 const double DEFAULT_MITRE_LIMIT = 5.0;
1010 const int DEFAULT_ENDCAP_STYLE = ENDCAP_ROUND;
1011 const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
1012 double mitreLimit = DEFAULT_MITRE_LIMIT;
1013 int endCapStyle = DEFAULT_ENDCAP_STYLE;
1014 int joinStyle = DEFAULT_JOIN_STYLE;
1017 double size = PG_GETARG_FLOAT8(1);
1022 params_text = PG_GETARG_TEXT_P(2);
1026 params_text = cstring_to_text(
"");
1035 PG_RETURN_POINTER(geometry_serialize(lwg));
1042 lwpgerror(
"Geometry contains invalid coordinates");
1054 if (VARSIZE_ANY_EXHDR(params_text) > 0)
1057 char *params = text_to_cstring(params_text);
1059 for (param=params; ; param=NULL)
1062 param = strtok(param,
" ");
1064 POSTGIS_DEBUGF(3,
"Param: %s", param);
1067 val = strchr(key,
'=');
1068 if (!val || *(val + 1) ==
'\0')
1070 lwpgerror(
"Missing value for buffer parameter %s", key);
1076 POSTGIS_DEBUGF(3,
"Param: %s : %s", key, val);
1078 if ( !strcmp(key,
"endcap") )
1083 if ( !strcmp(val,
"round") )
1085 endCapStyle = ENDCAP_ROUND;
1087 else if ( !strcmp(val,
"flat") ||
1088 !strcmp(val,
"butt") )
1090 endCapStyle = ENDCAP_FLAT;
1092 else if ( !strcmp(val,
"square") )
1094 endCapStyle = ENDCAP_SQUARE;
1098 lwpgerror(
"Invalid buffer end cap "
1099 "style: %s (accept: "
1100 "'round', 'flat', 'butt' "
1107 else if ( !strcmp(key,
"join") )
1109 if ( !strcmp(val,
"round") )
1111 joinStyle = JOIN_ROUND;
1113 else if ( !strcmp(val,
"mitre") ||
1114 !strcmp(val,
"miter") )
1116 joinStyle = JOIN_MITRE;
1118 else if ( !strcmp(val,
"bevel") )
1120 joinStyle = JOIN_BEVEL;
1124 lwpgerror(
"Invalid buffer end cap "
1125 "style: %s (accept: "
1126 "'round', 'mitre', 'miter' "
1132 else if ( !strcmp(key,
"mitre_limit") ||
1133 !strcmp(key,
"miter_limit") )
1136 mitreLimit = atof(val);
1138 else if ( !strcmp(key,
"quad_segs") )
1141 quadsegs = atoi(val);
1143 else if ( !strcmp(key,
"side") )
1145 if ( !strcmp(val,
"both") )
1149 else if ( !strcmp(val,
"left") )
1153 else if ( !strcmp(val,
"right") )
1160 lwpgerror(
"Invalid side parameter: %s (accept: 'right', 'left', 'both')", val);
1167 "Invalid buffer parameter: %s (accept: 'endcap', 'join', 'mitre_limit', 'miter_limit', 'quad_segs' and 'side')",
1176 POSTGIS_DEBUGF(3,
"endCap:%d joinStyle:%d mitreLimit:%g",
1177 endCapStyle, joinStyle, mitreLimit);
1179 bufferparams = GEOSBufferParams_create();
1182 if (GEOSBufferParams_setEndCapStyle(bufferparams, endCapStyle) &&
1183 GEOSBufferParams_setJoinStyle(bufferparams, joinStyle) &&
1184 GEOSBufferParams_setMitreLimit(bufferparams, mitreLimit) &&
1185 GEOSBufferParams_setQuadrantSegments(bufferparams, quadsegs) &&
1186 GEOSBufferParams_setSingleSided(bufferparams, singleside))
1188 g3 = GEOSBufferWithParams(g1, bufferparams, size);
1192 lwpgerror(
"Error setting buffer parameters.");
1194 GEOSBufferParams_destroy(bufferparams);
1198 lwpgerror(
"Error setting buffer parameters.");
1201 GEOSGeom_destroy(g1);
1205 POSTGIS_DEBUGF(3,
"result: %s", GEOSGeomToWKT(g3));
1210 GEOSGeom_destroy(g3);
1214 elog(ERROR,
"GEOS buffer() threw an error (result postgis geometry formation)!");
1218 PG_FREE_IF_COPY(geom1, 0);
1219 PG_RETURN_POINTER(
result);
1238 gser_input = PG_GETARG_GSERIALIZED_P(0);
1239 npoints = PG_GETARG_INT32(1);
1244 if (PG_NARGS() > 2 && ! PG_ARGISNULL(2))
1246 seed = PG_GETARG_INT32(2);
1249 lwpgerror(
"ST_GeneratePoints: seed must be greater than zero");
1258 PG_FREE_IF_COPY(gser_input, 0);
1265 gser_result = geometry_serialize(lwgeom_result);
1267 PG_RETURN_POINTER(gser_result);
1293 static const double DEFAULT_MITRE_LIMIT = 5.0;
1294 static const int DEFAULT_JOIN_STYLE = JOIN_ROUND;
1295 double mitreLimit = DEFAULT_MITRE_LIMIT;
1296 int joinStyle = DEFAULT_JOIN_STYLE;
1298 char *paramstr = NULL;
1302 gser_input = PG_GETARG_GSERIALIZED_P(0);
1303 size = PG_GETARG_FLOAT8(1);
1306 if (size == 0) PG_RETURN_POINTER(gser_input);
1310 if ( ! lwgeom_input )
1311 lwpgerror(
"ST_OffsetCurve: lwgeom_from_gserialized returned NULL");
1315 PG_RETURN_POINTER(gser_input);
1320 text *wkttext = PG_GETARG_TEXT_P(2);
1321 paramstr = text_to_cstring(wkttext);
1323 POSTGIS_DEBUGF(3,
"paramstr: %s", paramstr);
1325 for ( param=paramstr; ; param=NULL )
1328 param = strtok(param,
" ");
1330 POSTGIS_DEBUGF(3,
"Param: %s", param);
1333 val = strchr(key,
'=');
1334 if (!val || *(val + 1) ==
'\0')
1336 lwpgerror(
"ST_OffsetCurve: Missing value for buffer parameter %s", key);
1342 POSTGIS_DEBUGF(3,
"Param: %s : %s", key, val);
1344 if ( !strcmp(key,
"join") )
1346 if ( !strcmp(val,
"round") )
1348 joinStyle = JOIN_ROUND;
1350 else if ( !(strcmp(val,
"mitre") && strcmp(val,
"miter")) )
1352 joinStyle = JOIN_MITRE;
1354 else if ( ! strcmp(val,
"bevel") )
1356 joinStyle = JOIN_BEVEL;
1361 "Invalid buffer end cap style: %s (accept: 'round', 'mitre', 'miter' or 'bevel')",
1366 else if ( !strcmp(key,
"mitre_limit") ||
1367 !strcmp(key,
"miter_limit") )
1370 mitreLimit = atof(val);
1372 else if ( !strcmp(key,
"quad_segs") )
1375 quadsegs = atoi(val);
1380 "Invalid buffer parameter: %s (accept: 'join', 'mitre_limit', 'miter_limit and 'quad_segs')",
1385 POSTGIS_DEBUGF(3,
"joinStyle:%d mitreLimit:%g", joinStyle, mitreLimit);
1389 lwgeom_result =
lwgeom_offsetcurve(lwgeom_input, size, quadsegs, joinStyle, mitreLimit);
1392 lwpgerror(
"ST_OffsetCurve: lwgeom_offsetcurve returned NULL");
1394 gser_result = geometry_serialize(lwgeom_result);
1397 PG_RETURN_POINTER(gser_result);
1406 LWGEOM *lwgeom1, *lwgeom2, *lwresult;
1409 geom1 = PG_GETARG_GSERIALIZED_P(0);
1410 geom2 = PG_GETARG_GSERIALIZED_P(1);
1411 if (PG_NARGS() > 2 && ! PG_ARGISNULL(2))
1412 prec = PG_GETARG_FLOAT8(2);
1418 result = geometry_serialize(lwresult);
1424 PG_FREE_IF_COPY(geom1, 0);
1425 PG_FREE_IF_COPY(geom2, 1);
1427 PG_RETURN_POINTER(
result);
1436 LWGEOM *lwgeom1, *lwgeom2, *lwresult;
1439 geom1 = PG_GETARG_GSERIALIZED_P(0);
1440 geom2 = PG_GETARG_GSERIALIZED_P(1);
1441 if (PG_NARGS() > 2 && ! PG_ARGISNULL(2))
1442 prec = PG_GETARG_FLOAT8(2);
1448 result = geometry_serialize(lwresult);
1454 PG_FREE_IF_COPY(geom1, 0);
1455 PG_FREE_IF_COPY(geom2, 1);
1457 PG_RETURN_POINTER(
result);
1468 LWGEOM *lwgeom, *lwresult;
1470 geom = PG_GETARG_GSERIALIZED_P(0);
1475 PG_FREE_IF_COPY(geom, 0);
1477 if (!lwresult) PG_RETURN_NULL();
1479 result = geometry_serialize(lwresult);
1481 PG_RETURN_POINTER(
result);
1488 LWGEOM *lwgeom, *lwresult;
1490 geom = PG_GETARG_GSERIALIZED_P(0);
1495 PG_FREE_IF_COPY(geom, 0);
1497 if (!lwresult) PG_RETURN_NULL();
1499 result = geometry_serialize(lwresult);
1501 PG_RETURN_POINTER(
result);
1509 LWGEOM *lwgeom, *lwresult;
1510 double gridSize = PG_GETARG_FLOAT8(1);
1511 geom = PG_GETARG_GSERIALIZED_P(0);
1516 PG_FREE_IF_COPY(geom, 0);
1518 if (!lwresult) PG_RETURN_NULL();
1520 result = geometry_serialize(lwresult);
1522 PG_RETURN_POINTER(
result);
1529 static const uint32_t geom_idx = 0;
1530 static const uint32_t box2d_idx = 1;
1532 LWGEOM *lwgeom1, *lwresult ;
1542 PG_RETURN_DATUM(PG_GETARG_DATUM(geom_idx));
1546 bbox2 = (
GBOX *)PG_GETARG_POINTER(box2d_idx);
1552 PG_RETURN_DATUM(PG_GETARG_DATUM(geom_idx));
1560 result = geometry_serialize(lwresult) ;
1562 PG_RETURN_POINTER(
result);
1574 result = geometry_serialize(lwresult) ;
1575 PG_RETURN_POINTER(
result);
1589 geom1 = PG_GETARG_GSERIALIZED_P(0);
1593 PG_RETURN_BOOL(
true);
1600 lwpgerror(
"unable to deserialize input");
1607 PG_RETURN_BOOL(
false);
1610 result = GEOSisValid(g1);
1611 GEOSGeom_destroy(g1);
1615 elog(ERROR,
"GEOS isvalid() threw an error!");
1619 PG_FREE_IF_COPY(geom1, 0);
1627 char *reason_str = NULL;
1629 const GEOSGeometry *g1 = NULL;
1631 geom = PG_GETARG_GSERIALIZED_P(0);
1638 reason_str = GEOSisValidReason(g1);
1639 GEOSGeom_destroy((GEOSGeometry *)g1);
1641 result = cstring_to_text(reason_str);
1642 GEOSFree(reason_str);
1649 PG_FREE_IF_COPY(geom, 0);
1650 PG_RETURN_POINTER(
result);
1657 const GEOSGeometry *g1 = NULL;
1659 char *geos_reason = NULL;
1660 char *reason = NULL;
1661 GEOSGeometry *geos_location = NULL;
1667 AttInMetadata *attinmeta;
1674 get_call_result_type(fcinfo, 0, &tupdesc);
1675 BlessTupleDesc(tupdesc);
1681 attinmeta = TupleDescGetAttInMetadata(tupdesc);
1683 geom = PG_GETARG_GSERIALIZED_P(0);
1684 flags = PG_GETARG_INT32(1);
1692 valid = GEOSisValidDetail(g1, flags, &geos_reason, &geos_location);
1693 GEOSGeom_destroy((GEOSGeometry *)g1);
1696 reason = pstrdup(geos_reason);
1697 GEOSFree(geos_reason);
1699 if ( geos_location )
1701 location =
GEOS2LWGEOM(geos_location, GEOSHasZ(geos_location));
1702 GEOSGeom_destroy(geos_location);
1708 lwpgerror(
"GEOS isvaliddetail() threw an exception!");
1719 values[0] = valid ?
"t" :
"f";
1727 tuple = BuildTupleFromCStrings(attinmeta, values);
1728 result = (HeapTupleHeader) palloc(tuple->t_len);
1729 memcpy(
result, tuple->t_data, tuple->t_len);
1730 heap_freetuple(tuple);
1732 PG_RETURN_HEAPTUPLEHEADER(
result);
1743 POSTGIS_DEBUG(2,
"issimple called");
1745 geom = PG_GETARG_GSERIALIZED_P(0);
1748 PG_RETURN_BOOL(
true);
1753 PG_FREE_IF_COPY(geom, 0);
1769 geom = PG_GETARG_GSERIALIZED_P(0);
1773 PG_RETURN_BOOL(
false);
1781 if ( GEOSGeomTypeId(g1) != GEOS_LINESTRING )
1783 GEOSGeom_destroy(g1);
1784 elog(ERROR,
"ST_IsRing() should only be called on a linear feature");
1788 GEOSGeom_destroy(g1);
1792 PG_FREE_IF_COPY(geom, 0);
1805 lwpgerror(
"%s: GEOS2LWGEOM returned NULL", __func__);
1809 POSTGIS_DEBUGF(4,
"%s: GEOS2LWGEOM returned a %s", __func__,
lwgeom_summary(lwgeom, 0));
1813 result = geometry_serialize(lwgeom);
1828 lwpgerror(
"POSTGIS2GEOS: unable to deserialize input");
1840 ArrayIterator iterator;
1843 uint32_t nelems_not_null = 0;
1844 iterator = array_create_iterator(array, 0, NULL);
1845 while(array_iterate(iterator, &
value, &isnull))
1851 array_free_iterator(iterator);
1853 return nelems_not_null;
1859 ArrayIterator iterator;
1862 bool gotsrid =
false;
1867 iterator = array_create_iterator(array, 0, NULL);
1869 while (array_iterate(iterator, &
value, &isnull))
1881 lwpgerror(
"Geometry deserializing geometry");
1899 GEOSGeometry**
ARRAY2GEOS(ArrayType* array, uint32_t nelems,
int* is3d,
int* srid)
1901 ArrayIterator iterator;
1904 bool gotsrid =
false;
1907 GEOSGeometry** geos_geoms = palloc(nelems *
sizeof(GEOSGeometry*));
1909 iterator = array_create_iterator(array, 0, NULL);
1911 while(array_iterate(iterator, &
value, &isnull))
1924 lwpgerror(
"Geometry could not be converted to GEOS");
1926 for (j = 0; j < i; j++) {
1927 GEOSGeom_destroy(geos_geoms[j]);
1940 for (j = 0; j <= i; j++) {
1941 GEOSGeom_destroy(geos_geoms[j]);
1950 array_free_iterator(iterator);
1958 GEOSGeometry *geosgeom;
1963 geom = PG_GETARG_GSERIALIZED_P(0);
1965 if ( ! geosgeom ) PG_RETURN_NULL();
1968 GEOSGeom_destroy(geosgeom);
1970 PG_FREE_IF_COPY(geom, 0);
1972 PG_RETURN_POINTER(lwgeom_result);
1982 GEOSGeometry *geos_result;
1983 const GEOSGeometry **vgeoms;
1986 if (PG_ARGISNULL(0))
1989 array = PG_GETARG_ARRAYTYPE_P(0);
1995 POSTGIS_DEBUGF(3,
"polygonize_garray: number of non-null elements: %d", nelems);
2000 vgeoms = (
const GEOSGeometry**)
ARRAY2GEOS(array, nelems, &is3d, &srid);
2002 POSTGIS_DEBUG(3,
"polygonize_garray: invoking GEOSpolygonize");
2004 geos_result = GEOSPolygonize(vgeoms, nelems);
2006 POSTGIS_DEBUG(3,
"polygonize_garray: GEOSpolygonize returned");
2008 for (i=0; i<nelems; ++i) GEOSGeom_destroy((GEOSGeometry *)vgeoms[i]);
2011 if ( ! geos_result ) PG_RETURN_NULL();
2013 GEOSSetSRID(geos_result, srid);
2015 GEOSGeom_destroy(geos_result);
2018 elog(ERROR,
"%s returned an error", __func__);
2022 PG_RETURN_POINTER(
result);
2029 Datum* result_array_data;
2030 ArrayType *array, *
result;
2032 uint32 nelems, nclusters, i;
2033 GEOSGeometry **geos_inputs, **geos_results;
2042 if (PG_ARGISNULL(0))
2045 array = PG_GETARG_ARRAYTYPE_P(0);
2048 POSTGIS_DEBUGF(3,
"clusterintersecting_garray: number of non-null elements: %d", nelems);
2050 if ( nelems == 0 ) PG_RETURN_NULL();
2057 geos_inputs =
ARRAY2GEOS(array, nelems, &is3d, &srid);
2065 elog(ERROR,
"clusterintersecting: Error performing clustering");
2070 if (!geos_results) PG_RETURN_NULL();
2072 result_array_data = palloc(nclusters *
sizeof(Datum));
2073 for (i=0; i<nclusters; ++i)
2075 result_array_data[i] = PointerGetDatum(
GEOS2POSTGIS(geos_results[i], is3d));
2076 GEOSGeom_destroy(geos_results[i]);
2080 get_typlenbyvalalign(array->elemtype, &elmlen, &elmbyval, &elmalign);
2081 result = construct_array(result_array_data, nclusters, array->elemtype, elmlen, elmbyval, elmalign);
2085 elog(ERROR,
"clusterintersecting: Error constructing return-array");
2089 PG_RETURN_POINTER(
result);
2095 Datum* result_array_data;
2096 ArrayType *array, *
result;
2098 uint32 nelems, nclusters, i;
2110 if (PG_ARGISNULL(0))
2113 array = PG_GETARG_ARRAYTYPE_P(0);
2115 tolerance = PG_GETARG_FLOAT8(1);
2118 lwpgerror(
"Tolerance must be a positive number.");
2124 POSTGIS_DEBUGF(3,
"cluster_within_distance_garray: number of non-null elements: %d", nelems);
2126 if ( nelems == 0 ) PG_RETURN_NULL();
2141 elog(ERROR,
"cluster_within: Error performing clustering");
2146 if (!lw_results) PG_RETURN_NULL();
2148 result_array_data = palloc(nclusters *
sizeof(Datum));
2149 for (i=0; i<nclusters; ++i)
2151 result_array_data[i] = PointerGetDatum(geometry_serialize(lw_results[i]));
2156 get_typlenbyvalalign(array->elemtype, &elmlen, &elmbyval, &elmalign);
2157 result = construct_array(result_array_data, nclusters, array->elemtype, elmlen, elmbyval, elmalign);
2161 elog(ERROR,
"clusterwithin: Error constructing return-array");
2165 PG_RETURN_POINTER(
result);
2172 bool directed =
false;
2174 LWGEOM *lwgeom1, *lwresult ;
2176 geom1 = PG_GETARG_GSERIALIZED_P(0);
2178 if ( PG_NARGS() > 1 )
2179 directed = PG_GETARG_BOOL(1);
2184 result = geometry_serialize(lwresult) ;
2189 PG_FREE_IF_COPY(geom1, 0);
2191 PG_RETURN_POINTER(
result);
2206 LWGEOM *lwgeom_in, *lwgeom_out;
2208 geom = PG_GETARG_GSERIALIZED_P(0);
2216 PG_FREE_IF_COPY(geom, 0);
2220 result = geometry_serialize(lwgeom_out) ;
2223 PG_FREE_IF_COPY(geom, 0);
2224 PG_RETURN_POINTER(
result);
2236 LWGEOM *lwgeom_in, *lwgeom_out;
2237 double tolerance = 0.0;
2240 geom = PG_GETARG_GSERIALIZED_P(0);
2241 tolerance = PG_GETARG_FLOAT8(1);
2242 flags = PG_GETARG_INT32(2);
2250 PG_FREE_IF_COPY(geom, 0);
2254 result = geometry_serialize(lwgeom_out) ;
2257 PG_FREE_IF_COPY(geom, 0);
2258 PG_RETURN_POINTER(
result);
2269 #if POSTGIS_GEOS_VERSION < 31100
2271 lwpgerror(
"The GEOS version this PostGIS binary "
2272 "was compiled against (%d) doesn't support "
2273 "'GEOSConstrainedDelaunayTriangulation' function (3.11.0+ required)",
2286 PG_FREE_IF_COPY(geom, 0);
2290 result = geometry_serialize(lwgeom_out);
2293 PG_FREE_IF_COPY(geom, 0);
2294 PG_RETURN_POINTER(
result);
2303 Datum
ST_Snap(PG_FUNCTION_ARGS);
2308 LWGEOM *lwgeom1, *lwgeom2, *lwresult;
2311 geom1 = PG_GETARG_GSERIALIZED_P(0);
2312 geom2 = PG_GETARG_GSERIALIZED_P(1);
2313 tolerance = PG_GETARG_FLOAT8(2);
2318 lwresult =
lwgeom_snap(lwgeom1, lwgeom2, tolerance);
2321 PG_FREE_IF_COPY(geom1, 0);
2322 PG_FREE_IF_COPY(geom2, 1);
2324 result = geometry_serialize(lwresult);
2327 PG_RETURN_POINTER(
result);
2359 LWGEOM *lwgeom_in, *lwblade_in, *lwgeom_out;
2361 in = PG_GETARG_GSERIALIZED_P(0);
2362 blade_in = PG_GETARG_GSERIALIZED_P(1);
2370 lwpgerror(
"Input Geometry contains invalid coordinates");
2376 lwpgerror(
"Blade Geometry contains invalid coordinates");
2387 PG_FREE_IF_COPY(in, 0);
2388 PG_FREE_IF_COPY(blade_in, 1);
2392 out = geometry_serialize(lwgeom_out);
2394 PG_FREE_IF_COPY(in, 0);
2395 PG_FREE_IF_COPY(blade_in, 1);
2397 PG_RETURN_POINTER(out);
2420 LWGEOM *g1, *g2, *lwgeom_out;
2422 geom1 = PG_GETARG_GSERIALIZED_P(0);
2423 geom2 = PG_GETARG_GSERIALIZED_P(1);
2434 PG_FREE_IF_COPY(geom1, 0);
2435 PG_FREE_IF_COPY(geom2, 1);
2439 out = geometry_serialize(lwgeom_out);
2442 PG_FREE_IF_COPY(geom1, 0);
2443 PG_FREE_IF_COPY(geom2, 1);
2444 PG_RETURN_POINTER(out);
2456 Datum
ST_Node(PG_FUNCTION_ARGS);
2463 geom1 = PG_GETARG_GSERIALIZED_P(0);
2472 PG_FREE_IF_COPY(geom1, 0);
2476 out = geometry_serialize(lwgeom_out);
2479 PG_FREE_IF_COPY(geom1, 0);
2480 PG_RETURN_POINTER(out);
2502 int custom_clip_envelope;
2503 int return_polygons;
2506 if (PG_ARGISNULL(0))
2510 if (PG_ARGISNULL(2))
2512 lwpgerror(
"Tolerance must be a positive number.");
2516 tolerance = PG_GETARG_FLOAT8(2);
2520 lwpgerror(
"Tolerance must be a positive number.");
2525 if (PG_ARGISNULL(3))
2527 lwpgerror(
"return_polygons must be true or false.");
2530 return_polygons = PG_GETARG_BOOL(3);
2533 custom_clip_envelope = !PG_ARGISNULL(1);
2534 if (custom_clip_envelope) {
2535 clip = PG_GETARG_GSERIALIZED_P(1);
2538 lwpgerror(
"Could not determine envelope of clipping geometry.");
2539 PG_FREE_IF_COPY(clip, 1);
2542 PG_FREE_IF_COPY(clip, 1);
2546 input = PG_GETARG_GSERIALIZED_P(0);
2552 lwpgerror(
"Could not read input geometry.");
2553 PG_FREE_IF_COPY(input, 0);
2557 lwgeom_result =
lwgeom_voronoi_diagram(lwgeom_input, custom_clip_envelope ? &clip_envelope : NULL, tolerance, !return_polygons);
2562 lwpgerror(
"Error computing Voronoi diagram.");
2563 PG_FREE_IF_COPY(input, 0);
2567 result = geometry_serialize(lwgeom_result);
2570 PG_FREE_IF_COPY(input, 0);
2571 PG_RETURN_POINTER(
result);
2586 GEOSGeometry* input_geos;
2592 input = PG_GETARG_GSERIALIZED_P(0);
2597 error = GEOSMinimumClearance(input_geos, &
result);
2598 GEOSGeom_destroy(input_geos);
2601 PG_FREE_IF_COPY(input, 0);
2602 PG_RETURN_FLOAT8(
result);
2618 GEOSGeometry* input_geos;
2619 GEOSGeometry* result_geos;
2624 input = PG_GETARG_GSERIALIZED_P(0);
2630 result_geos = GEOSMinimumClearanceLine(input_geos);
2631 GEOSGeom_destroy(input_geos);
2635 GEOSSetSRID(result_geos, srid);
2637 GEOSGeom_destroy(result_geos);
2639 PG_FREE_IF_COPY(input, 0);
2640 PG_RETURN_POINTER(
result);
2654 GEOSGeometry* input_geos;
2655 GEOSGeometry* result_geos;
2660 input = PG_GETARG_GSERIALIZED_P(0);
2666 result_geos = GEOSMinimumRotatedRectangle(input_geos);
2667 GEOSGeom_destroy(input_geos);
2671 GEOSSetSRID(result_geos, srid);
2673 GEOSGeom_destroy(result_geos);
2675 PG_FREE_IF_COPY(input, 0);
2676 PG_RETURN_POINTER(
result);
2693 double radius = PG_GETARG_FLOAT8(2);
2694 GEOSGeometry *buffer1 = NULL;
2695 GEOSGeometry *geos1 = NULL, *geos2 = NULL;
2700 elog(ERROR,
"Tolerance cannot be less than zero\n");
2707 PG_RETURN_BOOL(
false);
2710 PG_RETURN_BOOL(
false);
2718 if (!(geos1 && geos2))
2721 buffer1 = GEOSBuffer(geos1, radius, 16);
2722 GEOSGeom_destroy(geos1);
2726 contained = GEOSCovers(buffer1, geos2);
2727 GEOSGeom_destroy(buffer1);
2728 GEOSGeom_destroy(geos2);
2732 PG_FREE_IF_COPY(geom1, 0);
2733 PG_FREE_IF_COPY(geom2, 1);
2735 PG_RETURN_BOOL(contained == 1);
char result[OUT_DOUBLE_BUFFER_SIZE]
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_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.
void gserialized_error_if_srid_mismatch(const GSERIALIZED *g1, const GSERIALIZED *g2, const char *funcname)
void gserialized_error_if_srid_mismatch_reference(const GSERIALIZED *g1, const int32_t srid2, const char *funcname)
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
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_has_z(const GSERIALIZED *g)
Check if a GSERIALIZED has a Z ordinate.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
int gserialized_datum_get_internals_p(Datum gsdatum, GBOX *gbox, lwflags_t *flags, uint8_t *type, int32_t *srid)
Peak into a GSERIALIZED datum to find its bounding box and some other metadata.
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
void lwgeom_geos_error(const char *fmt,...)
void(*) LWGEOM GEOS2LWGEOM)(const GEOSGeometry *geom, uint8_t want3d)
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...
LWPOINT * lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
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 lwgeom_free(LWGEOM *geom)
LWGEOM * lwgeom_concavehull(const LWGEOM *geom, double ratio, uint32_t allow_holes)
Take a geometry and build the concave hull.
LWGEOM * lwgeom_split(const LWGEOM *lwgeom_in, const LWGEOM *blade_in)
LWGEOM * lwgeom_offsetcurve(const LWGEOM *geom, double size, int quadsegs, int joinStyle, double mitreLimit)
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
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.
char * lwgeom_to_hexwkb_buffer(const LWGEOM *geom, uint8_t variant)
const char * lwgeom_geos_version(void)
Return GEOS version string (not to be freed)
int lwgeom_needs_bbox(const LWGEOM *geom)
Check whether or not a lwgeom is big enough to warrant a bounding box.
int lwgeom_isfinite(const LWGEOM *lwgeom)
Check if a LWGEOM has any non-finite (NaN or Inf) coordinates.
char * lwgeom_summary(const LWGEOM *lwgeom, int offset)
LWGEOM * lwgeom_pointonsurface(const LWGEOM *geom)
LWGEOM * lwgeom_sharedpaths(const LWGEOM *geom1, const LWGEOM *geom2)
LWGEOM * lwgeom_simplify_polygonal(const LWGEOM *geom, double vertex_fraction, uint32_t is_outer)
Computes a boundary-respecting hull of a polygonal geometry, with hull shape determined by a target p...
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.
LWGEOM * lwgeom_difference_prec(const LWGEOM *geom1, const LWGEOM *geom2, double gridSize)
LWGEOM * lwgeom_union_prec(const LWGEOM *geom1, const LWGEOM *geom2, double gridSize)
LWGEOM * lwgeom_unaryunion_prec(const LWGEOM *geom1, double gridSize)
const char * lwgeom_geos_compiled_version(void)
LWGEOM * lwgeom_buildarea(const LWGEOM *geom)
Take a geometry and return an areal geometry (Polygon or MultiPolygon).
LWGEOM * lwgeom_symdifference_prec(const LWGEOM *geom1, const LWGEOM *geom2, double gridSize)
LWGEOM * lwgeom_intersection_prec(const LWGEOM *geom1, const LWGEOM *geom2, double gridSize)
LWGEOM * lwgeom_linemerge_directed(const LWGEOM *geom1, int directed)
LWGEOM * lwgeom_triangulate_polygon(const LWGEOM *geom)
Take vertices of a polygon and build a constrained triangulation that respects the boundary of the po...
LWGEOM * lwgeom_clip_by_rect(const LWGEOM *geom1, double x0, double y0, double x1, double y1)
LWGEOM * lwgeom_reduceprecision(const LWGEOM *geom, double gridSize)
LWMPOINT * lwgeom_to_points(const LWGEOM *lwgeom, uint32_t npoints, int32_t seed)
#define LW_TRUE
Return types for functions with status returns.
#define SRID_UNKNOWN
Unknown SRID value.
LWPOLY * lwpoly_construct_empty(int32_t srid, char hasz, char hasm)
LWGEOM * lwgeom_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
This library is the generic geometry handling section of PostGIS.
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Datum ST_ReducePrecision(PG_FUNCTION_ARGS)
Datum polygonize_garray(PG_FUNCTION_ARGS)
Datum ST_Intersection(PG_FUNCTION_ARGS)
Datum isvaliddetail(PG_FUNCTION_ARGS)
Datum isvalid(PG_FUNCTION_ARGS)
Datum ST_SimplifyPolygonHull(PG_FUNCTION_ARGS)
Datum ST_Snap(PG_FUNCTION_ARGS)
Datum ST_Union(PG_FUNCTION_ARGS)
Datum ST_BuildArea(PG_FUNCTION_ARGS)
Datum postgis_geos_compiled_version(PG_FUNCTION_ARGS)
Datum ST_Split(PG_FUNCTION_ARGS)
Datum ST_Node(PG_FUNCTION_ARGS)
Datum LWGEOM_dfullywithin(PG_FUNCTION_ARGS)
Returns boolean true if the second argument is fully contained in a buffer of the first argument.
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 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)
Datum ST_ClipByBox2d(PG_FUNCTION_ARGS)
static uint32_t array_nelems_not_null(ArrayType *array)
Datum ST_SymDifference(PG_FUNCTION_ARGS)
Datum issimple(PG_FUNCTION_ARGS)
Datum symdifference(PG_FUNCTION_ARGS)
LWGEOM ** ARRAY2LWGEOM(ArrayType *array, uint32_t nelems, int *is3d, int *srid)
Datum topologypreservesimplify(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(postgis_geos_version)
Datum ST_MaximumInscribedCircle(PG_FUNCTION_ARGS)
GSERIALIZED * GEOS2POSTGIS(GEOSGeom geom, char want3d)
Datum ST_DelaunayTriangles(PG_FUNCTION_ARGS)
Datum ST_ConcaveHull(PG_FUNCTION_ARGS)
Datum boundary(PG_FUNCTION_ARGS)
Datum postgis_geos_version(PG_FUNCTION_ARGS)
GEOSGeometry * POSTGIS2GEOS(const GSERIALIZED *pglwgeom)
Datum ST_UnaryUnion(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 ST_Difference(PG_FUNCTION_ARGS)
Datum pgis_union_geometry_array(PG_FUNCTION_ARGS)
Datum ST_TriangulatePolygon(PG_FUNCTION_ARGS)
Datum ST_LargestEmptyCircle(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)
#define HANDLE_GEOS_ERROR(label)
#define POSTGIS_GEOS_VERSION