PostGIS  2.3.8dev-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  /* debugging..
401  lwnotice("Bounds poly: %s",
402  lwgeom_to_ewkt(GEOS2LWGEOM(g1_bounds, hasZ)));
403  lwnotice("Line: %s",
404  lwgeom_to_ewkt(GEOS2LWGEOM(g2, hasZ)));
405 
406  lwnotice("Noded bounds: %s",
407  lwgeom_to_ewkt(GEOS2LWGEOM(vgeoms[0], hasZ)));
408  */
409 
410  polygons = GEOSPolygonize(vgeoms, 1);
411  if ( NULL == polygons )
412  {
413  GEOSGeom_destroy(g1);
414  GEOSGeom_destroy(g2);
415  GEOSGeom_destroy(g1_bounds);
416  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
417  lwerror("GEOSPolygonize: %s", lwgeom_geos_errmsg);
418  return NULL;
419  }
420 
421 #if PARANOIA_LEVEL > 0
422  if ( GEOSGeometryTypeId(polygons) != COLLECTIONTYPE )
423  {
424  GEOSGeom_destroy(g1);
425  GEOSGeom_destroy(g2);
426  GEOSGeom_destroy(g1_bounds);
427  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
428  GEOSGeom_destroy(polygons);
429  lwerror("Unexpected return from GEOSpolygonize");
430  return 0;
431  }
432 #endif
433 
434  /* We should now have all polygons, just skip
435  * the ones which are in holes of the original
436  * geometries and return the rest in a collection
437  */
438  n = GEOSGetNumGeometries(polygons);
439  out = lwcollection_construct_empty(COLLECTIONTYPE, lwpoly_in->srid,
440  hasZ, 0);
441  /* Allocate space for all polys */
442  out->geoms = lwrealloc(out->geoms, sizeof(LWGEOM*)*n);
443  assert(0 == out->ngeoms);
444  for (i=0; i<n; ++i)
445  {
446  GEOSGeometry* pos; /* point on surface */
447  const GEOSGeometry* p = GEOSGetGeometryN(polygons, i);
448  int contains;
449 
450  pos = GEOSPointOnSurface(p);
451  if ( ! pos )
452  {
453  GEOSGeom_destroy(g1);
454  GEOSGeom_destroy(g2);
455  GEOSGeom_destroy(g1_bounds);
456  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
457  GEOSGeom_destroy(polygons);
458  lwerror("GEOSPointOnSurface: %s", lwgeom_geos_errmsg);
459  return NULL;
460  }
461 
462  contains = GEOSContains(g1, pos);
463  if ( 2 == contains )
464  {
465  GEOSGeom_destroy(g1);
466  GEOSGeom_destroy(g2);
467  GEOSGeom_destroy(g1_bounds);
468  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
469  GEOSGeom_destroy(polygons);
470  GEOSGeom_destroy(pos);
471  lwerror("GEOSContains: %s", lwgeom_geos_errmsg);
472  return NULL;
473  }
474 
475  GEOSGeom_destroy(pos);
476 
477  if ( 0 == contains )
478  {
479  /* Original geometry doesn't contain
480  * a point in this ring, must be an hole
481  */
482  continue;
483  }
484 
485  out->geoms[out->ngeoms++] = GEOS2LWGEOM(p, hasZ);
486  }
487 
488  GEOSGeom_destroy(g1);
489  GEOSGeom_destroy(g2);
490  GEOSGeom_destroy(g1_bounds);
491  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
492  GEOSGeom_destroy(polygons);
493 
494  return (LWGEOM*)out;
495 }
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:508
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:139
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, int autofix)
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:235
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:102
#define COLLECTIONTYPE
Definition: liblwgeom.h:90
Here is the call graph for this function:
Here is the caller graph for this function: