Changeset: 6c2e8137f950 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=6c2e8137f950
Modified Files:
        geom/monetdb5/geom.c
        geom/monetdb5/geom.h
        geom/monetdb5/geom.mal
        geom/sql/40_geom.sql
Branch: sfcgal
Log Message:

Filter join for ST_DWithin(geom, geom, dist) and for ST_DWithin(geom, x, y, z, 
srid, dist);


diffs (truncated from 462 to 300 lines):

diff --git a/geom/monetdb5/geom.c b/geom/monetdb5/geom.c
--- a/geom/monetdb5/geom.c
+++ b/geom/monetdb5/geom.c
@@ -8079,3 +8079,425 @@ IntersectsXYZsubjoin(bat *lres, bat *rre
     return IntersectsXYZsubjoin_intern(lres, rres, lid, xid, yid, zid, srid);
 }
 
+static str
+DWithinsubjoin_intern(bat *lres, bat *rres, bat *lid, bat *rid, double *dist)
+{
+       BAT *xl, *xr, *bl, *br;
+       oid lo, ro;
+       BATiter lBAT_iter, rBAT_iter;
+    uint32_t j = 0;
+    BUN pr = 0, pl = 0, qr = 0, ql = 0;
+       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 = COLnew(0, TYPE_oid, 0, TRANSIENT);
+       if ( xl == NULL){
+               BBPunfix(*lid);
+               BBPunfix(*rid);
+               throw(MAL, "algebra.instersects", MAL_MALLOC_FAIL);
+       }
+
+       xr = COLnew(0, TYPE_oid, 0, TRANSIENT);
+       if ( xr == NULL){
+               BBPunfix(*lid);
+               BBPunfix(*rid);
+               BBPunfix(xl->batCacheid);
+               throw(MAL, "algebra.instersects", MAL_MALLOC_FAIL);
+       }
+
+       /*iterator over the BATs*/
+       lBAT_iter = bat_iterator(bl);
+       rBAT_iter = bat_iterator(br);
+
+    /*Get the Geometry for the inner BAT*/
+    rGeometries = (GEOSGeom*) GDKzalloc(sizeof(GEOSGeom) * BATcount(br));
+    BATloop(br, pr, qr) {
+        wkb *rWKB = (wkb *) BUNtail(rBAT_iter, pr);
+        rGeometries[pr] = wkb2geos(rWKB);
+        if ( !rGeometries[pr] ) {
+                   BBPunfix(*lid);
+               BBPunfix(*rid);
+               BBPunfix(xl->batCacheid);
+               BBPunfix(xr->batCacheid);
+               throw(MAL, "algebra.instersects", "wkb2geos failed");
+        }
+    }
+
+    lo = bl->hseqbase;
+    BATloop(bl, pl, ql) {
+        str err = NULL;
+        wkb *lWKB = NULL;
+        mbr *lMBR = NULL;
+        GEOSGeom lGeometry = NULL;
+        ro = br->hseqbase;
+
+        lWKB = (wkb *) BUNtail(lBAT_iter, pl);
+        lGeometry = wkb2geos(lWKB);
+        if ( !lGeometry ) {
+            for (j = 0; j < pl;j++) {
+                GEOSGeom_destroy(rGeometries[j]);
+            }
+            GDKfree(rGeometries);
+            BBPunfix(*lid);
+            BBPunfix(*rid);
+            BBPunfix(xl->batCacheid);
+            BBPunfix(xr->batCacheid);
+            throw(MAL, "algebra.instersects", "wkb2geos failed");
+        }
+
+        lMBR = mbrFromGeos(lGeometry);
+        if (lMBR == NULL || mbr_isnil(lMBR)) {
+            BBPunfix(*lid);
+            BBPunfix(*rid);
+            BBPunfix(xl->batCacheid);
+            BBPunfix(xr->batCacheid);
+            return err;
+        }
+
+        for (j = 0; j < BATcount(br); j++, ro++) {
+            bit out = 0;
+            double distance;
+            GEOSGeom rGeometry = rGeometries[j];
+            if (!lGeometry ||!rGeometry) {
+                if (lGeometry)
+                    GEOSGeom_destroy(lGeometry);
+                for (j = 0; j < BATcount(br);j++) {
+                    GEOSGeom_destroy(rGeometries[j]);
+                }
+                GDKfree(rGeometries);
+                BBPunfix(*lid);
+                BBPunfix(*rid);
+                BBPunfix(xl->batCacheid);
+                BBPunfix(xr->batCacheid);
+                throw(MAL, "geom.DWithin", "One of the geometries is NULL");
+            }
+
+            if (GEOSGetSRID(lGeometry) != GEOSGetSRID(rGeometry)) {
+                GEOSGeom_destroy(lGeometry);
+                for (j = 0; j < BATcount(br);j++) {
+                    GEOSGeom_destroy(rGeometries[j]);
+                }
+                GDKfree(rGeometries);
+                BBPunfix(*lid);
+                BBPunfix(*rid);
+                BBPunfix(xl->batCacheid);
+                BBPunfix(xr->batCacheid);
+                throw(MAL, "geom.DWithin", "Geometries of different SRID");
+            }
+
+            if (!GEOSDistance(lGeometry, rGeometry, &distance)) {
+                GEOSGeom_destroy(lGeometry);
+                for (j = 0; j < BATcount(br);j++) {
+                    GEOSGeom_destroy(rGeometries[j]);
+                }
+                GDKfree(rGeometries);
+                BBPunfix(*lid);
+                BBPunfix(*rid);
+                BBPunfix(xl->batCacheid);
+                BBPunfix(xr->batCacheid);
+                throw(MAL, "geom.DWithinXYZ", "GEOSDistance failed");
+            }
+            out = (distance <= *dist);
+            if (out) {
+                BUNappend(xl, &lo, FALSE);
+                BUNappend(xr, &ro, FALSE);
+            }
+        }
+        if (lGeometry)
+            GEOSGeom_destroy(lGeometry);
+        GDKfree(lMBR);
+        lo++;
+    }
+    if (rGeometries) {
+        for (j = 0; j < BATcount(br);j++) {
+            GEOSGeom_destroy(rGeometries[j]);
+        }
+        GDKfree(rGeometries);
+    }
+    /*
+    BATrmprops(xl)
+    BATsettrivprop(xl);
+    BATrmprops(xr)
+    BATsettrivprop(xr);
+    */
+       BBPunfix(*lid);
+       BBPunfix(*rid);
+       BBPkeepref(*lres = xl->batCacheid);
+       BBPkeepref(*rres = xr->batCacheid);
+       return MAL_SUCCEED;
+}
+
+str
+DWithinsubjoin(bat *lres, bat *rres, bat *lid, bat *rid, double *dist, bat 
*sl, bat *sr, bit *nil_matches, lng *estimate)
+{
+    (void)sl;
+    (void)sr;
+    (void)nil_matches;
+    (void)estimate;
+    return DWithinsubjoin_intern(lres, rres, lid, rid, dist);
+}
+
+static str
+DWithinXYZsubjoin_intern(bat *lres, bat *rres, bat *lid, bat *xid, bat*yid, 
bat *zid, int *srid, double *dist)
+{
+       BAT *xl, *xr, *bl, *bx, *by, *bz;
+       oid lo, ro;
+       BATiter lBAT_iter, xBAT_iter, yBAT_iter, zBAT_iter;
+    uint32_t j = 0;
+    BUN px = 0, py = 0, pz =0, pl = 0, qx = 0, qy = 0, qz = 0, ql = 0;
+       GEOSGeom *rGeometries = NULL;
+
+       if( (bl= BATdescriptor(*lid)) == NULL )
+               throw(MAL, "algebra.instersects", RUNTIME_OBJECT_MISSING);
+
+       if( (bx= BATdescriptor(*xid)) == NULL ){
+               BBPunfix(*lid);
+               throw(MAL, "algebra.instersects", RUNTIME_OBJECT_MISSING);
+       }
+
+       if( (by= BATdescriptor(*yid)) == NULL ){
+               BBPunfix(*lid);
+               BBPunfix(*xid);
+               throw(MAL, "algebra.instersects", RUNTIME_OBJECT_MISSING);
+       }
+
+       if( (bz= BATdescriptor(*zid)) == NULL ){
+               BBPunfix(*lid);
+               BBPunfix(*xid);
+               BBPunfix(*yid);
+               throw(MAL, "algebra.instersects", RUNTIME_OBJECT_MISSING);
+       }
+
+       xl = COLnew(0, TYPE_oid, 0, TRANSIENT);
+       if ( xl == NULL){
+               BBPunfix(*lid);
+               BBPunfix(*xid);
+               BBPunfix(*yid);
+               BBPunfix(*zid);
+               throw(MAL, "algebra.instersects", MAL_MALLOC_FAIL);
+       }
+
+       xr = COLnew(0, TYPE_oid, 0, TRANSIENT);
+       if ( xr == NULL){
+               BBPunfix(*lid);
+               BBPunfix(*xid);
+               BBPunfix(*yid);
+               BBPunfix(*zid);
+               BBPunfix(xl->batCacheid);
+               throw(MAL, "algebra.instersects", MAL_MALLOC_FAIL);
+       }
+
+       /*iterator over the BATs*/
+       lBAT_iter = bat_iterator(bl);
+       xBAT_iter = bat_iterator(bx);
+       yBAT_iter = bat_iterator(by);
+       zBAT_iter = bat_iterator(bz);
+
+    /*Get the Geometry for the inner BAT*/
+    rGeometries = (GEOSGeom*) GDKzalloc(sizeof(GEOSGeom) * BATcount(bx));
+    BATloop(bx, px, qx) {
+        GEOSGeom rGeos = NULL;
+        double *x, *y, *z;
+           GEOSCoordSeq seq;
+        x = (double*) BUNtail(xBAT_iter, px);
+        y = (double*) BUNtail(yBAT_iter, px);
+        z = (double*) BUNtail(zBAT_iter, px);
+
+        /*Create Geometry*/
+        if (*x == dbl_nil || *y == dbl_nil || *z == dbl_nil) {
+            rGeos = GEOSGeom_createEmptyPoint();
+        } else {
+            //create the point from the coordinates
+            seq = GEOSCoordSeq_create(1, 3);
+
+            if (seq == NULL) {
+                for (j = 0; j < px;j++) {
+                    GEOSGeom_destroy(rGeometries[j]);
+                }
+                GDKfree(rGeometries);
+                BBPunfix(*lid);
+                BBPunfix(*xid);
+                BBPunfix(*yid);
+                BBPunfix(*zid);
+                BBPunfix(xl->batCacheid);
+                BBPunfix(xr->batCacheid);
+                throw(MAL, "algebra.instersects", "GEOSCoordSeq_create 
failed");
+            }
+
+            if (!GEOSCoordSeq_setOrdinate(seq, 0, 0, *x) ||
+                    !GEOSCoordSeq_setOrdinate(seq, 0, 1, *y) ||
+                    !GEOSCoordSeq_setOrdinate(seq, 0, 2, *z)) {
+                for (j = 0; j < px;j++) {
+                    GEOSGeom_destroy(rGeometries[j]);
+                }
+                GDKfree(rGeometries);
+                BBPunfix(*lid);
+                BBPunfix(*xid);
+                BBPunfix(*yid);
+                BBPunfix(*zid);
+                BBPunfix(xl->batCacheid);
+                BBPunfix(xr->batCacheid);
+                GEOSCoordSeq_destroy(seq);
+                throw(MAL, "algebra.instersects", "GEOSCoordSeq_setOrdinate 
failed");
+            }
+
+            if ((rGeos = GEOSGeom_createPoint(seq)) == NULL) {
+                for (j = 0; j < px;j++) {
+                    GEOSGeom_destroy(rGeometries[j]);
+                }
+                GDKfree(rGeometries);
+                BBPunfix(*lid);
+                BBPunfix(*xid);
+                BBPunfix(*yid);
+                BBPunfix(*zid);
+                BBPunfix(xl->batCacheid);
+                BBPunfix(xr->batCacheid);
+                GEOSCoordSeq_destroy(seq);
+                throw(MAL, "algebra.instersects", "Failed to create 
GEOSGeometry from the coordinates");
+            }
+
+            if (*srid != int_nil)
+                GEOSSetSRID(rGeos, *srid);
+        }
+
+        rGeometries[px] = rGeos;
+    }
+
+    lo = bl->hseqbase;
+    BATloop(bl, pl, ql) {
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to