PostGIS  3.1.6dev-r@@SVN_REVISION@@

◆ lwgeom_make_valid()

LWGEOM* lwgeom_make_valid ( LWGEOM geom)

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

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

899 {
900  int is3d;
901  GEOSGeom geosgeom;
902  GEOSGeometry* geosout;
903  LWGEOM* lwgeom_out;
904 
905  LWDEBUG(1, "lwgeom_make_valid enter");
906 
907  is3d = FLAGS_GET_Z(lwgeom_in->flags);
908 
909  /*
910  * Step 1 : try to convert to GEOS, if impossible, clean that up first
911  * otherwise (adding only duplicates of existing points)
912  */
913 
915 
916  lwgeom_out = lwgeom_make_geos_friendly(lwgeom_in);
917  if (!lwgeom_out) lwerror("Could not make a geos friendly geometry out of input");
918 
919  LWDEBUGF(4, "Input geom %p made GEOS-valid as %p", lwgeom_in, lwgeom_out);
920 
921  geosgeom = LWGEOM2GEOS(lwgeom_out, 1);
922  if ( lwgeom_in != lwgeom_out ) {
923  lwgeom_free(lwgeom_out);
924  }
925  if (!geosgeom)
926  {
927  lwerror("Couldn't convert POSTGIS geom to GEOS: %s", lwgeom_geos_errmsg);
928  return NULL;
929  }
930  else
931  {
932  LWDEBUG(4, "geom converted to GEOS");
933  }
934 
935 #if POSTGIS_GEOS_VERSION < 38
936  geosout = LWGEOM_GEOS_makeValid(geosgeom);
937 #else
938  geosout = GEOSMakeValid(geosgeom);
939 #endif
940  GEOSGeom_destroy(geosgeom);
941  if (!geosout) return NULL;
942 
943  lwgeom_out = GEOS2LWGEOM(geosout, is3d);
944  GEOSGeom_destroy(geosout);
945 
946  if (lwgeom_is_collection(lwgeom_in) && !lwgeom_is_collection(lwgeom_out))
947  {
948  LWGEOM** ogeoms = lwalloc(sizeof(LWGEOM*));
949  LWGEOM* ogeom;
950  LWDEBUG(3, "lwgeom_make_valid: forcing multi");
951  /* NOTE: this is safe because lwgeom_out is surely not lwgeom_in or
952  * otherwise we couldn't have a collection and a non-collection */
953  assert(lwgeom_in != lwgeom_out);
954  ogeoms[0] = lwgeom_out;
955  ogeom = (LWGEOM*)lwcollection_construct(
956  MULTITYPE[lwgeom_out->type], lwgeom_out->srid, lwgeom_out->bbox, 1, ogeoms);
957  lwgeom_out->bbox = NULL;
958  lwgeom_out = ogeom;
959  }
960 
961  lwgeom_out->srid = lwgeom_in->srid;
962  return lwgeom_out;
963 }
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)
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1138
#define FLAGS_GET_Z(flags)
Definition: liblwgeom.h:179
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1080
void * lwalloc(size_t size)
Definition: lwutil.c:227
LWCOLLECTION * lwcollection_construct(uint8_t type, int32_t srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
Definition: lwcollection.c:42
uint8_t MULTITYPE[NUMTYPES]
Look-up for the correct MULTI* type promotion for singleton types.
Definition: lwgeom.c:337
#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:476
GBOX * bbox
Definition: liblwgeom.h:472
int32_t srid
Definition: liblwgeom.h:474

References LWGEOM::bbox, LWGEOM::flags, FLAGS_GET_Z, GEOS2LWGEOM(), lwalloc(), lwcollection_construct(), LWDEBUG, LWDEBUGF, lwerror(), LWGEOM2GEOS(), lwgeom_free(), 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: