/* ** Does shape1 contain shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSContains(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = shape2->geometry; if(!g2) return -1; result = GEOSContains(g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSContains()"); return -1; #endif }
long long msudf_contains(UDF_INIT *initid,UDF_ARGS *args,char *is_null, char *error) { GEOSGeom geom1,geom2; long long result; DEBUG("msudf_contains"); geom1 = msudf_getGeometry((unsigned char *)args->args[0],args->lengths[0]); if (geom1 == NULL) { strcpy(error,"Invalid geometry."); *is_null = 1; return 0; } geom2 = msudf_getGeometry((unsigned char *)args->args[1],args->lengths[1]); if (geom2 == NULL) { strcpy(error,"Invalid geometry."); *is_null = 1; return 0; } result = GEOSContains(geom1,geom2); if (geom1 != NULL) GEOSGeom_destroy(geom1); if (geom2 != NULL) GEOSGeom_destroy(geom2); if (result >1) { *is_null = 1; return 0; } else { return result; } }
/* 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; }
Datum containsPrepared(PG_FUNCTION_ARGS) { #ifndef PREPARED_GEOM elog(ERROR,"Not implemented in this version!"); PG_RETURN_NULL(); #else PG_LWGEOM * geom1; PG_LWGEOM * geom2; bool result; BOX2DFLOAT4 box1, box2; PrepGeomCache * prep_cache; int32 key1; geom1 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); geom2 = (PG_LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); key1 = PG_GETARG_INT32(2); errorIfGeometryCollection(geom1,geom2); errorIfSRIDMismatch(pglwgeom_getSRID(geom1), pglwgeom_getSRID(geom2)); POSTGIS_DEBUG(3, "containsPrepared: entered function"); /* * short-circuit: if geom2 bounding box is not completely inside * geom1 bounding box we can prematurely return FALSE. * Do the test IFF BOUNDING BOX AVAILABLE. */ if ( getbox2d_p(SERIALIZED_FORM(geom1), &box1) && getbox2d_p(SERIALIZED_FORM(geom2), &box2) ) { if (( box2.xmin < box1.xmin ) || ( box2.xmax > box1.xmax ) || ( box2.ymin < box1.ymin ) || ( box2.ymax > box1.ymax )) PG_RETURN_BOOL(FALSE); } prep_cache = GetPrepGeomCache( fcinfo, geom1, 0 ); initGEOS(lwnotice, lwnotice); if ( prep_cache && prep_cache->prepared_geom && prep_cache->argnum == 1 ) { GEOSGeom g = POSTGIS2GEOS(geom2); POSTGIS_DEBUG(4, "containsPrepared: cache is live, running preparedcontains"); result = GEOSPreparedContains( prep_cache->prepared_geom, g); GEOSGeom_destroy(g); } else { GEOSGeom g1 = POSTGIS2GEOS(geom1); GEOSGeom g2 = POSTGIS2GEOS(geom2); POSTGIS_DEBUG(4, "containsPrepared: cache is not ready, running standard contains"); result = GEOSContains( g1, g2); GEOSGeom_destroy(g1); GEOSGeom_destroy(g2); } if (result == 2) { elog(ERROR,"GEOS contains() threw an error!"); PG_RETURN_NULL(); /* never get here */ } PG_FREE_IF_COPY(geom1, 0); PG_FREE_IF_COPY(geom2, 1); PG_RETURN_BOOL(result); #endif /* PREPARED_GEOM */ }