38 #define AUTOFIX LW_TRUE
39 #define LWGEOM_GEOS_ERRMSG_MAXSIZE 256
73 "%s requires a build against GEOS-%s or higher,"
74 " this version of PostGIS was built against version %s",
80 #define GEOS_FREE(...) \
82 geos_destroy((sizeof((void*[]){__VA_ARGS__})/sizeof(void*)), __VA_ARGS__); \
88 lwerror("%s: GEOS Error: %s", __func__, lwgeom_geos_errmsg); \
93 #define GEOS_FAIL_DEBUG() \
96 lwdebug(1, "%s: GEOS Error: %s", __func__, lwgeom_geos_errmsg); \
100 #define GEOS_FREE_AND_FAIL(...) \
102 GEOS_FREE(__VA_ARGS__); \
106 #define GEOS_FREE_AND_FAIL_DEBUG(...) \
109 GEOS_FREE(__VA_ARGS__); \
115 #define RESULT_SRID(...) \
116 (get_result_srid((sizeof((const void*[]){__VA_ARGS__})/sizeof(void*)), __func__, __VA_ARGS__))
125 GEOSGeometry* g = va_arg(ap, GEOSGeometry*);
149 #if POSTGIS_GEOS_VERSION < 31000
151 POINT4D point = { 0.0, 0.0, 0.0, 0.0 };
154 LWDEBUG(2,
"ptarray_fromGEOSCoordSeq called");
156 if (!GEOSCoordSeq_getSize(cs, &size))
lwerror(
"Exception thrown");
158 LWDEBUGF(4,
" GEOSCoordSeq size: %d", size);
162 if (!GEOSCoordSeq_getDimensions(cs, &dims))
lwerror(
"Exception thrown");
164 LWDEBUGF(4,
" GEOSCoordSeq dimensions: %d", dims);
167 if (dims > 3) dims = 3;
170 LWDEBUGF(4,
" output dimensions: %d", dims);
173 #if POSTGIS_GEOS_VERSION >= 31000
177 for (i = 0; i < size; i++)
180 GEOSCoordSeq_getXYZ(cs, i, &(point.
x), &(point.
y), &(point.
z));
182 GEOSCoordSeq_getXY(cs, i, &(point.
x), &(point.
y));
195 int type = GEOSGeomTypeId(geom);
196 int SRID = GEOSGetSRID(geom);
201 if (want3d && !GEOSHasZ(geom))
203 LWDEBUG(3,
"Geometry has no Z, won't provide one");
209 const GEOSCoordSequence* cs;
211 const GEOSGeometry* g;
216 LWDEBUG(4,
"lwgeom_from_geometry: it's a Point");
217 cs = GEOSGeom_getCoordSeq(geom);
222 case GEOS_LINESTRING:
223 case GEOS_LINEARRING:
224 LWDEBUG(4,
"lwgeom_from_geometry: it's a LineString or LinearRing");
227 cs = GEOSGeom_getCoordSeq(geom);
232 LWDEBUG(4,
"lwgeom_from_geometry: it's a Polygon");
234 ngeoms = GEOSGetNumInteriorRings(geom);
236 g = GEOSGetExteriorRing(geom);
237 cs = GEOSGeom_getCoordSeq(g);
239 for (i = 0; i < ngeoms; i++)
241 g = GEOSGetInteriorRingN(geom, i);
242 cs = GEOSGeom_getCoordSeq(g);
247 case GEOS_MULTIPOINT:
248 case GEOS_MULTILINESTRING:
249 case GEOS_MULTIPOLYGON:
250 case GEOS_GEOMETRYCOLLECTION:
251 LWDEBUG(4,
"lwgeom_from_geometry: it's a Collection or Multi");
253 ngeoms = GEOSGetNumGeometries(geom);
258 for (i = 0; i < ngeoms; i++)
260 g = GEOSGetGeometryN(geom, i);
267 lwerror(
"GEOS2LWGEOM: unknown geometry type: %d",
type);
279 int append_points = 0;
290 lwerror(
"ptarray_to_GEOSCoordSeq called with fix_ring and 0 vertices in ring, cannot fix");
300 #if POSTGIS_GEOS_VERSION >= 31000
301 if (append_points == 0) {
310 if (!(sq = GEOSCoordSeq_create(pa->
npoints + append_points, dims)))
315 for (i = 0; i < pa->
npoints; i++)
321 LWDEBUGF(4,
"Point: %g,%g,%g", p3d->
x, p3d->
y, p3d->
z);
330 GEOSCoordSeq_setXYZ(sq, i, p2d->
x, p2d->
y, p3d->
z);
332 GEOSCoordSeq_setXY(sq, i, p2d->
x, p2d->
y);
345 for (i = pa->
npoints; i < pa->npoints + append_points; i++)
348 GEOSCoordSeq_setXY(sq, i, p2d->
x, p2d->
y);
350 if (dims == 3) GEOSCoordSeq_setZ(sq, i, p3d->
z);
358 static inline GEOSGeometry*
364 g = GEOSGeom_createLinearRing(sq);
371 GEOSGeometry* envelope;
373 GEOSCoordSequence* seq = GEOSCoordSeq_create(5, 2);
374 if (!seq)
return NULL;
376 GEOSCoordSeq_setXY(seq, 0, box->
xmin, box->
ymin);
377 GEOSCoordSeq_setXY(seq, 1, box->
xmax, box->
ymin);
378 GEOSCoordSeq_setXY(seq, 2, box->
xmax, box->
ymax);
379 GEOSCoordSeq_setXY(seq, 3, box->
xmin, box->
ymax);
380 GEOSCoordSeq_setXY(seq, 4, box->
xmin, box->
ymin);
382 ring = GEOSGeom_createLinearRing(seq);
385 GEOSCoordSeq_destroy(seq);
389 envelope = GEOSGeom_createPolygon(ring, NULL, 0);
392 GEOSGeom_destroy(ring);
404 GEOSGeom* geoms = NULL;
405 uint32_t ngeoms, i, j;
407 #if LWDEBUG_LEVEL >= 4
423 GEOSGeometry* g =
LWGEOM2GEOS(lwgeom_stroked, autofix);
430 switch (lwgeom->
type)
435 g = GEOSGeom_createEmptyPoint();
442 g = GEOSGeom_createPoint(sq);
447 g = GEOSGeom_createPointFromXY(p->
x, p->
y);
457 g = GEOSGeom_createEmptyLineString();
471 g = GEOSGeom_createLineString(sq);
481 g = GEOSGeom_createEmptyPolygon();
485 if (!shell)
return NULL;
486 ngeoms = lwpoly->
nrings - 1;
487 if (ngeoms > 0) geoms =
lwalloc(
sizeof(GEOSGeom) * ngeoms);
489 for (i = 1; i < lwpoly->
nrings; i++)
495 for (k = 0; k < i - 1; k++)
496 GEOSGeom_destroy(geoms[k]);
498 GEOSGeom_destroy(shell);
502 g = GEOSGeom_createPolygon(shell, geoms, ngeoms);
512 g = GEOSGeom_createEmptyPolygon();
517 if (!shell)
return NULL;
518 g = GEOSGeom_createPolygon(shell, NULL, 0);
531 geostype = GEOS_MULTIPOINT;
533 geostype = GEOS_MULTILINESTRING;
535 geostype = GEOS_MULTIPOLYGON;
537 geostype = GEOS_GEOMETRYCOLLECTION;
542 if (ngeoms > 0) geoms =
lwalloc(
sizeof(GEOSGeom) * ngeoms);
545 for (i = 0; i < ngeoms; ++i)
555 for (k = 0; k < j; k++)
556 GEOSGeom_destroy(geoms[k]);
562 g = GEOSGeom_createCollection(geostype, geoms, j);
563 if (ngeoms > 0)
lwfree(geoms);
575 GEOSSetSRID(g, lwgeom->
srid);
577 #if LWDEBUG_LEVEL >= 4
578 wkt = GEOSGeomToWKT(g);
579 LWDEBUGF(4,
"LWGEOM2GEOS: GEOSGeom: %s", wkt);
589 GEOSCoordSequence* seq = GEOSCoordSeq_create(1, 2);
590 GEOSGeometry* geom = NULL;
592 if (!seq)
return NULL;
594 GEOSCoordSeq_setXY(seq, 0,
x,
y);
596 geom = GEOSGeom_createPoint(seq);
597 if (!geom) GEOSCoordSeq_destroy(seq);
604 GEOSCoordSequence* seq = GEOSCoordSeq_create(2, 2);
605 GEOSGeometry* geom = NULL;
607 if (!seq)
return NULL;
609 GEOSCoordSeq_setXY(seq, 0, x1, y1);
610 GEOSCoordSeq_setXY(seq, 1, x2, y2);
612 geom = GEOSGeom_createLineString(seq);
613 if (!geom) GEOSCoordSeq_destroy(seq);
620 const char* ver = GEOSversion();
630 va_start(ap, funcname);
633 for(i = 0; i <
count; i++)
638 lwerror(
"%s: Geometry is null", funcname);
650 lwerror(
"%s: Operation on mixed SRID geometries (%d != %d)", funcname, srid, g->
srid);
675 GEOSSetSRID(g, srid);
713 #if POSTGIS_GEOS_VERSION < 30900
718 g3 = GEOSIntersectionPrec(g1, g2, prec);
723 g3 = GEOSIntersection(g1, g2);
727 GEOSSetSRID(g3, srid);
761 #if POSTGIS_GEOS_VERSION < 31100
766 g3 = GEOSLineMergeDirected(g1);
771 g3 = GEOSLineMerge(g1);
775 GEOSSetSRID(g3, srid);
810 #if POSTGIS_GEOS_VERSION < 30900
815 g3 = GEOSUnaryUnionPrec(g1, prec);
820 g3 = GEOSUnaryUnion(g1);
824 GEOSSetSRID(g3, srid);
846 GEOSGeometry *g1, *g2, *g3;
862 #if POSTGIS_GEOS_VERSION < 30900
867 g3 = GEOSDifferencePrec(g1, g2, prec);
872 g3 = GEOSDifference(g1, g2);
876 GEOSSetSRID(g3, srid);
897 GEOSGeometry *g1, *g2, *g3;
913 #if POSTGIS_GEOS_VERSION < 30900
918 g3 = GEOSSymDifferencePrec(g1, g2, prec);
923 g3 = GEOSSymDifference(g1, g2);
927 GEOSSetSRID(g3, srid);
942 GEOSGeometry *g1, *g3;
956 g3 = GEOSGetCentroid(g1);
959 GEOSSetSRID(g3, srid);
972 #if POSTGIS_GEOS_VERSION < 30900
980 GEOSGeometry *g1, *g3;
991 g3 = GEOSGeom_setPrecision(g1, gridSize, 0);
994 GEOSSetSRID(g3, srid);
1011 GEOSGeometry *g1, *g3;
1025 g3 = GEOSPointOnSurface(g1);
1028 GEOSSetSRID(g3, srid);
1050 GEOSGeometry *g1, *g2, *g3;
1065 if ( gridSize >= 0) {
1066 #if POSTGIS_GEOS_VERSION < 30900
1071 g3 = GEOSUnionPrec(g1, g2, gridSize);
1076 g3 = GEOSUnion(g1, g2);
1080 GEOSSetSRID(g3, srid);
1093 GEOSGeometry *g1, *g3;
1107 if (!(g3 = GEOSClipByRect(g1, x1, y1, x2, y2)))
1129 GEOSGeometry *g1, *g3;
1140 g3 = GEOSBuildArea(g1);
1143 GEOSSetSRID(g3, srid);
1146 if (GEOSGetNumGeometries(g3) == 0)
1175 simple = GEOSisSimple(g);
1176 GEOSGeom_destroy(g);
1202 GEOSSetSRID(g, srid);
1218 GEOSGeometry *g1, *g2, *g3;
1227 g3 = GEOSSnap(g1, g2, tolerance);
1230 GEOSSetSRID(g3, srid);
1245 GEOSGeometry *g1, *g2, *g3;
1254 g3 = GEOSSharedPaths(g1, g2);
1257 GEOSSetSRID(g3, srid);
1273 GEOSGeometry *g1, *g3;
1281 g3 = GEOSOffsetCurve(g1, size, quadsegs, joinStyle, mitreLimit);
1289 GEOSSetSRID(g3, srid);
1311 for (i = 0; i < col->
ngeoms; i++)
1386 lwerror(
"lwgeom_offsetcurve: cannot node input");
1394 lwerror(
"lwgeom_offsetcurve: noded geometry cannot be offset");
1402 static GEOSGeometry*
1405 GEOSCoordSequence *cs = GEOSCoordSeq_create(5, 2);
1406 GEOSCoordSeq_setXY(cs, 0, xmin, ymin);
1407 GEOSCoordSeq_setXY(cs, 1, xmin + cell_size, ymin);
1408 GEOSCoordSeq_setXY(cs, 2, xmin + cell_size, ymin + cell_size);
1409 GEOSCoordSeq_setXY(cs, 3, xmin, ymin + cell_size);
1410 GEOSCoordSeq_setXY(cs, 4, xmin, ymin);
1411 return GEOSGeom_createPolygon(GEOSGeom_createLinearRing(cs), NULL, 0);
1418 typedef struct CellCorner {
1424 uint32_t num_cells = 0;
1426 double area, bbox_area, bbox_width, bbox_height, area_ratio;
1429 uint32_t sample_npoints, sample_sqrt, sample_width, sample_height;
1430 double sample_cell_size;
1432 uint32_t iterations = 0;
1433 uint32_t npoints_generated = 0;
1434 uint32_t npoints_tested = 0;
1436 const GEOSPreparedGeometry* gprep;
1443 lwerror(
"%s: only polygons supported", __func__);
1452 bbox = *(lwpoly->
bbox);
1455 bbox_width = bbox.
xmax - bbox.
xmin;
1456 bbox_height = bbox.
ymax - bbox.
ymin;
1457 bbox_area = bbox_width * bbox_height;
1459 if (area == 0.0 || bbox_area == 0.0)
1461 lwerror(
"%s: zero area input polygon, TBD", __func__);
1471 area_ratio =
FP_MIN(bbox_area / area, 10000.0);
1472 sample_npoints = npoints * area_ratio;
1478 sample_sqrt = ceil(sqrt(sample_npoints));
1481 if (bbox_width > bbox_height)
1483 sample_width = sample_sqrt;
1484 sample_height = ceil((
double)sample_npoints / (
double)sample_width);
1485 sample_cell_size = bbox_width / sample_width;
1489 sample_height = sample_sqrt;
1490 sample_width = ceil((
double)sample_npoints / (
double)sample_height);
1491 sample_cell_size = bbox_height / sample_height;
1502 gprep = GEOSPrepare(g);
1510 cells =
lwalloc(
sizeof(CellCorner) * sample_height * sample_width);
1512 for (i = 0; i < sample_width; i++)
1514 for (j = 0; j < sample_height; j++)
1517 double xmin = bbox.
xmin + i * sample_cell_size;
1518 double ymin = bbox.
ymin + j * sample_cell_size;
1520 intersects = GEOSPreparedIntersects(gprep, gcell);
1521 GEOSGeom_destroy(gcell);
1522 if (intersects == 2)
1524 GEOSPreparedGeom_destroy(gprep);
1525 GEOSGeom_destroy(g);
1529 if (intersects == 1)
1531 cells[num_cells].x = xmin;
1532 cells[num_cells].y = ymin;
1550 for (i = n - 1; i > 0; i--)
1554 memcpy( &tmp, cells + j,
sizeof(CellCorner));
1555 memcpy(cells + j, cells + i,
sizeof(CellCorner));
1556 memcpy(cells + i, &tmp,
sizeof(CellCorner));
1564 while (npoints_generated < npoints)
1567 for (i = 0; i < num_cells; i++)
1570 double y = cells[i].y;
1571 double x = cells[i].x;
1574 if (
x >= bbox.
xmax ||
y >= bbox.
ymax)
continue;
1576 #if POSTGIS_GEOS_VERSION >= 31200
1577 contains = GEOSPreparedIntersectsXY(gprep,
x,
y);
1581 GEOSCoordSequence *gseq = GEOSCoordSeq_create(1, 2);;
1582 GEOSCoordSeq_setXY(gseq, 0,
x,
y);
1583 gpt = GEOSGeom_createPoint(gseq);
1584 contains = GEOSPreparedIntersects(gprep, gpt);
1585 GEOSGeom_destroy(gpt);
1590 GEOSPreparedGeom_destroy(gprep);
1591 GEOSGeom_destroy(g);
1598 npoints_generated++;
1599 if (npoints_generated == npoints)
1608 if (npoints_tested % 10000 == 0)
1609 LW_ON_INTERRUPT(GEOSPreparedGeom_destroy(gprep); GEOSGeom_destroy(g);
return NULL);
1613 if (done || iterations > 100)
break;
1616 GEOSPreparedGeom_destroy(gprep);
1617 GEOSGeom_destroy(g);
1635 lwerror(
"%s: only multipolygons supported", __func__);
1642 for (i = 0; i < lwmpoly->
ngeoms; i++)
1645 int sub_npoints = lround(npoints * sub_area / area);
1646 if (sub_npoints > 0)
1654 for (j = 0; j < sub_mpt->
ngeoms; j++)
1684 int type = GEOSGeomTypeId(geom);
1685 int SRID = GEOSGetSRID(geom);
1690 if (want3d && !GEOSHasZ(geom))
1692 LWDEBUG(3,
"Geometry has no Z, won't provide one");
1700 case GEOS_GEOMETRYCOLLECTION:
1701 LWDEBUG(4,
"lwgeom_from_geometry: it's a Collection or Multi");
1703 ngeoms = GEOSGetNumGeometries(geom);
1707 geoms =
lwalloc(ngeoms *
sizeof *geoms);
1710 lwerror(
"lwtin_from_geos: can't allocate geoms");
1713 for (i = 0; i < ngeoms; i++)
1715 const GEOSGeometry *poly, *ring;
1716 const GEOSCoordSequence* cs;
1719 poly = GEOSGetGeometryN(geom, i);
1720 ring = GEOSGetExteriorRing(poly);
1721 cs = GEOSGeom_getCoordSeq(ring);
1729 case GEOS_MULTIPOINT:
1730 case GEOS_MULTILINESTRING:
1731 case GEOS_MULTIPOLYGON:
1732 case GEOS_LINESTRING:
1733 case GEOS_LINEARRING:
1735 lwerror(
"lwtin_from_geos: invalid geometry type for tin: %d",
type);
1739 lwerror(
"GEOS2LWGEOM: unknown geometry type: %d",
type);
1755 GEOSGeometry *g1, *g3;
1757 if (output < 0 || output > 2)
1759 lwerror(
"%s: invalid output type specified %d", __func__, output);
1770 g3 = GEOSDelaunayTriangulation(g1, tolerance, output == 1);
1773 GEOSSetSRID(g3, srid);
1781 lwerror(
"%s: cannot convert output geometry", __func__);
1794 static GEOSCoordSequence*
1798 uint8_t num_dims = 2;
1800 GEOSCoordSequence* coords;
1803 coords = GEOSCoordSeq_create(num_points, num_dims);
1804 if (!coords)
return NULL;
1809 if (i >= num_points)
1811 lwerror(
"Incorrect num_points provided to lwgeom_get_geos_coordseq_2d");
1812 GEOSCoordSeq_destroy(coords);
1817 #if POSTGIS_GEOS_VERSION < 30800
1818 if (!GEOSCoordSeq_setX(coords, i, tmp.
x) || !GEOSCoordSeq_setY(coords, i, tmp.
y))
1820 if (!GEOSCoordSeq_setXY(coords, i, tmp.
x, tmp.
y))
1823 GEOSCoordSeq_destroy(coords);
1841 GEOSCoordSequence* coords;
1842 GEOSGeometry* geos_geom;
1843 GEOSGeometry* geos_env = NULL;
1844 GEOSGeometry* geos_result;
1859 if (!coords)
return NULL;
1861 geos_geom = GEOSGeom_createLineString(coords);
1864 GEOSCoordSeq_destroy(coords);
1870 geos_result = GEOSVoronoiDiagram(geos_geom, geos_env, tolerance, output_edges);
1872 GEOSGeom_destroy(geos_geom);
1873 if (env) GEOSGeom_destroy(geos_env);
1882 GEOSGeom_destroy(geos_result);
1886 return lwgeom_result;
1890 #if POSTGIS_GEOS_VERSION >= 31100
1897 GEOSGeometry *g1, *g3;
1904 geosGeomType = GEOSGeomTypeId(g1);
1905 if (geosGeomType == GEOS_POLYGON || geosGeomType == GEOS_MULTIPOLYGON) {
1907 g3 = GEOSConcaveHullOfPolygons(g1, ratio, is_tight, allow_holes);
1910 g3 = GEOSConcaveHull(g1, ratio, allow_holes);
1916 GEOSSetSRID(g3, srid);
1931 GEOSGeometry *g1, *g3;
1937 g3 = GEOSPolygonHullSimplify(g1, is_outer, vertex_fraction);
1942 GEOSSetSRID(g3, srid);
1957 GEOSGeometry *g1, *g3;
1966 g3 = GEOSConstrainedDelaunayTriangulation(g1);
1969 GEOSSetSRID(g3, srid);
char result[OUT_DOUBLE_BUFFER_SIZE]
#define LWGEOM_GEOS_ERRMSG_MAXSIZE
LWGEOM * lwgeom_centroid(const LWGEOM *geom)
LWGEOM * lwgeom_intersection_prec(const LWGEOM *geom1, const LWGEOM *geom2, double prec)
LWGEOM * lwgeom_geos_noop(const LWGEOM *geom)
Convert an LWGEOM to a GEOS Geometry and convert back – for debug only.
static LWGEOM * lwcollection_offsetcurve(const LWCOLLECTION *col, double size, int quadsegs, int joinStyle, double mitreLimit)
LWGEOM * lwgeom_linemerge_directed(const LWGEOM *geom, int directed)
static GEOSGeometry * ptarray_to_GEOSLinearRing(const POINTARRAY *pa, uint8_t autofix)
LWGEOM * lwgeom_symdifference(const LWGEOM *geom1, const LWGEOM *geom2)
LWGEOM * lwgeom_concavehull(const LWGEOM *geom, double ratio, uint32_t allow_holes)
Take a geometry and build the concave hull.
LWGEOM * lwgeom_unaryunion(const LWGEOM *geom)
void lwgeom_geos_error_minversion(const char *functionality, const char *minver)
LWGEOM * lwgeom_union(const LWGEOM *g1, const LWGEOM *g2)
GEOSGeometry * make_geos_point(double x, double y)
static LWGEOM * lwline_offsetcurve(const LWLINE *lwline, double size, int quadsegs, int joinStyle, double mitreLimit)
LWGEOM * lwgeom_offsetcurve(const LWGEOM *geom, double size, int quadsegs, int joinStyle, double mitreLimit)
LWGEOM * lwgeom_delaunay_triangulation(const LWGEOM *geom, double tolerance, int32_t output)
Take vertices of a geometry and build a delaunay triangulation on them.
static GEOSGeometry * lwpoly_to_points_make_cell(double xmin, double ymin, double cell_size)
LWGEOM * lwgeom_difference_prec(const LWGEOM *geom1, const LWGEOM *geom2, double prec)
LWGEOM * lwgeom_snap(const LWGEOM *geom1, const LWGEOM *geom2, double tolerance)
Snap vertices and segments of a geometry to another using a given tolerance.
LWGEOM * lwgeom_difference(const LWGEOM *geom1, const LWGEOM *geom2)
int lwgeom_is_simple(const LWGEOM *geom)
LWGEOM * lwgeom_pointonsurface(const LWGEOM *geom)
LWGEOM * lwgeom_sharedpaths(const LWGEOM *geom1, const LWGEOM *geom2)
LWGEOM * lwgeom_symdifference_prec(const LWGEOM *geom1, const LWGEOM *geom2, double prec)
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
const char * lwgeom_geos_compiled_version()
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_union_prec(const LWGEOM *geom1, const LWGEOM *geom2, double gridSize)
LWGEOM * lwgeom_normalize(const LWGEOM *geom)
static int32_t get_result_srid(size_t count, const char *funcname,...)
#define GEOS_FREE_AND_FAIL_DEBUG(...)
LWGEOM * lwgeom_buildarea(const LWGEOM *geom)
Take a geometry and return an areal geometry (Polygon or MultiPolygon).
#define GEOS_FAIL_DEBUG()
LWGEOM * lwgeom_linemerge(const LWGEOM *geom)
#define GEOS_FREE_AND_FAIL(...)
GEOSGeometry * make_geos_segment(double x1, double y1, double x2, double y2)
static void geos_destroy(size_t count,...)
GEOSGeometry * GBOX2GEOS(const GBOX *box)
const char * lwgeom_geos_version()
Return GEOS version string (not to be freed)
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
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_reduceprecision(const LWGEOM *geom, double gridSize)
LWMPOINT * lwgeom_to_points(const LWGEOM *lwgeom, uint32_t npoints, int32_t seed)
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, uint8_t want3d)
GEOSCoordSeq ptarray_to_GEOSCoordSeq(const POINTARRAY *, uint8_t fix_ring)
LWMPOINT * lwmpoly_to_points(const LWMPOLY *lwmpoly, uint32_t npoints, int32_t seed)
LWGEOM * lwgeom_unaryunion_prec(const LWGEOM *geom, double prec)
POINTARRAY * ptarray_from_GEOSCoordSeq(const GEOSCoordSequence *cs, uint8_t want3d)
LWMPOINT * lwpoly_to_points(const LWPOLY *lwpoly, uint32_t npoints, int32_t seed)
LWGEOM * lwgeom_intersection(const LWGEOM *g1, const LWGEOM *g2)
LWGEOM * lwgeom_clip_by_rect(const LWGEOM *geom1, double x1, double y1, double x2, double y2)
void lwgeom_geos_error(const char *fmt,...)
static GEOSCoordSequence * lwgeom_get_geos_coordseq_2d(const LWGEOM *g, uint32_t num_points)
LWTIN * lwtin_from_geos(const GEOSGeometry *geom, uint8_t want3d)
LWPOINT * lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
LWGEOM * lwgeom_node(const LWGEOM *lwgeom_in)
LWPOINT * lwpoint_make2d(int32_t srid, double x, double y)
LWPOINTITERATOR * lwpointiterator_create(const LWGEOM *g)
Create a new LWPOINTITERATOR over supplied LWGEOM*.
void lwgeom_set_srid(LWGEOM *geom, int32_t srid)
Set the SRID on an LWGEOM For collections, only the parent gets an SRID, all the children get SRID_UN...
void lwgeom_free(LWGEOM *geom)
int lwpointiterator_next(LWPOINTITERATOR *s, POINT4D *p)
Attempts to assign the next point in the iterator to p, and advances the iterator to the next point.
POINTARRAY * ptarray_addPoint(const POINTARRAY *pa, uint8_t *p, size_t pdims, uint32_t where)
Add a point in a pointarray.
LWGEOM * lwgeom_stroke(const LWGEOM *geom, uint32_t perQuad)
Convert type with arcs into equivalent linearized type.
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
void lwpointiterator_destroy(LWPOINTITERATOR *s)
Free all memory associated with the iterator.
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
#define FLAGS_GET_Z(flags)
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
LWMPOINT * lwmpoint_add_lwpoint(LWMPOINT *mobj, const LWPOINT *obj)
double lwgeom_area(const LWGEOM *geom)
int lwgeom_type_arc(const LWGEOM *geom)
Geometry type is one of the potentially "arc containing" types (circstring, multicurve,...
uint32_t lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
int lwgeom_dimension(const LWGEOM *geom)
For an LWGEOM, returns 0 for points, 1 for lines, 2 for polygons, 3 for volume, and the max dimension...
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
#define FLAGS_NDIMS(flags)
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM contains sub-geometries or not This basically just checks that the struct ...
LWMPOINT * lwmpoint_construct_empty(int32_t srid, char hasz, char hasm)
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
void lwcollection_release(LWCOLLECTION *lwcollection)
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
#define FLAGS_GET_M(flags)
void lwcollection_free(LWCOLLECTION *col)
int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox)
Calculate bounding box of a geometry, automatically taking into account whether it is cartesian or ge...
LWCOLLECTION * lwcollection_concat_in_place(LWCOLLECTION *col1, const LWCOLLECTION *col2)
Appends all geometries from col2 to col1 in place.
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
void * lwalloc(size_t size)
LWCOLLECTION * lwcollection_construct(uint8_t type, int32_t srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
int ptarray_is_closed_2d(const POINTARRAY *pa)
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
#define LW_TRUE
Return types for functions with status returns.
void lwgeom_release(LWGEOM *lwgeom)
Free the containing LWGEOM and the associated BOX.
#define SRID_UNKNOWN
Unknown SRID value.
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
LWPOLY * lwpoly_construct_empty(int32_t srid, char hasz, char hasm)
LWPOLY * lwpoly_construct(int32_t srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
LWLINE * lwline_construct_empty(int32_t srid, char hasz, char hasm)
LWTRIANGLE * lwtriangle_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
This library is the generic geometry handling section of PostGIS.
#define LW_ON_INTERRUPT(x)
double lwpoly_area(const LWPOLY *poly)
Find the area of the outer ring - sum (area of inner rings).
Datum contains(PG_FUNCTION_ARGS)
#define LWDEBUG(level, msg)
#define LWDEBUGF(level, msg,...)
void lwnotice(const char *fmt,...) __attribute__((format(printf
Write a notice out to the notice handler.
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
static const POINT3D * getPoint3d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT3D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
static uint8_t * getPoint_internal(const POINTARRAY *pa, uint32_t n)
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
void lwrandom_set_seed(int32_t seed)
double lwrandom_uniform(void)
#define POSTGIS_GEOS_VERSION
uint8_t * serialized_pointlist