char *msudf_boundary(UDF_INIT *initid,UDF_ARGS *args, char *buf, unsigned long *length, char *is_null, char *error) { char *result; GEOSGeom geom1,geom2; DEBUG("msudf_boundary"); geom1 = msudf_getGeometry((unsigned char *)args->args[0],args->lengths[0]); if (geom1 == NULL) { strcpy(error,"Invalid geometry."); *is_null = 1; return NULL; } geom2 = GEOSBoundary(geom1); if (geom2 != NULL) { GEOSSetSRID(geom2,GEOSGetSRID(geom1)); result = msudf_returnGeometry(initid,length,geom2); GEOSGeom_destroy(geom1); GEOSGeom_destroy(geom2); return result; } else { GEOSGeom_destroy(geom1); *is_null = 1; return NULL; } }
shapeObj *msGEOSBoundary(shapeObj *shape) { #ifdef USE_GEOS GEOSGeom g1, g2; if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSBoundary(g1); return msGEOSGeometry2Shape(g2); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSBoundary()"); return NULL; #endif }
/* Initializes and uses GEOS internally */ static LWGEOM* lwline_split_by_line(const LWLINE* lwline_in, const LWGEOM* blade_in) { LWGEOM** components; LWGEOM* diff; LWCOLLECTION* out; GEOSGeometry* gdiff; /* difference */ GEOSGeometry* g1; GEOSGeometry* g2; int ret; /* ASSERT blade_in is LINE or MULTILINE */ assert (blade_in->type == LINETYPE || blade_in->type == MULTILINETYPE || blade_in->type == POLYGONTYPE || blade_in->type == MULTIPOLYGONTYPE ); /* Possible outcomes: * * 1. The lines do not cross or overlap * -> Return a collection with single element * 2. The lines cross * -> Return a collection of all elements resulting from the split */ initGEOS(lwgeom_geos_error, lwgeom_geos_error); g1 = LWGEOM2GEOS((LWGEOM*)lwline_in, 0); if ( ! g1 ) { lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg); return NULL; } g2 = LWGEOM2GEOS(blade_in, 0); if ( ! g2 ) { GEOSGeom_destroy(g1); lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg); return NULL; } /* If blade is a polygon, pick its boundary */ if ( blade_in->type == POLYGONTYPE || blade_in->type == MULTIPOLYGONTYPE ) { gdiff = GEOSBoundary(g2); GEOSGeom_destroy(g2); if ( ! gdiff ) { GEOSGeom_destroy(g1); lwerror("GEOSBoundary: %s", lwgeom_geos_errmsg); return NULL; } g2 = gdiff; gdiff = NULL; } /* If interior intersecton is linear we can't split */ ret = GEOSRelatePattern(g1, g2, "1********"); if ( 2 == ret ) { lwerror("GEOSRelatePattern: %s", lwgeom_geos_errmsg); GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); return NULL; } if ( ret ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); lwerror("Splitter line has linear intersection with input"); return NULL; } gdiff = GEOSDifference(g1,g2); GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); if (gdiff == NULL) { lwerror("GEOSDifference: %s", lwgeom_geos_errmsg); return NULL; } diff = GEOS2LWGEOM(gdiff, FLAGS_GET_Z(lwline_in->flags)); GEOSGeom_destroy(gdiff); if (NULL == diff) { lwerror("GEOS2LWGEOM: %s", lwgeom_geos_errmsg); return NULL; } out = lwgeom_as_lwcollection(diff); if ( ! out ) { components = lwalloc(sizeof(LWGEOM*)*1); components[0] = diff; out = lwcollection_construct(COLLECTIONTYPE, lwline_in->srid, NULL, 1, components); } else { /* Set SRID */ lwgeom_set_srid((LWGEOM*)out, lwline_in->srid); /* Force collection type */ out->type = COLLECTIONTYPE; } return (LWGEOM*)out; }
/* Initializes and uses GEOS internally */ static LWGEOM* lwpoly_split_by_line(const LWPOLY* lwpoly_in, const LWLINE* blade_in) { LWCOLLECTION* out; GEOSGeometry* g1; GEOSGeometry* g2; GEOSGeometry* g1_bounds; GEOSGeometry* polygons; const GEOSGeometry *vgeoms[1]; int i,n; int hasZ = FLAGS_GET_Z(lwpoly_in->flags); /* Possible outcomes: * * 1. The line does not split the polygon * -> Return a collection with single element * 2. The line does split the polygon * -> Return a collection of all elements resulting from the split */ initGEOS(lwgeom_geos_error, lwgeom_geos_error); g1 = LWGEOM2GEOS((LWGEOM*)lwpoly_in, 0); if ( NULL == g1 ) { lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg); return NULL; } g1_bounds = GEOSBoundary(g1); if ( NULL == g1_bounds ) { GEOSGeom_destroy(g1); lwerror("GEOSBoundary: %s", lwgeom_geos_errmsg); return NULL; } g2 = LWGEOM2GEOS((LWGEOM*)blade_in, 0); if ( NULL == g2 ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g1_bounds); lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg); return NULL; } vgeoms[0] = GEOSUnion(g1_bounds, g2); if ( NULL == vgeoms[0] ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g1_bounds); lwerror("GEOSUnion: %s", lwgeom_geos_errmsg); return NULL; } polygons = GEOSPolygonize(vgeoms, 1); if ( NULL == polygons ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g1_bounds); GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]); lwerror("GEOSPolygonize: %s", lwgeom_geos_errmsg); return NULL; } #if PARANOIA_LEVEL > 0 if ( GEOSGeomTypeId(polygons) != COLLECTIONTYPE ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g1_bounds); GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]); GEOSGeom_destroy(polygons); lwerror("%s [%s] Unexpected return from GEOSpolygonize", __FILE__, __LINE__); return 0; } #endif /* We should now have all polygons, just skip * the ones which are in holes of the original * geometries and return the rest in a collection */ n = GEOSGetNumGeometries(polygons); out = lwcollection_construct_empty(COLLECTIONTYPE, lwpoly_in->srid, hasZ, 0); /* Allocate space for all polys */ out->geoms = lwrealloc(out->geoms, sizeof(LWGEOM*)*n); assert(0 == out->ngeoms); for (i=0; i<n; ++i) { GEOSGeometry* pos; /* point on surface */ const GEOSGeometry* p = GEOSGetGeometryN(polygons, i); int contains; pos = GEOSPointOnSurface(p); if ( ! pos ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g1_bounds); GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]); GEOSGeom_destroy(polygons); lwerror("GEOSPointOnSurface: %s", lwgeom_geos_errmsg); return NULL; } contains = GEOSContains(g1, pos); if ( 2 == contains ) { GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g1_bounds); GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]); GEOSGeom_destroy(polygons); GEOSGeom_destroy(pos); lwerror("GEOSContains: %s", lwgeom_geos_errmsg); return NULL; } GEOSGeom_destroy(pos); if ( 0 == contains ) { /* Original geometry doesn't contain * a point in this ring, must be an hole */ continue; } out->geoms[out->ngeoms++] = GEOS2LWGEOM(p, hasZ); } GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); GEOSGeom_destroy(g1_bounds); GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]); GEOSGeom_destroy(polygons); return (LWGEOM*)out; }