From c304b64232cbbf7e72e4d54561700bbf81c2c416 Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Sun, 3 Oct 2004 15:52:23 +0000 Subject: [PATCH] Made GEOS<->LWGEOM converters keep geometry structures. Fixed bug in serializers. Added noop(geometry) for deserialize/serialize debugging. git-svn-id: http://svn.osgeo.org/postgis/trunk@920 b70326c6-7e19-0410-871a-916f4a2858ee --- lwgeom/liblwgeom.h | 12 +- lwgeom/lwcollection.c | 23 +- lwgeom/lwgeom.c | 24 ++- lwgeom/lwgeom_api.c | 4 +- lwgeom/lwgeom_functions_basic.c | 27 +++ lwgeom/lwgeom_geos.c | 364 ++++++++++++-------------------- lwgeom/lwgeom_geos_wrapper.cpp | 55 ++++- lwgeom/lwline.c | 13 +- lwgeom/lwpoint.c | 25 ++- lwgeom/lwpoly.c | 17 +- lwgeom/lwpostgis.sql.in | 5 + 11 files changed, 308 insertions(+), 261 deletions(-) diff --git a/lwgeom/liblwgeom.h b/lwgeom/liblwgeom.h index 031187d66..bd500e068 100644 --- a/lwgeom/liblwgeom.h +++ b/lwgeom/liblwgeom.h @@ -416,7 +416,7 @@ extern size_t lwpoint_serialize_size(LWPOINT *point); extern char *lwpoint_serialize(LWPOINT *point); // same as above, writes to buf -extern void lwpoint_serialize_buf(LWPOINT *point, char *buf, int *size); +extern void lwpoint_serialize_buf(LWPOINT *point, char *buf, size_t *size); // find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN) extern BOX3D *lwpoint_findbbox(LWPOINT *point); @@ -446,7 +446,7 @@ extern size_t lwline_serialize_size(LWLINE *line); extern char *lwline_serialize(LWLINE *line); // same as above, writes to buf -extern void lwline_serialize_buf(LWLINE *line, char *buf, int *size); +extern void lwline_serialize_buf(LWLINE *line, char *buf, size_t *size); // find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN) extern BOX3D *lwline_findbbox(LWLINE *line); @@ -472,7 +472,7 @@ extern size_t lwpoly_serialize_size(LWPOLY *poly); extern char *lwpoly_serialize(LWPOLY *poly); // same as above, writes to buf -extern void lwpoly_serialize_buf(LWPOLY *poly, char *buf, int *size); +extern void lwpoly_serialize_buf(LWPOLY *poly, char *buf, size_t *size); // find bounding box (standard one) zmin=zmax=0 if 2d (might change to NaN) extern BOX3D *lwpoly_findbbox(LWPOLY *poly); @@ -482,9 +482,9 @@ extern BOX3D *lwpoly_findbbox(LWPOLY *poly); extern size_t lwgeom_serialize_size(LWGEOM *geom); extern size_t lwcollection_serialize_size(LWCOLLECTION *coll); -extern void lwgeom_serialize_buf(LWGEOM *geom, char *buf, int *size); +extern void lwgeom_serialize_buf(LWGEOM *geom, char *buf, size_t *size); extern char *lwgeom_serialize(LWGEOM *geom); -extern void lwcollection_serialize_buf(LWCOLLECTION *mcoll, char *buf, int *size); +extern void lwcollection_serialize_buf(LWCOLLECTION *mcoll, char *buf, size_t *size); //----------------------------------------------------- @@ -578,7 +578,7 @@ extern uint32 lwexploded_findlength(LWGEOM_EXPLODED *exp, int wantbbox); extern char *lwexploded_serialize(LWGEOM_EXPLODED *exploded, int wantbbox); // Same as lwexploded_serialize but writing to pre-allocated space -extern void lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, char *buf, int *retsize); +extern void lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, char *buf, size_t *retsize); // note - for a simple type (ie. point), this will have sub_geom[0] = serialized_form. // for multi-geomtries sub_geom[0] will be a few bytes into the serialized form diff --git a/lwgeom/lwcollection.c b/lwgeom/lwcollection.c index 2e4cf9405..967b8c875 100644 --- a/lwgeom/lwcollection.c +++ b/lwgeom/lwcollection.c @@ -3,6 +3,8 @@ #include #include "liblwgeom.h" +//#define DEBUG_CALLS 1 + LWCOLLECTION * lwcollection_deserialize(char *srl) { @@ -53,8 +55,22 @@ lwcollection_serialize_size(LWCOLLECTION *col) if ( col->SRID != -1 ) size += 4; // SRID if ( col->hasbbox ) size += sizeof(BOX2DFLOAT4); +#ifdef DEBUG_CALLS + lwnotice("lwcollection_serialize_size[%p]: start size: %d", col, size); +#endif + + for (i=0; ingeoms; i++) + { size += lwgeom_serialize_size(lwcollection_getsubgeom(col, i)); +#ifdef DEBUG_CALLS + lwnotice("lwcollection_serialize_size[%p]: with geom%d: %d", col, i, size); +#endif + } + +#ifdef DEBUG_CALLS + lwnotice("lwcollection_serialize_size[%p]: returning %d", col, size); +#endif return size; } @@ -63,7 +79,7 @@ lwcollection_serialize_size(LWCOLLECTION *col) // the given buffer, and returning number of bytes written into // the given int pointer. void -lwcollection_serialize_buf(LWCOLLECTION *coll, char *buf, int *retsize) +lwcollection_serialize_buf(LWCOLLECTION *coll, char *buf, size_t *retsize) { int size=1; // type int subsize=0; @@ -73,8 +89,8 @@ lwcollection_serialize_buf(LWCOLLECTION *coll, char *buf, int *retsize) hasSRID = (coll->SRID != -1); - buf[0] = (unsigned char) lwgeom_makeType(coll->ndims, - hasSRID, COLLECTIONTYPE); + buf[0] = (unsigned char) lwgeom_makeType_full(coll->ndims, + hasSRID, coll->type, coll->hasbbox); loc = buf+1; // Add BBOX if requested @@ -103,6 +119,7 @@ lwcollection_serialize_buf(LWCOLLECTION *coll, char *buf, int *retsize) { lwgeom_serialize_buf(coll->geoms[i], loc, &subsize); size += subsize; + loc += subsize; } if (retsize) *retsize = size; diff --git a/lwgeom/lwgeom.c b/lwgeom/lwgeom.c index 7cf950c4d..57ebe2408 100644 --- a/lwgeom/lwgeom.c +++ b/lwgeom/lwgeom.c @@ -5,6 +5,8 @@ #include "lwgeom_pg.h" #include "liblwgeom.h" +//#define DEBUG_CALLS 1 + LWGEOM * lwgeom_deserialize(char *srl) { @@ -37,34 +39,39 @@ size_t lwgeom_serialize_size(LWGEOM *lwgeom) { int type = lwgeom->type; - size_t size; + +#ifdef DEBUG_CALLS + lwnotice("lwgeom_serialize_size called"); +#endif switch (type) { case POINTTYPE: - size = lwpoint_serialize_size((LWPOINT *)lwgeom); + return lwpoint_serialize_size((LWPOINT *)lwgeom); case LINETYPE: - size = lwline_serialize_size((LWLINE *)lwgeom); + return lwline_serialize_size((LWLINE *)lwgeom); case POLYGONTYPE: - size = lwpoly_serialize_size((LWPOLY *)lwgeom); + return lwpoly_serialize_size((LWPOLY *)lwgeom); case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: - size = lwcollection_serialize_size((LWCOLLECTION *)lwgeom); + return lwcollection_serialize_size((LWCOLLECTION *)lwgeom); default: lwerror("Unknown geometry type: %d", type); return 0; } - - return size; } void -lwgeom_serialize_buf(LWGEOM *lwgeom, char *buf, int *retsize) +lwgeom_serialize_buf(LWGEOM *lwgeom, char *buf, size_t *retsize) { int type = lwgeom->type; +#ifdef DEBUG_CALLS + lwnotice("lwgeom_serialize_buf called with a %s", + lwgeom_typename(type)); +#endif switch (type) { case POINTTYPE: @@ -318,3 +325,4 @@ lwgeom_add(const LWGEOM *to, uint32 where, const LWGEOM *what) return NULL; } } + diff --git a/lwgeom/lwgeom_api.c b/lwgeom/lwgeom_api.c index dea11b88b..111e04160 100644 --- a/lwgeom/lwgeom_api.c +++ b/lwgeom/lwgeom_api.c @@ -2222,9 +2222,9 @@ lwexploded_serialize(LWGEOM_EXPLODED *exploded, int wantbbox) */ void lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, - char *buf, int *retsize) + char *buf, size_t *retsize) { - unsigned int size=0; + size_t size=0; int i; int ntypes = 0; int ngeoms = 0; diff --git a/lwgeom/lwgeom_functions_basic.c b/lwgeom/lwgeom_functions_basic.c index dd166832e..d269d7665 100644 --- a/lwgeom/lwgeom_functions_basic.c +++ b/lwgeom/lwgeom_functions_basic.c @@ -2731,3 +2731,30 @@ Datum LWGEOM_forceRHR_poly(PG_FUNCTION_ARGS) PG_RETURN_POINTER(geom); } + +// Test deserialize/serialize operations +PG_FUNCTION_INFO_V1(LWGEOM_noop); +Datum LWGEOM_noop(PG_FUNCTION_ARGS) +{ + PG_LWGEOM *in, *out; + LWGEOM *lwgeom; + size_t size, retsize; + + in = (PG_LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)); + + lwgeom = lwgeom_deserialize(SERIALIZED_FORM(in)); + + lwnotice("Deserialized: %s", lwgeom_summary(lwgeom, 0)); + + size = lwgeom_serialize_size(lwgeom); + out = palloc(size+4); + out->size = size+4; + lwgeom_serialize_buf(lwgeom, SERIALIZED_FORM(out), &retsize); + + if ( size != retsize ) + { + lwerror ("lwgeom_serialize_buf returned size(%d) != lwgeom_serialize_size (%d)", retsize, size); + } + + PG_RETURN_POINTER(out); +} diff --git a/lwgeom/lwgeom_geos.c b/lwgeom/lwgeom_geos.c index 9991d4f5d..9da7a115d 100644 --- a/lwgeom/lwgeom_geos.c +++ b/lwgeom/lwgeom_geos.c @@ -44,8 +44,10 @@ Datum centroid(PG_FUNCTION_ARGS); * during postgis->geos and geos->postgis conversions */ #undef DEBUG_CONVERTER -#undef DEBUG_POSTGIS2GEOS -#undef DEBUG_GEOS2POSTGIS +#ifdef DEBUG_CONVERTER +#define DEBUG_POSTGIS2GEOS 1 +#define DEBUG_GEOS2POSTGIS 1 +#endif // DEBUG_CONVERTER typedef struct Geometry Geometry; @@ -96,19 +98,20 @@ extern int GEOSGetNumGeometries(Geometry *g1); extern Geometry *PostGIS2GEOS_point(const LWPOINT *point); extern Geometry *PostGIS2GEOS_linestring(const LWLINE *line); extern Geometry *PostGIS2GEOS_polygon(const LWPOLY *polygon); -extern Geometry *PostGIS2GEOS_multipolygon(LWPOLY *const *const geoms, uint32 ngeoms, int SRID, int is3d); -extern Geometry *PostGIS2GEOS_multilinestring(LWLINE *const *const geoms, uint32 ngeoms, int SRID, int is3d); -extern Geometry *PostGIS2GEOS_multipoint(LWPOINT *const *const geoms, uint32 ngeoms, int SRID, int is3d); -extern Geometry *PostGIS2GEOS_collection(Geometry **geoms, int ngeoms, int SRID, bool is3d); +extern Geometry *PostGIS2GEOS_multipolygon(LWPOLY **geoms, uint32 ngeoms, int SRID, int is3d); +extern Geometry *PostGIS2GEOS_multilinestring(LWLINE **geoms, uint32 ngeoms, int SRID, int is3d); +extern Geometry *PostGIS2GEOS_multipoint(LWPOINT **geoms, uint32 ngeoms, int SRID, int is3d); +extern Geometry *PostGIS2GEOS_collection(int type, Geometry **geoms, int ngeoms, int SRID, bool is3d); void NOTICE_MESSAGE(char *msg); PG_LWGEOM *GEOS2POSTGIS(Geometry *geom, char want3d); Geometry * POSTGIS2GEOS(PG_LWGEOM *g); void errorIfGeometryCollection(PG_LWGEOM *g1, PG_LWGEOM *g2); -char *PointFromGeometry(Geometry *g, char want3d); -char *LineFromGeometry(Geometry *g, char want3d); -char *PolyFromGeometry(Geometry *g, char want3d); -void addToExploded_recursive(Geometry *geom, LWGEOM_EXPLODED *exp); +LWPOINT *lwpoint_from_geometry(Geometry *g, char want3d); +LWLINE *lwline_from_geometry(Geometry *g, char want3d); +LWPOLY *lwpoly_from_geometry(Geometry *g, char want3d); +LWCOLLECTION *lwcollection_from_geometry(Geometry *geom, char want3d); +LWGEOM *lwgeom_from_geometry(Geometry *g, char want3d); void NOTICE_MESSAGE(char *msg) { @@ -1870,14 +1873,20 @@ Datum isring(PG_FUNCTION_ARGS) //= GEOS <=> POSTGIS CONVERSION ========================= -// Return a serialized line from a GEOS geometry (no SRID, no BBOX) -char *PointFromGeometry(Geometry *g, char want3d) +//-----=GEOS2POSTGIS= + +// Return a LWPOINT from a GEOS Point. +LWPOINT * +lwpoint_from_geometry(Geometry *g, char want3d) { POINTARRAY *pa; LWPOINT *point; - char *srl; POINT3D *pts; - int ptsize = want3d ? sizeof(POINT3D) : sizeof(POINT2D); + size_t ptsize = want3d ? sizeof(POINT3D) : sizeof(POINT2D); + +#ifdef DEBUG_GEOS2POSTGIS + elog(NOTICE, "lwpoint_from_geometry: point size %d", ptsize); +#endif // Construct point array pa = (POINTARRAY *)palloc(sizeof(POINTARRAY)); @@ -1885,7 +1894,7 @@ char *PointFromGeometry(Geometry *g, char want3d) pa->npoints = 1; // Fill point array - pa->serialized_pointlist = palloc(ptsize); + pa->serialized_pointlist = lwalloc(ptsize); pts = GEOSGetCoordinates(g); memcpy(pa->serialized_pointlist, pts, ptsize); GEOSdeleteChar( (char*) pts); @@ -1893,23 +1902,24 @@ char *PointFromGeometry(Geometry *g, char want3d) // Construct LWPOINT point = lwpoint_construct(pa->ndims, -1, pa); - // Serialize LWPOINT - srl = lwpoint_serialize(point); - - return srl; + return point; } -// Return a serialized line from a GEOS geometry (no SRID no BBOX) -char *LineFromGeometry(Geometry *g, char want3d) +// Return a LWLINE from a GEOS linestring +LWLINE * +lwline_from_geometry(Geometry *g, char want3d) { POINTARRAY *pa; LWLINE *line; int npoints; - char *srl; POINT3D *pts, *ip, *op; int ptsize = want3d ? sizeof(POINT3D) : sizeof(POINT2D); int i; +#ifdef DEBUG_GEOS2POSTGIS + elog(NOTICE, "lwline_from_geometry: point size %d", ptsize); +#endif + npoints = GEOSGetNumCoordinate(g); if (npoints <2) return NULL; @@ -1932,14 +1942,12 @@ char *LineFromGeometry(Geometry *g, char want3d) // Construct LWPOINT line = lwline_construct(pa->ndims, -1, pa); - // Serialize LWPOINT - srl = lwline_serialize(line); - - return srl; + return line; } -// Return a serialized polygon from a GEOS geometry (no SRID no BBOX) -char *PolyFromGeometry(Geometry *g, char want3d) +// Return a LWPOLY from a GEOS polygon +LWPOLY * +lwpoly_from_geometry(Geometry *g, char want3d) { POINTARRAY **rings, *pa; LWPOLY *poly; @@ -1947,10 +1955,13 @@ char *PolyFromGeometry(Geometry *g, char want3d) int nrings; int npoints; int i, j; - char *srl; POINT3D *pts, *ip, *op; int ptoff=0; // point offset inside POINT3D * - int ptsize = 8*ndims; + int ptsize = sizeof(double)*ndims; + +#ifdef DEBUG_GEOS2POSTGIS + elog(NOTICE, "lwpoly_from_geometry: point size %d", ptsize); +#endif // Get number of rings, and pointlist pts = GEOSGetCoordinates(g); @@ -1997,32 +2008,58 @@ char *PolyFromGeometry(Geometry *g, char want3d) // Construct LWPOLY poly = lwpoly_construct(pa->ndims, -1, nrings+1, rings); - // Serialize LWPOLY - srl = lwpoly_serialize(poly); + return poly; +} - // Get rid of GEOS points... - GEOSdeleteChar( (char*) pts); +// Return a lwcollection from a GEOS multi* +LWCOLLECTION * +lwcollection_from_geometry(Geometry *geom, char want3d) +{ + uint32 ngeoms; + LWGEOM **geoms; + LWCOLLECTION *ret; + int ndims = want3d ? 3 : 2; + int type = GEOSGeometryTypeId(geom) ; + int SRID = GEOSGetSRID(geom); + char wantbbox = 0; + int i; - return srl; -} + ngeoms = GEOSGetNumGeometries(geom); -//-----=GEOS2POSTGIS= +#ifdef DEBUG_GEOS2POSTGIS + lwnotice("lwcollection_from_geometry: type: %s, geoms %d", + lwgeom_typename(type), ngeoms); +#endif + geoms = lwalloc(sizeof(LWGEOM *)*ngeoms); -/* - * Recursively add a Geometry to the LWGEOM_EXPLODED structure - * The exploded struct contains note about the number of dimensions - * requested. - */ -void -addToExploded_recursive(Geometry *geom, LWGEOM_EXPLODED *exp) + for (i=0; itype)); +#endif + } + + ret = lwcollection_construct(type, ndims, SRID, + wantbbox, ngeoms, geoms); + return ret; +} + + +// Return an LWGEOM from a Geometry +LWGEOM * +lwgeom_from_geometry(Geometry *geom, char want3d) { - char *srl; int type = GEOSGeometryTypeId(geom) ; - char want3d = exp->ndims > 2 ? 1 : 0; - int ngeoms; - int t; +#ifdef DEBUG_GEOS2POSTGIS + lwnotice("lwgeom_from_geometry: it's a %s", lwgeom_typename(type)); +#endif switch (type) { @@ -2032,68 +2069,20 @@ addToExploded_recursive(Geometry *geom, LWGEOM_EXPLODED *exp) case MULTIPOLYGONTYPE: case MULTILINETYPE: case MULTIPOINTTYPE: - - //this is more difficult because GEOS allows GCs of GCs - ngeoms = GEOSGetNumGeometries(geom); -#ifdef DEBUG_GEOS2POSTGIS - elog(NOTICE, "GEOS2POSTGIS: It's a MULTI (of %d elems)", ngeoms); -#endif - if (ngeoms == 0) - { - return; // skip EMPTY geoms - } - if (ngeoms == 1) { - Geometry *g = GEOSGetGeometryN(geom, 0); - // short cut! - return addToExploded_recursive(g, exp); - } - for (t=0; tnpolys++; - exp->polys = repalloc(exp->polys, - sizeof(char *)*exp->npolys); - exp->polys[exp->npolys-1] = srl; - return; + return (LWGEOM *)lwpoly_from_geometry(geom, want3d); case LINETYPE: -#ifdef DEBUG_GEOS2POSTGIS - elog(NOTICE, "GEOS2POSTGIS: It's a LINE"); -#endif - srl = LineFromGeometry(geom, want3d); - if (srl == NULL) return; - exp->nlines++; - exp->lines = repalloc(exp->lines, - sizeof(char *)*exp->nlines); - exp->lines[exp->nlines-1] = srl; - return; + return (LWGEOM *)lwline_from_geometry(geom, want3d); case POINTTYPE: -#ifdef DEBUG_GEOS2POSTGIS - elog(NOTICE, "GEOS2POSTGIS: It's a POINT"); -#endif - srl = PointFromGeometry(geom, want3d); - if (srl == NULL) return; - exp->npoints++; - exp->points = repalloc(exp->points, - sizeof(char *)*exp->npoints); - exp->points[exp->npoints-1] = srl; - return; + return (LWGEOM *)lwpoint_from_geometry(geom, want3d); default: -#ifdef DEBUG_GEOS2POSTGIS - elog(NOTICE, "GEOS2POSTGIS: It's UNKNOWN!"); -#endif - return; + lwerror("lwgeom_from_geometry: unknown geometry type: %d", type); + return NULL; } @@ -2102,32 +2091,41 @@ addToExploded_recursive(Geometry *geom, LWGEOM_EXPLODED *exp) PG_LWGEOM * GEOS2POSTGIS(Geometry *geom, char want3d) { + LWGEOM *lwgeom; + size_t size, retsize; PG_LWGEOM *result; - LWGEOM_EXPLODED *oexp; - int SRID; - int wantbbox = 0; // might as well be 1 ... - int size; - - SRID = GEOSGetSRID(geom); - - // Initialize exploded lwgeom - oexp = (LWGEOM_EXPLODED *)palloc(sizeof(LWGEOM_EXPLODED)); - oexp->SRID = SRID; - oexp->ndims = want3d ? 3 : 2; - oexp->npoints = 0; - oexp->points = palloc(sizeof(char *)); - oexp->nlines = 0; - oexp->lines = palloc(sizeof(char *)); - oexp->npolys = 0; - oexp->polys = palloc(sizeof(char *)); - - addToExploded_recursive(geom, oexp); - - size = lwexploded_findlength(oexp, wantbbox); + + lwgeom = lwgeom_from_geometry(geom, want3d); + if ( ! lwgeom ) + { + lwerror("GEOS2POSTGIS: lwgeom_from_geometry returned NULL"); + return NULL; + } + +#ifdef DEBUG_GEOS2POSTGIS + lwnotice("GEOS2POSTGIS: lwgeom_from_geometry returned a %s", lwgeom_summary(lwgeom, 0)); //lwgeom_typename(lwgeom->type)); +#endif + + size = lwgeom_serialize_size(lwgeom); + +#ifdef DEBUG_GEOS2POSTGIS + lwnotice("GEOS2POSTGIS: lwgeom_serialize_size returned %d", size); +#endif + size += 4; // postgresql size header result = palloc(size); result->size = size; - lwexploded_serialize_buf(oexp, wantbbox, SERIALIZED_FORM(result), NULL); + +#ifdef DEBUG_GEOS2POSTGIS + lwnotice("GEOS2POSTGIS: about to serialize %s", lwgeom_typename(lwgeom->type)); +#endif + + lwgeom_serialize_buf(lwgeom, SERIALIZED_FORM(result), &retsize); + + if ( retsize != size-4 ) + { + lwerror("GEOS2POSTGIS: lwgeom_serialize_buf returned %d, lwgeom_serialize_size returned %d", retsize, size); + } return result; } @@ -2145,22 +2143,27 @@ LWGEOM2GEOS(LWGEOM *lwgeom) if ( ! lwgeom ) return NULL; #ifdef DEBUG_POSTGIS2GEOS - elog(NOTICE, "LWGEOM2GEOS: got lwgeom[%p]", lwgeom); + lwnotice("LWGEOM2GEOS: got lwgeom[%p]", lwgeom); #endif switch (lwgeom->type) { - LWPOINT *p; - case POINTTYPE: - p = (LWPOINT *)lwgeom; - elog(NOTICE, "LWGEOM2GEOS: lwpoint[%p]", p); - return PostGIS2GEOS_point(p); +#ifdef DEBUG_POSTGIS2GEOS + lwnotice("LWGEOM2GEOS: point[%p]", lwgeom); +#endif + return PostGIS2GEOS_point((LWPOINT *)lwgeom); case LINETYPE: +#ifdef DEBUG_POSTGIS2GEOS + lwnotice("LWGEOM2GEOS: line[%p]", lwgeom); +#endif return PostGIS2GEOS_linestring((LWLINE *)lwgeom); case POLYGONTYPE: +#ifdef DEBUG_POSTGIS2GEOS + lwnotice("LWGEOM2GEOS: poly[%p]", lwgeom); +#endif return PostGIS2GEOS_polygon((LWPOLY *)lwgeom); case MULTIPOINTTYPE: @@ -2168,13 +2171,17 @@ LWGEOM2GEOS(LWGEOM *lwgeom) case MULTIPOLYGONTYPE: case COLLECTIONTYPE: col = (LWCOLLECTION *)lwgeom; +#ifdef DEBUG_POSTGIS2GEOS + lwnotice("LWGEOM2GEOS: %s with %d subgeoms", lwgeom_typename(col->type), col->ngeoms); +#endif collected = (Geometry **)lwalloc(sizeof(Geometry *)*col->ngeoms); for (i=0; ingeoms; i++) { collected[i] = LWGEOM2GEOS(col->geoms[i]); } - return PostGIS2GEOS_collection(collected, col->ngeoms, - col->SRID, col->ndims > 2); + return PostGIS2GEOS_collection(col->type, + collected, col->ngeoms, col->SRID, + col->ndims>2); default: lwerror("Unknown geometry type: %d", lwgeom->type); @@ -2193,99 +2200,6 @@ POSTGIS2GEOS(PG_LWGEOM *geom) return ret; } -Geometry * -_POSTGIS2GEOS(PG_LWGEOM *geom) -{ - LWPOINT *point; - LWLINE *line; - LWPOLY *poly; - LWGEOM_EXPLODED *exploded; - int type; - int i, j; - Geometry **collected; - int ncollected; - Geometry *ret=NULL; - - type = lwgeom_getType(geom->type); - - switch (type) - { - case POINTTYPE: -#ifdef DEBUG_POSTGIS2GEOS - elog(NOTICE, "POSTGIS2GEOS: it's a point"); -#endif - point = lwpoint_deserialize(SERIALIZED_FORM(geom)); - ret = PostGIS2GEOS_point(point); - break; - - case LINETYPE: -#ifdef DEBUG_POSTGIS2GEOS - elog(NOTICE, "POSTGIS2GEOS: it's a line"); -#endif - line = lwline_deserialize(SERIALIZED_FORM(geom)); - ret = PostGIS2GEOS_linestring(line); - break; - - case POLYGONTYPE: -#ifdef DEBUG_POSTGIS2GEOS - elog(NOTICE, "POSTGIS2GEOS: it's a polygon"); -#endif - poly = lwpoly_deserialize(SERIALIZED_FORM(geom)); - ret = PostGIS2GEOS_polygon(poly); - break; - - default: - break; - } - - if ( ret ) - { - return ret; - } - -#ifdef DEBUG_POSTGIS2GEOS - elog(NOTICE, "POSTGIS2GEOS: out of switch"); -#endif - - // Since it is not a base type, let's explode... - exploded = lwgeom_explode(SERIALIZED_FORM(geom)); - -#ifdef DEBUG_POSTGIS2GEOS - elog(NOTICE, "POSTGIS2GEOS: exploded produced"); -#endif - - ncollected = exploded->npoints + exploded->nlines + exploded->npolys; - -#ifdef DEBUG_POSTGIS2GEOS - elog(NOTICE, "POSTGIS2GEOS: it's a collection of %d elems", ncollected); -#endif - - collected = (Geometry **)palloc(sizeof(Geometry *)*ncollected); - - j=0; - for (i=0; inpoints; i++) - { - point = lwpoint_deserialize(exploded->points[i]); - collected[j++] = PostGIS2GEOS_point(point); - } - for (i=0; inlines; i++) - { - line = lwline_deserialize(exploded->lines[j]); - collected[j++] = PostGIS2GEOS_linestring(line); - } - for (i=0; inpolys; i++) - { - poly = lwpoly_deserialize(exploded->polys[i]); - collected[j++] = PostGIS2GEOS_polygon(poly); - } - - ret = PostGIS2GEOS_collection(collected, ncollected, - exploded->SRID, exploded->ndims > 2); - - return ret; - -} - PG_FUNCTION_INFO_V1(GEOSnoop); Datum GEOSnoop(PG_FUNCTION_ARGS) { diff --git a/lwgeom/lwgeom_geos_wrapper.cpp b/lwgeom/lwgeom_geos_wrapper.cpp index 5709c1591..c8826a9de 100644 --- a/lwgeom/lwgeom_geos_wrapper.cpp +++ b/lwgeom/lwgeom_geos_wrapper.cpp @@ -10,7 +10,7 @@ #include "geos/geom.h" #include "geos/util.h" -#define DEBUG_POSTGIS2GEOS 1 +//#define DEBUG_POSTGIS2GEOS 1 using namespace geos; @@ -109,10 +109,7 @@ extern "C" char *GEOSjtsport(); extern "C" Geometry *PostGIS2GEOS_point(const LWPOINT *point); extern "C" Geometry *PostGIS2GEOS_linestring(const LWLINE *line); extern "C" Geometry *PostGIS2GEOS_polygon(const LWPOLY *polygon); -extern "C" Geometry *PostGIS2GEOS_multipolygon(LWPOLY *const *const geoms, uint32 ngeoms, int SRID, int is3d); -extern "C" Geometry *PostGIS2GEOS_multilinestring(LWLINE *const *const geoms, uint32 ngeoms, int SRID, int is3d); -extern "C" Geometry *PostGIS2GEOS_multipoint(LWPOINT *const *const geoms, uint32 ngeoms, int SRID, int is3d); -extern "C" Geometry *PostGIS2GEOS_collection(Geometry **geoms, int ngeoms, int SRID, bool is3d); +extern "C" Geometry *PostGIS2GEOS_collection(int type, Geometry **geoms, int ngeoms, int SRID, bool is3d); extern "C" Geometry *PostGIS2GEOS_box3d(BOX3D *box, int SRID); extern "C" char GEOSisvalid(Geometry *g1); @@ -281,6 +278,12 @@ PostGIS2GEOS_linestring(const LWLINE *lwline) bool is3d = pa->ndims > 2 ? 1 : 0; int SRID = lwline->SRID; +#ifdef DEBUG_POSTGIS2GEOS + char buf[256]; + sprintf(buf, "PostGIS2GEOS_line got lwline[%p]", lwline); + NOTICE_MESSAGE(buf); +#endif + try{ uint32 t; Coordinate c; @@ -356,6 +359,12 @@ Geometry *PostGIS2GEOS_polygon(const LWPOLY *lwpoly) int SRID = lwpoly->SRID; bool is3d = lwpoly->ndims > 2 ? 1 : 0; +#ifdef DEBUG_POSTGIS2GEOS + char buf[256]; + sprintf(buf, "PostGIS2GEOS_poly got lwpoly[%p]", lwpoly); + NOTICE_MESSAGE(buf); +#endif + try { Coordinate c; @@ -497,7 +506,7 @@ Geometry *PostGIS2GEOS_polygon(const LWPOLY *lwpoly) } } -Geometry *PostGIS2GEOS_multipoint(LWPOINT *const *const geoms, uint32 ngeoms, int SRID, bool is3d) +Geometry *PostGIS2GEOS_multipoint(LWPOINT **geoms, uint32 ngeoms, int SRID, bool is3d) { try { @@ -534,7 +543,7 @@ Geometry *PostGIS2GEOS_multipoint(LWPOINT *const *const geoms, uint32 ngeoms, in } } -Geometry *PostGIS2GEOS_multilinestring(LWLINE *const *const geoms, uint32 ngeoms, int SRID, bool is3d) +Geometry *PostGIS2GEOS_multilinestring(LWLINE **geoms, uint32 ngeoms, int SRID, bool is3d) { try { @@ -571,7 +580,7 @@ Geometry *PostGIS2GEOS_multilinestring(LWLINE *const *const geoms, uint32 ngeoms } } -Geometry *PostGIS2GEOS_multipolygon(LWPOLY *const *const polygons, uint32 npolys, int SRID, bool is3d) +Geometry *PostGIS2GEOS_multipolygon(LWPOLY **polygons, uint32 npolys, int SRID, bool is3d) { try { @@ -608,8 +617,15 @@ Geometry *PostGIS2GEOS_multipolygon(LWPOLY *const *const polygons, uint32 npolys } } -Geometry *PostGIS2GEOS_collection(Geometry **geoms, int ngeoms, int SRID, bool is3d) +Geometry *PostGIS2GEOS_collection(int type, Geometry **geoms, int ngeoms, int SRID, bool is3d) { +#ifdef DEBUG_POSTGIS2GEOS + char buf[256]; + sprintf(buf, "PostGIS2GEOS_collection: requested type %d, ngeoms: %d", + type, ngeoms); + NOTICE_MESSAGE(buf); +#endif + try { Geometry *g; @@ -620,7 +636,26 @@ Geometry *PostGIS2GEOS_collection(Geometry **geoms, int ngeoms, int SRID, bool i { (*subGeos)[t] = geoms[t]; } - g = geomFactory->buildGeometry(subGeos); + //g = geomFactory->buildGeometry(subGeos); + switch (type) + { + case COLLECTIONTYPE: + g = geomFactory->createGeometryCollection(subGeos); + break; + case MULTIPOINTTYPE: + g = geomFactory->createMultiPoint(subGeos); + break; + case MULTILINETYPE: + g = geomFactory->createMultiLineString(subGeos); + break; + case MULTIPOLYGONTYPE: + g = geomFactory->createMultiPolygon(subGeos); + break; + default: + NOTICE_MESSAGE("Unsupported type request for PostGIS2GEOS_collection"); + g = NULL; + + } #if GEOS_LAST_INTERFACE < 2 delete subGeos; #endif diff --git a/lwgeom/lwline.c b/lwgeom/lwline.c index ab99a7a2d..6262ca0aa 100644 --- a/lwgeom/lwline.c +++ b/lwgeom/lwline.c @@ -5,6 +5,9 @@ #include #include "liblwgeom.h" +//#define DEBUG_CALLS 1 + + // construct a new LWLINE. points will *NOT* be copied // use SRID=-1 for unknown SRID (will have 8bit type's S = 0) LWLINE *lwline_construct(int ndims, int SRID, POINTARRAY *points) @@ -107,7 +110,7 @@ char *lwline_serialize(LWLINE *line) // the given buffer, and returning number of bytes written into // the given int pointer. // result's first char will be the 8bit type. See serialized form doc -void lwline_serialize_buf(LWLINE *line, char *buf, int *retsize) +void lwline_serialize_buf(LWLINE *line, char *buf, size_t *retsize) { int size=1; // type byte char hasSRID; @@ -195,12 +198,20 @@ lwline_serialize_size(LWLINE *line) { size_t size = 1; //type +#ifdef DEBUG_CALLS + lwnotice("lwline_serialize_size called"); +#endif + if ( line->SRID != -1 ) size += 4; // SRID if ( line->hasbbox ) size += sizeof(BOX2DFLOAT4); size += sizeof(double)*line->ndims*line->points->npoints; // points size += 4; // npoints +#ifdef DEBUG_CALLS + lwnotice("lwline_serialize_size returning %d", size); +#endif + return size; } diff --git a/lwgeom/lwpoint.c b/lwgeom/lwpoint.c index 2e7c86d91..deb2d388b 100644 --- a/lwgeom/lwpoint.c +++ b/lwgeom/lwpoint.c @@ -3,6 +3,8 @@ #include #include "liblwgeom.h" +//#define DEBUG_CALLS 1 + // convert this point into its serialize form // result's first char will be the 8bit type. See serialized form doc char * @@ -28,20 +30,22 @@ lwpoint_serialize(LWPOINT *point) // the given int pointer. // result's first char will be the 8bit type. See serialized form doc void -lwpoint_serialize_buf(LWPOINT *point, char *buf, int *retsize) +lwpoint_serialize_buf(LWPOINT *point, char *buf, size_t *retsize) { int size=1; char hasSRID; char *loc; +#ifdef DEBUG_CALLS + lwnotice("lwpoint_serialize_buf(%p, %p) called", point, buf); +#endif + hasSRID = (point->SRID != -1); if (hasSRID) size +=4; //4 byte SRID if (point->hasbbox) size += sizeof(BOX2DFLOAT4); // bvol - if (point->ndims == 3) size += 24; //x,y,z - else if (point->ndims == 2) size += 16 ; //x,y,z - else if (point->ndims == 4) size += 32 ; //x,y,z,m + size += sizeof(double)*point->ndims; buf[0] = (unsigned char) lwgeom_makeType_full(point->ndims, hasSRID, POINTTYPE, point->hasbbox); @@ -121,11 +125,19 @@ lwpoint_serialize_size(LWPOINT *point) { size_t size = 1; // type +#ifdef DEBUG_CALLS + lwnotice("lwpoint_serialize_size called"); +#endif + if ( point->SRID != -1 ) size += 4; // SRID if ( point->hasbbox ) size += sizeof(BOX2DFLOAT4); size += point->ndims * sizeof(double); // point +#ifdef DEBUG_CALLS + lwnotice("lwpoint_serialize_size returning %d", size); +#endif + return size; } @@ -161,7 +173,7 @@ lwpoint_deserialize(char *serialized_form) char *loc = NULL; POINTARRAY *pa; -#ifdef DEBUG +#ifdef DEBUG_CALLS lwnotice("lwpoint_deserialize called"); #endif @@ -234,6 +246,9 @@ LWPOINT * lwpoint_clone(const LWPOINT *g) { LWPOINT *ret = lwalloc(sizeof(LWPOINT)); +#ifdef DEBUG_CALLS + lwnotice("lwpoint_clone called"); +#endif memcpy(ret, g, sizeof(LWPOINT)); return ret; } diff --git a/lwgeom/lwpoly.c b/lwgeom/lwpoly.c index 9dc6db231..d0e34659a 100644 --- a/lwgeom/lwpoly.c +++ b/lwgeom/lwpoly.c @@ -5,6 +5,8 @@ #include #include "liblwgeom.h" +//#define DEBUG_CALLS 1 + // construct a new LWPOLY. arrays (points/points per ring) will NOT be copied // use SRID=-1 for unknown SRID (will have 8bit type's S = 0) LWPOLY * @@ -134,7 +136,7 @@ lwpoly_serialize(LWPOLY *poly) // result's first char will be the 8bit type. See serialized form doc // points copied void -lwpoly_serialize_buf(LWPOLY *poly, char *buf, int *retsize) +lwpoly_serialize_buf(LWPOLY *poly, char *buf, size_t *retsize) { int size=1; // type byte char hasSRID; @@ -143,6 +145,10 @@ lwpoly_serialize_buf(LWPOLY *poly, char *buf, int *retsize) int npoints; char *loc; +#ifdef DEBUG_CALLS + lwnotice("lwpoly_serialize_buf called"); +#endif + hasSRID = (poly->SRID != -1); size += 4; // nrings @@ -321,6 +327,11 @@ lwpoly_serialize_size(LWPOLY *poly) if ( poly->SRID != -1 ) size += 4; // SRID if ( poly->hasbbox ) size += sizeof(BOX2DFLOAT4); +#ifdef DEBUG_CALLS + lwnotice("lwpoly_serialize_size called with poly[%p] (%d rings)", + poly, poly->nrings); +#endif + size += 4; // nrings for (i=0; inrings; i++) @@ -329,6 +340,10 @@ lwpoly_serialize_size(LWPOLY *poly) size += poly->rings[i]->npoints*poly->ndims*sizeof(double); } +#ifdef DEBUG_CALLS + lwnotice("lwpoly_serialize_size returning %d", size); +#endif + return size; } diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index 9057d5c1e..e4aeba9d1 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -1617,6 +1617,11 @@ CREATEFUNCTION ForceRHR(geometry) AS '@MODULE_FILENAME@', 'LWGEOM_forceRHR_poly' LANGUAGE 'C' WITH (iscachable,isstrict); +CREATEFUNCTION noop(geometry) + RETURNS geometry + AS '@MODULE_FILENAME@', 'LWGEOM_noop' + LANGUAGE 'C' WITH (iscachable,isstrict); + ------------------------------------------------------------------------ -- -- 2.40.0