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

Reply via email to