From: David Blasby Date: Tue, 6 Apr 2004 22:58:11 +0000 (+0000) Subject: Changes to make it work with all the PostGIS type. X-Git-Tag: pgis_0_8_2~60 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9e400d7b671e444ed1db58d5fa157e673936d6d9;p=postgis Changes to make it work with all the PostGIS type. git-svn-id: http://svn.osgeo.org/postgis/trunk@499 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/lwgeom/lwgeom.h b/lwgeom/lwgeom.h index 86db6a042..b636e91ad 100644 --- a/lwgeom/lwgeom.h +++ b/lwgeom/lwgeom.h @@ -424,6 +424,7 @@ extern void printPA(POINTARRAY *pa); extern void printLWLINE(LWLINE *line); extern void printLWPOLY(LWPOLY *poly); extern void printBYTES(unsigned char *a, int n); +extern void printMULTI(char *serialized); extern void deparse_hex(unsigned char str, unsigned char *result); diff --git a/lwgeom/lwgeom_api.c b/lwgeom/lwgeom_api.c index 02f2b0c47..040506247 100644 --- a/lwgeom/lwgeom_api.c +++ b/lwgeom/lwgeom_api.c @@ -381,7 +381,7 @@ POINTARRAY *pointArray_construct(char *points, int ndims, uint32 npoints) POINTARRAY *pa; pa = (POINTARRAY*)palloc(sizeof(pa)); - if (ndims>2) + if (ndims>4) elog(ERROR,"pointArray_construct:: called with dims = %i", (int) ndims); pa->ndims = ndims; @@ -617,7 +617,7 @@ if (line == NULL) loc +=4; //copy in points -elog(NOTICE," line serialize - size = %i", size); +//elog(NOTICE," line serialize - size = %i", size); if (line->ndims == 3) { @@ -694,7 +694,7 @@ uint32 lwline_findlength(char *serialized_line) { return result+ npoints * 32; } - elog(NOTICE,"lwline_findlength :: invalid ndims"); + elog(ERROR,"lwline_findlength :: invalid ndims"); return 0; //never get here } @@ -876,7 +876,7 @@ uint32 lwpoint_findlength(char *serialized_point) { return result + 24; } - else if (lwgeom_ndims(type) == 3) + else if (lwgeom_ndims(type) == 2) { return result + 16; } @@ -884,7 +884,7 @@ uint32 lwpoint_findlength(char *serialized_point) { return result + 32; } - elog(NOTICE,"lwpoint_findlength :: invalid ndims"); + elog(ERROR,"lwpoint_findlength :: invalid ndims = %i",lwgeom_ndims(type)); return 0; //never get here } @@ -1193,7 +1193,7 @@ LWGEOM_INSPECTED *lwgeom_inspect(char *serialized_form) result->ngeometries = get_uint32(loc); loc +=4; sub_geoms = (char**) palloc(sizeof(char*) * result->ngeometries ); - + result->sub_geoms = sub_geoms; sub_geoms[0] = loc; for (t=1;tngeometries; t++) { @@ -1288,15 +1288,18 @@ LWLINE *lwgeom_getline_inspected(LWGEOM_INSPECTED *inspected, int geom_number) char *sub_geom; char type; + sub_geom = lwgeom_getsubgeometry_inspected(inspected, geom_number); if (sub_geom == NULL) return NULL; + type = lwgeom_getType(sub_geom[0]); if (type != LINETYPE) return NULL; + return lwline_deserialize(sub_geom); } @@ -1869,3 +1872,41 @@ void printLWPOLY(LWPOLY *poly) } elog(NOTICE,"}"); } + +void printMULTI(char *serialized) +{ + LWGEOM_INSPECTED *inspected = lwgeom_inspect(serialized); + LWLINE *line; + LWPOINT *point; + LWPOLY *poly; + int t; + + elog(NOTICE,"MULTI* geometry (type = %i), with %i sub-geoms",lwgeom_getType(serialized[0]), inspected->ngeometries); + + for (t=0;tngeometries;t++) + { + elog(NOTICE," sub-geometry %i:", t); + line = NULL; point = NULL; poly = NULL; + + line = lwgeom_getline_inspected(inspected,t); + if (line !=NULL) + { + printLWLINE(line); + } + poly = lwgeom_getpoly_inspected(inspected,t); + if (poly !=NULL) + { + printLWPOLY(poly); + } + point = lwgeom_getpoint_inspected(inspected,t); + if (point !=NULL) + { + printPA(point->point); + } + } + + elog(NOTICE,"end multi*"); + + pfree_inspected(inspected); +} + diff --git a/lwgeom/lwgeom_inout.c b/lwgeom/lwgeom_inout.c index a90e5de12..5f943a3da 100644 --- a/lwgeom/lwgeom_inout.c +++ b/lwgeom/lwgeom_inout.c @@ -24,7 +24,7 @@ -extern char *wkb_to_lwgeom(char *wkb, int SRID,int *size); +extern char *wkb_to_lwgeom(char *wkb, int SRID,int *sizeLWGEOM, int *sizeWKB); extern char *lwgeom_to_wkb(char *serialized_form,int *wkblength,char desiredWKBEndian); extern void swap_char(char *a,char *b); extern void flip_endian_double(char *d); @@ -36,14 +36,16 @@ extern bool requiresflip(char WKBendianflag); extern void flipPoints(char *pts, int npoints, char dims); extern uint32 constructWKBType(int simple_type, char dims); -extern LWPOINT *wkb_point_to_lwpoint(char *wkb,int SRID); -extern LWLINE *wkb_line_to_lwline(char *wkb,int SRID); -extern LWPOLY *wkb_poly_to_lwpoly(char *wkb,int SRID); +extern LWPOINT *wkb_point_to_lwpoint(char *wkb,int SRID, int *sizeWKB); +extern LWLINE *wkb_line_to_lwline(char *wkb,int SRID, int *sizeWKB); +extern LWPOLY *wkb_poly_to_lwpoly(char *wkb,int SRID, int *sizeWKB); extern char *lwline_to_wkb(LWLINE *line, char desiredWKBEndian, int *wkbsize); extern char *lwpoint_to_wkb(LWPOINT *point, char desiredWKBEndian, int *wkbsize); extern char *lwpoly_to_wkb(LWPOLY *poly, char desiredWKBEndian, int *wkbsize); +extern char *wkb_multi_to_lwgeom_serialized(char *wkb,int type, int *serialized_size, int SRID, int *sizeWKB); +extern char *serialized_multi_to_wkb(char *serialized_form,char desiredWKBEndian,int *wkblength); extern unsigned char parse_hex(char *str); extern void deparse_hex(unsigned char str, unsigned char *result); @@ -78,6 +80,7 @@ Datum LWGEOM_in(PG_FUNCTION_ARGS) int size; int t; int input_str_len; + int sizeWKB; int SRID = -1; //default (change) @@ -104,7 +107,7 @@ Datum LWGEOM_in(PG_FUNCTION_ARGS) } //have WKB string (and we can safely modify it) - lwgeom = wkb_to_lwgeom(((char *) wkb)+4, SRID,&size); + lwgeom = wkb_to_lwgeom(((char *) wkb)+4, SRID,&size,&sizeWKB); pfree(wkb); // no longer referenced! @@ -156,6 +159,7 @@ Datum LWGEOMFromWKB(PG_FUNCTION_ARGS) char *lwgeom; char * result; char *wkb_copy; + int sizeWKB; if ( ( PG_NARGS()>1) && ( ! PG_ARGISNULL(1) )) @@ -163,15 +167,14 @@ Datum LWGEOMFromWKB(PG_FUNCTION_ARGS) else SRID = -1; -#ifdef DEBUG - elog(NOTICE,"LWGEOMFromWKB: entry with SRID=%i",SRID); -#endif + // elog(NOTICE,"LWGEOMFromWKB: entry with SRID=%i",SRID); + // need to do this because there might be a bunch of endian flips! wkb_copy = palloc( *((int32 *) wkb_input)); memcpy(wkb_copy, wkb_input+4, *((int32 *) wkb_input) -4); - lwgeom = wkb_to_lwgeom(wkb_copy, SRID,&size); + lwgeom = wkb_to_lwgeom(wkb_copy, SRID,&size,&sizeWKB); pfree(wkb_copy); // no longer referenced! @@ -219,7 +222,7 @@ Datum WKBFromLWGEOM(PG_FUNCTION_ARGS) // // also, wkb should point to the 1st wkb character; NOT // the postgresql length int32. -char *wkb_to_lwgeom(char *wkb, int SRID,int *size) +char *wkb_to_lwgeom(char *wkb, int SRID,int *sizeLWGEOM, int *sizeWKB) { uint32 wkbtype; char dims; @@ -228,7 +231,6 @@ char *wkb_to_lwgeom(char *wkb, int SRID,int *size) LWPOINT *pt; LWLINE *line; LWPOLY *poly; - char *multigeom = NULL; char *result = NULL; int simpletype; @@ -239,47 +241,50 @@ char *wkb_to_lwgeom(char *wkb, int SRID,int *size) dims = wkb_dims(wkbtype); simpletype = wkb_simpletype(wkbtype); -#ifdef DEBUG - elog(NOTICE,"wkb_to_lwgeom: entry with SRID=%i, dims=%i, simpletype=%i",SRID,(int) dims, (int) simpletype); -#endif + +// elog(NOTICE,"wkb_to_lwgeom: entry with SRID=%i, dims=%i, simpletype=%i",SRID,(int) dims, (int) simpletype); + switch (simpletype) { case POINTTYPE: - pt = wkb_point_to_lwpoint(wkb, SRID); + pt = wkb_point_to_lwpoint(wkb, SRID,sizeWKB); result = lwpoint_serialize(pt); - *size = lwpoint_findlength(result); + *sizeLWGEOM = lwpoint_findlength(result); pfree_point(pt); break; case LINETYPE: - line = wkb_line_to_lwline(wkb, SRID); + line = wkb_line_to_lwline(wkb, SRID,sizeWKB); //printLWLINE(line); result = lwline_serialize(line); // elog(NOTICE,"line serialized"); - *size = lwline_findlength(result); + *sizeLWGEOM = lwline_findlength(result); pfree_line(line); break; case POLYGONTYPE: - poly = wkb_poly_to_lwpoly(wkb, SRID); + poly = wkb_poly_to_lwpoly(wkb, SRID,sizeWKB); // printLWPOLY(poly); result = lwpoly_serialize(poly); - *size = lwpoly_findlength(result); +// { +// LWPOLY *poly2 = lwpoly_deserialize(result); +// printLWPOLY(poly2); +// } + *sizeLWGEOM = lwpoly_findlength(result); pfree_polygon(poly); break; case MULTIPOINTTYPE: - result = multigeom; - break; case MULTILINETYPE: - break; case MULTIPOLYGONTYPE: - break; case COLLECTIONTYPE: + result = wkb_multi_to_lwgeom_serialized(wkb,simpletype, sizeLWGEOM, SRID,sizeWKB); + //printBYTES(result,*size); + //printMULTI(result); break; } -#ifdef DEBUG - elog(NOTICE,"wkb_to_lwgeom:returning"); -#endif + +// elog(NOTICE,"wkb_to_lwgeom:returning"); + return result; } @@ -288,7 +293,7 @@ char *wkb_to_lwgeom(char *wkb, int SRID,int *size) // we make sure the point is correctly endianed // and make a LWPOINT that points into it. // wkb --> point to the endian definition of the wkb point -LWPOINT *wkb_point_to_lwpoint(char *wkb,int SRID) +LWPOINT *wkb_point_to_lwpoint(char *wkb,int SRID, int *sizeWKB) { uint32 wkbtype; char dims; @@ -303,9 +308,9 @@ LWPOINT *wkb_point_to_lwpoint(char *wkb,int SRID) dims = wkb_dims(wkbtype); simpletype = wkb_simpletype(wkbtype); -#ifdef DEBUG - elog(NOTICE,"wkb_point_to_lwpoint: entry with SRID=%i, dims=%i, simpletype=%i",SRID,(int) dims, (int) simpletype); -#endif + + // elog(NOTICE,"wkb_point_to_lwpoint: entry with SRID=%i, dims=%i, simpletype=%i",SRID,(int) dims, (int) simpletype); + @@ -316,11 +321,11 @@ LWPOINT *wkb_point_to_lwpoint(char *wkb,int SRID) pa = pointArray_construct(wkb+5, dims, 1); - + *sizeWKB = dims * 8 + 5; return lwpoint_construct(dims, SRID, pa); } -LWLINE *wkb_line_to_lwline(char *wkb,int SRID) +LWLINE *wkb_line_to_lwline(char *wkb,int SRID, int *sizeWKB) { uint32 wkbtype; char dims; @@ -348,21 +353,25 @@ LWLINE *wkb_line_to_lwline(char *wkb,int SRID) flipPoints(wkb+9,npoints,dims); pa = pointArray_construct(wkb+9, dims, npoints); + + *sizeWKB = dims * 8*npoints + 5 +4; + return lwline_construct(dims, SRID, pa); } -LWPOLY *wkb_poly_to_lwpoly(char *wkb,int SRID) +LWPOLY *wkb_poly_to_lwpoly(char *wkb,int SRID, int *sizeWKB) { uint32 wkbtype; char dims; char simpletype; POINTARRAY *pa; - int npoints; + int npoints =0; POINTARRAY **rings; int nrings; int t; char *loc; int ptsize =16; + int total_points=0; bool need_flip = requiresflip( wkb[0] ); if (need_flip) @@ -413,11 +422,121 @@ LWPOLY *wkb_poly_to_lwpoly(char *wkb,int SRID) loc += 4; loc += npoints * ptsize; rings[t] = pa; + total_points += npoints; } + *sizeWKB = dims * 8 *total_points + 4*nrings + 9; +//elog(NOTICE,"polygon: size wkb = %i; npoints = %i", *sizeWKB, total_points); return lwpoly_construct(dims, SRID, nrings,rings); } +// Takes a wkb thats a multi* (or GC) and returns it in the serialized form. +// serialized_size is filled in. +// resulting serialized form will have type 'type' (MULTI* or GC). +// +// Basically, all multi* geometries look the same - you just need to set +// the "main" type. For example, a multipoint and GC are the same except +// the type is "MULTIPOINT" or "GEOMETRYCOLLECTION". + +char *wkb_multi_to_lwgeom_serialized(char *wkb,int type, int *serialized_size, int SRID, int *sizeWKB) +{ + int *sub_obj_sizes; + char **sub_objs; + + + bool need_flip = requiresflip( wkb[0] ); + uint32 wkbtype; + char dims; + int ngeoms; + char simpletype; + char *loc; + int sum_size_sub_objs = 0; + int total_size = 0; + char *result; + int ndims = 2; + char sub_type; + int t; + int sizeWKB_sub; + + sizeWKB = 0; + + //make a list of all the serialized forms of the sub-objects + // NOTE: the sub-objects could possibly be MULTI* (gasp!). + + wkbtype = get_uint32(wkb+1); + dims = wkb_dims(wkbtype); + simpletype = wkb_simpletype(wkbtype); + + if ( (simpletype != MULTIPOINTTYPE) && (simpletype != MULTILINETYPE) && (simpletype != MULTIPOLYGONTYPE) && (simpletype != COLLECTIONTYPE)) + { + elog(ERROR,"wkb_multi_to_lwgeom_serialized:: got a non-multi* type"); + return NULL; + } + if (need_flip) + flip_endian_int32(wkb+5); // ngeoms + + ngeoms = get_uint32(wkb+5); // ngeoms + + sub_obj_sizes = (int *) palloc(sizeof(int *) * ngeoms); + sub_objs = palloc(sizeof(char *) * ngeoms); + + loc = wkb+9; // start of 1st geometry + + for (t=0;tpoint->ndims ); -#endif + + // elog(NOTICE,"lwpoint_to_wkb: pa dims = %i", (int)pt->point->ndims ); + *wkbsize = 1+ 4+ ptsize; //endian, type, point @@ -488,9 +605,9 @@ char *lwpoint_to_wkb(LWPOINT *pt, char desiredWKBEndian, int *wkbsize) wkbtype = constructWKBType(POINTTYPE, pt->point->ndims); -#ifdef DEBUG - elog(NOTICE,"lwpoint_to_wkb: entry with wkbtype=%i, pa dims = %i",wkbtype, (int)pt->point->ndims ); -#endif + + // elog(NOTICE,"lwpoint_to_wkb: entry with wkbtype=%i, pa dims = %i",wkbtype, (int)pt->point->ndims ); + @@ -549,13 +666,17 @@ char *lwpoly_to_wkb(LWPOLY *poly, char desiredWKBEndian, int *wkbsize) total_points += poly->rings[t]->npoints; } - *wkbsize = 1+ 4+ total_points * ptsize + 4* poly->nrings; //endian, type, all points, ring lengths + *wkbsize = 1+ 4+ 4+total_points * ptsize + 4* poly->nrings; //endian, type, npoints, all points, ring lengths + +//elog(NOTICE,"lwpoly_to_wkb:: a polygon with %i rings, total of %i points, wkbsize =%i",poly->nrings, total_points, *wkbsize); + result = palloc(*wkbsize); result[0] = desiredWKBEndian; //endian flag wkbtype = constructWKBType(POLYGONTYPE, poly->ndims); + memcpy(result+1, &wkbtype, 4); // type if (need_flip) flip_endian_int32(result+1); @@ -577,10 +698,83 @@ char *lwpoly_to_wkb(LWPOLY *poly, char desiredWKBEndian, int *wkbsize) flipPoints(loc+4, npoints, poly->ndims); loc += 4+ ptsize * npoints; } +//printBYTES(result, *wkbsize); return result; } +//given an LWGEOM thats a GC or MULTI*, return the corresponding WKB +char *serialized_multi_to_wkb(char *serialized_form,char desiredWKBEndian,int *wkblength) +{ + char *result; + uint32 wkbtype; + int t; + LWGEOM_INSPECTED *inspected; + int total_size_sub_objs = 0; //wkb + int total_size; + + int *sub_obj_sizes; //wkb + char **sub_objs; //wkb + bool need_flip = requiresflip( desiredWKBEndian ); + char *loc; + + wkbtype = constructWKBType(lwgeom_getType(serialized_form[0]), lwgeom_ndims(serialized_form[0]) ); + +//elog(NOTICE,"serialized_multi_to_wkb::wkbtype = %i", wkbtype); + + inspected = lwgeom_inspect(serialized_form); + sub_obj_sizes = (int *) palloc(sizeof(int *) * inspected->ngeometries); + sub_objs = palloc(sizeof(char *) * inspected->ngeometries); + + + for ( t=0;tngeometries;t++) + { + char *serial_sub = inspected->sub_geoms[t]; + sub_objs[t] = lwgeom_to_wkb(serial_sub,&sub_obj_sizes[t], desiredWKBEndian); + total_size_sub_objs += sub_obj_sizes[t]; + //elog(NOTICE,"serialized_multi_to_wkb:: sub geom %i has size %i (wkb)",t,sub_obj_sizes[t]); + } + + total_size = 1 + 4+ 4 + total_size_sub_objs;// endian + wkbtype + ngeoms + geoms + result = palloc(total_size); + +//elog(NOTICE,"serialized_multi_to_wkb::total size of wkb = %i", total_size); + + result[0] = desiredWKBEndian; + memcpy(result+1, &wkbtype, 4); + if (need_flip) + flip_endian_int32(result+1); + + memcpy(result+5, &inspected->ngeometries, 4); + if (need_flip) + flip_endian_int32(result+5); + + loc = result+9; + for ( t=0;tngeometries;t++) + { + memcpy(loc, sub_objs[t], sub_obj_sizes[t]); + loc += sub_obj_sizes[t]; + } + + + // clean up memory + for ( t=0;tngeometries;t++) + { + pfree(sub_objs[t]); + } + pfree(sub_obj_sizes); + pfree(sub_objs); + + pfree_inspected(inspected); + + *wkblength = total_size; + +// elog(NOTICE,"serialized_multi_to_wkb::returning"); + return result; +} + + + bool requiresflip(char WKBendianflag) { if (WKBendianflag == 1) // NDR