38 #define AUTOFIX LW_TRUE
39 #define LWGEOM_GEOS_ERRMSG_MAXSIZE 256
56 #define GEOS_FREE(...) \
58 geos_destroy((sizeof((void*[]){__VA_ARGS__})/sizeof(void*)), __VA_ARGS__); \
64 lwerror("%s: GEOS Error: %s", __func__, lwgeom_geos_errmsg); \
69 #define GEOS_FAIL_DEBUG() \
72 lwdebug(1, "%s: GEOS Error: %s", __func__, lwgeom_geos_errmsg); \
76 #define GEOS_FREE_AND_FAIL(...) \
78 GEOS_FREE(__VA_ARGS__); \
82 #define GEOS_FREE_AND_FAIL_DEBUG(...) \
85 GEOS_FREE(__VA_ARGS__); \
91 #define RESULT_SRID(...) \
92 (get_result_srid((sizeof((const void*[]){__VA_ARGS__})/sizeof(void*)), __func__, __VA_ARGS__))
101 GEOSGeometry* g = va_arg(ap, GEOSGeometry*);
122 uint32_t size = 0, i;
124 POINT4D point = { 0.0, 0.0, 0.0, 0.0 };
126 LWDEBUG(2,
"ptarray_fromGEOSCoordSeq called");
128 if (!GEOSCoordSeq_getSize(cs, &size))
lwerror(
"Exception thrown");
130 LWDEBUGF(4,
" GEOSCoordSeq size: %d", size);
134 if (!GEOSCoordSeq_getDimensions(cs, &dims))
lwerror(
"Exception thrown");
136 LWDEBUGF(4,
" GEOSCoordSeq dimensions: %d", dims);
139 if (dims > 3) dims = 3;
142 LWDEBUGF(4,
" output dimensions: %d", dims);
146 for (i = 0; i < size; i++)
148 #if POSTGIS_GEOS_VERSION < 38
149 GEOSCoordSeq_getX(cs, i, &(point.
x));
150 GEOSCoordSeq_getY(cs, i, &(point.
y));
151 if (dims >= 3) GEOSCoordSeq_getZ(cs, i, &(point.
z));
154 GEOSCoordSeq_getXYZ(cs, i, &(point.
x), &(point.
y), &(point.
z));
156 GEOSCoordSeq_getXY(cs, i, &(point.
x), &(point.
y));
168 int type = GEOSGeomTypeId(geom);
169 int SRID = GEOSGetSRID(geom);
174 if (want3d && !GEOSHasZ(geom))
176 LWDEBUG(3,
"Geometry has no Z, won't provide one");
182 const GEOSCoordSequence* cs;
184 const GEOSGeometry* g;
189 LWDEBUG(4,
"lwgeom_from_geometry: it's a Point");
190 cs = GEOSGeom_getCoordSeq(geom);
195 case GEOS_LINESTRING:
196 case GEOS_LINEARRING:
197 LWDEBUG(4,
"lwgeom_from_geometry: it's a LineString or LinearRing");
200 cs = GEOSGeom_getCoordSeq(geom);
205 LWDEBUG(4,
"lwgeom_from_geometry: it's a Polygon");
207 ngeoms = GEOSGetNumInteriorRings(geom);
209 g = GEOSGetExteriorRing(geom);
210 cs = GEOSGeom_getCoordSeq(g);
212 for (i = 0; i < ngeoms; i++)
214 g = GEOSGetInteriorRingN(geom, i);
215 cs = GEOSGeom_getCoordSeq(g);
220 case GEOS_MULTIPOINT:
221 case GEOS_MULTILINESTRING:
222 case GEOS_MULTIPOLYGON:
223 case GEOS_GEOMETRYCOLLECTION:
224 LWDEBUG(4,
"lwgeom_from_geometry: it's a Collection or Multi");
226 ngeoms = GEOSGetNumGeometries(geom);
231 for (i = 0; i < ngeoms; i++)
233 g = GEOSGetGeometryN(geom, i);
240 lwerror(
"GEOS2LWGEOM: unknown geometry type: %d",
type);
252 int append_points = 0;
263 lwerror(
"ptarray_to_GEOSCoordSeq called with fix_ring and 0 vertices in ring, cannot fix");
273 if (!(sq = GEOSCoordSeq_create(pa->
npoints + append_points, dims)))
275 lwerror(
"Error creating GEOS Coordinate Sequence");
279 for (i = 0; i < pa->
npoints; i++)
285 LWDEBUGF(4,
"Point: %g,%g,%g", p3d->
x, p3d->
y, p3d->
z);
293 #if POSTGIS_GEOS_VERSION < 38
294 GEOSCoordSeq_setX(sq, i, p2d->
x);
295 GEOSCoordSeq_setY(sq, i, p2d->
y);
296 if (dims == 3) GEOSCoordSeq_setZ(sq, i, p3d->
z);
299 GEOSCoordSeq_setXYZ(sq, i, p2d->
x, p2d->
y, p3d->
z);
301 GEOSCoordSeq_setXY(sq, i, p2d->
x, p2d->
y);
315 for (i = pa->
npoints; i < pa->npoints + append_points; i++)
317 #if POSTGIS_GEOS_VERSION < 38
318 GEOSCoordSeq_setX(sq, i, p2d->
x);
319 GEOSCoordSeq_setY(sq, i, p2d->
y);
321 GEOSCoordSeq_setXY(sq, i, p2d->
x, p2d->
y);
324 if (dims == 3) GEOSCoordSeq_setZ(sq, i, p3d->
z);
331 static inline GEOSGeometry*
337 g = GEOSGeom_createLinearRing(sq);
344 GEOSGeometry* envelope;
346 GEOSCoordSequence* seq = GEOSCoordSeq_create(5, 2);
347 if (!seq)
return NULL;
349 #if POSTGIS_GEOS_VERSION < 38
350 GEOSCoordSeq_setX(seq, 0, box->
xmin);
351 GEOSCoordSeq_setY(seq, 0, box->
ymin);
353 GEOSCoordSeq_setX(seq, 1, box->
xmax);
354 GEOSCoordSeq_setY(seq, 1, box->
ymin);
356 GEOSCoordSeq_setX(seq, 2, box->
xmax);
357 GEOSCoordSeq_setY(seq, 2, box->
ymax);
359 GEOSCoordSeq_setX(seq, 3, box->
xmin);
360 GEOSCoordSeq_setY(seq, 3, box->
ymax);
362 GEOSCoordSeq_setX(seq, 4, box->
xmin);
363 GEOSCoordSeq_setY(seq, 4, box->
ymin);
365 GEOSCoordSeq_setXY(seq, 0, box->
xmin, box->
ymin);
366 GEOSCoordSeq_setXY(seq, 1, box->
xmax, box->
ymin);
367 GEOSCoordSeq_setXY(seq, 2, box->
xmax, box->
ymax);
368 GEOSCoordSeq_setXY(seq, 3, box->
xmin, box->
ymax);
369 GEOSCoordSeq_setXY(seq, 4, box->
xmin, box->
ymin);
372 ring = GEOSGeom_createLinearRing(seq);
375 GEOSCoordSeq_destroy(seq);
379 envelope = GEOSGeom_createPolygon(ring, NULL, 0);
382 GEOSGeom_destroy(ring);
394 GEOSGeom* geoms = NULL;
395 uint32_t ngeoms, i, j;
397 #if LWDEBUG_LEVEL >= 4
413 GEOSGeometry* g =
LWGEOM2GEOS(lwgeom_stroked, autofix);
423 switch (lwgeom->
type)
429 g = GEOSGeom_createEmptyPolygon();
432 #if POSTGIS_GEOS_VERSION < 38
434 g = GEOSGeom_createPoint(sq);
439 g = GEOSGeom_createPoint(sq);
444 g = GEOSGeom_createPointFromXY(p->
x, p->
y);
463 g = GEOSGeom_createLineString(sq);
470 g = GEOSGeom_createEmptyPolygon();
474 if (!shell)
return NULL;
475 ngeoms = lwpoly->
nrings - 1;
476 if (ngeoms > 0) geoms =
lwalloc(
sizeof(GEOSGeom) * ngeoms);
478 for (i = 1; i < lwpoly->
nrings; i++)
484 for (k = 0; k < i - 1; k++)
485 GEOSGeom_destroy(geoms[k]);
487 GEOSGeom_destroy(shell);
491 g = GEOSGeom_createPolygon(shell, geoms, ngeoms);
499 g = GEOSGeom_createEmptyPolygon();
506 g = GEOSGeom_createPolygon(shell, NULL, 0);
517 geostype = GEOS_MULTIPOINT;
519 geostype = GEOS_MULTILINESTRING;
521 geostype = GEOS_MULTIPOLYGON;
523 geostype = GEOS_GEOMETRYCOLLECTION;
528 if (ngeoms > 0) geoms =
lwalloc(
sizeof(GEOSGeom) * ngeoms);
531 for (i = 0; i < ngeoms; ++i)
541 for (k = 0; k < j; k++)
542 GEOSGeom_destroy(geoms[k]);
548 g = GEOSGeom_createCollection(geostype, geoms, j);
549 if (ngeoms > 0)
lwfree(geoms);
558 GEOSSetSRID(g, lwgeom->
srid);
560 #if LWDEBUG_LEVEL >= 4
561 wkt = GEOSGeomToWKT(g);
562 LWDEBUGF(4,
"LWGEOM2GEOS: GEOSGeom: %s", wkt);
572 GEOSCoordSequence* seq = GEOSCoordSeq_create(1, 2);
573 GEOSGeometry* geom = NULL;
575 if (!seq)
return NULL;
577 #if POSTGIS_GEOS_VERSION < 38
578 GEOSCoordSeq_setX(seq, 0,
x);
579 GEOSCoordSeq_setY(seq, 0,
y);
581 GEOSCoordSeq_setXY(seq, 0,
x,
y);
584 geom = GEOSGeom_createPoint(seq);
585 if (!geom) GEOSCoordSeq_destroy(seq);
592 GEOSCoordSequence* seq = GEOSCoordSeq_create(2, 2);
593 GEOSGeometry* geom = NULL;
595 if (!seq)
return NULL;
597 #if POSTGIS_GEOS_VERSION < 38
598 GEOSCoordSeq_setX(seq, 0, x1);
599 GEOSCoordSeq_setY(seq, 0, y1);
600 GEOSCoordSeq_setX(seq, 1, x2);
601 GEOSCoordSeq_setY(seq, 1, y2);
603 GEOSCoordSeq_setXY(seq, 0, x1, y1);
604 GEOSCoordSeq_setXY(seq, 1, x2, y2);
607 geom = GEOSGeom_createLineString(seq);
608 if (!geom) GEOSCoordSeq_destroy(seq);
615 const char* ver = GEOSversion();
625 va_start(ap, funcname);
628 for(i = 0; i <
count; i++)
633 lwerror(
"%s: Geometry is null", funcname);
644 lwerror(
"%s: Operation on mixed SRID geometries (%d != %d)", funcname, srid, g->
srid);
667 GEOSSetSRID(g, srid);
698 g3 = GEOSIntersection(g1, g2);
701 GEOSSetSRID(g3, srid);
727 g3 = GEOSLineMerge(g1);
730 GEOSSetSRID(g3, srid);
758 g3 = GEOSUnaryUnion(g1);
761 GEOSSetSRID(g3, srid);
777 GEOSGeometry *g1, *g2, *g3;
792 g3 = GEOSDifference(g1, g2);
795 GEOSSetSRID(g3, srid);
810 GEOSGeometry *g1, *g2, *g3;
825 g3 = GEOSSymDifference(g1, g2);
828 GEOSSetSRID(g3, srid);
843 GEOSGeometry *g1, *g3;
857 g3 = GEOSGetCentroid(g1);
860 GEOSSetSRID(g3, srid);
876 GEOSGeometry *g1, *g3;
890 g3 = GEOSPointOnSurface(g1);
893 GEOSSetSRID(g3, srid);
909 GEOSGeometry *g1, *g2, *g3;
924 g3 = GEOSUnion(g1, g2);
927 GEOSSetSRID(g3, srid);
940 GEOSGeometry *g1, *g3;
954 if (!(g3 = GEOSClipByRect(g1, x1, y1, x2, y2)))
970 #if POSTGIS_GEOS_VERSION < 38
971 typedef struct Face_t
973 const GEOSGeometry* geom;
976 struct Face_t* parent;
979 static Face* newFace(
const GEOSGeometry* g);
980 static void delFace(Face* f);
981 static unsigned int countParens(
const Face* f);
982 static void findFaceHoles(Face** faces,
int nfaces);
985 newFace(
const GEOSGeometry* g)
987 Face* f =
lwalloc(
sizeof(Face));
989 f->env = GEOSEnvelope(f->geom);
990 GEOSArea(f->env, &f->envarea);
996 countParens(
const Face* f)
998 unsigned int pcount = 0;
1011 GEOSGeom_destroy(f->env);
1016 compare_by_envarea(
const void* g1,
const void* g2)
1018 Face* f1 = *(Face**)g1;
1019 Face* f2 = *(Face**)g2;
1020 double n1 = f1->envarea;
1021 double n2 = f2->envarea;
1023 if (n1 < n2)
return 1;
1024 if (n1 > n2)
return -1;
1030 findFaceHoles(Face** faces,
int nfaces)
1035 qsort(faces, nfaces,
sizeof(Face*), compare_by_envarea);
1036 for (i = 0; i < nfaces; ++i)
1039 int nholes = GEOSGetNumInteriorRings(f->geom);
1040 LWDEBUGF(2,
"Scanning face %d with env area %g and %d holes", i, f->envarea, nholes);
1041 for (h = 0; h < nholes; ++h)
1043 const GEOSGeometry* hole = GEOSGetInteriorRingN(f->geom, h);
1045 "Looking for hole %d/%d of face %d among %d other faces",
1050 for (j = i + 1; j < nfaces; ++j)
1052 const GEOSGeometry* f2er;
1053 Face* f2 = faces[j];
1054 if (f2->parent)
continue;
1055 f2er = GEOSGetExteriorRing(f2->geom);
1058 if (GEOSEquals(f2er, hole))
1060 LWDEBUGF(2,
"Hole %d/%d of face %d is face %d", h + 1, nholes, i, j);
1069 static GEOSGeometry*
1070 collectFacesWithEvenAncestors(Face** faces,
int nfaces)
1072 GEOSGeometry** geoms =
lwalloc(
sizeof(GEOSGeometry*) * nfaces);
1074 unsigned int ngeoms = 0;
1077 for (i = 0; i < nfaces; ++i)
1080 if (countParens(f) % 2)
continue;
1081 geoms[ngeoms++] = GEOSGeom_clone(f->geom);
1084 ret = GEOSGeom_createCollection(GEOS_MULTIPOLYGON, geoms, ngeoms);
1090 LWGEOM_GEOS_buildArea(
const GEOSGeometry* geom_in)
1093 GEOSGeometry *geos_result, *shp;
1094 GEOSGeometry
const* vgeoms[1];
1096 int srid = GEOSGetSRID(geom_in);
1098 #if POSTGIS_DEBUG_LEVEL >= 3
1103 vgeoms[0] = geom_in;
1104 geos_result = GEOSPolygonize(vgeoms, 1);
1106 LWDEBUGF(3,
"GEOSpolygonize returned @ %p", geos_result);
1109 if (!geos_result)
return 0;
1112 #if PARANOIA_LEVEL > 0
1115 GEOSGeom_destroy(geos_result);
1116 lwerror(
"%s [%d] Unexpected return from GEOSpolygonize", __FILE__, __LINE__);
1121 ngeoms = GEOSGetNumGeometries(geos_result);
1123 #if POSTGIS_DEBUG_LEVEL >= 3
1124 LWDEBUGF(3,
"GEOSpolygonize: ngeoms in polygonize output: %d", ngeoms);
1127 LWDEBUGF(3,
"GEOSpolygonize: polygonized:%s", geom_ewkt);
1135 GEOSSetSRID(geos_result, srid);
1142 tmp = (GEOSGeometry*)GEOSGetGeometryN(geos_result, 0);
1145 GEOSGeom_destroy(geos_result);
1148 shp = GEOSGeom_clone(tmp);
1149 GEOSGeom_destroy(geos_result);
1150 GEOSSetSRID(shp, srid);
1154 LWDEBUGF(2,
"Polygonize returned %d geoms", ngeoms);
1184 geoms =
lwalloc(
sizeof(Face**) * ngeoms);
1185 for (i = 0; i < ngeoms; ++i)
1186 geoms[i] = newFace(GEOSGetGeometryN(geos_result, i));
1189 findFaceHoles(geoms, ngeoms);
1192 tmp = collectFacesWithEvenAncestors(geoms, ngeoms);
1195 for (i = 0; i < ngeoms; ++i)
1200 GEOSGeom_destroy(geos_result);
1203 shp = GEOSUnionCascaded(tmp);
1206 GEOSGeom_destroy(tmp);
1210 GEOSGeom_destroy(tmp);
1212 GEOSSetSRID(shp, srid);
1224 GEOSGeometry *g1, *g3;
1235 #if POSTGIS_GEOS_VERSION < 38
1236 g3 = LWGEOM_GEOS_buildArea(g1);
1238 g3 = GEOSBuildArea(g1);
1242 GEOSSetSRID(g3, srid);
1245 if (GEOSGetNumGeometries(g3) == 0)
1274 simple = GEOSisSimple(g);
1275 GEOSGeom_destroy(g);
1301 GEOSSetSRID(g, srid);
1317 GEOSGeometry *g1, *g2, *g3;
1326 g3 = GEOSSnap(g1, g2, tolerance);
1329 GEOSSetSRID(g3, srid);
1344 GEOSGeometry *g1, *g2, *g3;
1353 g3 = GEOSSharedPaths(g1, g2);
1356 GEOSSetSRID(g3, srid);
1372 GEOSGeometry *g1, *g3;
1380 g3 = GEOSOffsetCurve(g1, size, quadsegs, joinStyle, mitreLimit);
1388 GEOSSetSRID(g3, srid);
1410 for (i = 0; i < col->
ngeoms; i++)
1437 tmp = result->
geoms[0];
1485 lwerror(
"lwgeom_offsetcurve: cannot node input");
1493 lwerror(
"lwgeom_offsetcurve: noded geometry cannot be offset");
1504 double area, bbox_area, bbox_width, bbox_height;
1507 uint32_t sample_npoints, sample_sqrt, sample_width, sample_height;
1508 double sample_cell_size;
1510 uint32_t iterations = 0;
1511 uint32_t npoints_generated = 0;
1512 uint32_t npoints_tested = 0;
1514 const GEOSPreparedGeometry* gprep;
1516 GEOSCoordSequence* gseq;
1521 const size_t size = 2 *
sizeof(int);
1522 char tmp[2 *
sizeof(int)];
1523 const size_t stride = 2 *
sizeof(int);
1527 lwerror(
"%s: only polygons supported", __func__);
1536 bbox = *(lwpoly->
bbox);
1539 bbox_width = bbox.
xmax - bbox.
xmin;
1540 bbox_height = bbox.
ymax - bbox.
ymin;
1541 bbox_area = bbox_width * bbox_height;
1543 if (area == 0.0 || bbox_area == 0.0)
1545 lwerror(
"%s: zero area input polygon, TBD", __func__);
1550 sample_npoints = npoints * bbox_area / area;
1555 sample_sqrt = lround(sqrt(sample_npoints));
1556 if (sample_sqrt == 0)
1560 if (bbox_width > bbox_height)
1562 sample_width = sample_sqrt;
1563 sample_height = ceil((
double)sample_npoints / (
double)sample_width);
1564 sample_cell_size = bbox_width / sample_width;
1568 sample_height = sample_sqrt;
1569 sample_width = ceil((
double)sample_npoints / (
double)sample_height);
1570 sample_cell_size = bbox_height / sample_height;
1581 gprep = GEOSPrepare(g);
1595 cells =
lwalloc(2 *
sizeof(
int) * sample_height * sample_width);
1596 for (i = 0; i < sample_width; i++)
1598 for (j = 0; j < sample_height; j++)
1600 cells[2 * (i * sample_height + j)] = i;
1601 cells[2 * (i * sample_height + j) + 1] = j;
1606 n = sample_height * sample_width;
1609 for (i = n - 1; i > 0; i--)
1613 memcpy(tmp, (
char *)cells + j * stride, size);
1614 memcpy((
char *)cells + j * stride, (
char *)cells + i * stride, size);
1615 memcpy((
char *)cells + i * stride, tmp, size);
1620 while (npoints_generated < npoints)
1623 for (i = 0; i < sample_width * sample_height; i++)
1626 double y = bbox.
ymin + cells[2 * i] * sample_cell_size;
1627 double x = bbox.
xmin + cells[2 * i + 1] * sample_cell_size;
1630 if (
x >= bbox.
xmax ||
y >= bbox.
ymax)
continue;
1632 gseq = GEOSCoordSeq_create(1, 2);
1633 #if POSTGIS_GEOS_VERSION < 38
1634 GEOSCoordSeq_setX(gseq, 0,
x);
1635 GEOSCoordSeq_setY(gseq, 0,
y);
1637 GEOSCoordSeq_setXY(gseq, 0,
x,
y);
1639 gpt = GEOSGeom_createPoint(gseq);
1641 contains = GEOSPreparedIntersects(gprep, gpt);
1643 GEOSGeom_destroy(gpt);
1647 GEOSPreparedGeom_destroy(gprep);
1648 GEOSGeom_destroy(g);
1654 npoints_generated++;
1656 if (npoints_generated == npoints)
1665 if (npoints_tested % 10000 == 0)
1666 LW_ON_INTERRUPT(GEOSPreparedGeom_destroy(gprep); GEOSGeom_destroy(g);
return NULL);
1670 if (done || iterations > 100)
break;
1673 GEOSPreparedGeom_destroy(gprep);
1674 GEOSGeom_destroy(g);
1692 lwerror(
"%s: only multipolygons supported", __func__);
1699 for (i = 0; i < lwmpoly->
ngeoms; i++)
1702 int sub_npoints = lround(npoints * sub_area / area);
1703 if (sub_npoints > 0)
1711 for (j = 0; j < sub_mpt->
ngeoms; j++)
1741 int type = GEOSGeomTypeId(geom);
1742 int SRID = GEOSGetSRID(geom);
1747 if (want3d && !GEOSHasZ(geom))
1749 LWDEBUG(3,
"Geometry has no Z, won't provide one");
1757 case GEOS_GEOMETRYCOLLECTION:
1758 LWDEBUG(4,
"lwgeom_from_geometry: it's a Collection or Multi");
1760 ngeoms = GEOSGetNumGeometries(geom);
1764 geoms =
lwalloc(ngeoms *
sizeof *geoms);
1767 lwerror(
"lwtin_from_geos: can't allocate geoms");
1770 for (i = 0; i < ngeoms; i++)
1772 const GEOSGeometry *poly, *ring;
1773 const GEOSCoordSequence* cs;
1776 poly = GEOSGetGeometryN(geom, i);
1777 ring = GEOSGetExteriorRing(poly);
1778 cs = GEOSGeom_getCoordSeq(ring);
1786 case GEOS_MULTIPOINT:
1787 case GEOS_MULTILINESTRING:
1788 case GEOS_MULTIPOLYGON:
1789 case GEOS_LINESTRING:
1790 case GEOS_LINEARRING:
1792 lwerror(
"lwtin_from_geos: invalid geometry type for tin: %d",
type);
1796 lwerror(
"GEOS2LWGEOM: unknown geometry type: %d",
type);
1812 GEOSGeometry *g1, *g3;
1814 if (output < 0 || output > 2)
1816 lwerror(
"%s: invalid output type specified %d", __func__, output);
1827 g3 = GEOSDelaunayTriangulation(g1, tolerance, output == 1);
1830 GEOSSetSRID(g3, srid);
1838 lwerror(
"%s: cannot convert output geometry", __func__);
1850 static GEOSCoordSequence*
1854 uint8_t num_dims = 2;
1856 GEOSCoordSequence* coords;
1859 coords = GEOSCoordSeq_create(num_points, num_dims);
1860 if (!coords)
return NULL;
1865 if (i >= num_points)
1867 lwerror(
"Incorrect num_points provided to lwgeom_get_geos_coordseq_2d");
1868 GEOSCoordSeq_destroy(coords);
1873 #if POSTGIS_GEOS_VERSION < 38
1874 if (!GEOSCoordSeq_setX(coords, i, tmp.
x) || !GEOSCoordSeq_setY(coords, i, tmp.
y))
1876 if (!GEOSCoordSeq_setXY(coords, i, tmp.
x, tmp.
y))
1879 GEOSCoordSeq_destroy(coords);
1897 GEOSCoordSequence* coords;
1898 GEOSGeometry* geos_geom;
1899 GEOSGeometry* geos_env = NULL;
1900 GEOSGeometry* geos_result;
1915 if (!coords)
return NULL;
1917 geos_geom = GEOSGeom_createLineString(coords);
1920 GEOSCoordSeq_destroy(coords);
1926 geos_result = GEOSVoronoiDiagram(geos_geom, geos_env, tolerance, output_edges);
1928 GEOSGeom_destroy(geos_geom);
1929 if (env) GEOSGeom_destroy(geos_env);
1938 GEOSGeom_destroy(geos_result);
1942 return lwgeom_result;
#define LWGEOM_GEOS_ERRMSG_MAXSIZE
LWGEOM * lwgeom_centroid(const LWGEOM *geom)
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)
static GEOSGeometry * ptarray_to_GEOSLinearRing(const POINTARRAY *pa, uint8_t autofix)
LWGEOM * lwgeom_symdifference(const LWGEOM *geom1, const LWGEOM *geom2)
LWGEOM * lwgeom_unaryunion(const LWGEOM *geom)
LWGEOM * lwgeom_intersection(const LWGEOM *geom1, const LWGEOM *geom2)
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.
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)
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
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_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)
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)
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_union(const LWGEOM *geom1, const LWGEOM *geom2)
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)
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.
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
#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)
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 can contain sub-geometries or not.
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.
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)
int lwgeom_has_arc(const LWGEOM *geom)
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).
#define LWDEBUG(level, msg)
#define LWDEBUGF(level, msg,...)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
void lwnotice(const char *fmt,...)
Write a notice out to the notice 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 POINT2D 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)
Datum contains(PG_FUNCTION_ARGS)