Changeset: 096b6a5df0c1 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/096b6a5df0c1
Modified Files:
        geom/monetdb5/geom.c
        geom/monetdb5/geom.h
        geom/monetdb5/geom.mal
Branch: geo-update
Log Message:

Added wkbUnionAggrSubGroupedCand function to add support for using st_collect() 
on a group by query.


diffs (truncated from 303 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
@@ -94,6 +94,7 @@ static GeoPoint deg2RadPoint(GeoPoint ge
 }
 
 #if 0
+
 /**
  *  Converts a longitude value in radians to degrees
  *  The normalization part was taken from PostGIS
@@ -153,7 +154,6 @@ static double rad2DegLatitude(double lat
 
        return lat;
 }
-
 /* Converts the GeoPoint from degrees to radians latitude and longitude*/
 static void rad2DegPoint(GeoPoint *geo)
 {
@@ -424,7 +424,7 @@ static GEOSGeom cartesianLineFromGeoPoin
        return GEOSGeom_createLineString(lineSeq);
 }
 
-//TODO Check if this works always
+//TODO Fix this
 //TODO For fast testing, we could use the polygon's minimum bounding box
 //TODO Implement intersection ourselves so we don't use GEOS?
 static bool pointWithinPolygon(GeoPoint point, GeoLines polygonRing)
@@ -448,7 +448,24 @@ static bool pointWithinPolygon(GeoPoint 
 
                //If there is an intersection, a point will be returned (line 
when there is none)
                if (GEOSGeomTypeId(intersectionPoints) == GEOS_POINT)
+               {
                        intersectionNum++;
+                       /*printf("Cross!\n");
+                       CartPoint pDegrees;
+                       GeoPoint pRadians;
+                       double x, y, z;
+                       GEOSGeomGetX(intersectionPoints, &x);
+                       GEOSGeomGetY(intersectionPoints, &y);
+                       GEOSGeomGetZ(intersectionPoints, &z);
+                       pDegrees.x = x;
+                       pDegrees.y = y;
+                       pDegrees.z = z;
+                       pRadians = cart2geo_r(pDegrees);
+                       printf("Intersection Num: %d\n", intersectionNum);
+                       printf("Intersection Point (%f %f)\n", pRadians.lon, 
pRadians.lat);
+                       printf("Line (%f %f)->(%f %f)\nLine (%f %f)->(%f 
%f)\n", lon_o, lat_o, point.lon, point.lat, polygonRing.segments[i].start.lon, 
polygonRing.segments[i].start.lat, polygonRing.segments[i].end.lon, 
polygonRing.segments[i].end.lat);
+                       fflush(stdout);*/
+               }
 
                if (intersectionPoints != NULL)
                        GEOSGeom_destroy(intersectionPoints);
@@ -467,7 +484,11 @@ static double geoDistancePointPolygon(Ge
 {
        //Check if point is in polygon
        if (pointWithinPolygon(point, polygonRing))
+       {
+               printf("Point within Polygon\n");
+               fflush(stdout);
                return 0;
+       }
 
        //Compare Point to the various polygon segments
        return geoDistancePointLine(point, polygonRing);
@@ -576,6 +597,10 @@ static double geoDistanceInternal(GEOSGe
        return min_distance;
 }
 
+/**
+* Distance 
+* 
+**/
 /* Calculates the distance, in meters, between two geographic geometries with 
latitude/longitude coordinates */
 str wkbDistanceGeographic(dbl *out, wkb **a, wkb **b)
 {
@@ -669,6 +694,13 @@ wkbNULLcopy(void)
        return n;
 }
 
+/* returns a pointer to a null wkb */
+static const void *
+wkbNULL(void)
+{
+       return &wkb_nil;
+}
+
 /* the first argument in the functions is the return variable */
 
 #ifdef HAVE_PROJ
@@ -5150,7 +5182,7 @@ str wkbUnion(wkb **out, wkb **a, wkb **b
 }
 
 //Gets a BAT with geometries and returns a single LineString
-str wkbUnionAggr(wkb **outWKB, bat *inBAT_id)
+str wkbUnionAggr(wkb **outWKB, const bat *inBAT_id)
 {
        BAT *inBAT = NULL;
        BATiter inBAT_iter;
@@ -5205,6 +5237,132 @@ str wkbUnionAggr(wkb **outWKB, bat *inBA
        return err;
 }
 
+static str wkbUnionAggrSubGroupedCand(bat *outid, const bat *bid, const bat 
*gid, const bat *eid, const bat *sid, const bit *skip_nils)
+{
+       BAT *b = NULL, *g = NULL, *e = NULL, *s = NULL, *out = NULL;
+       str msg = MAL_SUCCEED;
+       oid min, max;
+       BUN ngrp, ncand;
+       struct canditer ci;
+       const char *err;
+       const oid *gids = NULL;
+       BATiter bi;
+
+       //TODO Do we need to use skip_nils?
+       (void)skip_nils;
+
+       //Get the BAT descriptors for the value bat + the other 3 optional BATs
+       if ((b = BATdescriptor(*bid)) == NULL ||
+               (gid && !is_bat_nil(*gid) && (g = BATdescriptor(*gid)) == NULL) 
||
+               (eid && !is_bat_nil(*eid) && (e = BATdescriptor(*eid)) == NULL) 
||
+               (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL))
+       {
+               msg = createException(MAL, "geom.Union", 
RUNTIME_OBJECT_MISSING);
+               goto free;
+       }
+
+       //Fill in the values of the group aggregate operation
+       if ((err = BATgroupaggrinit(b, g, e, s, &min, &max, &ngrp, &ci, 
&ncand)) != NULL)
+       {
+               msg = createException(MAL, "geom.Union", "%s", err);
+               goto free;
+       }
+
+       //Create a new BAT column of wkb type, with lenght equal to the number 
of groups
+       if (((out = COLnew(min, ATOMindex("wkb"), ngrp, TRANSIENT))) == NULL)
+       {
+               createException(MAL, "geom.Union", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+               goto free;
+       }
+
+       //Allocate space for the intermediate unions of wkb's
+       wkb **unions = GDKzalloc(sizeof(wkb *) * ngrp);
+
+       bi = bat_iterator(b);
+       if (g && !BATtdense(g))
+               gids = (const oid *)Tloc(g, 0);
+
+       //Loop through the input rows and do the union operation for each 
different group
+       for (BUN i = 0; i < ncand; i++)
+       {
+               //Get the index of the next candidate
+               oid o = canditer_next(&ci);
+               BUN p = o - b->hseqbase;
+               wkb *inWKB = (wkb *)BUNtvar(bi, p);
+               //Determine the group id
+               oid grp = gids ? gids[p] : g ? min + (oid)p : 0;
+
+               char *geomSTR;
+               wkbAsText(&geomSTR, &inWKB, NULL);
+               printf("Row %zu: %s\n", i, geomSTR);
+               fflush(stdout);
+
+               if (unions[grp] == NULL)
+               {
+                       //First value for a group, copy input wkb
+                       if ((msg = wkbFromWKB(&(unions[grp]), &inWKB)) != 
MAL_SUCCEED)
+                       {
+                               msg = createException(MAL, "geom.Union", "%s", 
msg);
+                               goto free;
+                       }
+               }
+               else
+               {
+                       if ((err = wkbUnion(&(unions[grp]), &(unions[grp]), 
&inWKB)) != MAL_SUCCEED)
+                       {
+                               msg = createException(MAL, "geom.Union", "%s", 
err);
+                               goto free;
+                       }
+               }
+               //printf("Candidate %d\no = %zu\ngrp = %zu\n", (int)i, o, grp);
+               //printf("outWKB Len: %d\ninWKB Len: %d\n", unions[grp]->len, 
inWKB->len);
+       }
+
+       if (BUNappendmulti(out, unions, ngrp, false) != GDK_SUCCEED)
+       {
+               msg = createException(MAL, "geom.Union", SQLSTATE(38000) 
"BUNappend operation failed");
+               for (BUN i = 0; i < ngrp; i++)
+                       GDKfree(unions[i]);
+               GDKfree(unions);
+               goto free;
+       }
+
+       for (BUN i = 0; i < ngrp; i++)
+               GDKfree(unions[i]);
+       GDKfree(unions);
+
+       BBPkeepref(*outid = out->batCacheid);
+       BBPunfix(b->batCacheid);
+       if (g)
+               BBPunfix(g->batCacheid);
+       if (e)
+               BBPunfix(e->batCacheid);
+       if (s)
+               BBPunfix(s->batCacheid);
+       return MAL_SUCCEED;
+free:
+       if (b)
+               BBPunfix(b->batCacheid);
+       if (g)
+               BBPunfix(g->batCacheid);
+       if (e)
+               BBPunfix(e->batCacheid);
+       if (s)
+               BBPunfix(s->batCacheid);
+       return msg;
+}
+
+//static str wkbUnionAggrSubGrouped(wkb **outWKB, const bat *bid, const bat 
*gid, const bat *eid, const bit *skip_nils, const bit *abort_on_error)
+static str wkbUnionAggrSubGrouped(bat *out, const bat *bid, const bat *gid, 
const bat *eid, const bit *skip_nils)
+{
+       return wkbUnionAggrSubGroupedCand(out, bid, gid, eid, NULL, skip_nils);
+}
+
+static str wkbUnionAggrGrouped(bat *out, const bat *bid, const bat *gid, const 
bat *eid)
+{
+       return wkbUnionAggrSubGroupedCand(out, bid, gid, eid, NULL, &(bit){1});
+}
+
 str wkbDifference(wkb **out, wkb **a, wkb **b)
 {
        return wkbanalysis(out, a, b, GEOSDifference, "geom.Difference");
@@ -6106,13 +6264,6 @@ wkbHASH(const void *W)
        return h;
 }
 
-/* returns a pointer to a null wkb */
-static const void *
-wkbNULL(void)
-{
-       return &wkb_nil;
-}
-
 static int
 wkbCOMP(const void *L, const void *R)
 {
@@ -7529,8 +7680,15 @@ static mel_func geom_init_funcs[] = {
        command("geom", "Length", wkbLength, false, "Returns the cartesian 2D 
length of the geometry if it is a linestrin or multilinestring", args(1, 2, 
arg("", dbl), arg("w", wkb))),
        command("geom", "ConvexHull", wkbConvexHull, false, "Returns a geometry 
that represents the convex hull of this geometry. The convex hull of a geometry 
represents the minimum convex geometry that encloses all geometries within the 
set.", args(1, 2, arg("", wkb), arg("w", wkb))),
        command("geom", "Intersection", wkbIntersection, false, "Returns a 
geometry that represents the point set intersection of the Geometries a, b", 
args(1, 3, arg("", wkb), arg("a", wkb), arg("b", wkb))),
+
        command("geom", "Union", wkbUnion, false, "Returns a geometry that 
represents the point set union of the Geometries a, b", args(1, 3, arg("", 
wkb), arg("a", wkb), arg("b", wkb))),
        command("geom", "Union", wkbUnionAggr, false, "Gets a BAT with 
geometries and returns their union", args(1, 2, arg("", wkb), batarg("a", 
wkb))),
+
+       command("geom", "Union", wkbUnionAggrGrouped, false, "Gets a BAT with 
geometries and returns their union", args(1, 4, batarg("", wkb), batarg("val", 
wkb), batarg("g", oid), batargany("e", 1))),
+       //command("geom", "subUnion", wkbUnionAggrSubGrouped, false, "Gets a 
BAT with geometries and returns their union", args(1, 6, arg("", wkb), 
batarg("val", wkb), batarg("g", oid), batargany("e", 1), arg("skip_nils", bit), 
arg("abort_on_error", bit))),
+       command("geom", "subUnion", wkbUnionAggrSubGrouped, false, "Gets a BAT 
with geometries and returns their union", args(1, 5, batarg("", wkb), 
batarg("val", wkb), batarg("g", oid), batarg("e", oid), arg("skip_nils", bit))),
+       command("geom", "subUnion", wkbUnionAggrSubGroupedCand, false, "Gets a 
BAT with geometries and returns their union", args(1, 7, batarg("", wkb), 
batarg("val", wkb), batarg("g", oid), batargany("e", 1), batarg("g", oid), 
arg("skip_nils", bit), arg("abort_on_error", bit))),
+
        command("geom", "Difference", wkbDifference, false, "Returns a geometry 
that represents that part of geometry A that does not intersect with geometry 
B", args(1, 3, arg("", wkb), arg("a", wkb), arg("b", wkb))),
        command("geom", "SymDifference", wkbSymDifference, false, "Returns a 
geometry that represents the portions of A and B that do not intersect", 
args(1, 3, arg("", wkb), arg("a", wkb), arg("b", wkb))),
        command("geom", "Buffer", wkbBuffer, false, "Returns a geometry that 
represents all points whose distance from this geometry is less than or equal 
to distance. Calculations are in the Spatial Reference System of this 
Geometry.", args(1, 3, arg("", wkb), arg("a", wkb), arg("distance", dbl))),
diff --git a/geom/monetdb5/geom.h b/geom/monetdb5/geom.h
--- a/geom/monetdb5/geom.h
+++ b/geom/monetdb5/geom.h
@@ -184,7 +184,10 @@ geom_export str wkbLength(dbl *out, wkb 
 geom_export str wkbConvexHull(wkb **out, wkb **geom);
 geom_export str wkbIntersection(wkb **out, wkb **a, wkb **b);
 geom_export str wkbUnion(wkb **out, wkb **a, wkb **b);
-geom_export str wkbUnionAggr(wkb **outWKB, bat *inBAT_id);
+
+geom_export str wkbUnionAggr(wkb **outWKB, const bat *inBAT_id);
+
+
 geom_export str wkbDifference(wkb **out, wkb **a, wkb **b);
 geom_export str wkbSymDifference(wkb **out, wkb **a, wkb **b);
 geom_export str wkbBuffer(wkb **out, wkb **geom, dbl *distance);
diff --git a/geom/monetdb5/geom.mal b/geom/monetdb5/geom.mal
--- a/geom/monetdb5/geom.mal
+++ b/geom/monetdb5/geom.mal
@@ -154,10 +154,22 @@ command ConvexHull(w:wkb) :wkb address w
 comment "Returns a geometry that represents the convex hull of this geometry. 
The convex hull of a geometry represents the minimum convex geometry that 
encloses all geometries within the set.";
 command Intersection(a:wkb, b:wkb) :wkb address wkbIntersection
 comment "Returns a geometry that represents the point set intersection of the 
Geometries a, b";
+
 command Union(a:wkb, b:wkb) :wkb address wkbUnion
 comment "Returns a geometry that represents the point set union of the 
Geometries a, b";
 command Union(a:bat[:wkb]) :wkb address wkbUnionAggr
 comment "Gets a BAT with geometries and returns their union"; 
+
+# TODO: Fix descriptions
+command Union(val:bat[:wkb], g:bat[:oid], e:bat[:any_1]) :bat[:wkb] address 
wkbUnionAggrGrouped
+comment "Gets a BAT with geometries and returns their union"; 
+# TODO: Find out why there is only one bit value
+# command subUnion(val:bat[:wkb], g:bat[:oid], e:bat[:any_1], skip_nils:bit, 
abort_on_error:bit) :bat[:wkb] address wkbUnionAggrSubGrouped
+command subUnion(val:bat[:wkb], g:bat[:oid], e:bat[:oid], skip_nils:bit) 
:bat[:wkb] address wkbUnionAggrSubGrouped
+comment "Gets a BAT with geometries and returns their union"; 
+command subUnion(val:bat[:wkb], g:bat[:oid], e:bat[:any_1], s:bat[:oid], 
skip_nils:bit, abort_on_error:bit) :bat[:wkb] address wkbUnionAggrSubGroupedCand
+comment "Gets a BAT with geometries and returns their union"; 
+
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to