Changeset: 6bb5b00199e2 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=6bb5b00199e2
Modified Files:
geom/monetdb5/geom.c
geom/monetdb5/geom.h
geom/monetdb5/geom.mal
geom/sql/40_geom.sql
Branch: sfcgal
Log Message:
Add filterJoin for ST_intersect, with it we avoid the materialization of a
cross product followed by a ST_Intersects on each pair. Instead of using
wkbIntersects per each pair of geometries directly we opened the function and
adjusted to the nested loop. Like this we avoid multiple wkb2geos, and vice
verse, which is a expensive computation. We also check of the geometries mbr
orvalap before checking if they intersect.
diffs (213 lines):
diff --git a/geom/monetdb5/geom.c b/geom/monetdb5/geom.c
--- a/geom/monetdb5/geom.c
+++ b/geom/monetdb5/geom.c
@@ -6571,3 +6571,172 @@ wkbPatchToGeom_bat(wkb **res, wkb **geom
(void) pz;
return MAL_SUCCEED;
}
+
+static str
+Intersectssubjoin_intern(bat *lres, bat *rres, bat *lid, bat *rid)
+{
+ BAT *xl, *xr, *bl, *br;
+ oid lo, ro;
+ BATiter lBAT_iter, rBAT_iter;
+ uint32_t i = 0, j = 0;
+ int count = 0;
+ //struct timeval stop, start;
+ GEOSGeom *rGeometries = NULL;
+
+ if( (bl= BATdescriptor(*lid)) == NULL )
+ throw(MAL, "algebra.instersects", RUNTIME_OBJECT_MISSING);
+
+ if( (br= BATdescriptor(*rid)) == NULL ){
+ BBPunfix(*lid);
+ throw(MAL, "algebra.instersects", RUNTIME_OBJECT_MISSING);
+ }
+
+ xl = BATnew(TYPE_void, TYPE_oid, MIN(BATcount(bl), BATcount(br)),
TRANSIENT);
+ if ( xl == NULL){
+ BBPunfix(*lid);
+ BBPunfix(*rid);
+ throw(MAL, "algebra.instersects", MAL_MALLOC_FAIL);
+ }
+ BATseqbase(xl,0);
+
+ xr = BATnew(TYPE_void, TYPE_oid, MIN(BATcount(bl), BATcount(br)),
TRANSIENT);
+ if ( xr == NULL){
+ BBPunfix(*lid);
+ BBPunfix(*rid);
+ BBPunfix(xl->batCacheid);
+ throw(MAL, "algebra.instersects", MAL_MALLOC_FAIL);
+ }
+ BATseqbase(xr,0);
+
+ /*iterator over the BATs*/
+ lBAT_iter = bat_iterator(bl);
+ rBAT_iter = bat_iterator(br);
+ lo = BUNfirst(bl);
+
+ printf ("BATcount %d %d\n", (int) BATcount(bl), (int) BATcount(br));
+
+ /*Get the Geometry for the inner BAT*/
+ rGeometries = (GEOSGeom*) GDKmalloc(sizeof(GEOSGeom) * BATcount(br));
+ ro = BUNfirst(br);
+ for (j = 0; j < BATcount(br); j++, ro++) {
+ wkb *rWKB = (wkb *) BUNtail(rBAT_iter, ro);
+ rGeometries[j] = wkb2geos(rWKB);
+ }
+
+ for (i = 0; i < BATcount(bl); i++, lo++) {
+ str err = NULL;
+ wkb *lWKB = NULL;
+ mbr *lMBR = NULL;
+ GEOSGeom lGeometry = NULL;
+ ro = BUNfirst(br);
+
+ //lWKB = (wkb *) BUNtail(lBAT_iter, i + BUNfirst(bl));
+ lWKB = (wkb *) BUNtail(lBAT_iter, lo);
+ lGeometry = wkb2geos(lWKB);
+
+ lMBR = mbrFromGeos(lGeometry);
+ if (lMBR == NULL || mbr_isnil(lMBR)) {
+ BBPunfix(*lid);
+ BBPunfix(*rid);
+ BBPunfix(xl->batCacheid);
+ BBPunfix(xr->batCacheid);
+ return err;
+ }
+
+ // gettimeofday(&start, NULL);
+ for (j = 0; j < BATcount(br); j++, ro++) {
+ bit out = 0;
+ mbr *rMBR = NULL;
+ GEOSGeom rGeometry = rGeometries[j];
+ //rWKB = (wkb *) BUNtail(rBAT_iter, j + BUNfirst(br));
+
+ if (!lGeometry ||!rGeometry) {
+ if (lGeometry)
+ GEOSGeom_destroy(lGeometry);
+ if (rGeometry)
+ GEOSGeom_destroy(rGeometry);
+ BBPunfix(*lid);
+ BBPunfix(*rid);
+ BBPunfix(xl->batCacheid);
+ BBPunfix(xr->batCacheid);
+ throw(MAL, "geom.Intersects", "wkb2geos failed");
+ }
+
+ if (GEOSGetSRID(lGeometry) != GEOSGetSRID(rGeometry)) {
+ GEOSGeom_destroy(lGeometry);
+ GEOSGeom_destroy(rGeometry);
+ throw(MAL, "geom.Intersects", "Geometries of different SRID");
+ }
+
+ rMBR = mbrFromGeos(rGeometry);
+ if (rMBR == NULL || mbr_isnil(rMBR)) {
+ BBPunfix(*lid);
+ BBPunfix(*rid);
+ BBPunfix(xl->batCacheid);
+ BBPunfix(xr->batCacheid);
+ return err;
+ }
+
+ err = mbrOverlaps(&out, &lMBR, &rMBR);
+ if (err != MAL_SUCCEED) {
+ BBPunfix(*lid);
+ BBPunfix(*rid);
+ BBPunfix(xl->batCacheid);
+ BBPunfix(xr->batCacheid);
+ return err;
+ } else if (out) {
+
+ count++;
+ if ((out = GEOSIntersects(lGeometry, rGeometry)) == 2){
+ GEOSGeom_destroy(lGeometry);
+ GEOSGeom_destroy(rGeometry);
+ throw(MAL, "geom.Contains", "GEOSIntersects
failed");
+ }
+
+ /*
+ err = wkbIntersects(&out, &lWKB, &rWKB);
+ if (err != MAL_SUCCEED) {
+ BBPunfix(*lid);
+ BBPunfix(*rid);
+ BBPunfix(xl->batCacheid);
+ BBPunfix(xr->batCacheid);
+ return err;
+ }
+ */
+ if (out) {
+ BUNappend(xl, &lo, FALSE);
+ BUNappend(xr, &ro, FALSE);
+ }
+ }
+ GDKfree(rMBR);
+ }
+ if (lGeometry)
+ GEOSGeom_destroy(lGeometry);
+ GDKfree(lMBR);
+
+ //gettimeofday(&stop, NULL);
+ //printf("took %lu\n", stop.tv_usec - start.tv_usec);
+ }
+ if (rGeometries) {
+ for (j = 0; j < BATcount(br);j++) {
+ GEOSGeom_destroy(rGeometries[j]);
+ }
+ GDKfree(rGeometries);
+ }
+ BBPunfix(*lid);
+ BBPunfix(*rid);
+ BBPkeepref(*lres = xl->batCacheid);
+ BBPkeepref(*rres = xr->batCacheid);
+ return MAL_SUCCEED;
+}
+
+str
+Intersectssubjoin(bat *lres, bat *rres, bat *lid, bat *rid, bat *sl, bat *sr,
bit *nil_matches, lng *estimate)
+{
+ (void)sl;
+ (void)sr;
+ (void)nil_matches;
+ (void)estimate;
+ return Intersectssubjoin_intern(lres, rres, lid, rid);
+}
+
diff --git a/geom/monetdb5/geom.h b/geom/monetdb5/geom.h
--- a/geom/monetdb5/geom.h
+++ b/geom/monetdb5/geom.h
@@ -331,3 +331,5 @@ geom_export str wkbAsX3D_bat(bat *outBAT
geom_export str wkbAsGeoJson(str *res, wkb **geom, int *maxDecDigits, int
*options);
geom_export str wkbPatchToGeom(wkb **res, wkb **geom, dbl* px, dbl*py, dbl*pz);
geom_export str wkbPatchToGeom_bat(wkb **res, wkb **geom, bat* px, bat* py,
bat* pz);
+
+geom_export str Intersectssubjoin(bat *lres, bat *rres, bat *lid, bat *rid,
bat *sl, bat *sr, bit *nil_matches, lng *estimate);
diff --git a/geom/monetdb5/geom.mal b/geom/monetdb5/geom.mal
--- a/geom/monetdb5/geom.mal
+++ b/geom/monetdb5/geom.mal
@@ -820,3 +820,8 @@ module batgeom;
command asX3D(geom:bat[:oid,:wkb], maxDecDigits:int, options:int)
:bat[:oid,:str] address wkbAsX3D_bat
comment "Returns a Geometry in X3D xml node element format:
ISO-IEC-19776-1.2-X3DEncodings-XML";
+#Filter functions and joins
+
+command geom.Intersectssubjoin(l:bat[:oid,:wkb], r:bat[:oid,:wkb],
sl:bat[:oid], sr:bat[:oid], nil_matches:bit, estimate:lng)
(lr:bat[:oid],rr:bat[:oid])
+address Intersectssubjoin
+comment "Return the geometry pairs that intersect";
diff --git a/geom/sql/40_geom.sql b/geom/sql/40_geom.sql
--- a/geom/sql/40_geom.sql
+++ b/geom/sql/40_geom.sql
@@ -4460,4 +4460,11 @@ CREATE FUNCTION ST_SimplifyPreserveTopol
CREATE FUNCTION Contains(a Geometry, x double, y double) RETURNS BOOLEAN
external name geom."Contains";
CREATE FUNCTION ST_AsX3D(a Geometry, maxDecDigits int, options int) returns
string external name geom."asX3D";
CREATE FUNCTION ST_AsGeoJson(a Geometry, maxDecDigits int, options int)
returns string external name geom."asGeoJson";
-CREATE FUNCTION Patch_to_Geom(a Geometry, x double, y double, z double)
RETURNS Geometry external name geom."PatchToGeom';
+CREATE FUNCTION Patch_to_Geom(a Geometry, x double, y double, z double)
RETURNS Geometry external name geom."PatchToGeom";
+
+
+-------------------------------------------------------------------------
+--------------------------- Filter Functions ----------------------------
+-------------------------------------------------------------------------
+
+CREATE filter function Intersects(geom1 Geometry, geom2 Geometry) external
name geom."Intersects";
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list