PostGIS  2.5.0dev-r@@SVN_REVISION@@

◆ lwgeom_make_valid()

LWGEOM* lwgeom_make_valid ( LWGEOM geom)

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

NOTE: this is only available when liblwgeom is built against GEOS 3.3.0 or higher

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

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

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

846 {
847  int is3d;
848  GEOSGeom geosgeom;
849  GEOSGeometry* geosout;
850  LWGEOM* lwgeom_out;
851 
852  is3d = FLAGS_GET_Z(lwgeom_in->flags);
853 
854  /*
855  * Step 1 : try to convert to GEOS, if impossible, clean that up first
856  * otherwise (adding only duplicates of existing points)
857  */
858 
860 
861  lwgeom_out = lwgeom_in;
862  geosgeom = LWGEOM2GEOS(lwgeom_out, 1);
863  if (!geosgeom)
864  {
865  LWDEBUGF(4,
866  "Original geom can't be converted to GEOS (%s)"
867  " - will try cleaning that up first",
869 
870  lwgeom_out = lwgeom_make_geos_friendly(lwgeom_out);
871  if (!lwgeom_out) lwerror("Could not make a valid geometry out of input");
872 
873  /* try again as we did cleanup now */
874  /* TODO: invoke LWGEOM2GEOS directly with autoclean ? */
875  geosgeom = LWGEOM2GEOS(lwgeom_out, 0);
876  if (!geosgeom)
877  {
878  lwerror("Couldn't convert POSTGIS geom to GEOS: %s", lwgeom_geos_errmsg);
879  return NULL;
880  }
881  }
882  else
883  {
884  LWDEBUG(4, "original geom converted to GEOS");
885  lwgeom_out = lwgeom_in;
886  }
887 
888  geosout = LWGEOM_GEOS_makeValid(geosgeom);
889  GEOSGeom_destroy(geosgeom);
890  if (!geosout) return NULL;
891 
892  lwgeom_out = GEOS2LWGEOM(geosout, is3d);
893  GEOSGeom_destroy(geosout);
894 
895  if (lwgeom_is_collection(lwgeom_in) && !lwgeom_is_collection(lwgeom_out))
896  {
897  LWGEOM** ogeoms = lwalloc(sizeof(LWGEOM*));
898  LWGEOM* ogeom;
899  LWDEBUG(3, "lwgeom_make_valid: forcing multi");
900  /* NOTE: this is safe because lwgeom_out is surely not lwgeom_in or
901  * otherwise we couldn't have a collection and a non-collection */
902  assert(lwgeom_in != lwgeom_out);
903  ogeoms[0] = lwgeom_out;
904  ogeom = (LWGEOM*)lwcollection_construct(
905  MULTITYPE[lwgeom_out->type], lwgeom_out->srid, lwgeom_out->bbox, 1, ogeoms);
906  lwgeom_out->bbox = NULL;
907  lwgeom_out = ogeom;
908  }
909 
910  lwgeom_out->srid = lwgeom_in->srid;
911  return lwgeom_out;
912 }
GBOX * bbox
Definition: liblwgeom.h:400
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1085
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, uint8_t want3d)
static LWGEOM * lwgeom_make_geos_friendly(LWGEOM *geom)
LWCOLLECTION * lwcollection_construct(uint8_t type, int srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
Definition: lwcollection.c:43
GEOSGeometry * LWGEOM_GEOS_makeValid(const GEOSGeometry *gin)
uint8_t flags
Definition: liblwgeom.h:399
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
int32_t srid
Definition: liblwgeom.h:401
void lwgeom_geos_error(const char *fmt,...)
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:139
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
uint8_t MULTITYPE[NUMTYPES]
Look-up for the correct MULTI* type promotion for singleton types.
Definition: lwgeom.c:345
uint8_t type
Definition: liblwgeom.h:398
void * lwalloc(size_t size)
Definition: lwutil.c:229
#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
Here is the call graph for this function:
Here is the caller graph for this function: