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