PostGIS  2.1.10dev-r@@SVN_REVISION@@
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 995 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 lwgeom_clean(), rt_raster_gdal_polygonize(), rt_raster_surface(), ST_MakeValid(), and test_lwgeom_make_valid().

996 {
997  int is3d;
998  GEOSGeom geosgeom;
999  GEOSGeometry* geosout;
1000  LWGEOM *lwgeom_out;
1001 
1002  is3d = FLAGS_GET_Z(lwgeom_in->flags);
1003 
1004  /*
1005  * Step 1 : try to convert to GEOS, if impossible, clean that up first
1006  * otherwise (adding only duplicates of existing points)
1007  */
1008 
1010 
1011  lwgeom_out = lwgeom_in;
1012  geosgeom = LWGEOM2GEOS(lwgeom_out);
1013  if ( ! geosgeom )
1014  {
1015  LWDEBUGF(4,
1016  "Original geom can't be converted to GEOS (%s)"
1017  " - will try cleaning that up first",
1019 
1020 
1021  lwgeom_out = lwgeom_make_geos_friendly(lwgeom_out);
1022  if ( ! lwgeom_out )
1023  {
1024  lwerror("Could not make a valid geometry out of input");
1025  }
1026 
1027  /* try again as we did cleanup now */
1028  geosgeom = LWGEOM2GEOS(lwgeom_out);
1029  if ( ! geosgeom )
1030  {
1031  lwerror("Couldn't convert POSTGIS geom to GEOS: %s",
1033  return NULL;
1034  }
1035 
1036  }
1037  else
1038  {
1039  LWDEBUG(4, "original geom converted to GEOS");
1040  lwgeom_out = lwgeom_in;
1041  }
1042 
1043  geosout = LWGEOM_GEOS_makeValid(geosgeom);
1044  GEOSGeom_destroy(geosgeom);
1045  if ( ! geosout )
1046  {
1047  return NULL;
1048  }
1049 
1050  lwgeom_out = GEOS2LWGEOM(geosout, is3d);
1051  GEOSGeom_destroy(geosout);
1052 
1053  if ( lwgeom_is_collection(lwgeom_in) && ! lwgeom_is_collection(lwgeom_out) )
1054  {{
1055  LWGEOM **ogeoms = lwalloc(sizeof(LWGEOM*));
1056  LWGEOM *ogeom;
1057  LWDEBUG(3, "lwgeom_make_valid: forcing multi");
1058  /* NOTE: this is safe because lwgeom_out is surely not lwgeom_in or
1059  * otherwise we couldn't have a collection and a non-collection */
1060  assert(lwgeom_in != lwgeom_out);
1061  ogeoms[0] = lwgeom_out;
1062  ogeom = (LWGEOM *)lwcollection_construct(MULTITYPE[lwgeom_out->type],
1063  lwgeom_out->srid, lwgeom_out->bbox, 1, ogeoms);
1064  lwgeom_out->bbox = NULL;
1065  lwgeom_out = ogeom;
1066  }}
1067 
1068  lwgeom_out->srid = lwgeom_in->srid;
1069  return lwgeom_out;
1070 }
GBOX * bbox
Definition: liblwgeom.h:354
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:947
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:30
uint8_t flags
Definition: liblwgeom.h:353
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:50
static GEOSGeometry * LWGEOM_GEOS_makeValid(const GEOSGeometry *)
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom)
int32_t srid
Definition: liblwgeom.h:355
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
void lwgeom_geos_error(const char *fmt,...)
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:106
uint8_t MULTITYPE[NUMTYPES]
Look-up for the correct MULTI* type promotion for singleton types.
Definition: lwgeom.c:264
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, char want3d)
uint8_t type
Definition: liblwgeom.h:352
void * lwalloc(size_t size)
Definition: lwutil.c:175
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55

Here is the call graph for this function:

Here is the caller graph for this function: