396 GEOSGeom geos_cut_edges, geos_area, collapse_points;
397 GEOSGeometry *vgeoms[3];
398 unsigned int nvgeoms=0;
400 assert (GEOSGeomTypeId(gin) == GEOS_POLYGON ||
401 GEOSGeomTypeId(gin) == GEOS_MULTIPOLYGON);
403 geos_bound = GEOSBoundary(gin);
404 if ( NULL == geos_bound )
415 #ifdef LWGEOM_PROFILE_MAKEVALID
416 lwnotice(
"ST_MakeValid: noding lines");
421 if ( NULL == geos_cut_edges )
423 GEOSGeom_destroy(geos_bound);
434 #ifdef LWGEOM_PROFILE_MAKEVALID
435 lwnotice(
"ST_MakeValid: extracting unique points from bounds");
438 pi = GEOSGeom_extractUniquePoints(geos_bound);
441 GEOSGeom_destroy(geos_bound);
442 lwnotice(
"GEOSGeom_extractUniquePoints(): %s",
448 "Boundaries input points %s",
451 #ifdef LWGEOM_PROFILE_MAKEVALID
452 lwnotice(
"ST_MakeValid: extracting unique points from cut_edges");
455 po = GEOSGeom_extractUniquePoints(geos_cut_edges);
458 GEOSGeom_destroy(geos_bound);
459 GEOSGeom_destroy(pi);
460 lwnotice(
"GEOSGeom_extractUniquePoints(): %s",
466 "Boundaries output points %s",
469 #ifdef LWGEOM_PROFILE_MAKEVALID
470 lwnotice(
"ST_MakeValid: find collapse points");
473 collapse_points = GEOSDifference(pi, po);
474 if ( NULL == collapse_points )
476 GEOSGeom_destroy(geos_bound);
477 GEOSGeom_destroy(pi);
478 GEOSGeom_destroy(po);
484 "Collapse points: %s",
487 #ifdef LWGEOM_PROFILE_MAKEVALID
488 lwnotice(
"ST_MakeValid: cleanup(1)");
491 GEOSGeom_destroy(pi);
492 GEOSGeom_destroy(po);
494 GEOSGeom_destroy(geos_bound);
497 "Noded Boundaries: %s",
501 geos_area = GEOSGeom_createEmptyPolygon();
505 GEOSGeom_destroy(geos_cut_edges);
515 while (GEOSGetNumGeometries(geos_cut_edges))
517 GEOSGeometry* new_area=0;
518 GEOSGeometry* new_area_bound=0;
519 GEOSGeometry* symdif=0;
520 GEOSGeometry* new_cut_edges=0;
522 #ifdef LWGEOM_PROFILE_MAKEVALID
523 lwnotice(
"ST_MakeValid: building area from %d edges", GEOSGetNumGeometries(geos_cut_edges));
533 GEOSGeom_destroy(geos_cut_edges);
534 GEOSGeom_destroy(geos_area);
535 lwnotice(
"LWGEOM_GEOS_buildArea() threw an error: %s",
540 if ( GEOSisEmpty(new_area) )
543 GEOSGeom_destroy(new_area);
551 #ifdef LWGEOM_PROFILE_MAKEVALID
552 lwnotice(
"ST_MakeValid: ring built with %d cut edges, saving boundaries", GEOSGetNumGeometries(geos_cut_edges));
559 new_area_bound = GEOSBoundary(new_area);
560 if ( ! new_area_bound )
564 lwnotice(
"GEOSBoundary('%s') threw an error: %s",
567 GEOSGeom_destroy(new_area);
568 GEOSGeom_destroy(geos_area);
572 #ifdef LWGEOM_PROFILE_MAKEVALID
573 lwnotice(
"ST_MakeValid: running SymDifference with new area");
579 symdif = GEOSSymDifference(geos_area, new_area);
582 GEOSGeom_destroy(geos_cut_edges);
583 GEOSGeom_destroy(new_area);
584 GEOSGeom_destroy(new_area_bound);
585 GEOSGeom_destroy(geos_area);
586 lwnotice(
"GEOSSymDifference() threw an error: %s",
591 GEOSGeom_destroy(geos_area);
592 GEOSGeom_destroy(new_area);
607 #ifdef LWGEOM_PROFILE_MAKEVALID
608 lwnotice(
"ST_MakeValid: computing new cut_edges (GEOSDifference)");
611 new_cut_edges = GEOSDifference(geos_cut_edges, new_area_bound);
612 GEOSGeom_destroy(new_area_bound);
613 if ( ! new_cut_edges )
616 GEOSGeom_destroy(geos_cut_edges);
617 GEOSGeom_destroy(geos_area);
619 lwnotice(
"GEOSDifference() threw an error: %s",
623 GEOSGeom_destroy(geos_cut_edges);
624 geos_cut_edges = new_cut_edges;
627 #ifdef LWGEOM_PROFILE_MAKEVALID
628 lwnotice(
"ST_MakeValid: final checks");
631 if ( ! GEOSisEmpty(geos_area) )
633 vgeoms[nvgeoms++] = geos_area;
637 GEOSGeom_destroy(geos_area);
640 if ( ! GEOSisEmpty(geos_cut_edges) )
642 vgeoms[nvgeoms++] = geos_cut_edges;
646 GEOSGeom_destroy(geos_cut_edges);
649 if ( ! GEOSisEmpty(collapse_points) )
651 vgeoms[nvgeoms++] = collapse_points;
655 GEOSGeom_destroy(collapse_points);
666 gout = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, vgeoms, nvgeoms);
671 lwnotice(
"GEOSGeom_createCollection() threw an error: %s",
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, char want3d)
#define LWDEBUGF(level, msg,...)
static GEOSGeometry * LWGEOM_GEOS_nodeLines(const GEOSGeometry *lines)
GEOSGeometry * LWGEOM_GEOS_buildArea(const GEOSGeometry *geom_in)