Changeset: 96c494c40104 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/96c494c40104 Modified Files: geom/monetdb5/geom.c geom/monetdb5/geom.h geom/sql/40_geom.sql Branch: geo-update Log Message:
First version of the distance filter functions. diffs (truncated from 355 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 @@ -778,53 +778,6 @@ wkbDWithinGeographic(bit *out, wkb **a, return err; } -/* -str -wkbDWithinGeographicSelect(bat* outid, const bat *aid, const bat *bid, dbl *d, const bat *s1_id, const bat *s2_id, const bit *anti) -{ - (void) anti; (void) d; - BAT *out = NULL, *a = NULL, *b = NULL, *s1 = NULL, *s2 = NULL; - BATiter a_iter, b_iter; - str msg = MAL_SUCCEED; - BUN count = 0; - struct canditer ci1, ci2; - - //get the BATs - if ((a = BATdescriptor(*aid)) == NULL || (b = BATdescriptor(*bid)) == NULL) { - msg = createException(MAL, "geom.wkbDWithinGeographicSelect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); - } - - //check for candidate lists - if (s1_id && !is_bat_nil(*s1_id) && !(s1 = BATdescriptor(*s1_id))) { - msg = createException(MAL, "geom.wkbDWithinGeographicSelect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); - } - if (s2_id && !is_bat_nil(*s2_id) && !(s2 = BATdescriptor(*s2_id))) { - msg = createException(MAL, "geom.wkbDWithinGeographicSelect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); - if (s1) - BBPunfix(s1->batCacheid); - } - count = canditer_init(&ci1, a, s1); - canditer_init(&ci2, b, s2); - - //create a new BAT for the output - if ((out = COLnew(a->hseqbase, ATOMindex("oid"), BATcount(a), TRANSIENT)) == NULL) { - msg = createException(MAL, "geom.wkbDWithinGeographicSelect", SQLSTATE(HY013) MAL_MALLOC_FAIL); - } - - //iterator over the BATs - a_iter = bat_iterator(a); - b_iter = bat_iterator(b); - return MAL_SUCCEED; -} - -str -wkbDWithinGeographicJoin(bat *lres, bat *rres, const bat *lwkb, const bat *rwkb, const bat *lsid, const bat *rsid, const bit *nil_matches, const lng *estimate) -{ - (void) lres; (void) rres; (void) lwkb; (void) rwkb; (void) lsid; (void) rsid; (void) nil_matches; (void) estimate; - return MAL_SUCCEED; -} -*/ - /** * Intersects * @@ -954,6 +907,217 @@ wkbCoversGeographic(bit *out, wkb **a, w } /** + * FILTER FUNCTIONS + **/ +static str +filter_select(bat* outid, const bat *bid , const bat *sid, wkb *wkb_const, dbl distance_within, bit anti) +{ + BAT *out = NULL, *b = NULL, *s = NULL; + BATiter b_iter; + struct canditer ci; + GEOSGeom col_geom, const_geom; + + //Check if the geometry is null and convert to GEOS + if ((const_geom = wkb2geos(wkb_const)) == NULL) { + if ((out = BATdense(0, 0, 0)) == NULL) + throw(MAL, "geom.wkbDWithinGeographicSelect", GDK_EXCEPTION); + *outid = out->batCacheid; + BBPkeepref(*outid); + return MAL_SUCCEED; + } + //get the BATs + if ((b = BATdescriptor(*bid)) == NULL) + throw(MAL, "geom.wkbDWithinGeographicSelect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + //get the candidate lists + if (sid && !is_bat_nil(*sid) && !(s = BATdescriptor(*sid))) { + BBPunfix(b->batCacheid); + throw(MAL, "geom.wkbDWithinGeographicSelect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + } + canditer_init(&ci, b, s); + //create a new BAT for the output + if ((out = COLnew(0, ATOMindex("oid"), ci.ncand, TRANSIENT)) == NULL) { + BBPunfix(b->batCacheid); + if (s) + BBPunfix(s->batCacheid); + throw(MAL, "geom.wkbDWithinGeographicSelect", SQLSTATE(HY013) MAL_MALLOC_FAIL); + } + b_iter = bat_iterator(b); + //Loop through column and compare with constant + for (BUN i = 0; i < ci.ncand; i++) { + oid c_oid = canditer_next(&ci); + const wkb *col_wkb = BUNtvar(b_iter, c_oid - b->hseqbase); + if (is_wkb_nil(col_wkb) || (col_geom = wkb2geos(col_wkb)) == NULL) + continue; + double distance = geoDistanceInternal(col_geom, const_geom); + if ((distance <= distance_within && !anti) || (distance > distance_within && anti) ) { + if (BUNappend(out, &c_oid, false) != GDK_SUCCEED) { + if (col_geom) + GEOSGeom_destroy(col_geom); + if (const_geom) + GEOSGeom_destroy(const_geom); + bat_iterator_end(&b_iter); + BBPunfix(b->batCacheid); + if (s) + BBPunfix(s->batCacheid); + BBPreclaim(out); + throw(MAL, "geom.wkbDWithinGeographicSelect", SQLSTATE(HY013) MAL_MALLOC_FAIL); + } + } + GEOSGeom_destroy(col_geom); + } + GEOSGeom_destroy(const_geom); + bat_iterator_end(&b_iter); + BBPunfix(b->batCacheid); + if (s) + BBPunfix(s->batCacheid); + *outid = out->batCacheid; + BBPkeepref(*outid); + return MAL_SUCCEED; +} + +static str +filter_join(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, double distance_within, const bat *ls_id, const bat *rs_id, bit nil_matches, lng *estimate, bit anti) +{ + //TODO Use nil_matches? + (void) nil_matches; + BAT *lres = NULL, *rres = NULL, *l = NULL, *r = NULL, *ls = NULL, *rs = NULL; + BATiter l_iter, r_iter; + str msg = MAL_SUCCEED; + struct canditer l_ci, r_ci; + GEOSGeom l_geom, r_geom; + + //get the input BATs + if ((l = BATdescriptor(*l_id)) == NULL || (r = BATdescriptor(*r_id)) == NULL) { + msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + goto free; + } + //get the candidate lists + if (ls_id && !is_bat_nil(*ls_id) && !(ls = BATdescriptor(*ls_id))) { + msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + goto free; + } + if (rs_id && !is_bat_nil(*rs_id) && !(rs = BATdescriptor(*rs_id))) { + msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + goto free; + } + canditer_init(&l_ci, l, ls); + canditer_init(&r_ci, r, rs); + //create new BATs for the output + if (is_lng_nil(*estimate) || *estimate == 0) + *estimate = l_ci.ncand; + if ((lres = COLnew(0, ATOMindex("oid"), *estimate, TRANSIENT)) == NULL) { + msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); + goto free; + } + if ((rres = COLnew(0, ATOMindex("oid"), *estimate, TRANSIENT)) == NULL) { + msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); + goto free; + } + + l_iter = bat_iterator(l); + r_iter = bat_iterator(r); + for (BUN i = 0; i < l_ci.ncand; i++) { + oid l_oid = canditer_next(&l_ci); + const wkb *l_wkb = BUNtvar(l_iter, l_oid - l->hseqbase); + if (is_wkb_nil(l_wkb) || (l_geom = wkb2geos(l_wkb)) == NULL) + continue; + canditer_reset(&r_ci); + for (BUN j = 0; j < r_ci.ncand; j++) { + oid r_oid = canditer_next(&r_ci); + const wkb *r_wkb = BUNtvar(r_iter, r_oid - r->hseqbase); + if (is_wkb_nil(r_wkb) || (r_geom = wkb2geos(r_wkb)) == NULL) + continue; + if (GEOSGetSRID(l_geom) != GEOSGetSRID(r_geom)) { + msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(38000) "Geometries of different SRID"); + GEOSGeom_destroy(r_geom); + GEOSGeom_destroy(l_geom); + goto free; + } + double distance = geoDistanceInternal(l_geom, r_geom); + if ((distance <= distance_within && !anti) || (distance > distance_within && anti) ) { + if (BUNappend(lres, &l_oid, false) != GDK_SUCCEED || BUNappend(rres, &r_oid, false) != GDK_SUCCEED) { + msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); + goto free; + } + } + GEOSGeom_destroy(r_geom); + } + GEOSGeom_destroy(l_geom); + } + bat_iterator_end(&l_iter); + bat_iterator_end(&r_iter); + BBPunfix(l->batCacheid); + BBPunfix(r->batCacheid); + if (ls) + BBPunfix(ls->batCacheid); + if (rs) + BBPunfix(rs->batCacheid); + *lres_id = lres->batCacheid; + *rres_id = rres->batCacheid; + BBPkeepref(*lres_id); + BBPkeepref(*rres_id); + return MAL_SUCCEED; +free: + //TODO: Test this + bat_iterator_end(&l_iter); + bat_iterator_end(&r_iter); + if (l) + BBPunfix(l->batCacheid); + if (r) + BBPunfix(r->batCacheid); + if (ls) + BBPunfix(ls->batCacheid); + if (rs) + BBPunfix(rs->batCacheid); + if (lres) + BBPreclaim(lres); + if (rres) + BBPreclaim(rres); + return msg; +} + +//select * from brittany_ports as q1 join wpi_ports as q2 on [q1.geom] st_dwithingeographic [q2.geom,5000]; +str +wkbDWithinGeographicJoin(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, const bat *d_id, const bat *ls_id, const bat *rs_id, bit *nil_matches, lng *estimate, bit *anti) { + double distance_within = 0; + BAT *d = NULL; + //Get the distance (const) BAT and get the double value + if ((d = BATdescriptor(*d_id)) == NULL) { + if (d) + BBPunfix(d->batCacheid); + throw(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + } + if (BATcount(d) == 1) { + distance_within = *((double*) Tloc(d, 0)); + } + BBPunfix(d->batCacheid); + return filter_join(lres_id,rres_id,l_id,r_id,distance_within,ls_id,rs_id,*nil_matches,estimate,*anti); +} + +//select gml_id,st_distancegeographic(st_setsrid(st_makepoint(-4.50,48.32),4326),q1.geom) from brittany_ports as q1 where [q1.geom] st_dwithingeographic [st_setsrid(st_makepoint(-4.50,48.32),4326),5000]; +str +wkbDWithinGeographicSelect(bat* outid, const bat *bid , const bat *sid, wkb **wkb_const, dbl *distance_within, bit *anti) { + return filter_select(outid,bid,sid,*wkb_const,*distance_within,*anti); +} + +//select * from brittany_ports as q1 join brittany_ports as q2 on [q1.geom] ST_IntersectsGeographic [q2.geom]; +str +wkbIntersectsGeographicJoin(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, const bat *ls_id, const bat *rs_id, bit *nil_matches, lng *estimate, bit *anti) { + return filter_join(lres_id,rres_id,l_id,r_id,0,ls_id,rs_id,*nil_matches,estimate,*anti); +} + +//select gml_id,st_distancegeographic(st_setsrid(st_makepoint(-1.7717988686592332,48.602742696725414),4326),q1.geom) from brittany_ports as q1 where [q1.geom] ST_IntersectsGeographic [st_setsrid(st_makepoint(-1.7717988686592332,48.602742696725414),4326)]; +str +wkbIntersectsGeographicSelect(bat* outid, const bat *bid , const bat *sid, wkb **wkb_const, bit *anti) { + return filter_select(outid,bid,sid,*wkb_const,0,*anti); +} + + +/** + * AGGREGATES + **/ + +/** * Collect (Group By implementation) * **/ @@ -7641,16 +7805,19 @@ static mel_atom geom_init_atoms[] = { }; static mel_func geom_init_funcs[] = { //TODO Fill in descriptions + command("geom", "CoversGeographic", wkbCoversGeographic, false, "TODO", args(1, 3, arg("", bit), arg("a", wkb), arg("b", wkb))), + command("geom", "DistanceGeographic", wkbDistanceGeographic, false, "TODO", args(1, 3, arg("", dbl), arg("a", wkb), arg("b", wkb))), - command("geom", "IntersectsGeographic", wkbIntersectsGeographic, false, "Returns true if the geographic Geometries intersect in any point", args(1, 3, arg("", bit), arg("a", wkb), arg("b", wkb))), - command("geom", "CoversGeographic", wkbCoversGeographic, false, "TODO", args(1, 3, arg("", bit), arg("a", wkb), arg("b", wkb))), - command("batgeom", "DistanceGeographic", wkbDistanceGeographic_bat, false, "TODO", args(1, 3, batarg("", dbl), batarg("a", wkb), batarg("b", wkb))), command("batgeom", "DistanceGeographic", wkbDistanceGeographic_bat_cand, false, "TODO", args(1, 5, batarg("", dbl), batarg("a", wkb), batarg("b", wkb), batarg("s1", oid), batarg("s2", oid))), + //Filter functions command("geom", "DWithinGeographic", wkbDWithinGeographic, false, "TODO", args(1, 4, arg("", bit), arg("a", wkb), arg("b", wkb), arg("d", dbl))), - //command("geom", "DWithinGeographicselect", wkbDWithinGeographicSelect, false, "TODO", args(1, 7, batarg("", oid), batarg("a", wkb), batarg("b", wkb), arg("d", dbl), batarg("s1", oid), batarg("s2", oid),arg("anti",bit))), - //command("geom", "DWithinGeographicjoin", wkbDWithinGeographicJoin, false, "TODO", args(2, 9, batarg("lr",oid),batarg("rr",oid), batarg("a", wkb), batarg("b", wkb), arg("d", dbl), batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng))), + command("geom", "DWithinGeographicselect", wkbDWithinGeographicSelect, false, "TODO", args(1, 6, batarg("", oid), batarg("b", wkb), batarg("s", oid), arg("c", wkb), arg("d", dbl),arg("anti",bit))), + command("geom", "DWithinGeographicjoin", wkbDWithinGeographicJoin, false, "TODO", args(2, 10, batarg("lr",oid),batarg("rr",oid), batarg("a", wkb), batarg("b", wkb), batarg("d", dbl), batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng),arg("anti",bit))), + command("geom", "IntersectsGeographic", wkbIntersectsGeographic, false, "Returns true if the geographic Geometries intersect in any point", args(1, 3, arg("", bit), arg("a", wkb), arg("b", wkb))), + command("geom", "IntersectsGeographicselect", wkbIntersectsGeographicSelect, false, "TODO", args(1, 5, batarg("", oid), batarg("b", wkb), batarg("s", oid), arg("c", wkb), arg("anti",bit))), + command("geom", "IntersectsGeographicjoin", wkbIntersectsGeographicJoin, false, "TODO", args(2, 9, batarg("lr",oid),batarg("rr",oid), batarg("a", wkb), batarg("b", wkb), batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng),arg("anti",bit))), command("aggr", "Collect", wkbCollectAggr, false, "TODO", args(1, 2, arg("", wkb), batarg("val", wkb))), command("aggr", "subCollect", wkbCollectAggrSubGrouped, false, "TODO", args(1, 5, batarg("", wkb), batarg("val", wkb), batarg("g", oid), batarg("e", oid), arg("skip_nils", bit))), _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list