Changeset: 19bc280b55bf for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=19bc280b55bf
Modified Files:
        geom/monetdb5/geom.h
        geom/monetdb5/geomPoints.c
Branch: geo
Log Message:

ROmulos contains


diffs (281 lines):

diff --git a/geom/monetdb5/geom.h b/geom/monetdb5/geom.h
--- a/geom/monetdb5/geom.h
+++ b/geom/monetdb5/geom.h
@@ -271,3 +271,6 @@ geom_export str wkbPointsDistance_geom_b
 geom_export str wkbFilteredPointsDistance_geom_bat(bat* outBAT_id, wkb** 
geomWKB, bat* xBAT_id, bat* yBAT_id, bat* OIDsBAT_id, int* srid);
 
 geom_export str wkbFilterWithImprints_geom_bat(bat*, wkb**, bat*, bat*);
+
+geom_export double isLeft( double P0x, double P0y, double P1x, double P1y, 
double P2x, double P2y);
+
diff --git a/geom/monetdb5/geomPoints.c b/geom/monetdb5/geomPoints.c
--- a/geom/monetdb5/geomPoints.c
+++ b/geom/monetdb5/geomPoints.c
@@ -248,6 +248,267 @@ clean:
        return ret;
 }
 
+//Aternative implementation of contains using ???
+inline double isLeft( double P0x, double P0y, double P1x, double P1y, double 
P2x, double P2y) {
+    return ( (P1x - P0x) * (P2y - P0y) - (P2x -  P0x) * (P1y - P0y) );
+}
+
+//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;
+    BUN i = 0;
+    unsigned int j = 0;
+    struct timeval stop, start;
+    unsigned long long t;
+    bte *cs = NULL;
+
+       const GEOSCoordSequence *coordSeq;
+       unsigned int geometryPointsNum=0 ;
+
+       /* get the coordinates of the points comprising the geometry */
+       if(!(coordSeq = GEOSGeom_getCoordSeq(geosGeometry)))
+               return createException(MAL, "batgeom.Contains", 
"GEOSGeom_getCoordSeq failed");
+       
+       /* get the number of points in the geometry */
+       GEOSCoordSeq_getSize(coordSeq, &geometryPointsNum);
+
+       /*Get the BATs*/
+       if ((bpx = BATdescriptor(*point_x)) == NULL) {
+               throw(MAL, "geom.point", RUNTIME_OBJECT_MISSING);
+       }
+
+       if ((bpy = BATdescriptor(*point_y)) == NULL) {
+               BBPreleaseref(bpx->batCacheid);
+               throw(MAL, "geom.point", RUNTIME_OBJECT_MISSING);
+       }
+
+       /*Check BATs alignment*/
+       if ( bpx->htype != TYPE_void || bpy->htype != TYPE_void ||bpx->hseqbase 
!= bpy->hseqbase || BATcount(bpx) != BATcount(bpy)) {
+               BBPreleaseref(bpx->batCacheid);
+               BBPreleaseref(bpy->batCacheid);
+               throw(MAL, "geom.point", "both point bats must have dense and 
aligned heads");
+       }
+
+       /*Create output BAT*/
+       if ((bo = BATnew(TYPE_void, ATOMindex("bte"), BATcount(bpx), 
TRANSIENT)) == NULL) {
+               BBPreleaseref(bpx->batCacheid);
+               BBPreleaseref(bpy->batCacheid);
+               throw(MAL, "geom.point", MAL_MALLOC_FAIL);
+       }
+       BATseqbase(bo, bpx->hseqbase);
+
+       /*Iterate over the Point BATs and determine if they are in Polygon 
represented by vertex BATs*/
+       px = (dbl *) Tloc(bpx, BUNfirst(bpx));
+       py = (dbl *) Tloc(bpy, BUNfirst(bpx));
+
+       gettimeofday(&start, NULL);
+       cs = (bte*) Tloc(bo,BUNfirst(bo));
+       for (i = 0; i < BATcount(bpx); i++) { //for each point in the x, y BATs
+                       int wn = 0;
+               for (j = 0; j < geometryPointsNum; j++) { //check each point in 
the geometry (the exteriorRing)
+                       double xCurrent=0.0, yCurrent=0.0, xNext=0.0, yNext=0.0;
+                       if(GEOSCoordSeq_getX(coordSeq, j, &xCurrent) == -1 || 
GEOSCoordSeq_getX(coordSeq, j+1, &xNext) == -1)
+                               return createException(MAL, "batgeom.Contains", 
"GEOSCoordSeq_getX failed");
+                       if(GEOSCoordSeq_getY(coordSeq, j, &yCurrent) == -1 || 
GEOSCoordSeq_getY(coordSeq, j+1, &yNext) == -1)
+                               return createException(MAL, "batgeom.Contains", 
"GEOSCoordSeq_getY failed");
+                       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;
+       }
+    gettimeofday(&stop, NULL);
+    t = 1000 * (stop.tv_sec - start.tv_sec) + (stop.tv_usec - start.tv_usec) / 
1000;
+    printf("took %llu ms\n", t);
+
+    gettimeofday(&start, NULL);
+    //BATsetcount(bo,cnt);
+    BATderiveProps(bo,FALSE);
+    gettimeofday(&stop, NULL);
+    t = 1000 * (stop.tv_sec - start.tv_sec) + (stop.tv_usec - start.tv_usec) / 
1000;
+    printf("Append took %llu ms\n", t);
+
+    BBPreleaseref(bpx->batCacheid);
+    BBPreleaseref(bpy->batCacheid);
+    BBPkeepref(*out = bo->batCacheid);
+    return MAL_SUCCEED;
+}
+
+//static str pnpolyWithHoles_(int *out, int nvert, dbl *vx, dbl *vy, int 
nholes, dbl **hx, dbl **hy, int *hn, int *point_x, int *point_y) {
+static str pnpolyWithHoles_(int *out, GEOSGeom geosGeometry, unsigned int 
interiorRingsNum, int *point_x, int *point_y) {
+    BAT *bo = NULL, *bpx = NULL, *bpy;
+    dbl *px = NULL, *py = NULL;
+    BUN i = 0;
+    unsigned int j = 0, h = 0;
+    bte *cs = NULL;
+
+       const GEOSGeometry *exteriorRingGeometry;
+       const GEOSCoordSequence *exteriorRingCoordSeq;
+       unsigned int exteriorRingPointsNum=0 ;
+
+    /*Get the BATs*/
+    if ((bpx = BATdescriptor(*point_x)) == NULL) {
+        throw(MAL, "geom.point", RUNTIME_OBJECT_MISSING);
+    }
+    if ((bpy = BATdescriptor(*point_y)) == NULL) {
+        BBPreleaseref(bpx->batCacheid);
+        throw(MAL, "geom.point", RUNTIME_OBJECT_MISSING);
+    }
+
+    /*Check BATs alignment*/
+    if ( bpx->htype != TYPE_void ||
+            bpy->htype != TYPE_void ||
+            bpx->hseqbase != bpy->hseqbase ||
+            BATcount(bpx) != BATcount(bpy)) {
+        BBPreleaseref(bpx->batCacheid);
+        BBPreleaseref(bpy->batCacheid);
+        throw(MAL, "geom.point", "both point bats must have dense and aligned 
heads");
+    }
+
+    /*Create output BAT*/
+    if ((bo = BATnew(TYPE_void, ATOMindex("bte"), BATcount(bpx), TRANSIENT)) 
== NULL) {
+        BBPreleaseref(bpx->batCacheid);
+        BBPreleaseref(bpy->batCacheid);
+        throw(MAL, "geom.point", MAL_MALLOC_FAIL);
+    }
+    BATseqbase(bo, bpx->hseqbase);
+
+       //get the exterior ring of the geometry 
+       if(!(exteriorRingGeometry = GEOSGetExteriorRing(geosGeometry)))
+               return createException(MAL, "batgeom.Contains", 
"GEOSGetExteriorRing failed");
+
+       /* get the coordinates of the points comprising the exteriorRing */
+       if(!(exteriorRingCoordSeq = GEOSGeom_getCoordSeq(exteriorRingGeometry)))
+               return createException(MAL, "batgeom.Contains", 
"GEOSGeom_getCoordSeq failed");
+       
+       /* get the number of points in the exterior ring */
+       GEOSCoordSeq_getSize(exteriorRingCoordSeq, &exteriorRingPointsNum);
+
+    /*Iterate over the Point BATs and determine if they are in Polygon 
represented by vertex BATs*/
+    px = (dbl *) Tloc(bpx, BUNfirst(bpx));
+    py = (dbl *) Tloc(bpy, BUNfirst(bpx));
+   // cnt = BATcount(bpx);
+    cs = (bte*) Tloc(bo,BUNfirst(bo));
+    for (i = 0; i < BATcount(bpx); i++) {
+        int wn = 0;
+
+        //First check the holes
+        for (h = 0; h < interiorRingsNum; h++) {
+               const GEOSGeometry *interiorRingGeometry;
+               const GEOSCoordSequence *interiorRingCoordSeq;
+               unsigned int interiorRingPointsNum=0 ;
+
+               //get the interior ring
+               if(!(interiorRingGeometry = GEOSGetInteriorRingN(geosGeometry, 
h)))
+                       return createException(MAL, "batgeom.Contains", 
"GEOSGetInteriorRingN failed");
+               
+               /* get the coordinates of the points comprising the interior 
ring */
+               if(!(interiorRingCoordSeq = 
GEOSGeom_getCoordSeq(interiorRingGeometry)))
+                       return createException(MAL, "batgeom.Contains", 
"GEOSGeom_getCoordSeq failed");
+       
+               /* get the number of points in the interior ring */
+               GEOSCoordSeq_getSize(interiorRingCoordSeq, 
&interiorRingPointsNum);
+            
+               wn = 0;
+               for (j = 0; j < interiorRingPointsNum; j++) { //check each 
point in the interior ring
+                       double xCurrent=0.0, yCurrent=0.0, xNext=0.0, yNext=0.0;
+
+                       if(GEOSCoordSeq_getX(interiorRingCoordSeq, j, 
&xCurrent) == -1 || GEOSCoordSeq_getX(interiorRingCoordSeq, j+1, &xNext) == -1)
+                               return createException(MAL, "batgeom.Contains", 
"GEOSCoordSeq_getX failed");
+                       if(GEOSCoordSeq_getY(interiorRingCoordSeq, j, 
&yCurrent) == -1 || GEOSCoordSeq_getY(interiorRingCoordSeq, j+1, &yNext) == -1)
+                               return createException(MAL, "batgeom.Contains", 
"GEOSCoordSeq_getY failed");
+                       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
+               if (wn)
+                       break;
+        }
+
+       //found in the holes there is no reason to check the external ring
+        if (wn) 
+            continue;
+
+        /*If not in any of the holes, check inside the Polygon*/
+       for (j = 0; j < exteriorRingPointsNum; j++) { //check each point in the 
exterior ring)
+               double xCurrent=0.0, yCurrent=0.0, xNext=0.0, yNext=0.0;
+               if(GEOSCoordSeq_getX(exteriorRingCoordSeq, j, &xCurrent) == -1 
|| GEOSCoordSeq_getX(exteriorRingCoordSeq, j+1, &xNext) == -1)
+                       return createException(MAL, "batgeom.Contains", 
"GEOSCoordSeq_getX failed");
+               if(GEOSCoordSeq_getY(exteriorRingCoordSeq, j, &yCurrent) == -1 
|| GEOSCoordSeq_getY(exteriorRingCoordSeq, j+1, &yNext) == -1)
+                       return createException(MAL, "batgeom.Contains", 
"GEOSCoordSeq_getY failed");
+               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;
+    }
+   // BATsetcount(bo,cnt);
+    BATderiveProps(bo,FALSE);
+    BBPreleaseref(bpx->batCacheid);
+    BBPreleaseref(bpy->batCacheid);
+    BBPkeepref(*out = bo->batCacheid);
+    return MAL_SUCCEED;
+}
+
+#define POLY_NUM_VERT 120
+#define POLY_NUM_HOLE 10
+
+str wkbPointsContains2_geom_bat(bat* out, wkb** geomWKB, bat* point_x, bat* 
point_y, int* srid) {
+       int interiorRingsNum = 0;
+       GEOSGeom geosGeometry;
+       str msg = NULL;
+
+       //check if geometry a and the points have the same srid
+       if((*geomWKB)->srid != *srid) 
+               return createException(MAL, "batgeom.Contains", "Geometry and 
points should have the same srid");
+
+       //get the GEOS representation of the geometry
+       if(!(geosGeometry = wkb2geos(*geomWKB)))
+               return createException(MAL, "batgeom.Contains", "wkb2geos 
failed");
+       //check if the geometry is a polygon
+       if((GEOSGeomTypeId(geosGeometry)+1) != wkbPolygon)
+               return createException(MAL, "batgeom.Contains", "Geometry 
should be a polygon");
+
+       //get the number of interior rings of the polygon
+       if((interiorRingsNum = GEOSGetNumInteriorRings(geosGeometry)) == -1) {
+               return createException(MAL, "batgeom.Contains", 
"GEOSGetNumInteriorRings failed");
+       }
+
+       if(interiorRingsNum > 0) {
+               msg = pnpolyWithHoles_(out, geosGeometry, interiorRingsNum, 
point_x, point_y);
+       } else {
+               //get the exterior ring
+               const GEOSGeometry *exteriorRingGeometry;
+               if(!(exteriorRingGeometry = GEOSGetExteriorRing(geosGeometry)))
+                       return createException(MAL, "batgeom.Contains", 
"GEOSGetExteriorRing failed");
+               msg = pnpoly_(out, exteriorRingGeometry, point_x, point_y);
+       }
+       return msg;
+}
+
+
 str wkbFilteredPointsContains_geom_bat(bat* outBAT_id, wkb** geomWKB, bat* 
xBAT_id, bat* yBAT_id, bat* candidatesBAT_id, int* srid) {
        BAT *xBAT=NULL, *yBAT=NULL, *candidatesBAT=NULL, *outBAT=NULL;
        BAT *pointsBAT = NULL, *pointsWithSRIDBAT=NULL;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to