PostGIS  2.2.8dev-r@@SVN_REVISION@@

◆ LWGEOM_GEOS_makeValid()

static GEOSGeometry * LWGEOM_GEOS_makeValid ( const GEOSGeometry *  gin)
static

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

References GEOS2LWGEOM(), LWDEBUGF, lwerror(), lwgeom_geos_errmsg, LWGEOM_GEOS_makeValidCollection(), LWGEOM_GEOS_makeValidLine(), LWGEOM_GEOS_makeValidMultiLine(), LWGEOM_GEOS_makeValidPolygon(), lwgeom_to_ewkt(), and lwnotice().

Referenced by LWGEOM_GEOS_makeValidCollection(), LWGEOM_GEOS_makeValidMultiLine(), and lwgeom_make_valid().

853 {
854  GEOSGeometry* gout;
855  char ret_char;
856 
857  /*
858  * Step 2: return what we got so far if already valid
859  */
860 
861  ret_char = GEOSisValid(gin);
862  if ( ret_char == 2 )
863  {
864  /* I don't think should ever happen */
865  lwerror("GEOSisValid(): %s", lwgeom_geos_errmsg);
866  return NULL;
867  }
868  else if ( ret_char )
869  {
870  LWDEBUGF(3,
871  "Geometry [%s] is valid. ",
872  lwgeom_to_ewkt(GEOS2LWGEOM(gin, 0)));
873 
874  /* It's valid at this step, return what we have */
875  return GEOSGeom_clone(gin);
876  }
877 
878  LWDEBUGF(3,
879  "Geometry [%s] is still not valid: %s. "
880  "Will try to clean up further.",
882 
883 
884 
885  /*
886  * Step 3 : make what we got valid
887  */
888 
889  switch (GEOSGeomTypeId(gin))
890  {
891  case GEOS_MULTIPOINT:
892  case GEOS_POINT:
893  /* points are always valid, but we might have invalid ordinate values */
894  lwnotice("PUNTUAL geometry resulted invalid to GEOS -- dunno how to clean that up");
895  return NULL;
896  break;
897 
898  case GEOS_LINESTRING:
899  gout = LWGEOM_GEOS_makeValidLine(gin);
900  if ( ! gout ) /* an exception or something */
901  {
902  /* cleanup and throw */
904  return NULL;
905  }
906  break; /* we've done */
907 
908  case GEOS_MULTILINESTRING:
909  gout = LWGEOM_GEOS_makeValidMultiLine(gin);
910  if ( ! gout ) /* an exception or something */
911  {
912  /* cleanup and throw */
914  return NULL;
915  }
916  break; /* we've done */
917 
918  case GEOS_POLYGON:
919  case GEOS_MULTIPOLYGON:
920  {
921  gout = LWGEOM_GEOS_makeValidPolygon(gin);
922  if ( ! gout ) /* an exception or something */
923  {
924  /* cleanup and throw */
926  return NULL;
927  }
928  break; /* we've done */
929  }
930 
931  case GEOS_GEOMETRYCOLLECTION:
932  {
934  if ( ! gout ) /* an exception or something */
935  {
936  /* cleanup and throw */
938  return NULL;
939  }
940  break; /* we've done */
941  }
942 
943  default:
944  {
945  char* typname = GEOSGeomType(gin);
946  lwnotice("ST_MakeValid: doesn't support geometry type: %s",
947  typname);
948  GEOSFree(typname);
949  return NULL;
950  break;
951  }
952  }
953 
954  /*
955  * Now check if every point of input is also found
956  * in output, or abort by returning NULL
957  *
958  * Input geometry was lwgeom_in
959  */
960  {
961  const int paranoia = 2;
962  /* TODO: check if the result is valid */
963  if (paranoia)
964  {
965  int loss;
966  GEOSGeometry *pi, *po, *pd;
967 
968  /* TODO: handle some errors here...
969  * Lack of exceptions is annoying indeed,
970  * I'm getting old --strk;
971  */
972  pi = GEOSGeom_extractUniquePoints(gin);
973  po = GEOSGeom_extractUniquePoints(gout);
974  pd = GEOSDifference(pi, po); /* input points - output points */
975  GEOSGeom_destroy(pi);
976  GEOSGeom_destroy(po);
977  loss = !GEOSisEmpty(pd);
978  GEOSGeom_destroy(pd);
979  if ( loss )
980  {
981  lwnotice("Vertices lost in LWGEOM_GEOS_makeValid");
982  /* return NULL */
983  }
984  }
985  }
986 
987 
988  return gout;
989 }
static GEOSGeometry * LWGEOM_GEOS_makeValidPolygon(const GEOSGeometry *gin)
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:61
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
Definition: lwgeom.c:469
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
static GEOSGeometry * LWGEOM_GEOS_makeValidLine(const GEOSGeometry *gin)
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, char want3d)
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55
static GEOSGeometry * LWGEOM_GEOS_makeValidMultiLine(const GEOSGeometry *gin)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:74
static GEOSGeometry * LWGEOM_GEOS_makeValidCollection(const GEOSGeometry *gin)
Here is the call graph for this function:
Here is the caller graph for this function: