diff --git a/lwgeom/liblwgeom.h b/lwgeom/liblwgeom.h index 7bf0847cb..cf454f2f1 100644 --- a/lwgeom/liblwgeom.h +++ b/lwgeom/liblwgeom.h @@ -596,49 +596,6 @@ typedef struct extern int lwgeom_size_inspected(const LWGEOM_INSPECTED *inspected, int geom_number); -/* - * This structure is intended to be used for geometry collection construction. - * Does not allow specification of collection structure - * (serialization chooses the simpler form) - */ -typedef struct -{ - int SRID; - uchar dims; - uint32 npoints; - uchar **points; - uint32 nlines; - uchar **lines; - uint32 npolys; - uchar **polys; -} LWGEOM_EXPLODED; - -void pfree_exploded(LWGEOM_EXPLODED *exploded); - -// Returns a 'palloced' union of the two input exploded geoms. -// Returns NULL if SRID or ndims do not match. -LWGEOM_EXPLODED * lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2); - -/* - * This function recursively scan the given serialized geometry - * and returns a list of _all_ subgeoms in it (deep-first) - */ -extern LWGEOM_EXPLODED *lwgeom_explode(uchar *serialized); - -/* - * Return the length of the serialized form corresponding - * to this exploded structure. - */ -extern size_t lwexploded_findlength(LWGEOM_EXPLODED *exp, int wantbbox); - -// Serialize an LWGEOM_EXPLODED object. -// SRID and ndims will be taken from exploded structure. -// wantbbox will determine result bbox. -extern uchar *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, uchar *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 // This function just computes the length of each sub-object and pre-caches this info. @@ -777,6 +734,7 @@ extern void pfree_POINTARRAY(POINTARRAY *pa); extern uint32 get_uint32(const uchar *loc); extern int32 get_int32(const uchar *loc); +extern void printBOX3D(BOX3D *b); extern void printPA(POINTARRAY *pa); extern void printLWPOINT(LWPOINT *point); extern void printLWLINE(LWLINE *line); @@ -1042,7 +1000,6 @@ extern POINTARRAY *ptarray_addPoint(POINTARRAY *pa, uchar *p, size_t pdims, unsi extern int ptarray_isclosed2d(const POINTARRAY *pa); extern int32 lwgeom_nrings_recursive(uchar *serialized); -extern void dump_lwexploded(LWGEOM_EXPLODED *exploded); extern void ptarray_reverse(POINTARRAY *pa); // Ensure every segment is at most 'dist' long. diff --git a/lwgeom/lwgeom_api.c b/lwgeom/lwgeom_api.c index d25e52af8..05037da93 100644 --- a/lwgeom/lwgeom_api.c +++ b/lwgeom/lwgeom_api.c @@ -8,14 +8,10 @@ #include "liblwgeom.h" //#define PGIS_DEBUG 1 -//#define PGIS_DEBUG_EXPLODED 1 // This is an implementation of the functions defined in lwgeom.h //forward decs -#ifdef PGIS_DEBUG_EXPLODED -void checkexplodedsize(uchar *srl, LWGEOM_EXPLODED *exploded, int alloced, char wantbbox); -#endif extern uchar *parse_lwg(const char* geometry, lwallocator allocfunc, lwreporter errfunc); //********************************************************************* @@ -1469,11 +1465,20 @@ lwnotice("compute_serialized_box3d: bbox found"); result = NULL; for (t=0; txmin, box->ymin, + box->xmax, box->ymax); +} + void printPA(POINTARRAY *pa) { int t; @@ -1733,622 +1744,6 @@ pglwgeom_setSRID(PG_LWGEOM *lwgeom, int32 newSRID) return result; } -void -pfree_exploded(LWGEOM_EXPLODED *exploded) -{ - if ( exploded->npoints ) - lwfree(exploded->points); - if ( exploded->nlines ) - lwfree(exploded->lines); - if ( exploded->npolys ) - lwfree(exploded->polys); - lwfree(exploded); -}; - -/* - * This function recursively scan the given serialized geometry - * and returns a list of _all_ subgeoms in it (deep-first) - */ -LWGEOM_EXPLODED * -lwgeom_explode(uchar *serialized) -{ - LWGEOM_INSPECTED *inspected; - LWGEOM_EXPLODED *subexploded, *result; - int i; - -#ifdef PGIS_DEBUG - lwnotice("lwgeom_explode called"); -#endif - - inspected = lwgeom_inspect(serialized); - - -#ifdef PGIS_DEBUG -lwnotice("lwgeom_explode: serialized inspected"); -#endif - - result = lwalloc(sizeof(LWGEOM_EXPLODED)); - result->points = lwalloc(1); - result->lines = lwalloc(1); - result->polys = lwalloc(1); - result->npoints = 0; - result->nlines = 0; - result->npolys = 0; - - if ( ! inspected->ngeometries ) - { - lwfree(result->points); - lwfree(result->lines); - lwfree(result->polys); - result->SRID = -1; - result->dims = inspected->type; - pfree_inspected(inspected); - //lwnotice("lwgeom_explode: no geometries"); - return result; - } - - result->SRID = lwgeom_getsrid(serialized); - result->dims = inspected->type; // will use ZM only - - for (i=0; ingeometries; i++) - { - - uchar *subgeom = inspected->sub_geoms[i]; - int type = lwgeom_getType(subgeom[0]); - - if ( type == POINTTYPE ) - { -#ifdef PGIS_DEBUG -lwnotice("lwgeom_explode: it's a point"); -#endif - result->points = lwrealloc(result->points, - (result->npoints+1)*sizeof(uchar *)); - result->points[result->npoints] = subgeom; - result->npoints++; - continue; - } - - if ( type == LINETYPE ) - { -#ifdef PGIS_DEBUG -lwnotice("lwgeom_explode: it's a line"); -#endif - result->lines = lwrealloc(result->lines, - (result->nlines+1)*sizeof(uchar *)); - result->lines[result->nlines] = subgeom; - result->nlines++; - continue; - } - - if ( type == POLYGONTYPE ) - { -#ifdef PGIS_DEBUG -lwnotice("lwgeom_explode: it's a polygon"); -#endif - result->polys = lwrealloc(result->polys, - (result->npolys+1)*sizeof(uchar *)); - result->polys[result->npolys] = subgeom; - result->npolys++; - continue; - } - -#ifdef PGIS_DEBUG - lwnotice("type of subgeom %d is %d, recursing", i, type); -#endif - - // it's a multi geometry, recurse - subexploded = lwgeom_explode(subgeom); - -#ifdef PGIS_DEBUG - lwnotice("subgeom %d, exploded: %d point, %d lines, %d polys", i, subexploded->npoints, subexploded->nlines, subexploded->npolys); -#endif - - // Re-allocate adding space for new exploded geoms - // (-1 because 1 was already allocated for the collection) - // Copy subgeom pointers from subexploded to current - // exploded. - - if ( subexploded->npoints ) - { - result->points = lwrealloc(result->points, - sizeof(uchar *)*(result->npoints+subexploded->npoints-1)); - if ( ! result ) - lwerror("Out of virtual memory"); - -#ifdef PGIS_DEBUG - lwnotice("lwrealloc'ed exploded->points"); -#endif - - memcpy(&(result->points[result->npoints]), - subexploded->points, - subexploded->npoints*sizeof(uchar *)); - -#ifdef PGIS_DEBUG - lwnotice("memcpied exploded->points"); -#endif - - result->npoints += subexploded->npoints; - -#ifdef PGIS_DEBUG - lwnotice("memcopied %d points from subexploded (exploded points: %d", subexploded->npoints, result->npoints); -#endif - } - - if ( subexploded->nlines ) - { - result->lines = lwrealloc(result->lines, - sizeof(uchar *)* - (result->nlines+subexploded->nlines-1)); - - memcpy(&(result->lines[result->nlines]), - subexploded->lines, - subexploded->nlines*sizeof(uchar *)); - - result->nlines += subexploded->nlines; - } - - if ( subexploded->npolys ) - { - result->polys = lwrealloc(result->polys, - sizeof(uchar *)* - (result->npolys+subexploded->npolys-1)); - - memcpy(&(result->polys[result->npolys]), - subexploded->polys, - subexploded->npolys*sizeof(uchar *)); - - result->npolys += subexploded->npolys; - } - - // release subexploded memory - pfree_exploded(subexploded); - - } - - pfree_inspected(inspected); - -#ifdef PGIS_DEBUG -lwnotice("lwgeom_explode: returning"); -#endif - - return result; -} - -// Returns a 'lwalloced' union of the two input exploded geoms -// Returns NULL if SRID or ndims do not match. -LWGEOM_EXPLODED * -lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2) -{ - LWGEOM_EXPLODED *expcoll; - uchar *loc; - - if ( TYPE_GETZM(exp1->dims) != TYPE_GETZM(exp2->dims) ) - { - lwerror("lwexploded_sum: can't sum mixed DIMS geoms (%d/%d)", - TYPE_GETZM(exp1->dims), TYPE_GETZM(exp2->dims)); - return NULL; - } - if ( exp1->SRID != exp2->SRID ) - { - lwerror("lwexploded_sum: can't sum mixed SRID geoms (%d/%d)", - exp1->SRID, exp2->SRID); - return NULL; - } - - expcoll = lwalloc(sizeof(LWGEOM_EXPLODED)); - - expcoll->npoints = exp1->npoints + exp2->npoints; - if ( expcoll->npoints ) { - expcoll->points = lwalloc(expcoll->npoints*sizeof(char *)); - loc = (char *)&(expcoll->points[0]); - if ( exp1->npoints ) { - memcpy(loc, exp1->points, - exp1->npoints*sizeof(char *)); - loc += exp1->npoints*sizeof(char *); - } - if ( exp2->npoints ) { - memcpy(loc, exp2->points, - exp2->npoints*sizeof(char *)); - } - } - - expcoll->nlines = exp1->nlines + exp2->nlines; - if ( expcoll->nlines ) { - expcoll->lines = lwalloc(expcoll->nlines*sizeof(char *)); - loc = (char *)&(expcoll->lines[0]); - if ( exp1->nlines ) { - memcpy(loc, exp1->lines, - exp1->nlines*sizeof(char *)); - loc += exp1->nlines*sizeof(char *); - } - if ( exp2->nlines ) { - memcpy(loc, exp2->lines, - exp2->nlines*sizeof(char *)); - } - } - - expcoll->npolys = exp1->npolys + exp2->npolys; - if ( expcoll->npolys ) { - expcoll->polys = lwalloc(expcoll->npolys*sizeof(char *)); - loc = (char *)&(expcoll->polys[0]); - if ( exp1->npolys ) { - memcpy(loc, exp1->polys, - exp1->npolys*sizeof(char *)); - loc += exp1->npolys*sizeof(char *); - } - if ( exp2->npolys ) { - memcpy(loc, exp2->polys, - exp2->npolys*sizeof(char *)); - } - } - - expcoll->dims = exp1->dims; - expcoll->SRID = exp1->SRID; - - return expcoll; -} - -/* - * Serialized a LWGEOM_EXPLODED structure - */ -uchar * -lwexploded_serialize(LWGEOM_EXPLODED *exploded, int wantbbox) -{ - size_t sizecom = 0; - size_t size; - uchar *result; - - size = lwexploded_findlength(exploded, wantbbox); - result = lwalloc(size); - lwexploded_serialize_buf(exploded, wantbbox, result, &sizecom); -#ifdef PGIS_DEBUG - lwnotice("lwexploded_serialize: findlength:%d, serialize_buf:%d", size, sizecom); -#endif - return result; -} - -/* - * Serialized a LWGEOM_EXPLODED structure into a - * pre-allocated memory space. - * Use lwexploded_findlength to know the required size - * of the provided buffer. - */ -void -lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, - uchar *buf, size_t *retsize) -{ - size_t size=0; - int i; - int ntypes = 0; - int ngeoms = 0; - uchar *loc; - int outtype = 0; - LWPOLY *poly; - LWLINE *line; - LWPOINT *point; - BOX2DFLOAT4 *box2d; - BOX3D *box3d; - - ngeoms = exploded->npoints + exploded->nlines + exploded->npolys; - - if ( ngeoms == 0 ) - { - lwgeom_constructempty_buf(exploded->SRID, - TYPE_HASZ(exploded->dims), TYPE_HASM(exploded->dims), - buf, retsize); - return; - } - - - // For a single geometry just set SRID and BBOX (if requested) - if ( ngeoms == 1 ) - { - loc = buf; - - if ( exploded->npoints ) { - - if ( wantbbox && ! - lwgeom_hasBBOX(exploded->points[0][0]) ) - { - loc += sizeof(BOX2DFLOAT4); - } - point = lwpoint_deserialize(exploded->points[0]); - point->SRID = exploded->SRID; - lwpoint_serialize_buf(point, loc, &size); - pfree_point(point); - } - else if ( exploded->nlines ) { - if ( wantbbox && ! - lwgeom_hasBBOX(exploded->lines[0][0]) ) - { - loc += sizeof(BOX2DFLOAT4); - } - line = lwline_deserialize(exploded->lines[0]); - line->SRID = exploded->SRID; - lwline_serialize_buf(line, loc, &size); - pfree_line(line); - } - else if ( exploded->npolys ) { - if ( wantbbox && ! - lwgeom_hasBBOX(exploded->polys[0][0]) ) - { - loc += sizeof(BOX2DFLOAT4); - } - poly = lwpoly_deserialize(exploded->polys[0]); - poly->SRID = exploded->SRID; - lwpoly_serialize_buf(poly, loc, &size); - pfree_polygon(poly); - - } - else { - if ( retsize ) *retsize = 0; - return; // ERROR !! - } - - - // Now compute the bounding box and write it - if ( wantbbox && ! lwgeom_hasBBOX(loc[0]) ) - { - buf[0] = loc[0]; - TYPE_SETHASBBOX(buf[0], 1); - box3d = compute_serialized_box3d(loc); - box2d = box3d_to_box2df(box3d); - loc = buf+1; - memcpy(loc, box2d, sizeof(BOX2DFLOAT4)); - size += sizeof(BOX2DFLOAT4); - } - - if (retsize) *retsize = size; - return; - } - - if ( exploded->npoints ) { - ntypes++; - outtype = (exploded->npoints>1) ? MULTIPOINTTYPE : POINTTYPE; - } - if ( exploded->nlines ) { - ntypes++; - if ( outtype ) outtype = COLLECTIONTYPE; - else outtype = (exploded->nlines>1) ? MULTILINETYPE : LINETYPE; - } - if ( exploded->npolys ) { - ntypes++; - if ( outtype ) outtype = COLLECTIONTYPE; - else outtype = (exploded->npolys>1) ? MULTIPOLYGONTYPE : POLYGONTYPE; - } - -#ifdef PGIS_DEBUG - lwnotice(" computed outtype: %d, ngeoms: %d", outtype, ngeoms); -#endif - - - loc = buf+1; // skip type - - if ( wantbbox ) loc += sizeof(BOX2DFLOAT4); // skip box - if ( exploded->SRID != -1 ) loc += 4; // skip SRID - - // If we have more then one type of geom - // write that number in the 'ngeoms' field of the - // output serialized form (internal geoms would be multi themself). - // Else rewind location pointer so to overwrite result type. - if ( ntypes > 1 ) { - memcpy(loc, &ntypes, 4); - loc += 4; - } else { - loc--; // let the type be specified later. - } - - if ( exploded->npoints > 1 ) - { - loc[0] = lwgeom_makeType_full( - TYPE_HASZ(exploded->dims), TYPE_HASM(exploded->dims), - 0, MULTIPOINTTYPE, 0); - loc++; - memcpy(loc, &exploded->npoints, 4); // numpoints - loc += 4; - } - // Serialize points stripping BBOX and SRID if any - for (i=0; inpoints; i++) - { - size_t subsize; - point = lwpoint_deserialize(exploded->points[i]); - point->SRID = -1; - lwpoint_serialize_buf(point, loc, &subsize); - pfree_point(point); - loc += subsize; - } - - if ( exploded->nlines > 1 ) - { - loc[0] = lwgeom_makeType_full( - TYPE_HASZ(exploded->dims), - TYPE_HASM(exploded->dims), - 0, MULTILINETYPE, 0); - loc++; - memcpy(loc, &exploded->nlines, 4); // numlines - loc += 4; - } - // Serialize lines stripping BBOX and SRID if any - for (i=0; inlines; i++) - { - size_t subsize; - - line = lwline_deserialize(exploded->lines[i]); - if ( line == NULL ) - { - lwerror("Error deserializing %dnt line from exploded geom", i); - return; - } - line->SRID = -1; - lwline_serialize_buf(line, loc, &subsize); - pfree_line(line); - loc += subsize; - } - - if ( exploded->npolys > 1 ) - { - loc[0] = lwgeom_makeType_full( - TYPE_HASZ(exploded->dims), - TYPE_HASM(exploded->dims), - 0, MULTIPOLYGONTYPE, 0); - loc++; - memcpy(loc, &exploded->npolys, 4); // numpolys - loc += 4; - } - // Serialize polys stripping BBOX and SRID if any - for (i=0; inpolys; i++) - { - size_t subsize; - - poly = lwpoly_deserialize(exploded->polys[i]); - if ( poly == NULL ) - { - lwerror("Error deserializing %dnt polygon from exploded geom", i); - return; - } - poly->SRID = -1; - lwpoly_serialize_buf(poly, loc, &subsize); - pfree_polygon(poly); - loc += subsize; - } - - // Register now the number of written bytes - if (retsize) *retsize = (loc-buf); - - // Ok. now we need to add type, SRID and bbox - buf[0] = lwgeom_makeType_full( - TYPE_HASZ(exploded->dims), - TYPE_HASM(exploded->dims), - (exploded->SRID!=-1), outtype, wantbbox); - loc = buf+1; - - if ( wantbbox ) - { - box3d = compute_serialized_box3d(buf); - box2d = box3d_to_box2df(box3d); - memcpy(loc, box2d, sizeof(BOX2DFLOAT4)); - loc += sizeof(BOX2DFLOAT4); - } - - if ( exploded->SRID != -1 ) - { - memcpy(loc, &(exploded->SRID), 4); - loc += 4; // useless.. we've finished - } - -#ifdef PGIS_DEBUG - lwnotice("lwexploded_serialize finished"); - lwnotice(" type: %d", lwgeom_getType(buf[0])); - lwnotice(" SRID: %d", lwgeom_getsrid(buf)); - if ( lwgeom_hasBBOX(buf[0]) ) - { - { - BOX2DFLOAT4 boxbuf; - getbox2d_p(buf, &boxbuf); - lwnotice(" BBOX: %f,%f %f,%f", - boxbuf.xmin, boxbuf.ymin, - boxbuf.xmax, boxbuf.ymax); - } - } - lwnotice(" numgeoms: %d", lwgeom_getnumgeometries(buf)); -#endif - - return; -} - -#ifdef PGIS_DEBUG_EXPLODED -void -checkexplodedsize(uchar *srl, LWGEOM_EXPLODED *exp, int alloced, char wantbbox) -{ - lwnotice("exploded len: serialized:%d computed:%d alloced:%d", - lwgeom_size(srl), lwexploded_findlength(exp, wantbbox), - alloced); -} -#endif - -size_t -lwexploded_findlength(LWGEOM_EXPLODED *exploded, int wantbbox) -{ - size_t size=0; - char ntypes=0; - uint32 i; - - - // find sum of sizes of all geoms. - // substract size of eventually embedded SRID and BBOXes - if ( exploded->npoints ) - { - ntypes++; - for (i=0; inpoints; i++) - { - size += lwgeom_size_point(exploded->points[i]); - if ( lwgeom_hasBBOX(exploded->points[i][0]) ) - size -= sizeof(BOX2DFLOAT4); - if ( lwgeom_hasSRID(exploded->points[i][0]) ) - size -= 4; - } - // add multigeom header size - if ( exploded->npoints > 1 ) - { - size += 1; // type - size += 4; // numgeometries - } - } - if ( exploded->nlines ) - { - ntypes++; - for (i=0; inlines; i++) - { - size += lwgeom_size_line(exploded->lines[i]); - if ( lwgeom_hasBBOX(exploded->lines[i][0]) ) - size -= sizeof(BOX2DFLOAT4); - if ( lwgeom_hasSRID(exploded->lines[i][0]) ) - size -= 4; - } - // add multigeom header size - if ( exploded->nlines > 1 ) - { - size += 1; // type - size += 4; // numgeometries - } - } - if ( exploded->npolys ) - { - ntypes++; - for (i=0; inpolys; i++) - { - size += lwgeom_size_poly(exploded->polys[i]); - if ( lwgeom_hasBBOX(exploded->polys[i][0]) ) - size -= sizeof(BOX2DFLOAT4); - if ( lwgeom_hasSRID(exploded->polys[i][0]) ) - size -= 4; - } - // add multigeom header size - if ( exploded->npolys > 1 ) - { - size += 1; // type - size += 4; // numgeometries - } - } - - /* structure is empty */ - if ( ! ntypes ) return lwgeom_empty_length(exploded->SRID); - - /* multi-typed geom (collection), add collection header */ - if ( ntypes > 1 ) - { - size += 1; // type - size += 4; // numgeometries - } - - /* - * Add BBOX and SRID if required - */ - if ( exploded->SRID != -1 ) size += 4; - if ( wantbbox ) size += sizeof(BOX2DFLOAT4); - - return size; -} char ptarray_isccw(const POINTARRAY *pa) diff --git a/lwgeom/lwgeom_box3d.c b/lwgeom/lwgeom_box3d.c index afeb51539..c320e6b6c 100644 --- a/lwgeom/lwgeom_box3d.c +++ b/lwgeom/lwgeom_box3d.c @@ -231,6 +231,7 @@ Datum LWGEOM_to_BOX3D(PG_FUNCTION_ARGS) BOX3D *result; result = compute_serialized_box3d(SERIALIZED_FORM(lwgeom)); + if ( ! result ) PG_RETURN_NULL(); PG_RETURN_POINTER(result); } @@ -369,7 +370,8 @@ Datum BOX3D_construct(PG_FUNCTION_ARGS) } //min(a,b) -double LWGEOM_Mind(double a, double b) +double +LWGEOM_Mind(double a, double b) { if (aa) return b; return a; } +