Changeset: 3edb154ecc00 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3edb154ecc00
Modified Files:
        geom/monetdb5/geom.c
        geom/monetdb5/geom.h
        geom/monetdb5/geom.mal
Branch: sfcgal
Log Message:

Start the implementation of sub functions to be used in spatial aggregations. 
subCollect is the first one. It uses the generic function BATgroupWKBWKBtoWKB, 
to each you pass the CollectAppend (starts with empty collection for each group 
and then it adds geoms to the Collection as it walks over b). It works similar 
to aggr.sum operator.


diffs (truncated from 468 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
@@ -403,7 +403,7 @@ wkbTransform(wkb **transformedWKB, wkb *
        (void) srid_dst;
        (void) proj4_src_str;
        (void) proj4_dst_str;
-       throw(MAL, "geom.Transform", "Function Not Implemented");
+       throw(MAL, "geom.Transform", "Function Not Implemented because proj4 is 
not available.");
 #else
        projPJ proj4_src, proj4_dst;
        GEOSGeom geosGeometry, transformedGeosGeometry;
@@ -4885,6 +4885,387 @@ wkbCollectCascade(wkb **outWKB, bat *inB
        return MAL_SUCCEED;
 }
 
+static str wkbCollectAppend(wkb **out, wkb **geom1WKB, wkb **geom2WKB);
+
+static str
+BATgroupWKBWKBtoWKB(bat *outBAT_id, BAT *b, BAT *g, BAT *e, int skip_nils, oid 
min, oid max, BUN ngrp, BUN start, BUN end, wkb **empty_geoms, str (*func) (wkb 
**, wkb **, wkb**), const char* name)
+{
+    BAT *outBAT = NULL;
+    BATiter bBAT_iter;
+    BUN nils = 0;
+    str err, msg;
+    int nonil, i = 0, j = 0;
+    wkb **aWKBs = NULL, **outWKBs = NULL, **grpWKBs = NULL;
+       const oid *restrict gids;
+    wkb *bWKB = NULL;
+    int gid;
+
+    if (g == NULL) {
+        throw(MAL, "BATgroup%s: b and g must be aligned\n", name);
+    }
+
+    if (BATcount(b) == 0 || ngrp == 0) {
+        /* trivial: no collects, so return bat aligned with g with
+         *          * nil in the tail */
+        outBAT = BATconstant(ngrp == 0 ? 0 : min, ATOMindex("wkb"), 
ATOMnilptr(ATOMindex("wkb")), ngrp, TRANSIENT);
+        *outBAT_id = outBAT->batCacheid;
+        return MAL_SUCCEED;
+    }
+
+    outBAT = COLnew(min, ATOMindex("wkb"), ngrp, TRANSIENT);
+    if (outBAT == NULL) {
+        *outBAT_id = bat_nil;
+        throw(MAL, "geom.", name, MAL_MALLOC_FAIL);
+    }
+
+    if (BATtdense(g))
+        gids = NULL;
+    else
+        gids = (const oid *) Tloc(g, BUNfirst(g) + start);
+
+    /*Allocate structures*/
+    if ((aWKBs = (wkb **) GDKzalloc(sizeof(wkb*)*ngrp)) == NULL) {
+        BBPunfix(outBAT->batCacheid);
+        *outBAT_id = bat_nil;
+        throw(MAL, "geom.", name, MAL_MALLOC_FAIL);
+    }
+    if ((outWKBs = (wkb **) GDKzalloc(sizeof(wkb*)*ngrp)) == NULL) {
+        GDKfree(aWKBs);
+        BBPunfix(outBAT->batCacheid);
+        *outBAT_id = bat_nil;
+        throw(MAL, "geom.", name, MAL_MALLOC_FAIL);
+    }
+    if ((grpWKBs = (wkb **) GDKzalloc(sizeof(wkb*)*ngrp)) == NULL) {
+        GDKfree(aWKBs);
+        GDKfree(outWKBs);
+        BBPunfix(outBAT->batCacheid);
+        *outBAT_id = bat_nil;
+        throw(MAL, "geom.", name, MAL_MALLOC_FAIL);
+    }
+
+    bBAT_iter = bat_iterator(b);
+    nonil = b->tnonil;
+    if (ngrp == 1) {
+        /* single group, no candidate list */
+        ALGODEBUG fprintf(stderr,
+                "#%s: no candidates, no groups; "
+                "start " BUNFMT ", end " BUNFMT
+                ", nonil = %d\n",
+                name, start, end, nonil);
+        if (nonil) {
+            aWKBs[0] = empty_geoms[0];
+
+            // add one more segment for each following row
+            for (i = start; i < end; i++) {
+                bWKB = (wkb *) BUNtail(bBAT_iter, i);
+                outWKBs[0] = NULL;
+
+                if ( (err = (*func)(&outWKBs[0], &aWKBs[0], &bWKB)) != 
MAL_SUCCEED )
+                    break;
+                else
+                    *aWKBs[0] = *outWKBs[0];
+            }
+        } else {
+            nils = 1;
+            aWKBs[0] = empty_geoms[0];
+
+            for (i = start; i < end && nils == 0; i++) {
+                bWKB = (wkb *) BUNtail(bBAT_iter, i);
+
+                if (wkb_isnil(bWKB)) {
+                    if (!skip_nils) {
+                        if ((outWKBs[0] = wkbNULLcopy()) == NULL) {
+                            GDKfree(aWKBs);
+                            GDKfree(outWKBs);
+                            GDKfree(grpWKBs);
+                            BBPunfix(outBAT->batCacheid);
+                            outBAT = NULL;
+                            throw(MAL, "geom.", name, MAL_MALLOC_FAIL);
+                        }
+                        nils = 1;
+                    }
+                } else {
+                    if ( (err = (*func) (&outWKBs[0], &aWKBs[0], &bWKB)) != 
MAL_SUCCEED )
+                        break;
+                    else
+                        aWKBs[0] = outWKBs[0];
+                }
+            }
+        }
+        grpWKBs[0] = outWKBs[0];
+    } else {
+        /* multiple groups, no candidate list */
+        ALGODEBUG fprintf(stderr,
+                "#%s: no candidates, with groups; "
+                "start " BUNFMT ", end " BUNFMT
+                "\n",
+                name, start, end);
+        for (i = start; i < end; i++) {
+            if (gids == NULL ||
+                    (gids[i] >= min && gids[i] <= max)) {
+                gid = gids ? gids[i] - min : (oid) i;
+                
+                /*It will be empty anyway*/
+                if (grpWKBs[gid])
+                    continue;
+
+                /*Check if you already have aWKB*/
+                if (aWKBs[gid] == NULL) {
+                    aWKBs[gid] = empty_geoms[gid];
+                }
+                /*Lets look for bWKB*/
+                bWKB = (wkb *) BUNtail(bBAT_iter, i);
+                if (wkb_isnil(bWKB)) {
+                    if (!skip_nils) {
+                        if ((grpWKBs[gid] = empty_geoms[gid]) == NULL) {
+                            GDKfree(aWKBs);
+                            GDKfree(outWKBs);
+                            GDKfree(grpWKBs);
+                            BBPunfix(outBAT->batCacheid);
+                            outBAT = NULL;
+                            throw(MAL, "geom.", name, MAL_MALLOC_FAIL);
+                        }
+                        nils++;
+                    }
+                } else {
+                    if ( (msg = (*func)(&outWKBs[gid], &aWKBs[gid], &bWKB)) != 
MAL_SUCCEED ) {
+                        GDKfree(aWKBs);
+                        GDKfree(outWKBs);
+                        GDKfree(grpWKBs);
+                        BBPunfix(outBAT->batCacheid);
+                        outBAT = NULL;
+                        err = createException(MAL, name, msg);
+                        GDKfree(msg);
+                        return err;
+                    }
+                    else
+                        aWKBs[gid] = outWKBs[gid];
+                }
+            }
+            if (!outWKBs[gid])
+                outWKBs[gid] = aWKBs[gid];
+        }
+
+        for (i = start; i < end; i++) {
+            if (gids == NULL || (gids[i] >= min && gids[i] <= max)) {
+                gid = gids ? gids[i] - min : (oid) i;
+                if (grpWKBs[gid] == NULL) {
+                    bit empty = 0;
+                    assert(!wkb_isnil(outWKBs[gid]));
+                    grpWKBs[gid] = outWKBs[gid];
+                }
+            }
+        }
+    }
+
+    /*Debug*/
+#ifdef GEOM_DEBUG
+    for (i = 0; i < ngrp; i++) {
+               char *geomSTR;
+               if ((err = wkbAsText(&geomSTR, &grpWKBs[i], NULL)) != 
MAL_SUCCEED) {
+            GDKfree(aWKBs);
+            GDKfree(outWKBs);
+            GDKfree(grpWKBs);
+            BBPunfix(outBAT->batCacheid);
+            outBAT = NULL;
+               throw(MAL, "geom.", name, "wkbAsText failed");
+        }
+        fprintf(stdout, "%d, %s\n", i, geomSTR);
+    }
+#endif
+
+    /*Add the wkbs to the output bat*/
+    for (i = 0; i < ngrp; i++) {
+        if ( (BUNappend(outBAT, grpWKBs[i], TRUE) != GDK_SUCCEED) ) {
+            GDKfree(aWKBs);
+            GDKfree(outWKBs);
+            GDKfree(grpWKBs);
+            BBPunfix(outBAT->batCacheid);
+            outBAT = NULL;
+               throw(MAL, "geom.", name, "BUNappend failed");
+        }
+    }
+
+    if (nils < BUN_NONE) {
+        BATsetcount(outBAT, ngrp);
+        outBAT->tkey = BATcount(outBAT) <= 1; 
+        outBAT->tsorted = BATcount(outBAT) <= 1; 
+        outBAT->trevsorted = BATcount(outBAT) <= 1;
+        outBAT->tnil = nils != 0;
+        outBAT->tnonil = nils == 0;
+    } else {
+        BBPunfix(outBAT->batCacheid);
+        outBAT = NULL;
+    }
+
+    if (aWKBs)
+        GDKfree(aWKBs);
+    if (outWKBs)
+        GDKfree(outWKBs);
+    if (grpWKBs)
+        GDKfree(grpWKBs);
+
+    *outBAT_id = outBAT->batCacheid;
+    return MAL_SUCCEED;
+}
+
+static str
+wkbCollectAppend(wkb **out, wkb **geom1WKB, wkb **geom2WKB)
+{
+       GEOSGeom outGeometry, geom1Geometry, geom2Geometry;
+    GEOSGeometry **geomGeometries = NULL;
+       str err = MAL_SUCCEED;
+    int i, type, geometry1Type, geometry2Type, num_geoms = 0;
+
+       if (wkb_isnil(*geom1WKB) || wkb_isnil(*geom2WKB)) {
+               if ((*out = wkbNULLcopy()) == NULL)
+            throw(MAL, "geom.collect", MAL_MALLOC_FAIL);
+        return MAL_SUCCEED;
+    }
+
+    geom1Geometry = wkb2geos(*geom1WKB);
+    geom2Geometry = wkb2geos(*geom2WKB);
+    if (geom1Geometry == NULL || geom2Geometry == NULL) {
+        *out = NULL;
+        if (geom1Geometry)
+            GEOSGeom_destroy(geom1Geometry);
+        if (geom2Geometry)
+            GEOSGeom_destroy(geom2Geometry);
+        throw(MAL, "geom.collect" , "wkb2geos failed");
+    }
+
+    //make sure the geometries are of the same srid
+    if (GEOSGetSRID(geom1Geometry) != GEOSGetSRID(geom2Geometry)) {
+        err = createException(MAL, "geom.collect", "Geometries of different 
SRID");
+    } else { 
+        geometry1Type = GEOSGeomTypeId(geom1Geometry);
+        geometry2Type = GEOSGeomTypeId(geom2Geometry);
+        if ( (GEOSisEmpty(geom1Geometry) != 1) &&  (geometry1Type != 
geometry2Type)) {
+            type = geometry1Type;
+            switch (geometry1Type + 1) {
+                case wkbMultiPoint_mdb:
+                    if (geometry2Type == (wkbPoint_mdb-1))
+                        break;
+                case wkbMultiLineString_mdb:
+                    if (geometry2Type == (wkbLineString_mdb-1) || 
geometry2Type == (wkbLinearRing_mdb-1))
+                        break;
+                case wkbMultiPolygon_mdb:
+                    if (geometry2Type == (wkbPolygon_mdb-1))
+                        break;
+                case wkbPoint_mdb:
+                case wkbLineString_mdb:
+                case wkbLinearRing_mdb:
+                case wkbPolygon_mdb:
+                    type = wkbGeometryCollection_mdb - 1;
+                    break;
+                default:
+                    *out = NULL;
+                    GEOSGeom_destroy(geom1Geometry);
+                    GEOSGeom_destroy(geom2Geometry);
+                    throw(MAL, "geom.Collect", "Unknown1 geometry type");
+            } 
+        } else {
+            switch (geometry2Type + 1) {
+                case wkbPoint_mdb:
+                    type = wkbMultiPoint_mdb - 1;
+                    break;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to