PostGIS  2.2.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 358 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().

359 {
360  LWCOLLECTION* out;
361  GEOSGeometry* g1;
362  GEOSGeometry* g2;
363  GEOSGeometry* g1_bounds;
364  GEOSGeometry* polygons;
365  const GEOSGeometry *vgeoms[1];
366  int i,n;
367  int hasZ = FLAGS_GET_Z(lwpoly_in->flags);
368 
369 
370  /* Possible outcomes:
371  *
372  * 1. The line does not split the polygon
373  * -> Return a collection with single element
374  * 2. The line does split the polygon
375  * -> Return a collection of all elements resulting from the split
376  */
377 
379 
380  g1 = LWGEOM2GEOS((LWGEOM*)lwpoly_in, 0);
381  if ( NULL == g1 )
382  {
383  lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
384  return NULL;
385  }
386  g1_bounds = GEOSBoundary(g1);
387  if ( NULL == g1_bounds )
388  {
389  GEOSGeom_destroy(g1);
390  lwerror("GEOSBoundary: %s", lwgeom_geos_errmsg);
391  return NULL;
392  }
393 
394  g2 = LWGEOM2GEOS((LWGEOM*)blade_in, 0);
395  if ( NULL == g2 )
396  {
397  GEOSGeom_destroy(g1);
398  GEOSGeom_destroy(g1_bounds);
399  lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
400  return NULL;
401  }
402 
403  vgeoms[0] = GEOSUnion(g1_bounds, g2);
404  if ( NULL == vgeoms[0] )
405  {
406  GEOSGeom_destroy(g1);
407  GEOSGeom_destroy(g2);
408  GEOSGeom_destroy(g1_bounds);
409  lwerror("GEOSUnion: %s", lwgeom_geos_errmsg);
410  return NULL;
411  }
412 
413  /* debugging..
414  lwnotice("Bounds poly: %s",
415  lwgeom_to_ewkt(GEOS2LWGEOM(g1_bounds, hasZ)));
416  lwnotice("Line: %s",
417  lwgeom_to_ewkt(GEOS2LWGEOM(g2, hasZ)));
418 
419  lwnotice("Noded bounds: %s",
420  lwgeom_to_ewkt(GEOS2LWGEOM(vgeoms[0], hasZ)));
421  */
422 
423  polygons = GEOSPolygonize(vgeoms, 1);
424  if ( NULL == polygons )
425  {
426  GEOSGeom_destroy(g1);
427  GEOSGeom_destroy(g2);
428  GEOSGeom_destroy(g1_bounds);
429  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
430  lwerror("GEOSPolygonize: %s", lwgeom_geos_errmsg);
431  return NULL;
432  }
433 
434 #if PARANOIA_LEVEL > 0
435  if ( GEOSGeometryTypeId(polygons) != COLLECTIONTYPE )
436  {
437  GEOSGeom_destroy(g1);
438  GEOSGeom_destroy(g2);
439  GEOSGeom_destroy(g1_bounds);
440  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
441  GEOSGeom_destroy(polygons);
442  lwerror("Unexpected return from GEOSpolygonize");
443  return 0;
444  }
445 #endif
446 
447  /* We should now have all polygons, just skip
448  * the ones which are in holes of the original
449  * geometries and return the rest in a collection
450  */
451  n = GEOSGetNumGeometries(polygons);
452  out = lwcollection_construct_empty(COLLECTIONTYPE, lwpoly_in->srid,
453  hasZ, 0);
454  /* Allocate space for all polys */
455  out->geoms = lwrealloc(out->geoms, sizeof(LWGEOM*)*n);
456  assert(0 == out->ngeoms);
457  for (i=0; i<n; ++i)
458  {
459  GEOSGeometry* pos; /* point on surface */
460  const GEOSGeometry* p = GEOSGetGeometryN(polygons, i);
461  int contains;
462 
463  pos = GEOSPointOnSurface(p);
464  if ( ! pos )
465  {
466  GEOSGeom_destroy(g1);
467  GEOSGeom_destroy(g2);
468  GEOSGeom_destroy(g1_bounds);
469  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
470  GEOSGeom_destroy(polygons);
471  lwerror("GEOSPointOnSurface: %s", lwgeom_geos_errmsg);
472  return NULL;
473  }
474 
475  contains = GEOSContains(g1, pos);
476  if ( 2 == contains )
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  GEOSGeom_destroy(pos);
484  lwerror("GEOSContains: %s", lwgeom_geos_errmsg);
485  return NULL;
486  }
487 
488  GEOSGeom_destroy(pos);
489 
490  if ( 0 == contains )
491  {
492  /* Original geometry doesn't contain
493  * a point in this ring, must be an hole
494  */
495  continue;
496  }
497 
498  out->geoms[out->ngeoms++] = GEOS2LWGEOM(p, hasZ);
499  }
500 
501  GEOSGeom_destroy(g1);
502  GEOSGeom_destroy(g2);
503  GEOSGeom_destroy(g1_bounds);
504  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
505  GEOSGeom_destroy(polygons);
506 
507  return (LWGEOM*)out;
508 }
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:493
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:124
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, int autofix)
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:207
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, char want3d)
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:81
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:74
#define COLLECTIONTYPE
Definition: liblwgeom.h:76
Here is the call graph for this function:
Here is the caller graph for this function: