Changeset: e7f20b0bc1d8 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/e7f20b0bc1d8
Modified Files:
        geom/monetdb5/geom.c
        geom/monetdb5/geom.h
        geom/monetdb5/geomBulk.c
        geom/sql/40_geom.sql
        monetdb5/optimizer/opt_mitosis.c
Branch: geo-update-dev
Log Message:

DWithin with RTree index implementation, add distance parameter to 
rtree/no_index C functions


diffs (248 lines):

diff --git a/geom/monetdb5/geom.c b/geom/monetdb5/geom.c
--- a/geom/monetdb5/geom.c
+++ b/geom/monetdb5/geom.c
@@ -5517,14 +5517,16 @@ static mel_func geom_init_funcs[] = {
  command("rtree", "Intersectsselect", wkbIntersectsSelectRTree, false, "TODO", 
args(1, 5, batarg("", oid), batarg("b", wkb), batarg("s", oid), arg("c", wkb), 
arg("anti",bit))),
  command("rtree", "Intersectsjoin", wkbIntersectsJoinRTree, false, "TODO", 
args(2, 8, 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))),
 
- //command("rtree", "DWithin", wkbIntersects, false, "Returns true if these 
Geometries 'spatially intersect in 2D'", args(1,3, 
arg("",bit),arg("a",wkb),arg("b",wkb))),
- //command("rtree", "DWithinselect", wkbIntersectsSelectRTree, false, "TODO", 
args(1, 5, batarg("", oid), batarg("b", wkb), batarg("s", oid), arg("c", wkb), 
arg("anti",bit))),
- //command("rtree", "DWithinjoin", wkbIntersectsJoinRTree, false, "TODO", 
args(2, 8, 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))),
+ command("rtree", "DWithin", wkbDWithin, false, "Returns true if these 
Geometries 'spatially intersect in 2D'", args(1,4, 
arg("",bit),arg("a",wkb),arg("b",wkb),arg("dst",dbl))),
+ command("rtree", "DWithinselect", wkbDWithinSelectRTree, false, "TODO", 
args(1, 6, batarg("", oid), batarg("b", wkb), batarg("s", oid), arg("c", wkb), 
arg("dst",dbl), arg("anti",bit))),
+ command("rtree", "DWithinjoin", wkbDWithinJoinRTree, false, "TODO", args(2, 
9, batarg("lr",oid),batarg("rr",oid), batarg("a", wkb), batarg("b", wkb), 
batarg("sl",oid),batarg("sr",oid), 
arg("dst",dbl),arg("nil_matches",bit),arg("estimate",lng))),
 
  command("geom", "Intersects_noindex", wkbIntersects, false, "Returns true if 
these Geometries 'spatially intersect in 2D'", args(1,3, 
arg("",bit),arg("a",wkb),arg("b",wkb))),
  command("geom", "Intersects_noindexselect", wkbIntersectsSelectNoIndex, 
false, "TODO", args(1, 5, batarg("", oid), batarg("b", wkb), batarg("s", oid), 
arg("c", wkb), arg("anti",bit))),
  command("geom", "Intersects_noindexjoin", wkbIntersectsJoinNoIndex, false, 
"TODO", args(2, 8, 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))),
 
+ command("geom", "DWithin", wkbDWithin, false, "Returns true if the two 
geometries are within the specifies distance from each other", args(1,4, 
arg("",bit),arg("a",wkb),arg("b",wkb),arg("dst",dbl))),
+
  command("geom", "IntersectsMBR", mbrIntersects, false, "TODO", args(1,3, 
arg("",bit),arg("a",mbr),arg("b",mbr))),
 
  command("aggr", "Collect", wkbCollectAggr, false, "TODO", args(1, 2, arg("", 
wkb), batarg("val", wkb))),
@@ -5586,7 +5588,6 @@ static mel_func geom_init_funcs[] = {
  command("geom", "Within", wkbWithin, false, "Returns TRUE if the geometry A 
is completely inside geometry B", args(1,3, 
arg("",bit),arg("a",wkb),arg("b",wkb))),
  command("geom", "Covers", wkbCovers, false, "Returns TRUE if no point of 
geometry B is outside geometry A", args(1,3, 
arg("",bit),arg("a",wkb),arg("b",wkb))),
  command("geom", "CoveredBy", wkbCoveredBy, false, "Returns TRUE if no point 
of geometry A is outside geometry B", args(1,3, 
arg("",bit),arg("a",wkb),arg("b",wkb))),
- command("geom", "DWithin", wkbDWithin, false, "Returns true if the two 
geometries are within the specifies distance from each other", args(1,4, 
arg("",bit),arg("a",wkb),arg("b",wkb),arg("dst",dbl))),
  command("geom", "DWithin2", wkbDWithinMbr, false, "" /* <<< desc TODO */, 
args(1,6, 
arg("",bit),arg("a",wkb),arg("b",wkb),arg("a_mbr",mbr),arg("b_mbr",mbr),arg("dst",dbl))),
  command("geom", "GeometryN", wkbGeometryN, false, "Returns the 1-based Nth 
geometry if the geometry is a GEOMETRYCOLLECTION, (MULTI)POINT, 
(MULTI)LINESTRING, MULTICURVE or (MULTI)POLYGON. Otherwise, return NULL", 
args(1,3, arg("",wkb),arg("g",wkb),arg("n",int))),
  command("geom", "NumGeometries", wkbNumGeometries, false, "Returns the number 
of geometries", args(1,2, arg("",int),arg("g",wkb))),
diff --git a/geom/monetdb5/geom.h b/geom/monetdb5/geom.h
--- a/geom/monetdb5/geom.h
+++ b/geom/monetdb5/geom.h
@@ -219,6 +219,11 @@ geom_export str geom_sql_upgrade(int);
 
 geom_export str wkbIntersectsJoinNoIndex(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);
 geom_export str wkbIntersectsSelectNoIndex(bat* outid, const bat *bid , const 
bat *sid, wkb **wkb_const, bit *anti);
+
 geom_export str wkbIntersectsJoinRTree(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);
 geom_export str wkbIntersectsSelectRTree(bat* outid, const bat *bid , const 
bat *sid, wkb **wkb_const, bit *anti);
+
+geom_export str wkbDWithinJoinRTree(bat *lres_id, bat *rres_id, const bat 
*l_id, const bat *r_id, const bat *ls_id, const bat *rs_id, double *distance, 
bit *nil_matches, lng *estimate);
+geom_export str wkbDWithinSelectRTree(bat* outid, const bat *bid , const bat 
*sid, wkb **wkb_const, double *distance, bit *anti);
+
 geom_export str mbrIntersects(bit* out, mbr** mbr1, mbr** mbr2);
diff --git a/geom/monetdb5/geomBulk.c b/geom/monetdb5/geomBulk.c
--- a/geom/monetdb5/geomBulk.c
+++ b/geom/monetdb5/geomBulk.c
@@ -14,23 +14,16 @@
 #include "geod.h"
 #include "geom_atoms.h"
 
+//TODO Is GEOSDistanceWithin(g1,g2,0) the same (performance) as 
GEOSIntersects(g1,g2)?
+
 /********** Geo Update Start **********/
 static str
-filterSelectRTree(bat* outid, const bat *bid , const bat *sid, wkb *wkb_const, 
bit anti, char (*func) (const GEOSGeometry *, const GEOSGeometry *), const char 
*name)
+filterSelectRTree(bat* outid, const bat *bid , const bat *sid, GEOSGeom 
const_geom, mbr *const_mbr, double distance, bit anti, char (*func) (const 
GEOSGeometry *, const GEOSGeometry *, double), const char *name)
 {
        BAT *out = NULL, *b = NULL, *s = NULL;
        BATiter b_iter;
        struct canditer ci;
-       GEOSGeom col_geom, const_geom;
-
-       //WKB constant is NULL
-       if ((const_geom = wkb2geos(wkb_const)) == NULL) {
-               if ((out = BATdense(0, 0, 0)) == NULL)
-                       throw(MAL, name, GDK_EXCEPTION);
-               *outid = out->batCacheid;
-               BBPkeepref(out);
-               return MAL_SUCCEED;
-       }
+       GEOSGeom col_geom;
 
        //Get BAT, BATiter and candidate list
        if ((b = BATdescriptor(*bid)) == NULL)
@@ -50,19 +43,13 @@ filterSelectRTree(bat* outid, const bat 
                throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
        }
 
-       //Calculate the MBR for the constant geometry
-       mbr *const_mbr = NULL;
-       wkbMBR(&const_mbr,&wkb_const);
-
        //Get a candidate list from searching on the rtree with the constant mbr
-       //Note: the candidates returned from RTREEsearch are BUNs not OIDs
        BUN* results_rtree = RTREEsearch(b,(mbr_t*)const_mbr, b->batCount);
 
+       //TODO Change literal value of BUN_NONE to BUN_NONE in loop condition
        //Cycle through rtree candidates
        //If there is a original candidate list, make sure the rtree cand is in 
there
        //Then do the actual calculation for the predicate using the GEOS 
function
-
-       //TODO Change literal value of BUN_NONE to BUN_NONE in loop condition
        for (int i = 0; results_rtree[i] != 18446744073709551615U && i < (int) 
b->batCount; i++) {
                oid cand = results_rtree[i];
 
@@ -87,7 +74,7 @@ filterSelectRTree(bat* outid, const bat 
                        throw(MAL, name, SQLSTATE(38000) "Geometries of 
different SRID");
                }
                //GEOS function returns 1 on true, 0 on false and 2 on exception
-               bit cond = ((*func)(col_geom, const_geom) == 1);
+               bit cond = ((*func)(col_geom, const_geom, distance) == 1);
                if (cond != anti) {
                        if (BUNappend(out, (oid*) &cand, false) != GDK_SUCCEED) 
{
                                GEOSGeom_destroy(col_geom);
@@ -113,12 +100,12 @@ filterSelectRTree(bat* outid, const bat 
 }
 
 static str
-filterSelectNoIndex(bat* outid, const bat *bid , const bat *sid, wkb 
*wkb_const, bit anti, char (*func) (const GEOSGeometry *, const GEOSGeometry 
*), const char *name)
+filterSelectNoIndex(bat* outid, const bat *bid , const bat *sid, wkb 
*wkb_const, double distance, bit anti, char (*func) (const GEOSGeometry *, 
const GEOSGeometry *, double), const char *name)
 {
        BAT *out = NULL, *b = NULL, *s = NULL;
        BATiter b_iter;
        struct canditer ci;
-       GEOSGeom const_geom, col_geom;
+       GEOSGeom col_geom, const_geom;
 
        //WKB constant is NULL
        if ((const_geom = wkb2geos(wkb_const)) == NULL) {
@@ -163,7 +150,7 @@ filterSelectNoIndex(bat* outid, const ba
                        throw(MAL, name, SQLSTATE(38000) "Geometries of 
different SRID");
                }
                //GEOS function returns 1 on true, 0 on false and 2 on exception
-               bit cond = ((*func)(col_geom, const_geom) == 1);
+               bit cond = ((*func)(col_geom, const_geom, distance) == 1);
                if (cond != anti) {
                        if (BUNappend(out, (oid*) &cand, false) != GDK_SUCCEED) 
{
                                if (col_geom)
@@ -194,15 +181,62 @@ filterSelectNoIndex(bat* outid, const ba
 str
 wkbIntersectsSelectRTree(bat* outid, const bat *bid , const bat *sid, wkb 
**wkb_const, bit *anti) {
        //If there is an RTree on memory or on file, use the RTree method. 
Otherwise, use the no index version.
-       if (RTREEexists_bid((bat*)bid))
-               return 
filterSelectRTree(outid,bid,sid,*wkb_const,*anti,GEOSIntersects,"geom.wkbIntersectsSelectRTree");
+       if (RTREEexists_bid((bat*)bid)) {
+               //Calculate MBR of constant geometry first
+               GEOSGeom const_geom;
+               if ((const_geom = wkb2geos(*wkb_const)) == NULL) {
+                       BAT *out = NULL;
+                       if ((out = BATdense(0, 0, 0)) == NULL)
+                               throw(MAL, "geom.wkbIntersectsSelectRTree", 
GDK_EXCEPTION);
+                       *outid = out->batCacheid;
+                       BBPkeepref(out);
+                       return MAL_SUCCEED;
+               }
+               //Calculate the MBR for the constant geometry
+               mbr *const_mbr = NULL;
+               wkbMBR(&const_mbr,wkb_const);
+
+               return 
filterSelectRTree(outid,bid,sid,const_geom,const_mbr,0,*anti,GEOSDistanceWithin,"geom.wkbIntersectsSelectRTree");
+       }
        else
-               return 
filterSelectNoIndex(outid,bid,sid,*wkb_const,*anti,GEOSIntersects,"geom.wkbIntersectsSelectNoIndex");
+               return 
filterSelectNoIndex(outid,bid,sid,*wkb_const,0,*anti,GEOSDistanceWithin,"geom.wkbIntersectsSelectNoIndex");
+}
+
+str
+wkbDWithinSelectRTree(bat* outid, const bat *bid , const bat *sid, wkb 
**wkb_const, double* distance, bit *anti) {
+       //If there is an RTree on memory or on file, use the RTree method. 
Otherwise, use the no index version.
+       if (RTREEexists_bid((bat*)bid)) {
+               //Calculate MBR of constant geometry first
+               GEOSGeom const_geom;
+               if ((const_geom = wkb2geos(*wkb_const)) == NULL) {
+                       BAT *out = NULL;
+                       if ((out = BATdense(0, 0, 0)) == NULL)
+                               throw(MAL, "geom.wkbDWithinSelectRTree", 
GDK_EXCEPTION);
+                       *outid = out->batCacheid;
+                       BBPkeepref(out);
+                       return MAL_SUCCEED;
+               }
+               //Calculate the MBR for the constant geometry
+               mbr *const_mbr = NULL;
+               wkbMBR(&const_mbr,wkb_const);
+
+               //We expand the bounding box to cover the "distance within" area
+               //And use GEOSIntersects with the expanded bounding box
+               //TODO This expansion is too much
+               const_mbr->xmin -=(*distance);
+               const_mbr->ymin -=(*distance);
+               const_mbr->xmax +=(*distance);
+               const_mbr->ymax +=(*distance);
+
+               return 
filterSelectRTree(outid,bid,sid,const_geom,const_mbr,*distance,*anti,GEOSDistanceWithin,"geom.wkbDWithinSelectRTree");
+       }
+       else
+               return 
filterSelectNoIndex(outid,bid,sid,*wkb_const,*distance,*anti,GEOSDistanceWithin,"geom.wkbDWithinSelectNoIndex");
 }
 
 str
 wkbIntersectsSelectNoIndex(bat* outid, const bat *bid , const bat *sid, wkb 
**wkb_const, bit *anti) {
-       return 
filterSelectNoIndex(outid,bid,sid,*wkb_const,*anti,GEOSIntersects,"geom.wkbIntersectsSelectNoIndex");
+       return 
filterSelectNoIndex(outid,bid,sid,*wkb_const,0,*anti,GEOSDistanceWithin,"geom.wkbIntersectsSelectNoIndex");
 }
 
 static str
@@ -377,6 +411,12 @@ wkbIntersectsJoinRTree(bat *lres_id, bat
 }
 
 str
+wkbDWithinJoinRTree(bat *lres_id, bat *rres_id, const bat *l_id, const bat 
*r_id, const bat *ls_id, const bat *rs_id, double *distance, bit *nil_matches, 
lng *estimate) {
+       (void) distance;
+       return 
filterJoinRTree(lres_id,rres_id,l_id,r_id,0,ls_id,rs_id,*nil_matches,estimate,GEOSIntersects,"geom.wkbDWithinJoinRTree");
+}
+
+str
 wkbIntersectsJoinNoIndex(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) 
{
        return 
filterJoinNoIndex(lres_id,rres_id,l_id,r_id,0,ls_id,rs_id,*nil_matches,estimate,GEOSIntersects,"geom.wkbIntersectsJoinNoIndex");
 }
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
@@ -22,6 +22,9 @@ CREATE FILTER FUNCTION ST_IntersectsGeog
 CREATE FUNCTION ST_IntersectsMBR(mbr1 mbr, mbr2 mbr) RETURNS bool EXTERNAL 
NAME geom."IntersectsMBR";
 CREATE FILTER FUNCTION ST_Intersects(geom1 Geometry, geom2 Geometry) EXTERNAL 
NAME rtree."Intersects";
 CREATE FILTER FUNCTION ST_Intersects_NoIndex(geom1 Geometry, geom2 Geometry) 
EXTERNAL NAME geom."Intersects_noindex";
+
+CREATE FILTER FUNCTION ST_DWithin(geom1 Geometry, geom2 Geometry, distance 
double) EXTERNAL NAME rtree."DWithin";
+CREATE FUNCTION ST_DWithin_NoIndex(geom1 Geometry, geom2 Geometry, distance 
double) RETURNS boolean EXTERNAL NAME geom."DWithin";
 -------------------------------------------------------------------------
 ------------------------- Geography functions ---------------------------
 -------------------------------------------------------------------------
@@ -513,8 +516,6 @@ GRANT EXECUTE ON FUNCTION ST_CoveredBy(G
 --CREATE FUNCTION ST_LineCrossingDirection RETURNS EXTERNAL NAME
 --CREATE FUNCTION ST_Distance(geog1 Geometry, geog2 Geometry) RETURNS double 
EXTERNAL NAME geom."Distance"
 --CREATE FUNCTION ST_Distance(geog1 Geometry, geog2 Geometry, use_spheroid 
boolean) RETURNS double EXTERNAL NAME geom."Distance"
-CREATE FUNCTION ST_DWithin(geom1 Geometry, geom2 Geometry, dst double) RETURNS 
boolean EXTERNAL NAME geom."DWithin";
-GRANT EXECUTE ON FUNCTION ST_DWithin(Geometry, Geometry, double) TO PUBLIC;
 CREATE FUNCTION ST_DWithin2(geom1 Geometry, geom2 Geometry, bbox1 mbr, bbox2 
mbr, dst double) RETURNS boolean EXTERNAL NAME geom."DWithin2";
 GRANT EXECUTE ON FUNCTION ST_DWithin2(Geometry, Geometry, mbr, mbr, double) TO 
PUBLIC;
 --CREATE FUNCTION ST_HausdorffDistance RETURNS EXTERNAL NAME
diff --git a/monetdb5/optimizer/opt_mitosis.c b/monetdb5/optimizer/opt_mitosis.c
--- a/monetdb5/optimizer/opt_mitosis.c
+++ b/monetdb5/optimizer/opt_mitosis.c
@@ -70,8 +70,10 @@ OPTmitosisImplementation(Client cntxt, M
                        }
 
                /* rtree functions should not be optimized by mitosis 
(single-threaded execution) */
-               if ( getModuleId(p) == rtreeRef)
+               if ( getModuleId(p) == rtreeRef){
+                       pieces = 0;
                        goto bailout;
+               }
 
                /* do not split up floating point bat that is being summed */
                if (p->retc == 1 &&
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to