Changeset: d34e2d0e2e93 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/d34e2d0e2e93
Added Files:
        geom/monetdb5/geom_io.c
        geom/monetdb5/geom_io.h
        geom/monetdb5/geom_srid.c
        geom/monetdb5/geom_srid.h
        geom/monetdb5/mbr.c
        geom/monetdb5/mbr.h
        geom/monetdb5/wkb.c
        geom/monetdb5/wkb.h
        geom/monetdb5/wkba.c
        geom/monetdb5/wkba.h
Branch: geo-update
Log Message:

Missing files from last commit; Divided the C functions according to the 
structure in geom/monetdb5/cleanup.md


diffs (truncated from 2304 to 300 lines):

diff --git a/geom/monetdb5/geom_io.c b/geom/monetdb5/geom_io.c
new file mode 100644
--- /dev/null
+++ b/geom/monetdb5/geom_io.c
@@ -0,0 +1,299 @@
+#include "geom.h"
+#include "geom_io.h"
+#include "wkb.h"
+
+/* Input functions (from type to geom) */
+/* From text */
+
+/* Creates WKB representation (including srid) from WKT representation */
+/* return number of parsed characters. */
+str
+wkbFROMSTR_withSRID(const char *geomWKT, size_t *len, wkb **geomWKB, int srid, 
size_t *nread)
+{
+       GEOSGeom geosGeometry = NULL;   /* The geometry object that is parsed 
from the src string. */
+       GEOSWKTReader *WKT_reader;
+       const char *polyhedralSurface = "POLYHEDRALSURFACE";
+       const char *multiPolygon = "MULTIPOLYGON";
+       char *geomWKT_new = NULL;
+       size_t parsedCharacters = 0;
+
+       *nread = 0;
+
+       /* we always allocate new memory */
+       GDKfree(*geomWKB);
+       *len = 0;
+       *geomWKB = NULL;
+
+       if (strNil(geomWKT)) {
+               *geomWKB = wkbNULLcopy();
+               if (*geomWKB == NULL)
+                       throw(MAL, "wkb.FromText", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+               *len = sizeof(wkb_nil);
+               return MAL_SUCCEED;
+       }
+       //check whether the representation is binary (hex)
+       if (geomWKT[0] == '0') {
+               str ret = wkbFromBinary(geomWKB, &geomWKT);
+
+               if (ret != MAL_SUCCEED)
+                       return ret;
+               *nread = strlen(geomWKT);
+               *len = (size_t) wkb_size((*geomWKB)->len);
+               return MAL_SUCCEED;
+       }
+       //check whether the geometry type is polyhedral surface
+       //geos cannot handle this type of geometry but since it is
+       //a special type of multipolygon I just change the type before
+       //continuing. Of course this means that isValid for example does
+       //not work correctly.
+       if (strncasecmp(geomWKT, polyhedralSurface, strlen(polyhedralSurface)) 
== 0) {
+               size_t sizeOfInfo = strlen(geomWKT) - strlen(polyhedralSurface) 
+ strlen(multiPolygon) + 1;
+               geomWKT_new = GDKmalloc(sizeOfInfo);
+               if (geomWKT_new == NULL)
+                       throw(MAL, "wkb.FromText", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+               snprintf(geomWKT_new, sizeOfInfo, "%s%s", multiPolygon, geomWKT 
+ strlen(polyhedralSurface));
+               geomWKT = geomWKT_new;
+       }
+       ////////////////////////// UP TO HERE ///////////////////////////
+
+       WKT_reader = GEOSWKTReader_create();
+       if (WKT_reader == NULL) {
+               if (geomWKT_new)
+                       GDKfree(geomWKT_new);
+               throw(MAL, "wkb.FromText", SQLSTATE(38000) "Geos operation 
GEOSWKTReader_create failed");
+       }
+       geosGeometry = GEOSWKTReader_read(WKT_reader, geomWKT);
+       GEOSWKTReader_destroy(WKT_reader);
+
+       if (geosGeometry == NULL) {
+               if (geomWKT_new)
+                       GDKfree(geomWKT_new);
+               throw(MAL, "wkb.FromText", SQLSTATE(38000) "Geos operation 
GEOSWKTReader_read failed");
+       }
+
+       if (GEOSGeomTypeId(geosGeometry) == -1) {
+               if (geomWKT_new)
+                       GDKfree(geomWKT_new);
+               GEOSGeom_destroy(geosGeometry);
+               throw(MAL, "wkb.FromText", SQLSTATE(38000) "Geos operation 
GEOSGeomTypeId failed");
+       }
+
+       GEOSSetSRID(geosGeometry, srid);
+       /* the srid was lost with the transformation of the GEOSGeom to wkb
+        * so we decided to store it in the wkb */
+
+       /* we have a GEOSGeometry with number of coordinates and SRID and we
+        * want to get the wkb out of it */
+       *geomWKB = geos2wkb(geosGeometry);
+       GEOSGeom_destroy(geosGeometry);
+       if (*geomWKB == NULL) {
+               if (geomWKT_new)
+                       GDKfree(geomWKT_new);
+               throw(MAL, "wkb.FromText", SQLSTATE(38000) "Geos operation 
geos2wkb failed");
+       }
+
+       *len = (size_t) wkb_size((*geomWKB)->len);
+       parsedCharacters = strlen(geomWKT);
+       assert(parsedCharacters <= GDK_int_max);
+
+       GDKfree(geomWKT_new);
+
+       *nread = parsedCharacters;
+       return MAL_SUCCEED;
+}
+
+/* creates a wkb from the given textual representation */
+/* int* tpe is needed to verify that the type of the FromText function used is 
the
+ * same with the type of the geometry created from the wkt representation */
+str
+wkbFromText(wkb **geomWKB, str *geomWKT, int *srid, int *tpe)
+{
+       size_t len = 0;
+       int te = 0;
+       str err;
+       size_t parsedBytes;
+
+       *geomWKB = NULL;
+       if (strNil(*geomWKT) || is_int_nil(*srid) || is_int_nil(*tpe)) {
+               if ((*geomWKB = wkbNULLcopy()) == NULL)
+                       throw(MAL, "wkb.FromText", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+               return MAL_SUCCEED;
+       }
+       err = wkbFROMSTR_withSRID(*geomWKT, &len, geomWKB, *srid, &parsedBytes);
+       if (err != MAL_SUCCEED)
+               return err;
+
+       if (is_wkb_nil(*geomWKB) || *tpe == 0 ||
+           *tpe == wkbGeometryCollection_mdb ||
+           ((te = *((*geomWKB)->data + 1) & 0x0f) + (*tpe > 2)) == *tpe) {
+               return MAL_SUCCEED;
+       }
+
+       GDKfree(*geomWKB);
+       *geomWKB = NULL;
+
+       te += (te > 2);
+       if (*tpe > 0 && te != *tpe)
+               throw(SQL, "wkb.FromText", SQLSTATE(38000) "Geometry not type 
'%d: %s' but '%d: %s' instead", *tpe, geom_type2str(*tpe, 0), te, 
geom_type2str(te, 0));
+       throw(MAL, "wkb.FromText", SQLSTATE(38000) "%s", "cannot parse string");
+}
+
+/* From Binary */
+static int
+decit(char hex)
+{
+       switch (hex) {
+       case '0':
+               return 0;
+       case '1':
+               return 1;
+       case '2':
+               return 2;
+       case '3':
+               return 3;
+       case '4':
+               return 4;
+       case '5':
+               return 5;
+       case '6':
+               return 6;
+       case '7':
+               return 7;
+       case '8':
+               return 8;
+       case '9':
+               return 9;
+       case 'A':
+       case 'a':
+               return 10;
+       case 'B':
+       case 'b':
+               return 11;
+       case 'C':
+       case 'c':
+               return 12;
+       case 'D':
+       case 'd':
+               return 13;
+       case 'E':
+       case 'e':
+               return 14;
+       case 'F':
+       case 'f':
+               return 15;
+       default:
+               return -1;
+       }
+}
+
+str
+wkbFromBinary(wkb **geomWKB, const char **inStr)
+{
+       size_t strLength, wkbLength, i;
+       wkb *w;
+
+       if (strNil(*inStr)) {
+               if ((*geomWKB = wkbNULLcopy()) == NULL)
+                       throw(MAL, "geom.FromBinary", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+               return MAL_SUCCEED;
+       }
+
+       strLength = strlen(*inStr);
+       if (strLength & 1)
+               throw(MAL, "geom.FromBinary", SQLSTATE(38000) "Geos odd length 
input string");
+
+       wkbLength = strLength / 2;
+       assert(wkbLength <= GDK_int_max);
+
+       w = GDKmalloc(wkb_size(wkbLength));
+       if (w == NULL)
+               throw(MAL, "geom.FromBinary", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+
+       //compute the value for s
+       for (i = 0; i < strLength; i += 2) {
+               int firstHalf = decit((*inStr)[i]);
+               int secondHalf = decit((*inStr)[i + 1]);
+               if (firstHalf == -1 || secondHalf == -1) {
+                       GDKfree(w);
+                       throw(MAL, "geom.FromBinary", SQLSTATE(38000) "Geos 
incorrectly formatted input string");
+               }
+               w->data[i / 2] = (firstHalf << 4) | secondHalf;
+       }
+
+       w->len = (int) wkbLength;
+       w->srid = 0;
+       *geomWKB = w;
+
+       return MAL_SUCCEED;
+}
+
+/* Output functions (from geom to type) */
+/* AsText */
+/* create textual representation of the wkb */
+str
+wkbAsText(char **txt, wkb **geomWKB, int *withSRID)
+{
+       size_t len = 0;
+       char *wkt = NULL;
+       const char *sridTxt = "SRID:";
+
+       if (is_wkb_nil(*geomWKB) || (withSRID && is_int_nil(*withSRID))) {
+               if ((*txt = GDKstrdup(str_nil)) == NULL)
+                       throw(MAL, "geom.AsText", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+               return MAL_SUCCEED;
+       }
+
+       if ((*geomWKB)->srid < 0)
+               throw(MAL, "geom.AsText", SQLSTATE(38000) "Geod negative SRID");
+
+       if (wkbTOSTR(&wkt, &len, *geomWKB, false) < 0)
+               throw(MAL, "geom.AsText", SQLSTATE(38000) "Geos failed to 
create Text from Well Known Format");
+
+       if (withSRID == NULL || *withSRID == 0) {       //accepting NULL 
withSRID to make internal use of it easier
+               *txt = wkt;
+               return MAL_SUCCEED;
+       }
+
+       /* 10 for maximum number of digits to represent an INT */
+       len = strlen(wkt) + 10 + strlen(sridTxt) + 2;
+       *txt = GDKmalloc(len);
+       if (*txt == NULL) {
+               GDKfree(wkt);
+               throw(MAL, "geom.AsText", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+       }
+
+       snprintf(*txt, len, "%s%d;%s", sridTxt, (*geomWKB)->srid, wkt);
+
+       GDKfree(wkt);
+       return MAL_SUCCEED;
+}
+
+/* AsBinary */
+//Returns the wkb in a hex representation */
+static char hexit[] = "0123456789ABCDEF";
+
+str
+wkbAsBinary(char **toStr, wkb **geomWKB)
+{
+       char *s;
+       int i;
+
+       if (is_wkb_nil(*geomWKB)) {
+               if ((*toStr = GDKstrdup(str_nil)) == NULL)
+                       throw(MAL, "geom.AsBinary", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+               return MAL_SUCCEED;
+       }
+       if ((*toStr = GDKmalloc(1 + (*geomWKB)->len * 2)) == NULL)
+               throw(MAL, "geom.AsBinary", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+
+       s = *toStr;
+       for (i = 0; i < (*geomWKB)->len; i++) {
+               int val = ((*geomWKB)->data[i] >> 4) & 0xf;
+               *s++ = hexit[val];
+               val = (*geomWKB)->data[i] & 0xf;
+               *s++ = hexit[val];
+               TRC_DEBUG(GEOM, "%d: First: %c - Second: %c ==> Original %c 
(%d)\n", i, *(s-2), *(s-1), (*geomWKB)->data[i], (int)((*geomWKB)->data[i]));
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to