PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ lwgeom_make_valid()

LWGEOM * lwgeom_make_valid ( LWGEOM lwgeom_in)

Attempts to make an invalid geometries valid w/out losing points.

Definition at line 854 of file liblwgeom/lwgeom_geos_clean.c.

855{
856 int is3d;
857 GEOSGeom geosgeom;
858 GEOSGeometry* geosout;
859 LWGEOM* lwgeom_out;
860
861 is3d = FLAGS_GET_Z(lwgeom_in->flags);
862
863 /*
864 * Step 1 : try to convert to GEOS, if impossible, clean that up first
865 * otherwise (adding only duplicates of existing points)
866 */
867
869
870 lwgeom_out = lwgeom_in;
871 geosgeom = LWGEOM2GEOS(lwgeom_out, 1);
872 if (!geosgeom)
873 {
874 LWDEBUGF(4,
875 "Original geom can't be converted to GEOS (%s)"
876 " - will try cleaning that up first",
878
879 lwgeom_out = lwgeom_make_geos_friendly(lwgeom_out);
880 if (!lwgeom_out) lwerror("Could not make a valid geometry out of input");
881
882 /* try again as we did cleanup now */
883 /* TODO: invoke LWGEOM2GEOS directly with autoclean ? */
884 geosgeom = LWGEOM2GEOS(lwgeom_out, 0);
885 if (!geosgeom)
886 {
887 lwerror("Couldn't convert POSTGIS geom to GEOS: %s", lwgeom_geos_errmsg);
888 return NULL;
889 }
890 }
891 else
892 {
893 LWDEBUG(4, "original geom converted to GEOS");
894 lwgeom_out = lwgeom_in;
895 }
896
897#if POSTGIS_GEOS_VERSION < 38
898 geosout = LWGEOM_GEOS_makeValid(geosgeom);
899#else
900 geosout = GEOSMakeValid(geosgeom);
901#endif
902 GEOSGeom_destroy(geosgeom);
903 if (!geosout) return NULL;
904
905 lwgeom_out = GEOS2LWGEOM(geosout, is3d);
906 GEOSGeom_destroy(geosout);
907
908 if (lwgeom_is_collection(lwgeom_in) && !lwgeom_is_collection(lwgeom_out))
909 {
910 LWGEOM** ogeoms = lwalloc(sizeof(LWGEOM*));
911 LWGEOM* ogeom;
912 LWDEBUG(3, "lwgeom_make_valid: forcing multi");
913 /* NOTE: this is safe because lwgeom_out is surely not lwgeom_in or
914 * otherwise we couldn't have a collection and a non-collection */
915 assert(lwgeom_in != lwgeom_out);
916 ogeoms[0] = lwgeom_out;
918 MULTITYPE[lwgeom_out->type], lwgeom_out->srid, lwgeom_out->bbox, 1, ogeoms);
919 lwgeom_out->bbox = NULL;
920 lwgeom_out = ogeom;
921 }
922
923 lwgeom_out->srid = lwgeom_in->srid;
924 return lwgeom_out;
925}
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, uint8_t want3d)
void lwgeom_geos_error(const char *fmt,...)
static LWGEOM * lwgeom_make_geos_friendly(LWGEOM *geom)
LWCOLLECTION * lwcollection_construct(uint8_t type, int32_t srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
#define FLAGS_GET_Z(flags)
Definition liblwgeom.h:179
void * lwalloc(size_t size)
Definition lwutil.c:227
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition lwgeom.c:1079
uint8_t MULTITYPE[NUMTYPES]
Look-up for the correct MULTI* type promotion for singleton types.
Definition lwgeom.c:336
#define LWDEBUG(level, msg)
Definition lwgeom_log.h:83
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:88
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition lwutil.c:190
uint8_t type
Definition liblwgeom.h:448
GBOX * bbox
Definition liblwgeom.h:444
int32_t srid
Definition liblwgeom.h:446
lwflags_t flags
Definition liblwgeom.h:447

References LWGEOM::bbox, LWGEOM::flags, FLAGS_GET_Z, GEOS2LWGEOM(), lwalloc(), lwcollection_construct(), LWDEBUG, LWDEBUGF, lwerror(), LWGEOM2GEOS(), lwgeom_geos_errmsg, lwgeom_geos_error(), lwgeom_is_collection(), lwgeom_make_geos_friendly(), MULTITYPE, LWGEOM::srid, and LWGEOM::type.

Referenced by _lwt_AddLineEdge(), lwgeom_clean(), mvt_safe_clip_polygon_by_box(), rt_raster_gdal_polygonize(), rt_raster_surface(), ST_MakeValid(), test_geos_makevalid(), and test_lwgeom_make_valid().

Here is the call graph for this function:
Here is the caller graph for this function: