PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ lwgeom_make_valid_params()

LWGEOM* lwgeom_make_valid_params ( LWGEOM geom,
char *  make_valid_params 
)

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

907 {
908  int is3d;
909  GEOSGeom geosgeom;
910  GEOSGeometry* geosout;
911  LWGEOM* lwgeom_out;
912 
913  LWDEBUG(1, "lwgeom_make_valid enter");
914 
915  is3d = FLAGS_GET_Z(lwgeom_in->flags);
916 
917  /*
918  * Step 1 : try to convert to GEOS, if impossible, clean that up first
919  * otherwise (adding only duplicates of existing points)
920  */
921 
923 
924  lwgeom_out = lwgeom_make_geos_friendly(lwgeom_in);
925  if (!lwgeom_out) lwerror("Could not make a geos friendly geometry out of input");
926 
927  LWDEBUGF(4, "Input geom %p made GEOS-valid as %p", lwgeom_in, lwgeom_out);
928 
929  geosgeom = LWGEOM2GEOS(lwgeom_out, 1);
930  if ( lwgeom_in != lwgeom_out ) {
931  lwgeom_free(lwgeom_out);
932  }
933  if (!geosgeom)
934  {
935  lwerror("Couldn't convert POSTGIS geom to GEOS: %s", lwgeom_geos_errmsg);
936  return NULL;
937  }
938  else
939  {
940  LWDEBUG(4, "geom converted to GEOS");
941  }
942 
943 #if POSTGIS_GEOS_VERSION < 30800
944  geosout = LWGEOM_GEOS_makeValid(geosgeom);
945 #elif POSTGIS_GEOS_VERSION < 31000
946  geosout = GEOSMakeValid(geosgeom);
947 #else
948  if (!make_valid_params) {
949  geosout = GEOSMakeValid(geosgeom);
950  }
951  else {
952  /*
953  * Set up a parameters object for this
954  * make valid operation before calling
955  * it
956  */
957  const char *value;
958  char *param_list[OPTION_LIST_SIZE];
959  char param_list_text[OPTION_LIST_SIZE];
960  strncpy(param_list_text, make_valid_params, OPTION_LIST_SIZE-1);
961  param_list_text[OPTION_LIST_SIZE-1] = '\0'; /* ensure null-termination */
962  memset(param_list, 0, sizeof(param_list));
963  option_list_parse(param_list_text, param_list);
964  GEOSMakeValidParams *params = GEOSMakeValidParams_create();
965  value = option_list_search(param_list, "method");
966  if (value) {
967  if (strcasecmp(value, "linework") == 0) {
968  GEOSMakeValidParams_setMethod(params, GEOS_MAKE_VALID_LINEWORK);
969  }
970  else if (strcasecmp(value, "structure") == 0) {
971  GEOSMakeValidParams_setMethod(params, GEOS_MAKE_VALID_STRUCTURE);
972  }
973  else
974  {
975  GEOSMakeValidParams_destroy(params);
976  lwerror("Unsupported value for 'method', '%s'. Use 'linework' or 'structure'.", value);
977  }
978  }
979  value = option_list_search(param_list, "keepcollapsed");
980  if (value) {
981  if (strcasecmp(value, "true") == 0) {
982  GEOSMakeValidParams_setKeepCollapsed(params, 1);
983  }
984  else if (strcasecmp(value, "false") == 0) {
985  GEOSMakeValidParams_setKeepCollapsed(params, 0);
986  }
987  else
988  {
989  GEOSMakeValidParams_destroy(params);
990  lwerror("Unsupported value for 'keepcollapsed', '%s'. Use 'true' or 'false'", value);
991  }
992  }
993  geosout = GEOSMakeValidWithParams(geosgeom, params);
994  GEOSMakeValidParams_destroy(params);
995  }
996 #endif
997  GEOSGeom_destroy(geosgeom);
998  if (!geosout) return NULL;
999 
1000  lwgeom_out = GEOS2LWGEOM(geosout, is3d);
1001  GEOSGeom_destroy(geosout);
1002 
1003  if (lwgeom_is_collection(lwgeom_in) && !lwgeom_is_collection(lwgeom_out))
1004  {
1005  LWGEOM** ogeoms = lwalloc(sizeof(LWGEOM*));
1006  LWGEOM* ogeom;
1007  LWDEBUG(3, "lwgeom_make_valid: forcing multi");
1008  /* NOTE: this is safe because lwgeom_out is surely not lwgeom_in or
1009  * otherwise we couldn't have a collection and a non-collection */
1010  assert(lwgeom_in != lwgeom_out);
1011  ogeoms[0] = lwgeom_out;
1012  ogeom = (LWGEOM*)lwcollection_construct(
1013  MULTITYPE[lwgeom_out->type], lwgeom_out->srid, lwgeom_out->bbox, 1, ogeoms);
1014  lwgeom_out->bbox = NULL;
1015  lwgeom_out = ogeom;
1016  }
1017 
1018  lwgeom_out->srid = lwgeom_in->srid;
1019  return lwgeom_out;
1020 }
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:1155
#define FLAGS_GET_Z(flags)
Definition: liblwgeom.h:165
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1097
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:354
#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
int value
Definition: genraster.py:62
const char * option_list_search(char **olist, const char *key)
Returns null if the key cannot be found.
Definition: optionlist.c:54
void option_list_parse(char *input, char **olist)
option_list is a null-terminated list of strings, where every odd string is a key and every even stri...
Definition: optionlist.c:86
#define OPTION_LIST_SIZE
Definition: optionlist.h:31
uint8_t type
Definition: liblwgeom.h:462
GBOX * bbox
Definition: liblwgeom.h:458
int32_t srid
Definition: liblwgeom.h:460

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, option_list_parse(), option_list_search(), OPTION_LIST_SIZE, LWGEOM::srid, LWGEOM::type, and genraster::value.

Referenced by lwgeom_make_valid(), and ST_MakeValid().

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