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

Implemented the rtree build in the bulk mbr function. Implemented wkbIntersects 
filter function using the rtree index to filter out candidates before doing the 
actual intersects calculation. Implemented the bulk verison of st_transform, 
with substancial improvements. Implemented mbr intersects.


diffs (truncated from 726 to 300 lines):

diff --git a/geom/monetdb5/geod.c b/geom/monetdb5/geod.c
--- a/geom/monetdb5/geod.c
+++ b/geom/monetdb5/geod.c
@@ -1166,7 +1166,6 @@ free:
        return msg;
 }
 
-//select st_distancegeographic(q1.geom,q2.geom) 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;
@@ -1184,19 +1183,16 @@ wkbDWithinGeographicJoin(bat *lres_id, b
        return 
filterJoinGeomGeomDoubleToBit(lres_id,rres_id,l_id,r_id,distance_within,ls_id,rs_id,*nil_matches,estimate,*anti,geosDistanceWithin,"geom.wkbDWithinGeographicJoin");
 }
 
-//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 
filterSelectGeomGeomDoubleToBit(outid,bid,sid,*wkb_const,*distance_within,*anti,geosDistanceWithin,"geom.wkbDWithinGeographicSelect");
 }
 
-//select q1.gml_id,q2.gml_id,st_distancegeographic(q1.geom,q2.geom) 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 
filterJoinGeomGeomDoubleToBit(lres_id,rres_id,l_id,r_id,0,ls_id,rs_id,*nil_matches,estimate,*anti,geosDistanceWithin,"geom.wkbIntersectsGeographicJoin");
 }
 
-//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 
filterSelectGeomGeomDoubleToBit(outid,bid,sid,*wkb_const,0,*anti,geosDistanceWithin,"geom.wkbIntersectsGeographicSelect");
diff --git a/geom/monetdb5/geom.c b/geom/monetdb5/geom.c
--- a/geom/monetdb5/geom.c
+++ b/geom/monetdb5/geom.c
@@ -16,6 +16,7 @@
 #include "geom_atoms.h"
 #include "gdk_logger.h"
 #include "mal_exception.h"
+#include "gdk_rtree.h"
 
 mbr mbrNIL = {0}; // will be initialized properly by geom prelude
 
@@ -369,7 +370,7 @@ transformCoordSeq(int idx, int coordinat
        return MAL_SUCCEED;
 }
 
-static str
+str
 transformPoint(GEOSGeometry **transformedGeometry, const GEOSGeometry 
*geosGeometry, PJ *P)
 {
        int coordinatesNum = 0;
@@ -409,7 +410,7 @@ transformPoint(GEOSGeometry **transforme
        return MAL_SUCCEED;
 }
 
-static str
+str
 transformLine(GEOSCoordSeq *gcs_new, const GEOSGeometry *geosGeometry, PJ *P)
 {
        int coordinatesNum = 0;
@@ -447,7 +448,7 @@ transformLine(GEOSCoordSeq *gcs_new, con
        return MAL_SUCCEED;
 }
 
-static str
+str
 transformLineString(GEOSGeometry **transformedGeometry, const GEOSGeometry 
*geosGeometry, PJ *P)
 {
        GEOSCoordSeq coordSeq;
@@ -469,7 +470,7 @@ transformLineString(GEOSGeometry **trans
        return ret;
 }
 
-static str
+str
 transformLinearRing(GEOSGeometry **transformedGeometry, const GEOSGeometry 
*geosGeometry, PJ *P)
 {
        GEOSCoordSeq coordSeq = NULL;
@@ -491,7 +492,7 @@ transformLinearRing(GEOSGeometry **trans
        return ret;
 }
 
-static str
+str
 transformPolygon(GEOSGeometry **transformedGeometry, const GEOSGeometry 
*geosGeometry, PJ *P, int srid)
 {
        const GEOSGeometry *exteriorRingGeometry;
@@ -556,7 +557,7 @@ transformPolygon(GEOSGeometry **transfor
        return ret;
 }
 
-static str
+str
 transformMultiGeometry(GEOSGeometry **transformedGeometry, const GEOSGeometry 
*geosGeometry, PJ *P, int srid, int geometryType)
 {
        int geometriesNum, subGeometryType, i;
@@ -5513,11 +5514,16 @@ static mel_func geom_init_funcs[] = {
  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("geom", "Intersects", wkbIntersects, false, "Returns true if these 
Geometries 'spatially intersect in 2D'", args(1,3, 
arg("",bit),arg("a",wkb),arg("b",wkb))),
+ command("geom", "Intersectsselect", wkbIntersectsSelect, false, "TODO", 
args(1, 5, batarg("", oid), batarg("b", wkb), batarg("s", oid), arg("c", wkb), 
arg("anti",bit))),
+ command("geom", "Intersectsjoin", wkbIntersectsJoin, 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", "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))),
  command("aggr", "subCollect", wkbCollectAggrSubGrouped, false, "TODO", 
args(1, 5, batarg("", wkb), batarg("val", wkb), batarg("g", oid), batarg("e", 
oid), arg("skip_nils", bit))),
  command("aggr", "subCollect", wkbCollectAggrSubGroupedCand, false, "TODO", 
args(1, 6, batarg("", wkb), batarg("val", wkb), batarg("g", oid), 
batargany("e", 1), batarg("g", oid), arg("skip_nils", bit))),
 
- //TODO: See if we can remove (used in SQL level on 39_spatial_ref_sys.sql)
  command("geom", "hasZ", geoHasZ, false, "returns 1 if the geometry has z 
coordinate", args(1,2, arg("",int),arg("flags",int))),
  command("geom", "hasM", geoHasM, false, "returns 1 if the geometry has m 
coordinate", args(1,2, arg("",int),arg("flags",int))),
  command("geom", "getType", geoGetType, false, "returns the str representation 
of the geometry type", args(1,3, 
arg("",str),arg("flags",int),arg("format",int))),
@@ -5567,7 +5573,6 @@ static mel_func geom_init_funcs[] = {
  command("geom", "Crosses", wkbCrosses, false, "Returns TRUE if the supplied 
geometries have some, but not all, interior points in common.", args(1,3, 
arg("",bit),arg("a",wkb),arg("b",wkb))),
  command("geom", "Disjoint", wkbDisjoint, false, "Returns true if these 
Geometries are 'spatially disjoint'", args(1,3, 
arg("",bit),arg("a",wkb),arg("b",wkb))),
  command("geom", "Equals", wkbEquals, false, "Returns true if the given 
geometries represent the same geometry. Directionality is ignored.", args(1,3, 
arg("",bit),arg("a",wkb),arg("b",wkb))),
- command("geom", "Intersects", wkbIntersects, false, "Returns true if these 
Geometries 'spatially intersect in 2D'", args(1,3, 
arg("",bit),arg("a",wkb),arg("b",wkb))),
  command("geom", "Overlaps", wkbOverlaps, false, "Returns TRUE if the 
Geometries intersect but are not completely contained by each other.", 
args(1,3, arg("",bit),arg("a",wkb),arg("b",wkb))),
  command("geom", "Relate", wkbRelate, false, "Returns true if the Geometry a 
'spatially related' to Geometry b, by testing for intersection between the 
Interior, Boundary and Exterior of the two geometries as specified by the 
values in the intersectionPatternMatrix.", args(1,4, 
arg("",bit),arg("a",wkb),arg("b",wkb),arg("intersection_matrix_pattern",str))),
  command("geom", "Touches", wkbTouches, false, "Returns TRUE if the geometries 
have at least one point in common, but their interiors do not intersect.", 
args(1,3, arg("",bit),arg("a",wkb),arg("b",wkb))),
@@ -5655,6 +5660,7 @@ static mel_func geom_init_funcs[] = {
  command("batgeom", "mbr", wkbMBR_bat, false, "Creates the mbr for the given 
wkb.", args(1,2, batarg("",mbr),batarg("",wkb))),
  command("batgeom", "coordinateFromWKB", wkbCoordinateFromWKB_bat, false, 
"returns xmin (=1), ymin (=2), xmax (=3) or ymax(=4) of the provided geometry", 
args(1,3, batarg("",dbl),batarg("",wkb),arg("",int))),
  command("batgeom", "coordinateFromMBR", wkbCoordinateFromMBR_bat, false, 
"returns xmin (=1), ymin (=2), xmax (=3) or ymax(=4) of the provided mbr", 
args(1,3, batarg("",dbl),batarg("",mbr),arg("",int))),
+ command("batgeom", "Transform", wkbTransform_bat, false, "Transforms a bat of 
geometries from one srid to another", args(1,6, 
batarg("",wkb),batarg("g",wkb),arg("srid_src",int),arg("srid_dst",int),arg("proj_src",str),arg("proj_dest",str))),
  command("calc", "mbr", mbrFromString, false, "", args(1,2, 
arg("",mbr),arg("v",str))),
  command("calc", "mbr", mbrFromMBR, false, "", args(1,2, 
arg("",mbr),arg("v",mbr))),
  command("calc", "wkb", wkbFromWKB, false, "It is called when adding a new 
geometry column to an existing table", args(1,2, arg("",wkb),arg("v",wkb))),
diff --git a/geom/monetdb5/geom.h b/geom/monetdb5/geom.h
--- a/geom/monetdb5/geom.h
+++ b/geom/monetdb5/geom.h
@@ -169,7 +169,15 @@ geom_export str wkbGeometryN_bat(bat *ou
 geom_export str wkbNumGeometries(int* out, wkb** geom);
 geom_export str wkbNumGeometries_bat(bat *outBAT_id, bat *inBAT_id);
 
+str transformPoint(GEOSGeometry **transformedGeometry, const GEOSGeometry 
*geosGeometry, PJ *P);
+str transformLine(GEOSCoordSeq *gcs_new, const GEOSGeometry *geosGeometry, PJ 
*P);
+str transformLineString(GEOSGeometry **transformedGeometry, const GEOSGeometry 
*geosGeometry, PJ *P);
+str transformLinearRing(GEOSGeometry **transformedGeometry, const GEOSGeometry 
*geosGeometry, PJ *P);
+str transformPolygon(GEOSGeometry **transformedGeometry, const GEOSGeometry 
*geosGeometry, PJ *P, int srid);
+str transformMultiGeometry(GEOSGeometry **transformedGeometry, const 
GEOSGeometry *geosGeometry, PJ *P, int srid, int geometryType);
 geom_export str wkbTransform(wkb**, wkb**, int*, int*, char**, char**);
+geom_export str wkbTransform_bat(bat *outBAT_id, bat *inBAT_id, int *srid_src, 
int *srid_dst, char **proj4_src_str, char **proj4_dst_str);
+geom_export str wkbTransform_bat_cand(bat *outBAT_id, bat *inBAT_id, bat 
*s_id, int *srid_src, int *srid_dst, char **proj4_src_str, char 
**proj4_dst_str);
 geom_export str wkbTranslate(wkb**, wkb**, dbl*, dbl*, dbl*);
 geom_export str wkbDelaunayTriangles(wkb**, wkb**, dbl*, int*);
 geom_export str wkbPointOnSurface(wkb**, wkb**);
@@ -208,3 +216,7 @@ geom_export str wkbCoordinateFromWKB_bat
 geom_export str wkbCoordinateFromMBR_bat(bat *outBAT_id, bat *inBAT_id, int* 
coordinateIdx);
 
 geom_export str geom_sql_upgrade(int);
+
+geom_export str wkbIntersectsJoin(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 wkbIntersectsSelect(bat* outid, const bat *bid , const bat 
*sid, wkb **wkb_const, 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
@@ -13,10 +13,460 @@
 #include "geom.h"
 #include "geod.h"
 #include "geom_atoms.h"
+#include "gdk_rtree.h"
 
 /********** Geo Update **********/
+static str
+filterSelectGeomGeomToBitIndex(bat* outid, const bat *bid , const bat *sid, 
wkb *wkb_const, bit anti, char (*func) (const GEOSGeometry *, const 
GEOSGeometry *), const char *name)
+{
+       BAT *out = NULL, *b = NULL, *s = NULL;
+       BATiter b_iter;
+       struct canditer ci;
+       GEOSGeom col_geom, const_geom;
 
-//TODO: Rename these functions with Stefanos
+       //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, name, GDK_EXCEPTION);
+               *outid = out->batCacheid;
+               BBPkeepref(out);
+               return MAL_SUCCEED;
+       }
+
+       if ((b = BATdescriptor(*bid)) == NULL)
+               throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
+       if (sid && !is_bat_nil(*sid) && !(s = BATdescriptor(*sid))) {
+               BBPunfix(b->batCacheid);
+               throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
+       }
+       if ((out = COLnew(0, ATOMindex("oid"), ci.ncand, TRANSIENT)) == NULL) {
+               BBPunfix(b->batCacheid);
+               if (s)
+                       BBPunfix(s->batCacheid);
+               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
+       BUN* results_rtree = RTREEsearch(b,(mbr_t*)const_mbr, b->batCount);
+
+       canditer_init(&ci, b, s);
+       b_iter = bat_iterator(b);
+
+       //Intersect prev_cands with rtree_cands
+       //Cycle through rtree_cands
+       //              if there is prev_cands -> bin search
+       //              if there is not -> just cycle through rtree_cands
+
+       for (BUN i = 0; i < ci.ncand; i++) {
+               oid c_oid = canditer_next(&ci);
+
+               int i = 0;
+               while (results_rtree[i] != BUN_NONE && results_rtree[i] != 
c_oid) {
+                       i++;
+               }
+               if (results_rtree[i] == BUN_NONE)
+                       continue;
+
+               const wkb *col_wkb = BUNtvar(b_iter, c_oid - b->hseqbase);
+               if ((col_geom = wkb2geos(col_wkb)) == NULL)
+                       continue;
+               if (GEOSGetSRID(col_geom) != GEOSGetSRID(const_geom)) {
+                       GEOSGeom_destroy(col_geom);
+                       GEOSGeom_destroy(const_geom);
+                       bat_iterator_end(&b_iter);
+                       BBPunfix(b->batCacheid);
+                       if (s)
+                               BBPunfix(s->batCacheid);
+                       BBPreclaim(out);
+                       throw(MAL, name, SQLSTATE(38000) "Geometries of 
different SRID");
+               }
+
+               //GEOS functino returns 1 on true, 0 on false and 2 on exception
+               char ret = ((*func)(col_geom, const_geom));
+               bit cond = (ret == 1);
+               if (cond != 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, name, SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+                       }
+               }
+               //TODO Deal with exception?
+               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(out);
+       return MAL_SUCCEED;
+}
+
+str
+wkbIntersectsSelect(bat* outid, const bat *bid , const bat *sid, wkb 
**wkb_const, bit *anti) {
+       return 
filterSelectGeomGeomToBitIndex(outid,bid,sid,*wkb_const,*anti,GEOSIntersects,"geom.wkbIntersectsSelect");
+}
+
+static str
+filterJoinGeomGeomDoubleToBit(bat *lres_id, bat *rres_id, const bat *l_id, 
const bat *r_id, double double_flag, const bat *ls_id, const bat *rs_id, bit 
nil_matches, lng *estimate, char (*func) (const GEOSGeometry *, const 
GEOSGeometry *, double), const char *name)
+{
+       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;
+       GEOSGeom *l_geoms = NULL, *r_geoms = NULL;
+       bool anti = false;
+
+       //get the input BATs
+       if ((l = BATdescriptor(*l_id)) == NULL || (r = BATdescriptor(*r_id)) == 
NULL) {
+               if (l)
+                       BBPunfix(l->batCacheid);
+               if (r)
+                       BBPunfix(r->batCacheid);
+               throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
+       }
+       //get the candidate lists
+       if (ls_id && !is_bat_nil(*ls_id) && !(ls = BATdescriptor(*ls_id)) && 
rs_id && !is_bat_nil(*rs_id) && !(rs = BATdescriptor(*rs_id))) {
+               msg = createException(MAL, name, 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)
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to