PostGIS  2.1.10dev-r@@SVN_REVISION@@
static LWGEOM * lwpoly_split_by_line ( const LWPOLY lwgeom_in,
const LWLINE blade_in 
)
static

Definition at line 243 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 LWPOLY::srid.

Referenced by lwpoly_split().

244 {
245  LWCOLLECTION* out;
246  GEOSGeometry* g1;
247  GEOSGeometry* g2;
248  GEOSGeometry* g1_bounds;
249  GEOSGeometry* polygons;
250  const GEOSGeometry *vgeoms[1];
251  int i,n;
252  int hasZ = FLAGS_GET_Z(lwpoly_in->flags);
253 
254 
255  /* Possible outcomes:
256  *
257  * 1. The line does not split the polygon
258  * -> Return a collection with single element
259  * 2. The line does split the polygon
260  * -> Return a collection of all elements resulting from the split
261  */
262 
264 
265  g1 = LWGEOM2GEOS((LWGEOM*)lwpoly_in);
266  if ( NULL == g1 )
267  {
268  lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
269  return NULL;
270  }
271  g1_bounds = GEOSBoundary(g1);
272  if ( NULL == g1_bounds )
273  {
274  GEOSGeom_destroy(g1);
275  lwerror("GEOSBoundary: %s", lwgeom_geos_errmsg);
276  return NULL;
277  }
278 
279  g2 = LWGEOM2GEOS((LWGEOM*)blade_in);
280  if ( NULL == g2 )
281  {
282  GEOSGeom_destroy(g1);
283  GEOSGeom_destroy(g1_bounds);
284  lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
285  return NULL;
286  }
287 
288  vgeoms[0] = GEOSUnion(g1_bounds, g2);
289  if ( NULL == vgeoms[0] )
290  {
291  GEOSGeom_destroy(g1);
292  GEOSGeom_destroy(g2);
293  GEOSGeom_destroy(g1_bounds);
294  lwerror("GEOSUnion: %s", lwgeom_geos_errmsg);
295  return NULL;
296  }
297 
298  /* debugging..
299  lwnotice("Bounds poly: %s",
300  lwgeom_to_ewkt(GEOS2LWGEOM(g1_bounds, hasZ)));
301  lwnotice("Line: %s",
302  lwgeom_to_ewkt(GEOS2LWGEOM(g2, hasZ)));
303 
304  lwnotice("Noded bounds: %s",
305  lwgeom_to_ewkt(GEOS2LWGEOM(vgeoms[0], hasZ)));
306  */
307 
308  polygons = GEOSPolygonize(vgeoms, 1);
309  if ( NULL == polygons )
310  {
311  GEOSGeom_destroy(g1);
312  GEOSGeom_destroy(g2);
313  GEOSGeom_destroy(g1_bounds);
314  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
315  lwerror("GEOSPolygonize: %s", lwgeom_geos_errmsg);
316  return NULL;
317  }
318 
319 #if PARANOIA_LEVEL > 0
320  if ( GEOSGeometryTypeId(polygons) != COLLECTIONTYPE )
321  {
322  GEOSGeom_destroy(g1);
323  GEOSGeom_destroy(g2);
324  GEOSGeom_destroy(g1_bounds);
325  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
326  GEOSGeom_destroy(polygons);
327  lwerror("Unexpected return from GEOSpolygonize");
328  return 0;
329  }
330 #endif
331 
332  /* We should now have all polygons, just skip
333  * the ones which are in holes of the original
334  * geometries and return the rest in a collection
335  */
336  n = GEOSGetNumGeometries(polygons);
337  out = lwcollection_construct_empty(COLLECTIONTYPE, lwpoly_in->srid,
338  hasZ, 0);
339  /* Allocate space for all polys */
340  out->geoms = lwrealloc(out->geoms, sizeof(LWGEOM*)*n);
341  assert(0 == out->ngeoms);
342  for (i=0; i<n; ++i)
343  {
344  GEOSGeometry* pos; /* point on surface */
345  const GEOSGeometry* p = GEOSGetGeometryN(polygons, i);
346  int contains;
347 
348  pos = GEOSPointOnSurface(p);
349  if ( ! pos )
350  {
351  GEOSGeom_destroy(g1);
352  GEOSGeom_destroy(g2);
353  GEOSGeom_destroy(g1_bounds);
354  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
355  GEOSGeom_destroy(polygons);
356  lwerror("GEOSPointOnSurface: %s", lwgeom_geos_errmsg);
357  return NULL;
358  }
359 
360  contains = GEOSContains(g1, pos);
361  if ( 2 == contains )
362  {
363  GEOSGeom_destroy(g1);
364  GEOSGeom_destroy(g2);
365  GEOSGeom_destroy(g1_bounds);
366  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
367  GEOSGeom_destroy(polygons);
368  GEOSGeom_destroy(pos);
369  lwerror("GEOSContains: %s", lwgeom_geos_errmsg);
370  return NULL;
371  }
372 
373  GEOSGeom_destroy(pos);
374 
375  if ( 0 == contains )
376  {
377  /* Original geometry doesn't contain
378  * a point in this ring, must be an hole
379  */
380  continue;
381  }
382 
383  out->geoms[out->ngeoms++] = GEOS2LWGEOM(p, hasZ);
384  }
385 
386  GEOSGeom_destroy(g1);
387  GEOSGeom_destroy(g2);
388  GEOSGeom_destroy(g1_bounds);
389  GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
390  GEOSGeom_destroy(polygons);
391 
392  return (LWGEOM*)out;
393 }
Datum contains(PG_FUNCTION_ARGS)
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
void lwgeom_geos_error(const char *fmt,...)
LWGEOM ** geoms
Definition: liblwgeom.h:465
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:106
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:183
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, char want3d)
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:81
#define COLLECTIONTYPE
Definition: liblwgeom.h:66

Here is the call graph for this function:

Here is the caller graph for this function: