PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ lwpoly_split_by_line()

static LWGEOM * lwpoly_split_by_line ( const LWPOLY lwgeom_in,
const LWLINE blade_in 
)
static

Definition at line 345 of file lwgeom_geos_split.c.

References COLLECTIONTYPE, contains(), LWPOLY::flags, FLAGS_GET_Z, LWCOLLECTION::geoms, GEOS2LWGEOM(), lwcollection_construct_empty(), lwerror(), LWGEOM2GEOS(), lwgeom_geos_errmsg, lwgeom_geos_error(), lwrealloc(), LWCOLLECTION::ngeoms, and LWGEOM::srid.

Referenced by lwpoly_split().

346 {
347  LWCOLLECTION* out;
348  GEOSGeometry* g1;
349  GEOSGeometry* g2;
350  GEOSGeometry* g1_bounds;
351  GEOSGeometry* polygons;
352  const GEOSGeometry *vgeoms[1];
353  int i,n;
354  int hasZ = FLAGS_GET_Z(lwpoly_in->flags);
355 
356 
357  /* Possible outcomes:
358  *
359  * 1. The line does not split the polygon
360  * -> Return a collection with single element
361  * 2. The line does split the polygon
362  * -> Return a collection of all elements resulting from the split
363  */
364 
366 
367  g1 = LWGEOM2GEOS((LWGEOM*)lwpoly_in, 0);
368  if ( NULL == g1 )
369  {
370  lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
371  return NULL;
372  }
373  g1_bounds = GEOSBoundary(g1);
374  if ( NULL == g1_bounds )
375  {
376  GEOSGeom_destroy(g1);
377  lwerror("GEOSBoundary: %s", lwgeom_geos_errmsg);
378  return NULL;
379  }
380 
381  g2 = LWGEOM2GEOS((LWGEOM*)blade_in, 0);
382  if ( NULL == g2 )
383  {
384  GEOSGeom_destroy(g1);
385  GEOSGeom_destroy(g1_bounds);
386  lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
387  return NULL;
388  }
389 
390  vgeoms[0] = GEOSUnion(g1_bounds, g2);
391  if ( NULL == vgeoms[0] )
392  {
393  GEOSGeom_destroy(g1);
394  GEOSGeom_destroy(g2);
395  GEOSGeom_destroy(g1_bounds);
396  lwerror("GEOSUnion: %s", lwgeom_geos_errmsg);
397  return NULL;
398  }
399 
400  polygons = GEOSPolygonize(vgeoms, 1);
401  if ( NULL == polygons )
402  {
403  GEOSGeom_destroy(g1);
404  GEOSGeom_destroy(g2);
405  GEOSGeom_destroy(g1_bounds);
406  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
407  lwerror("GEOSPolygonize: %s", lwgeom_geos_errmsg);
408  return NULL;
409  }
410 
411 #if PARANOIA_LEVEL > 0
412  if ( GEOSGeomTypeId(polygons) != COLLECTIONTYPE )
413  {
414  GEOSGeom_destroy(g1);
415  GEOSGeom_destroy(g2);
416  GEOSGeom_destroy(g1_bounds);
417  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
418  GEOSGeom_destroy(polygons);
419  lwerror("%s [%s] Unexpected return from GEOSpolygonize", __FILE__, __LINE__);
420  return 0;
421  }
422 #endif
423 
424  /* We should now have all polygons, just skip
425  * the ones which are in holes of the original
426  * geometries and return the rest in a collection
427  */
428  n = GEOSGetNumGeometries(polygons);
429  out = lwcollection_construct_empty(COLLECTIONTYPE, lwpoly_in->srid,
430  hasZ, 0);
431  /* Allocate space for all polys */
432  out->geoms = lwrealloc(out->geoms, sizeof(LWGEOM*)*n);
433  assert(0 == out->ngeoms);
434  for (i=0; i<n; ++i)
435  {
436  GEOSGeometry* pos; /* point on surface */
437  const GEOSGeometry* p = GEOSGetGeometryN(polygons, i);
438  int contains;
439 
440  pos = GEOSPointOnSurface(p);
441  if ( ! pos )
442  {
443  GEOSGeom_destroy(g1);
444  GEOSGeom_destroy(g2);
445  GEOSGeom_destroy(g1_bounds);
446  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
447  GEOSGeom_destroy(polygons);
448  lwerror("GEOSPointOnSurface: %s", lwgeom_geos_errmsg);
449  return NULL;
450  }
451 
452  contains = GEOSContains(g1, pos);
453  if ( 2 == contains )
454  {
455  GEOSGeom_destroy(g1);
456  GEOSGeom_destroy(g2);
457  GEOSGeom_destroy(g1_bounds);
458  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
459  GEOSGeom_destroy(polygons);
460  GEOSGeom_destroy(pos);
461  lwerror("GEOSContains: %s", lwgeom_geos_errmsg);
462  return NULL;
463  }
464 
465  GEOSGeom_destroy(pos);
466 
467  if ( 0 == contains )
468  {
469  /* Original geometry doesn't contain
470  * a point in this ring, must be an hole
471  */
472  continue;
473  }
474 
475  out->geoms[out->ngeoms++] = GEOS2LWGEOM(p, hasZ);
476  }
477 
478  GEOSGeom_destroy(g1);
479  GEOSGeom_destroy(g2);
480  GEOSGeom_destroy(g1_bounds);
481  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
482  GEOSGeom_destroy(polygons);
483 
484  return (LWGEOM*)out;
485 }
Datum contains(PG_FUNCTION_ARGS)
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
void lwgeom_geos_error(const char *fmt,...)
LWGEOM ** geoms
Definition: liblwgeom.h:509
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:140
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, int autofix)
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:237
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, char want3d)
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:94
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
#define COLLECTIONTYPE
Definition: liblwgeom.h:91
Here is the call graph for this function:
Here is the caller graph for this function: