36 #undef LWGEOM_PROFILE_BUILDAREA 38 #define LWGEOM_GEOS_ERRMSG_MAXSIZE 256 75 LWDEBUG(2,
"ptarray_fromGEOSCoordSeq called");
77 if ( ! GEOSCoordSeq_getSize(cs, &size) )
80 LWDEBUGF(4,
" GEOSCoordSeq size: %d", size);
84 if ( ! GEOSCoordSeq_getDimensions(cs, &dims) )
87 LWDEBUGF(4,
" GEOSCoordSeq dimensions: %d", dims);
90 if ( dims > 3 ) dims = 3;
93 LWDEBUGF(4,
" output dimensions: %d", dims);
97 for (i=0; i<size; i++)
99 GEOSCoordSeq_getX(cs, i, &(point.
x));
100 GEOSCoordSeq_getY(cs, i, &(point.
y));
101 if ( dims >= 3 ) GEOSCoordSeq_getZ(cs, i, &(point.
z));
112 int type = GEOSGeomTypeId(geom) ;
114 int SRID = GEOSGetSRID(geom);
121 hasZ = GEOSHasZ(geom);
124 LWDEBUG(3,
"Geometry has no Z, won't provide one");
139 const GEOSCoordSequence *cs;
141 const GEOSGeometry *g;
146 LWDEBUG(4,
"lwgeom_from_geometry: it's a Point");
147 cs = GEOSGeom_getCoordSeq(geom);
148 if ( GEOSisEmpty(geom) )
153 case GEOS_LINESTRING:
154 case GEOS_LINEARRING:
155 LWDEBUG(4,
"lwgeom_from_geometry: it's a LineString or LinearRing");
156 if ( GEOSisEmpty(geom) )
159 cs = GEOSGeom_getCoordSeq(geom);
164 LWDEBUG(4,
"lwgeom_from_geometry: it's a Polygon");
165 if ( GEOSisEmpty(geom) )
167 ngeoms = GEOSGetNumInteriorRings(geom);
169 g = GEOSGetExteriorRing(geom);
170 cs = GEOSGeom_getCoordSeq(g);
172 for (i=0; i<ngeoms; i++)
174 g = GEOSGetInteriorRingN(geom, i);
175 cs = GEOSGeom_getCoordSeq(g);
182 case GEOS_MULTIPOINT:
183 case GEOS_MULTILINESTRING:
184 case GEOS_MULTIPOLYGON:
185 case GEOS_GEOMETRYCOLLECTION:
186 LWDEBUG(4,
"lwgeom_from_geometry: it's a Collection or Multi");
188 ngeoms = GEOSGetNumGeometries(geom);
193 for (i=0; i<ngeoms; i++)
195 g = GEOSGetGeometryN(geom, i);
200 SRID, NULL, ngeoms, geoms);
203 lwerror(
"GEOS2LWGEOM: unknown geometry type: %d", type);
219 int append_points = 0;
231 lwerror(
"ptarray_to_GEOSCoordSeq called with fix_ring and 0 vertices in ring, cannot fix");
238 append_points = 4 - pa->
npoints;
247 if ( ! (sq = GEOSCoordSeq_create(pa->
npoints + append_points, dims)) )
249 lwerror(
"Error creating GEOS Coordinate Sequence");
253 for ( i=0; i < pa->
npoints; i++ )
259 LWDEBUGF(4,
"Point: %g,%g,%g", p3d->
x, p3d->
y, p3d->
z);
267 GEOSCoordSeq_setX(sq, i, p2d->
x);
268 GEOSCoordSeq_setY(sq, i, p2d->
y);
272 GEOSCoordSeq_setZ(sq, i, p3d->
z);
287 for ( i = pa->
npoints; i < pa->npoints + append_points; i++ )
289 GEOSCoordSeq_setX(sq, i, p2d->
x);
290 GEOSCoordSeq_setY(sq, i, p2d->
y);
294 GEOSCoordSeq_setZ(sq, i, p3d->
z);
302 static inline GEOSGeometry *
308 g = GEOSGeom_createLinearRing(sq);
316 GEOSGeometry* envelope;
318 GEOSCoordSequence* seq = GEOSCoordSeq_create(5, 2);
324 GEOSCoordSeq_setX(seq, 0, box->
xmin);
325 GEOSCoordSeq_setY(seq, 0, box->
ymin);
327 GEOSCoordSeq_setX(seq, 1, box->
xmax);
328 GEOSCoordSeq_setY(seq, 1, box->
ymin);
330 GEOSCoordSeq_setX(seq, 2, box->
xmax);
331 GEOSCoordSeq_setY(seq, 2, box->
ymax);
333 GEOSCoordSeq_setX(seq, 3, box->
xmin);
334 GEOSCoordSeq_setY(seq, 3, box->
ymax);
336 GEOSCoordSeq_setX(seq, 4, box->
xmin);
337 GEOSCoordSeq_setY(seq, 4, box->
ymin);
339 ring = GEOSGeom_createLinearRing(seq);
342 GEOSCoordSeq_destroy(seq);
346 envelope = GEOSGeom_createPolygon(ring, NULL, 0);
349 GEOSGeom_destroy(ring);
361 GEOSGeom *geoms = NULL;
367 #if LWDEBUG_LEVEL >= 4 376 GEOSGeometry *g =
LWGEOM2GEOS(lwgeom_stroked, autofix);
381 switch (lwgeom->
type)
393 g = GEOSGeom_createEmptyPolygon();
398 g = GEOSGeom_createPoint(sq);
417 g = GEOSGeom_createLineString(sq);
426 lwpoly = (
LWPOLY *)lwgeom;
429 g = GEOSGeom_createEmptyPolygon();
434 if ( ! shell )
return NULL;
436 ngeoms = lwpoly->
nrings-1;
438 geoms =
malloc(
sizeof(GEOSGeom)*ngeoms);
440 for (i=1; i<lwpoly->
nrings; ++i)
446 while (i) GEOSGeom_destroy(geoms[--i]);
448 GEOSGeom_destroy(shell);
453 g = GEOSGeom_createPolygon(shell, geoms, ngeoms);
454 if (geoms)
free(geoms);
456 if ( ! g )
return NULL;
463 geostype = GEOS_MULTIPOINT;
465 geostype = GEOS_MULTILINESTRING;
467 geostype = GEOS_MULTIPOLYGON;
469 geostype = GEOS_GEOMETRYCOLLECTION;
475 geoms =
malloc(
sizeof(GEOSGeom)*ngeoms);
478 for (i=0; i<ngeoms; ++i)
488 while (j) GEOSGeom_destroy(geoms[--j]);
494 g = GEOSGeom_createCollection(geostype, geoms, j);
495 if ( geoms )
free(geoms);
496 if ( ! g )
return NULL;
504 GEOSSetSRID(g, lwgeom->
srid);
506 #if LWDEBUG_LEVEL >= 4 507 wkt = GEOSGeomToWKT(g);
508 LWDEBUGF(4,
"LWGEOM2GEOS: GEOSGeom: %s", wkt);
518 GEOSCoordSequence* seq = GEOSCoordSeq_create(1, 2);
519 GEOSGeometry*
geom = NULL;
524 GEOSCoordSeq_setX(seq, 0, x);
525 GEOSCoordSeq_setY(seq, 0, y);
527 geom = GEOSGeom_createPoint(seq);
529 GEOSCoordSeq_destroy(seq);
536 GEOSCoordSequence* seq = GEOSCoordSeq_create(2, 2);
537 GEOSGeometry*
geom = NULL;
542 GEOSCoordSeq_setX(seq, 0, x1);
543 GEOSCoordSeq_setY(seq, 0, y1);
544 GEOSCoordSeq_setX(seq, 1, x2);
545 GEOSCoordSeq_setY(seq, 1, y2);
547 geom = GEOSGeom_createLineString(seq);
549 GEOSCoordSeq_destroy(seq);
556 const char *ver = GEOSversion();
568 srid = (int)(geom1->
srid);
580 if ( -1 == GEOSNormalize(g1) )
586 GEOSSetSRID(g1, srid);
588 GEOSGeom_destroy(g1);
603 GEOSGeometry *g1, *g2, *g3 ;
616 srid = (int)(geom1->
srid);
623 LWDEBUG(3,
"intersection() START");
635 lwerror(
"Second argument geometry could not be converted to GEOS.");
636 GEOSGeom_destroy(g1);
640 LWDEBUG(3,
" constructed geometrys - calling geos");
641 LWDEBUGF(3,
" g1 = %s", GEOSGeomToWKT(g1));
642 LWDEBUGF(3,
" g2 = %s", GEOSGeomToWKT(g2));
646 g3 = GEOSIntersection(g1,g2);
648 LWDEBUG(3,
" intersection finished");
652 GEOSGeom_destroy(g1);
653 GEOSGeom_destroy(g2);
654 lwerror(
"Error performing intersection: %s",
659 LWDEBUGF(3,
"result: %s", GEOSGeomToWKT(g3) ) ;
661 GEOSSetSRID(g3, srid);
667 GEOSGeom_destroy(g1);
668 GEOSGeom_destroy(g2);
669 GEOSGeom_destroy(g3);
670 lwerror(
"Error performing intersection: GEOS2LWGEOM: %s",
675 GEOSGeom_destroy(g1);
676 GEOSGeom_destroy(g2);
677 GEOSGeom_destroy(g3);
686 GEOSGeometry *g1, *g3 ;
688 int srid = geom1->
srid;
697 LWDEBUG(3,
"linemerge() START");
706 LWDEBUG(3,
" constructed geometrys - calling geos");
707 LWDEBUGF(3,
" g1 = %s", GEOSGeomToWKT(g1));
710 g3 = GEOSLineMerge(g1);
712 LWDEBUG(3,
" linemerge finished");
716 GEOSGeom_destroy(g1);
717 lwerror(
"Error performing linemerge: %s",
722 LWDEBUGF(3,
"result: %s", GEOSGeomToWKT(g3) ) ;
724 GEOSSetSRID(g3, srid);
730 GEOSGeom_destroy(g1);
731 GEOSGeom_destroy(g3);
732 lwerror(
"Error performing linemerge: GEOS2LWGEOM: %s",
737 GEOSGeom_destroy(g1);
738 GEOSGeom_destroy(g3);
747 GEOSGeometry *g1, *g3 ;
749 int srid = geom1->
srid;
764 g3 = GEOSUnaryUnion(g1);
768 GEOSGeom_destroy(g1);
769 lwerror(
"Error performing unaryunion: %s",
774 LWDEBUGF(3,
"result: %s", GEOSGeomToWKT(g3) ) ;
776 GEOSSetSRID(g3, srid);
782 GEOSGeom_destroy(g1);
783 GEOSGeom_destroy(g3);
784 lwerror(
"Error performing unaryunion: GEOS2LWGEOM: %s",
789 GEOSGeom_destroy(g1);
790 GEOSGeom_destroy(g3);
798 GEOSGeometry *g1, *g2, *g3;
812 srid = (int)(geom1->
srid);
829 GEOSGeom_destroy(g1);
834 g3 = GEOSDifference(g1,g2);
838 GEOSGeom_destroy(g1);
839 GEOSGeom_destroy(g2);
844 LWDEBUGF(3,
"result: %s", GEOSGeomToWKT(g3) ) ;
846 GEOSSetSRID(g3, srid);
852 GEOSGeom_destroy(g1);
853 GEOSGeom_destroy(g2);
854 GEOSGeom_destroy(g3);
855 lwerror(
"Error performing difference: GEOS2LWGEOM: %s",
860 GEOSGeom_destroy(g1);
861 GEOSGeom_destroy(g2);
862 GEOSGeom_destroy(g3);
872 GEOSGeometry *g1, *g2, *g3;
886 srid = (int)(geom1->
srid);
906 GEOSGeom_destroy(g1);
910 g3 = GEOSSymDifference(g1,g2);
914 GEOSGeom_destroy(g1);
915 GEOSGeom_destroy(g2);
920 LWDEBUGF(3,
"result: %s", GEOSGeomToWKT(g3));
922 GEOSSetSRID(g3, srid);
928 GEOSGeom_destroy(g1);
929 GEOSGeom_destroy(g2);
930 GEOSGeom_destroy(g3);
931 lwerror(
"GEOS symdifference() threw an error (result postgis geometry formation)!");
935 GEOSGeom_destroy(g1);
936 GEOSGeom_destroy(g2);
937 GEOSGeom_destroy(g3);
945 GEOSGeometry *g, *g_centroid;
971 g_centroid = GEOSGetCentroid(g);
974 if (g_centroid == NULL)
980 LWDEBUGF(3,
"result: %s", GEOSGeomToWKT(g_centroid));
982 GEOSSetSRID(g_centroid, srid);
985 GEOSGeom_destroy(g_centroid);
987 if (centroid == NULL)
989 lwerror(
"GEOS GEOSGetCentroid() threw an error (result postgis geometry formation)!");
1001 GEOSGeometry *g1, *g2, *g3;
1016 srid = (int)(geom1->
srid);
1035 GEOSGeom_destroy(g1);
1040 LWDEBUGF(3,
"g1=%s", GEOSGeomToWKT(g1));
1041 LWDEBUGF(3,
"g2=%s", GEOSGeomToWKT(g2));
1043 g3 = GEOSUnion(g1,g2);
1045 LWDEBUGF(3,
"g3=%s", GEOSGeomToWKT(g3));
1047 GEOSGeom_destroy(g1);
1048 GEOSGeom_destroy(g2);
1057 GEOSSetSRID(g3, srid);
1061 GEOSGeom_destroy(g3);
1065 lwerror(
"Error performing union: GEOS2LWGEOM: %s",
1076 #if POSTGIS_GEOS_VERSION < 35 1077 lwerror(
"The GEOS version this postgis binary " 1078 "was compiled against (%d) doesn't support " 1079 "'GEOSClipByRect' function (3.5.0+ required)",
1084 GEOSGeometry *g1, *g3 ;
1095 LWDEBUG(3,
"clip_by_rect() START");
1104 LWDEBUG(3,
" constructed geometrys - calling geos");
1105 LWDEBUGF(3,
" g1 = %s", GEOSGeomToWKT(g1));
1108 g3 = GEOSClipByRect(g1,x0,y0,x1,y1);
1109 GEOSGeom_destroy(g1);
1111 LWDEBUG(3,
" clip_by_rect finished");
1119 LWDEBUGF(3,
"result: %s", GEOSGeomToWKT(g3) ) ;
1122 GEOSGeom_destroy(g3);
1156 f->
env = GEOSEnvelope(f->
geom);
1166 unsigned int pcount = 0;
1178 GEOSGeom_destroy(f->
env);
1191 if ( n1 < n2 )
return 1;
1192 if ( n1 > n2 )
return -1;
1205 for (i=0; i<nfaces; ++i) {
1207 int nholes = GEOSGetNumInteriorRings(f->
geom);
1208 LWDEBUGF(2,
"Scanning face %d with env area %g and %d holes", i, f->
envarea, nholes);
1209 for (h=0; h<nholes; ++h) {
1210 const GEOSGeometry *hole = GEOSGetInteriorRingN(f->
geom, h);
1211 LWDEBUGF(2,
"Looking for hole %d/%d of face %d among %d other faces", h+1, nholes, i, nfaces-i-1);
1212 for (j=i+1; j<nfaces; ++j) {
1213 const GEOSGeometry *f2er;
1214 Face* f2 = faces[j];
1215 if ( f2->
parent )
continue;
1216 f2er = GEOSGetExteriorRing(f2->
geom);
1222 if ( GEOSEquals(f2er, hole) ) {
1223 LWDEBUGF(2,
"Hole %d/%d of face %d is face %d", h+1, nholes, i, j);
1232 static GEOSGeometry*
1235 GEOSGeometry **geoms =
lwalloc(
sizeof(GEOSGeometry*)*nfaces);
1237 unsigned int ngeoms = 0;
1240 for (i=0; i<nfaces; ++i) {
1243 geoms[ngeoms++] = GEOSGeom_clone(f->
geom);
1246 ret = GEOSGeom_createCollection(GEOS_MULTIPOLYGON, geoms, ngeoms);
1255 GEOSGeometry *geos_result, *shp;
1256 GEOSGeometry
const *vgeoms[1];
1258 int srid = GEOSGetSRID(geom_in);
1261 vgeoms[0] = geom_in;
1262 #ifdef LWGEOM_PROFILE_BUILDAREA 1265 geos_result = GEOSPolygonize(vgeoms, 1);
1267 LWDEBUGF(3,
"GEOSpolygonize returned @ %p", geos_result);
1270 if ( ! geos_result )
return 0;
1275 #if PARANOIA_LEVEL > 0 1278 GEOSGeom_destroy(geos_result);
1279 lwerror(
"%s [%d] Unexpected return from GEOSpolygonize", __FILE__, __LINE__);
1284 ngeoms = GEOSGetNumGeometries(geos_result);
1285 #ifdef LWGEOM_PROFILE_BUILDAREA 1286 lwnotice(
"Num geometries from polygonizer: %d", ngeoms);
1290 LWDEBUGF(3,
"GEOSpolygonize: ngeoms in polygonize output: %d", ngeoms);
1291 LWDEBUGF(3,
"GEOSpolygonize: polygonized:%s",
1299 GEOSSetSRID(geos_result, srid);
1309 tmp = (GEOSGeometry *)GEOSGetGeometryN(geos_result, 0);
1312 GEOSGeom_destroy(geos_result);
1315 shp = GEOSGeom_clone(tmp);
1316 GEOSGeom_destroy(geos_result);
1317 GEOSSetSRID(shp, srid);
1321 LWDEBUGF(2,
"Polygonize returned %d geoms", ngeoms);
1351 #ifdef LWGEOM_PROFILE_BUILDAREA 1352 lwnotice(
"Preparing face structures");
1357 for (i=0; i<ngeoms; ++i)
1358 geoms[i] =
newFace(GEOSGetGeometryN(geos_result, i));
1360 #ifdef LWGEOM_PROFILE_BUILDAREA 1367 #ifdef LWGEOM_PROFILE_BUILDAREA 1368 lwnotice(
"Colletting even ancestor faces");
1375 #ifdef LWGEOM_PROFILE_BUILDAREA 1380 for (i=0; i<ngeoms; ++i)
delFace(geoms[i]);
1385 GEOSGeom_destroy(geos_result);
1387 #ifdef LWGEOM_PROFILE_BUILDAREA 1392 shp = GEOSUnionCascaded(tmp);
1395 GEOSGeom_destroy(tmp);
1399 #ifdef LWGEOM_PROFILE_BUILDAREA 1403 GEOSGeom_destroy(tmp);
1405 GEOSSetSRID(shp, srid);
1413 GEOSGeometry* geos_in;
1414 GEOSGeometry* geos_out;
1416 int SRID = (int)(geom->
srid);
1425 LWDEBUG(3,
"buildarea called");
1427 LWDEBUGF(3,
"ST_BuildArea got geom @ %p", geom);
1439 GEOSGeom_destroy(geos_in);
1448 if ( GEOSGetNumGeometries(geos_out) == 0 )
1450 GEOSGeom_destroy(geos_out);
1455 GEOSGeom_destroy(geos_out);
1457 #if PARANOIA_LEVEL > 0 1458 if ( geom_out == NULL )
1460 lwerror(
"%s [%s] serialization error", __FILE__, __LINE__);
1472 GEOSGeometry* geos_in;
1489 simple = GEOSisSimple(geos_in);
1490 GEOSGeom_destroy(geos_in);
1498 return simple ? 1 : 0;
1506 GEOSGeometry *geosgeom;
1514 lwerror(
"Geometry could not be converted to GEOS: %s",
1519 GEOSGeom_destroy(geosgeom);
1521 lwerror(
"GEOS Geometry could not be converted to LWGEOM: %s",
1532 GEOSGeometry *g1, *g2, *g3;
1553 GEOSGeom_destroy(g1);
1557 g3 = GEOSSnap(g1, g2, tolerance);
1560 GEOSGeom_destroy(g1);
1561 GEOSGeom_destroy(g2);
1566 GEOSGeom_destroy(g1);
1567 GEOSGeom_destroy(g2);
1569 GEOSSetSRID(g3, srid);
1573 GEOSGeom_destroy(g3);
1574 lwerror(
"GEOSSnap() threw an error (result LWGEOM geometry formation)!");
1577 GEOSGeom_destroy(g3);
1585 GEOSGeometry *g1, *g2, *g3;
1607 GEOSGeom_destroy(g1);
1611 g3 = GEOSSharedPaths(g1,g2);
1613 GEOSGeom_destroy(g1);
1614 GEOSGeom_destroy(g2);
1622 GEOSSetSRID(g3, srid);
1624 GEOSGeom_destroy(g3);
1628 lwerror(
"GEOS2LWGEOM threw an error");
1638 GEOSGeometry *g1, *g3;
1651 g3 = GEOSOffsetCurve(g1, size, quadsegs, joinStyle, mitreLimit);
1654 GEOSGeom_destroy(g1);
1662 LWDEBUGF(3,
"result: %s", GEOSGeomToWKT(g3));
1666 GEOSGeom_destroy(g3);
1668 if (lwgeom_result == NULL)
1670 lwerror(
"lwgeom_offsetcurve: GEOS2LWGEOM returned null");
1674 return lwgeom_result;
1682 double area, bbox_area, bbox_width, bbox_height;
1685 int sample_npoints, sample_sqrt, sample_width, sample_height;
1686 double sample_cell_size;
1689 int npoints_generated = 0;
1690 int npoints_tested = 0;
1692 const GEOSPreparedGeometry *gprep;
1694 GEOSCoordSequence *gseq;
1699 const size_t size = 2*
sizeof(int);
1700 char tmp[2*
sizeof(int)];
1701 const size_t stride = 2*
sizeof(int);
1706 lwerror(
"%s: only polygons supported", __func__);
1722 bbox = *(lwpoly->
bbox);
1725 bbox_width = bbox.
xmax - bbox.
xmin;
1726 bbox_height = bbox.
ymax - bbox.
ymin;
1727 bbox_area = bbox_width * bbox_height;
1729 if (area == 0.0 || bbox_area == 0.0)
1731 lwerror(
"%s: zero area input polygon, TBD", __func__);
1737 sample_npoints = npoints * bbox_area /
area;
1743 sample_sqrt = lround(sqrt(sample_npoints));
1744 if (sample_sqrt == 0)
1748 if (bbox_width > bbox_height)
1750 sample_width = sample_sqrt;
1751 sample_height = ceil((
double)sample_npoints / (
double)sample_width);
1752 sample_cell_size = bbox_width / sample_width;
1756 sample_height = sample_sqrt;
1757 sample_width = ceil((
double)sample_npoints / (
double)sample_height);
1758 sample_cell_size = bbox_height / sample_height;
1769 gprep = GEOSPrepare(g);
1780 cells =
lwalloc(2*
sizeof(
int)*sample_height*sample_width);
1781 for (i = 0; i < sample_width; i++)
1783 for (j = 0; j < sample_height; j++)
1785 cells[2*(i*sample_height+j)] = i;
1786 cells[2*(i*sample_height+j)+1] = j;
1792 n = sample_height*sample_width;
1794 for (i = 0; i < n - 1; ++i) {
1795 size_t rnd = (size_t) rand();
1796 size_t j = i + rnd / (RAND_MAX / (n - i) + 1);
1798 memcpy(tmp, (
char *)cells + j * stride, size);
1799 memcpy((
char *)cells + j * stride, (
char *)cells + i * stride, size);
1800 memcpy((
char *)cells + i * stride, tmp, size);
1807 while (npoints_generated < npoints)
1810 for (i = 0; i < sample_width*sample_height; i++)
1813 double y = bbox.
ymin + cells[2*i] * sample_cell_size;
1814 double x = bbox.
xmin + cells[2*i+1] * sample_cell_size;
1815 x += rand() * sample_cell_size / RAND_MAX;
1816 y += rand() * sample_cell_size / RAND_MAX;
1817 if (x >= bbox.
xmax || y >= bbox.
ymax)
1820 gseq = GEOSCoordSeq_create(1, 2);
1821 GEOSCoordSeq_setX(gseq, 0, x);
1822 GEOSCoordSeq_setY(gseq, 0, y);
1823 gpt = GEOSGeom_createPoint(gseq);
1825 contains = GEOSPreparedIntersects(gprep, gpt);
1827 GEOSGeom_destroy(gpt);
1831 GEOSPreparedGeom_destroy(gprep);
1832 GEOSGeom_destroy(g);
1838 npoints_generated++;
1840 if (npoints_generated == npoints)
1849 if (npoints_tested % 10000 == 0)
1851 LW_ON_INTERRUPT(GEOSPreparedGeom_destroy(gprep); GEOSGeom_destroy(g);
return NULL);
1856 if (done || iterations > 100)
break;
1859 GEOSPreparedGeom_destroy(gprep);
1860 GEOSGeom_destroy(g);
1881 lwerror(
"%s: only multipolygons supported", __func__);
1891 for (i = 0; i < lwmpoly->
ngeoms; i++)
1894 int sub_npoints = lround(npoints * sub_area / area);
1905 for (j = 0; j < sub_mpt->
ngeoms; j++)
1940 int type = GEOSGeomTypeId(geom);
1942 int SRID = GEOSGetSRID(geom);
1948 hasZ = GEOSHasZ(geom);
1950 LWDEBUG(3,
"Geometry has no Z, won't provide one");
1958 case GEOS_GEOMETRYCOLLECTION:
1959 LWDEBUG(4,
"lwgeom_from_geometry: it's a Collection or Multi");
1961 ngeoms = GEOSGetNumGeometries(geom);
1964 geoms =
lwalloc(ngeoms *
sizeof *geoms);
1966 lwerror(
"lwtin_from_geos: can't allocate geoms");
1969 for (i=0; i<ngeoms; i++) {
1970 const GEOSGeometry *poly, *ring;
1971 const GEOSCoordSequence *cs;
1974 poly = GEOSGetGeometryN(geom, i);
1975 ring = GEOSGetExteriorRing(poly);
1976 cs = GEOSGeom_getCoordSeq(ring);
1984 case GEOS_MULTIPOINT:
1985 case GEOS_MULTILINESTRING:
1986 case GEOS_MULTIPOLYGON:
1987 case GEOS_LINESTRING:
1988 case GEOS_LINEARRING:
1990 lwerror(
"lwtin_from_geos: invalid geometry type for tin: %d", type);
1994 lwerror(
"GEOS2LWGEOM: unknown geometry type: %d", type);
2005 #if POSTGIS_GEOS_VERSION < 34 2006 lwerror(
"lwgeom_delaunay_triangulation: GEOS 3.4 or higher required");
2009 GEOSGeometry *g1, *g3;
2012 if (output < 0 || output > 2) {
2013 lwerror(
"lwgeom_delaunay_triangulation: invalid output type specified %d", output);
2027 g3 = GEOSDelaunayTriangulation(g1, tolerance, output == 1);
2030 GEOSGeom_destroy(g1);
2048 GEOSGeom_destroy(g3);
2050 if (lwgeom_result == NULL) {
2052 lwerror(
"lwgeom_delaunay_triangulation: GEOS2LWGEOM returned null");
2054 lwerror(
"lwgeom_delaunay_triangulation: lwtin_from_geos returned null");
2059 return lwgeom_result;
2070 GEOSCoordSequence* coords;
2073 coords = GEOSCoordSeq_create(num_points, num_dims);
2082 lwerror(
"Incorrect num_points provided to lwgeom_get_geos_coordseq_2d");
2083 GEOSCoordSeq_destroy(coords);
2088 if(!GEOSCoordSeq_setX(coords, i, tmp.
x) || !GEOSCoordSeq_setY(coords, i, tmp.
y))
2090 GEOSCoordSeq_destroy(coords);
2102 #if POSTGIS_GEOS_VERSION < 35 2103 lwerror(
"lwgeom_voronoi_diagram: GEOS 3.5 or higher required");
2110 GEOSCoordSequence* coords;
2111 GEOSGeometry* geos_geom;
2112 GEOSGeometry* geos_env = NULL;
2113 GEOSGeometry* geos_result;
2133 geos_geom = GEOSGeom_createLineString(coords);
2136 GEOSCoordSeq_destroy(coords);
2143 geos_result = GEOSVoronoiDiagram(geos_geom, geos_env, tolerance, output_edges);
2145 GEOSGeom_destroy(geos_geom);
2147 GEOSGeom_destroy(geos_env);
2156 GEOSGeom_destroy(geos_result);
2160 return lwgeom_result;
void ptarray_set_point4d(POINTARRAY *pa, int n, const POINT4D *p4d)
LWGEOM * lwgeom_stroke(const LWGEOM *geom, uint32_t perQuad)
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.
#define POSTGIS_GEOS_VERSION
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_is_simple(const LWGEOM *geom)
LWLINE * lwline_construct_empty(int srid, char hasz, char hasm)
GEOSGeometry * make_geos_segment(double x1, double y1, double x2, double y2)
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...
LWCOLLECTION * lwcollection_construct(uint8_t type, int srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
static void delFace(Face *f)
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
LWMPOINT * lwpoly_to_points(const LWPOLY *lwpoly, int npoints)
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
static int compare_by_envarea(const void *g1, const void *g2)
LWPOINT * lwpoint_make2d(int srid, double x, double y)
Datum area(PG_FUNCTION_ARGS)
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
void lwgeom_free(LWGEOM *geom)
LWGEOM * lwgeom_symdifference(const LWGEOM *geom1, const LWGEOM *geom2)
Datum contains(PG_FUNCTION_ARGS)
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
Datum centroid(PG_FUNCTION_ARGS)
GEOSGeometry * GBOX2GEOS(const GBOX *box)
#define LWDEBUG(level, msg)
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
#define LW_ON_INTERRUPT(x)
LWTIN * lwtin_from_geos(const GEOSGeometry *geom, int want3d)
static void findFaceHoles(Face **faces, int nfaces)
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
void error_if_srid_mismatch(int srid1, int srid2)
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
LWGEOM * lwgeom_centroid(const LWGEOM *geom)
int ptarray_is_closed_2d(const POINTARRAY *pa)
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
LWPOINTITERATOR * lwpointiterator_create(const LWGEOM *g)
Create a new LWPOINTITERATOR over supplied LWGEOM*.
GEOSGeometry * make_geos_point(double x, double y)
LWGEOM * lwgeom_intersection(const LWGEOM *geom1, const LWGEOM *geom2)
static GEOSCoordSequence * lwgeom_get_geos_coordseq_2d(const LWGEOM *g, uint32_t num_points)
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...
LWGEOM * lwgeom_linemerge(const LWGEOM *geom1)
LWGEOM * lwgeom_buildarea(const LWGEOM *geom)
Take a geometry and return an areal geometry (Polygon or MultiPolygon).
POINTARRAY * ptarray_addPoint(const POINTARRAY *pa, uint8_t *p, size_t pdims, uint32_t where)
Add a point in a pointarray.
void lwpointiterator_destroy(LWPOINTITERATOR *s)
Free all memory associated with the iterator.
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
void lwgeom_geos_error(const char *fmt,...)
LWGEOM * lwgeom_sharedpaths(const LWGEOM *geom1, const LWGEOM *geom2)
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, int n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
LWPOLY * lwpoly_construct(int srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
LWGEOM * lwgeom_geos_noop(const LWGEOM *geom_in)
Convert an LWGEOM to a GEOS Geometry and convert back – for debug only.
static GEOSGeometry * collectFacesWithEvenAncestors(Face **faces, int nfaces)
#define SRID_UNKNOWN
Unknown SRID value.
const GEOSGeometry * geom
LWGEOM * lwgeom_union(const LWGEOM *geom1, const LWGEOM *geom2)
static unsigned int countParens(const Face *f)
uint8_t * getPoint_internal(const POINTARRAY *pa, int n)
LWGEOM * lwgeom_normalize(const LWGEOM *geom1)
LWGEOM * lwgeom_difference(const LWGEOM *geom1, const LWGEOM *geom2)
double lwpoly_area(const LWPOLY *poly)
Find the area of the outer ring - sum (area of inner rings).
LWGEOM * lwgeom_delaunay_triangulation(const LWGEOM *lwgeom_in, double tolerance, int output)
Take vertices of a geometry and build a delaunay triangulation on them.
LWGEOM * lwgeom_clip_by_rect(const LWGEOM *geom1, double x0, double y0, double x1, double y1)
LWMPOINT * lwmpoint_construct_empty(int srid, char hasz, char hasm)
int lwgeom_has_arc(const LWGEOM *geom)
static Face * newFace(const GEOSGeometry *g)
#define LWGEOM_GEOS_ERRMSG_MAXSIZE
LWMPOINT * lwmpoly_to_points(const LWMPOLY *lwmpoly, int npoints)
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, int autofix)
LWTRIANGLE * lwtriangle_construct(int srid, GBOX *bbox, POINTARRAY *points)
GEOSCoordSeq ptarray_to_GEOSCoordSeq(const POINTARRAY *, int fix_ring)
LWGEOM * lwgeom_unaryunion(const LWGEOM *geom1)
const POINT3DZ * getPoint3dz_cp(const POINTARRAY *pa, int n)
Returns a POINT3DZ pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
LWGEOM * lwgeom_snap(const LWGEOM *geom1, const LWGEOM *geom2, double tolerance)
Snap vertices and segments of a geometry to another using a given tolerance.
double lwgeom_area(const LWGEOM *geom)
LWMPOINT * lwmpoint_add_lwpoint(LWMPOINT *mobj, const LWPOINT *obj)
static GEOSGeometry * ptarray_to_GEOSLinearRing(const POINTARRAY *pa, int autofix)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, char want3d)
void lwgeom_release(LWGEOM *lwgeom)
Free the containing LWGEOM and the associated BOX.
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
const char * lwgeom_geos_version()
Return GEOS version string (not to be freed)
void lwgeom_set_srid(LWGEOM *geom, int srid)
Set the SRID on an LWGEOM For collections, only the parent gets an SRID, all the children get SRID_UN...
LWGEOM * lwgeom_offsetcurve(const LWLINE *lwline, double size, int quadsegs, int joinStyle, double mitreLimit)
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
void * lwalloc(size_t size)
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
int lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
POINTARRAY * ptarray_from_GEOSCoordSeq(const GEOSCoordSequence *cs, char want3d)
#define LWDEBUGF(level, msg,...)
#define FLAGS_NDIMS(flags)
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
LWMPOINT * lwgeom_to_points(const LWGEOM *lwgeom, int npoints)
This library is the generic geometry handling section of PostGIS.
GEOSGeometry * LWGEOM_GEOS_buildArea(const GEOSGeometry *geom_in)
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)