Changeset: 84c2d53795b9 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=84c2d53795b9
Modified Files:
        geom/monetdb5/geom.h
        geom/monetdb5/geom.mal
        geom/monetdb5/geomPoints.c
        geom/sql/40_geom.sql
        monetdb5/optimizer/opt_geospatial.c
Branch: geo
Log Message:

implementation of distance for x,y coordinates without the use of geos


diffs (259 lines):

diff --git a/geom/monetdb5/geom.h b/geom/monetdb5/geom.h
--- a/geom/monetdb5/geom.h
+++ b/geom/monetdb5/geom.h
@@ -266,7 +266,8 @@ geom_export str wkbCoordinateFromMBR_bat
 
 geom_export str wkbPointsContains1_geom_bat(bat* outBAT_id, wkb** geomWKB, 
bat* xBAT_id, bat* yBAT_id, int* srid);
 geom_export str wkbPointsContains2_geom_bat(bat* outBAT_id, wkb** geomWKB, 
bat* xBAT_id, bat* yBAT_id, int* srid);
-geom_export str wkbPointsDistance_geom_bat(bat* outBAT_id, wkb** geomWKB, bat* 
xBAT_id, bat* yBAT_id, int* srid);
+geom_export str wkbPointsDistance1_geom_bat(bat* outBAT_id, wkb** geomWKB, 
bat* xBAT_id, bat* yBAT_id, int* srid);
+geom_export str wkbPointsDistance2_geom_bat(bat* outBAT_id, wkb** geomWKB, 
bat* xBAT_id, bat* yBAT_id, int* srid);
 
 geom_export str wkbFilterWithImprints_geom_bat(bat*, wkb**, bat*, bat*);
 
diff --git a/geom/monetdb5/geom.mal b/geom/monetdb5/geom.mal
--- a/geom/monetdb5/geom.mal
+++ b/geom/monetdb5/geom.mal
@@ -443,12 +443,13 @@ geom.prelude();
 
 module batgeom;
 
+#the 1 version of the functions use geos the 2 versions have custom 
implementations
+
 command Distance(a:bat[:oid,:wkb], b:bat[:oid,:wkb]) :bat[:oid,:dbl] address 
wkbDistance_bat;
 command Distance(a:wkb, b:bat[:oid,:wkb]) :bat[:oid,:dbl] address 
wkbDistance_geom_bat;
 command Distance(a:bat[:oid,:wkb], b:wkb) :bat[:oid,:dbl] address 
wkbDistance_bat_geom;
-command Distance(g:wkb, x:bat[:oid,:dbl], y:bat[:oid,:dbl], srid:int) 
:bat[:oid,:dbl] address wkbPointsDistance_geom_bat;
-command Distance(g:wkb, x:bat[:oid,:dbl], y:bat[:oid,:dbl], o:bat[:oid,:oid], 
srid:int) :bat[:oid,:dbl] address wkbFilteredPointsDistance_geom_bat;
-
+command Distance1(g:wkb, x:bat[:oid,:dbl], y:bat[:oid,:dbl], srid:int) 
:bat[:oid,:dbl] address wkbPointsDistance1_geom_bat;
+command Distance2(g:wkb, x:bat[:oid,:dbl], y:bat[:oid,:dbl], srid:int) 
:bat[:oid,:dbl] address wkbPointsDistance2_geom_bat;
 
 command Contains(a:bat[:oid,:wkb], b:bat[:oid,:wkb]) :bat[:oid,:bit] address 
wkbContains_bat;
 command Contains(a:wkb, b:bat[:oid,:wkb]) :bat[:oid,:bit] address 
wkbContains_geom_bat;
diff --git a/geom/monetdb5/geomPoints.c b/geom/monetdb5/geomPoints.c
--- a/geom/monetdb5/geomPoints.c
+++ b/geom/monetdb5/geomPoints.c
@@ -255,7 +255,6 @@ inline int isLeft( double P0x, double P0
 
 #define isRight(x0, y0, x1, y1, x2, y2) isLeft(x0, y0, x1, y1, x2, y2)-1
 
-//static str pnpoly_(int *out, int nvert, dbl *vx, dbl *vy, int *point_x, int 
*point_y) {
 static str pnpoly_(int *out, const GEOSGeometry *geosGeometry, int *point_x, 
int *point_y) {
     BAT *bo = NULL, *bpx = NULL, *bpy = NULL;
     dbl *px = NULL, *py = NULL;
@@ -432,16 +431,6 @@ static str pnpolyWithHoles_(int *out, GE
                        else if (yCurrent >= py[i] && yNext <= py[i]) {
                                wn+=isRight( xCurrent, yCurrent, xNext, yNext, 
px[i], py[i]); 
                        }
-
-               //      if (yCurrent <= py[i]) {
-                //             if (yNext > py[i])
-                  //                   if (isLeft( xCurrent, yCurrent, xNext, 
yNext, px[i], py[i]) > 0)
-                    //                         ++wn;
-               //      } else {
-                //             if (yNext  <= py[i])
-                  //                   if (isLeft(xCurrent, yCurrent, xNext, 
yNext, px[i], py[i]) < 0)
-                    //                         --wn;
-               //      }
                }
 
                //It is in one of the holes no reason to check the others
@@ -468,15 +457,6 @@ static str pnpolyWithHoles_(int *out, GE
                else if (yCurrent >= py[i] && yNext <= py[i]) {
                        wn+=isRight( xCurrent, yCurrent, xNext, yNext, px[i], 
py[i]); 
                }       
-               //if (yCurrent <= py[i]) {
-                       //      if (yNext > py[i])
-                       //              if (isLeft( xCurrent, yCurrent, xNext, 
yNext, px[i], py[i]) > 0)
-                  ///                          ++wn;
-               //} else {
-                //     if (yNext  <= py[i])
-                       //              if (isLeft(xCurrent, yCurrent, xNext, 
yNext, px[i], py[i]) < 0)
-                //                             --wn;
-               //}
         }
         *cs++ = wn&1;
     }
@@ -541,7 +521,7 @@ static BAT* BATDistance(wkb** geomWKB, B
                return NULL;
        }
 
-       //set the first idx of the new BAT equal to that of the x BAT (which is 
equal to the y BAT)
+       //set the first idx of the new BAT equal to that of the geometries BAT
        BATseqbase(outBAT, geometriesBAT->hseqbase);
 
        //iterator over the BATs        
@@ -564,7 +544,7 @@ static BAT* BATDistance(wkb** geomWKB, B
        return outBAT;
 }
 
-str wkbPointsDistance_geom_bat(bat* outBAT_id, wkb** geomWKB, bat* xBAT_id, 
bat* yBAT_id, int* srid) {
+str wkbPointsDistance1_geom_bat(bat* outBAT_id, wkb** geomWKB, bat* xBAT_id, 
bat* yBAT_id, int* srid) {
        BAT *xBAT=NULL, *yBAT=NULL, *outBAT=NULL;
        BAT *pointsBAT = NULL, *pointsWithSRIDBAT=NULL;
        str ret=MAL_SUCCEED;
@@ -620,6 +600,123 @@ clean:
        return ret;
 }
 
+
+/* Alternative implementation of distance that computes the euclidean distance 
of two points
+ * (other geometries are not yet supported)
+ * Using the Euclidean distance is appropriate when the geometries are 
expressed in projected
+ * reference system, but what happens with the rest? Maybe we should check nd 
report an error
+ * when a geographic srid is used. PostGIS, however, does not perform any 
check on the srid
+ * and always computes the Euclidean distance 
+ * */
+
+static BAT* point2point_distance(GEOSGeom geosGeometry, BAT *xBAT, BAT *yBAT) {
+       BAT *outBAT = NULL;
+       const GEOSCoordSequence *coordSeq;
+       double xPointCoordinate = 0.0, yPointCoordinate = 0.0;
+       double *xBATCoordinate = NULL, *yBATCoordinate = NULL, *distancesArray 
= NULL;
+       BUN i=0;
+
+       //create a new BAT
+       if ((outBAT = BATnew(TYPE_void, ATOMindex("dbl"), BATcount(xBAT), 
TRANSIENT)) == NULL) {
+               GDKerror("BATDistance: Could not create new BAT for the 
output");
+               return NULL;
+       }
+
+       //set the first idx of the new BAT equal to that of the x BAT (which is 
equal to the y BAT)
+       BATseqbase(outBAT, xBAT->hseqbase);
+
+
+       //the geometry is a point. Get the x, y coordinates of it
+       if(!(coordSeq = GEOSGeom_getCoordSeq(geosGeometry))) {
+               GDKerror("batgeom.Distance: GEOSGeom_getCoordSeq failed");
+               return NULL;
+       }
+       if(GEOSCoordSeq_getX(coordSeq, 0, &xPointCoordinate) == -1) {
+               GDKerror("batgeom.Distance: GEOSCoordSeq_getX failed");
+               return NULL;
+       }       
+       if(GEOSCoordSeq_getY(coordSeq, 0, &yPointCoordinate) == -1) {
+               GDKerror("batgeom.Distance: GEOSCoordSeq_getY failed");
+               return NULL;
+       }
+
+       //get the x and y coordinates from the BATs (fixed size)
+       xBATCoordinate = (double*) Tloc(xBAT, BUNfirst(xBAT));
+       yBATCoordinate = (double*) Tloc(yBAT, BUNfirst(yBAT));
+       distancesArray = (double*) Tloc(outBAT,BUNfirst(outBAT));
+       //iterate
+       for (i = 0; i < BATcount(xBAT); i++) {
+                       distancesArray[i] = 
sqrt(pow((xBATCoordinate[i]-xPointCoordinate), 
2.0)+pow((yBATCoordinate[i]-yPointCoordinate), 2.0));
+/*             if(i%1000 == 0) {
+                       fprintf(stderr, "%u: %f\n", (unsigned int)i, 
distancesArray[i]);
+                       fprintf(stderr, "\t(%f, %f), (%f, %f)\n", 
xPointCoordinate, yPointCoordinate, xBATCoordinate[i], yBATCoordinate[i]);
+               }
+*/
+       }
+
+       BATsetcount(outBAT,BATcount(xBAT));
+       BATderiveProps(outBAT,FALSE);
+
+       return outBAT;
+
+
+}
+
+str wkbPointsDistance2_geom_bat(bat* outBAT_id, wkb** geomWKB, bat* xBAT_id, 
bat* yBAT_id, int* srid) {
+       BAT *xBAT=NULL, *yBAT=NULL, *outBAT=NULL;
+       GEOSGeom geosGeometry;
+       str ret=MAL_SUCCEED;
+
+       //check if geometry a and the points have the same srid
+       if((*geomWKB)->srid != *srid) 
+               return createException(MAL, "batgeom.Distance", "Geometry and 
points should have the same srid");
+
+       //get the descriptors of the BATs
+       if ((xBAT = BATdescriptor(*xBAT_id)) == NULL) {
+               throw(MAL, "batgeom.Distance", RUNTIME_OBJECT_MISSING);
+       }
+       if ((yBAT = BATdescriptor(*yBAT_id)) == NULL) {
+               BBPreleaseref(xBAT->batCacheid);
+               throw(MAL, "batgeom.Distance", RUNTIME_OBJECT_MISSING);
+       }
+       
+       //check if the BATs have dense heads and are aligned
+       if (!BAThdense(xBAT) || !BAThdense(yBAT)) {
+               ret = createException(MAL, "batgeom.Distance", "BATs must have 
dense heads");
+               goto clean;
+       }
+       if(xBAT->hseqbase != yBAT->hseqbase || BATcount(xBAT) != 
BATcount(yBAT)) {
+               ret=createException(MAL, "batgeom.Distance", "BATs must be 
aligned");
+               goto clean;
+       }
+
+       //get the GEOS representation of the geometry
+       if(!(geosGeometry = wkb2geos(*geomWKB)))
+               return createException(MAL, "batgeom.Contains", "wkb2geos 
failed");
+
+       //chech the type of the geometry and choose the appropriate distance 
function
+       switch(GEOSGeomTypeId(geosGeometry)+1) {
+       case wkbPoint:
+               if((outBAT = point2point_distance(geosGeometry, xBAT, yBAT)) == 
NULL) {
+                       ret = createException(MAL, "batgeom.Distance", "Problem 
evalauting the contains");
+                       goto clean;
+               }
+               break;
+       default:
+               return createException(MAL, "batgeom.Distance", "This Geometry 
type is not supported");
+       }
+
+       BBPkeepref(*outBAT_id = outBAT->batCacheid);
+       goto clean;
+
+clean:
+       if(xBAT)
+               BBPreleaseref(xBAT->batCacheid);
+       if(yBAT)
+               BBPreleaseref(yBAT->batCacheid);
+       return ret;
+}
+
 /*
 static BAT* BATMBRfilter(double xmin, double ymin, double xmax, double ymax, 
wkb** geomWKB, int srid) {
        BAT *outBAT = NULL, *leftBottomBAT = NULL, *leftTopBAT = NULL, 
*rightBottomBAT = NULL, *rightTopBAT = NULL;
@@ -808,7 +905,7 @@ str wkbFilterWithImprints_geom_bat(bat* 
                return createException(MAL,"batgeom.Filter","Problem filtering 
yBAT");
        }
 
-fprintf(stderr, "Original MBR contains %u points\n", (unsigned 
int)BATcount(candidateOIDsBAT));
+//fprintf(stderr, "Original MBR contains %u points\n", (unsigned 
int)BATcount(candidateOIDsBAT));
 //BATMBRfilter(xmin, ymin, xmax, ymax, geomWKB, (*geomWKB)->srid);
        BBPreleaseref(xBAT->batCacheid);
        BBPreleaseref(yBAT->batCacheid);
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
@@ -4058,7 +4058,8 @@ CREATE FUNCTION ST_Overlaps(geom1 Geomet
 CREATE FUNCTION ST_Relate(geom1 Geometry, geom2 Geometry, 
intersection_matrix_pattern string) RETURNS boolean EXTERNAL NAME geom."Relate";
 --Distance between Geometries
 CREATE FUNCTION ST_Distance(geom1 Geometry, geom2 Geometry) RETURNS double 
EXTERNAL NAME geom."Distance";
-CREATE FUNCTION ST_Distance(geom1 Geometry, xCoordinate double, yCoordinate 
double, srid integer) RETURNS double EXTERNAL NAME geom."Distance";
+CREATE FUNCTION ST_Distance1(geom1 Geometry, xCoordinate double, yCoordinate 
double, srid integer) RETURNS double EXTERNAL NAME geom."Distance1";
+CREATE FUNCTION ST_Distance2(geom1 Geometry, xCoordinate double, yCoordinate 
double, srid integer) RETURNS double EXTERNAL NAME geom."Distance2";
 --Functions that implement spatial operators
 CREATE FUNCTION ST_Intersection(geom1 Geometry, geom2 Geometry) RETURNS 
Geometry EXTERNAL NAME geom."Intersection";
 CREATE FUNCTION ST_Difference(geom1 Geometry, geom2 Geometry) RETURNS Geometry 
EXTERNAL NAME geom."Differnce";
diff --git a/monetdb5/optimizer/opt_geospatial.c 
b/monetdb5/optimizer/opt_geospatial.c
--- a/monetdb5/optimizer/opt_geospatial.c
+++ b/monetdb5/optimizer/opt_geospatial.c
@@ -118,8 +118,12 @@ int OPTgeospatialImplementation(Client c
 
                                        actions +=2;
                                }
-                       } else if(strcasecmp(getFunctionId(oldInstrPtr[i]), 
"distance") == 0 && strcasecmp(getFunctionId(oldInstrPtr[i+1]), 
"thetasubselect") == 0) {
-                               //I should check the theta comparison. In case 
it is > OR >= then there should be no filtering
+                       } else if((strcasecmp(getFunctionId(oldInstrPtr[i]), 
"distance1") == 0 || strcasecmp(getFunctionId(oldInstrPtr[i]), "distance2") == 
0)  
+                                       && 
strcasecmp(getFunctionId(oldInstrPtr[i+1]), "thetasubselect") == 0) {
+                               //the filter does not make sense if comparison 
is > OR >= 
+                       //      if(strcmp(getArg(oldInstrPtr[i+1],4), ">")==0 
||  strcmp(getArg(oldInstrPtr[i+1],4),">=")==0) {
+                       //              pushInstruction(mb, oldInstrPtr[i]);
+                       //      } else 
                                if(oldInstrPtr[i]->argc == 5) {
                                        InstrPtr bufferInstrPtr;
                                        int bufferReturnId;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to