From 948fef638da81da1078be00425203dfc705ef2b1 Mon Sep 17 00:00:00 2001 From: Regina Obe Date: Mon, 8 Jan 2018 17:09:09 +0000 Subject: [PATCH] Rewrite to use stringbuffer instead of the mess of sprintfs Closes #3974 git-svn-id: http://svn.osgeo.org/postgis/trunk@16224 b70326c6-7e19-0410-871a-916f4a2858ee --- liblwgeom/lwout_x3d.c | 649 ++++++++++-------------------------------- liblwgeom/lwout_x3d.h | 28 +- 2 files changed, 168 insertions(+), 509 deletions(-) diff --git a/liblwgeom/lwout_x3d.c b/liblwgeom/lwout_x3d.c index 9010a710c..e66f83822 100644 --- a/liblwgeom/lwout_x3d.c +++ b/liblwgeom/lwout_x3d.c @@ -31,12 +31,13 @@ /* * VERSION X3D 3.0.2 http://www.web3d.org/specifications/x3d-3.0.dtd */ - -/* takes a GEOMETRY and returns an X3D representation */ -extern char * +/* takes a GEOMETRY and returns a X3D representation */ +char* lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid) { - int type = geom->type; + stringbuffer_t *sb; + int rv; + char *result; /* Empty string for empties */ if( lwgeom_is_empty(geom) ) @@ -47,13 +48,33 @@ lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const cha return ret; } + sb = stringbuffer_create(); + rv = lwgeom_to_x3d3_sb(geom, srs, precision, opts, defid, sb); + + if ( rv == LW_FAILURE ) + { + stringbuffer_destroy(sb); + return NULL; + } + + result = stringbuffer_getstringcopy(sb); + stringbuffer_destroy(sb); + + return result; +} +/* takes a GEOMETRY and appends to string buffer the x3d output */ +static int +lwgeom_to_x3d3_sb(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb) +{ + int type = geom->type; + switch (type) { case POINTTYPE: - return asx3d3_point((LWPOINT*)geom, srs, precision, opts, defid); + return asx3d3_point_sb((LWPOINT*)geom, srs, precision, opts, defid, sb); case LINETYPE: - return asx3d3_line((LWLINE*)geom, srs, precision, opts, defid); + return asx3d3_line_sb((LWLINE*)geom, srs, precision, opts, defid, sb); case POLYGONTYPE: { @@ -61,141 +82,52 @@ lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const cha * seems like the simplest way to go so treat just like a mulitpolygon */ LWCOLLECTION *tmp = (LWCOLLECTION*)lwgeom_as_multi(geom); - char *ret = asx3d3_multi(tmp, srs, precision, opts, defid); + asx3d3_multi_sb(tmp, srs, precision, opts, defid, sb); lwcollection_free(tmp); - return ret; + return LW_SUCCESS; } case TRIANGLETYPE: - return asx3d3_triangle((LWTRIANGLE*)geom, srs, precision, opts, defid); + return asx3d3_triangle_sb((LWTRIANGLE*)geom, srs, precision, opts, defid, sb); case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: - return asx3d3_multi((LWCOLLECTION*)geom, srs, precision, opts, defid); + return asx3d3_multi_sb((LWCOLLECTION*)geom, srs, precision, opts, defid, sb); case POLYHEDRALSURFACETYPE: - return asx3d3_psurface((LWPSURFACE*)geom, srs, precision, opts, defid); + return asx3d3_psurface_sb((LWPSURFACE*)geom, srs, precision, opts, defid, sb); case TINTYPE: - return asx3d3_tin((LWTIN*)geom, srs, precision, opts, defid); + return asx3d3_tin_sb((LWTIN*)geom, srs, precision, opts, defid, sb); case COLLECTIONTYPE: - return asx3d3_collection((LWCOLLECTION*)geom, srs, precision, opts, defid); + return asx3d3_collection_sb((LWCOLLECTION*)geom, srs, precision, opts, defid, sb); default: lwerror("lwgeom_to_x3d3: '%s' geometry type not supported", lwtype_name(type)); - return NULL; - } -} - -static size_t -asx3d3_point_size(const LWPOINT *point, char *srs, int precision, int opts, const char *defid) -{ - int size; - /* size_t defidlen = strlen(defid); */ - - size = pointArray_X3Dsize(point->point, precision); - /* size += ( sizeof("/") + (defidlen*2) ) * 2; */ - /* if (srs) size += strlen(srs) + sizeof(" srsName=.."); */ - return size; -} - -static size_t -asx3d3_point_buf(const LWPOINT *point, char *srs, char *output, int precision, int opts, const char *defid) -{ - char *ptr = output; - /* int dimension=2; */ - - /* if (FLAGS_GET_Z(point->flags)) dimension = 3; */ - /* if ( srs ) - { - ptr += sprintf(ptr, "<%sPoint srsName=\"%s\">", defid, srs); - } - else*/ - /* ptr += sprintf(ptr, "%s", defid); */ - - /* ptr += sprintf(ptr, "<%spos>", defid); */ - ptr += pointArray_toX3D3(point->point, ptr, precision, opts, 0); - /* ptr += sprintf(ptr, "", defid, defid); */ - - return (ptr-output); -} - -static char * -asx3d3_point(const LWPOINT *point, char *srs, int precision, int opts, const char *defid) -{ - char *output; - int size; - - size = asx3d3_point_size(point, srs, precision, opts, defid); - output = lwalloc(size); - asx3d3_point_buf(point, srs, output, precision, opts, defid); - return output; -} - - -static size_t -asx3d3_line_size(const LWLINE *line, char *srs, int precision, int opts, const char *defid) -{ - int size; - size_t defidlen = strlen(defid); - - size = pointArray_X3Dsize(line->points, precision)*2; - - if ( X3D_USE_GEOCOORDS(opts) ) { - size += ( - sizeof("") + defidlen - ) * 2; - } - else { - size += ( - sizeof("") + defidlen - ) * 2; + return LW_FAILURE; } - - /* if (srs) size += strlen(srs) + sizeof(" srsName=.."); */ - return size; } -static size_t -asx3d3_line_buf(const LWLINE *line, char *srs, char *output, int precision, int opts, const char *defid) +static int +asx3d3_point_sb(const LWPOINT *point, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb) { - char *ptr=output; - /* int dimension=2; */ - POINTARRAY *pa; - - - /* if (FLAGS_GET_Z(line->flags)) dimension = 3; */ - - pa = line->points; - ptr += sprintf(ptr, "", defid, pa->npoints); - - if ( X3D_USE_GEOCOORDS(opts) ) ptr += sprintf(ptr, "points, ptr, precision, opts, lwline_is_closed((LWLINE *) line)); - - ptr += sprintf(ptr, "' />"); - - ptr += sprintf(ptr, ""); - return (ptr-output); + /** for point we just output the coordinates **/ + return ptarray_to_x3d3_sb(point->point, precision, opts, 0, sb); } -static size_t -asx3d3_line_coords(const LWLINE *line, char *output, int precision, int opts) +static int +asx3d3_line_coords_sb(const LWLINE *line, int precision, int opts, stringbuffer_t *sb) { - char *ptr=output; - /* ptr += sprintf(ptr, ""); */ - ptr += pointArray_toX3D3(line->points, ptr, precision, opts, lwline_is_closed(line)); - return (ptr-output); + return ptarray_to_x3d3_sb(line->points, precision, opts, lwline_is_closed(line), sb); } -/* Calculate the coordIndex property of the IndexedLineSet for the multilinestring */ -static size_t -asx3d3_mline_coordindex(const LWMLINE *mgeom, char *output) +/* Calculate the coordIndex property of the IndexedLineSet for the multilinestring +and add to string buffer */ +static int +asx3d3_mline_coordindex_sb(const LWMLINE *mgeom, stringbuffer_t *sb) { - char *ptr=output; LWLINE *geom; int i, j, k, si; POINTARRAY *pa; @@ -212,36 +144,35 @@ asx3d3_mline_coordindex(const LWMLINE *mgeom, char *output) { if (k) { - ptr += sprintf(ptr, " "); + stringbuffer_aprintf(sb, " "); } /** if the linestring is closed, we put the start point index * for the last vertex to denote use first point * and don't increment the index **/ if (!lwline_is_closed(geom) || k < (np -1) ) { - ptr += sprintf(ptr, "%d", j); + stringbuffer_aprintf(sb, "%d", j); j += 1; } else { - ptr += sprintf(ptr,"%d", si); + stringbuffer_aprintf(sb,"%d", si); } } if (i < (mgeom->ngeoms - 1) ) { - ptr += sprintf(ptr, " -1 "); /* separator for each linestring */ + stringbuffer_aprintf(sb, " -1 "); /* separator for each linestring */ } } - return (ptr-output); + return LW_SUCCESS; } /* Calculate the coordIndex property of the IndexedLineSet for a multipolygon This is not ideal -- would be really nice to just share this function with psurf, but I'm not smart enough to do that yet*/ -static size_t -asx3d3_mpoly_coordindex(const LWMPOLY *psur, char *output) +static int +asx3d3_mpoly_coordindex_sb(const LWMPOLY *psur, stringbuffer_t *sb) { - char *ptr=output; LWPOLY *patch; int i, j, k, l; int np; @@ -256,9 +187,9 @@ asx3d3_mpoly_coordindex(const LWMPOLY *psur, char *output) { if (k) { - ptr += sprintf(ptr, " "); + stringbuffer_aprintf(sb, " "); } - ptr += sprintf(ptr, "%d", (j + k)); + stringbuffer_aprintf(sb, "%d", (j + k)); } j += k; if (l < (patch->nrings - 1) ) @@ -271,155 +202,75 @@ asx3d3_mpoly_coordindex(const LWMPOLY *psur, char *output) * For now will leave it as polygons stacked on top of each other -- which is what we are doing here and perhaps an option * to color differently. It's not ideal but the alternative sounds complicated. **/ - ptr += sprintf(ptr, " -1 "); /* separator for each inner ring. Ideally we should probably triangulate and cut around as others do */ + stringbuffer_aprintf(sb, " -1 "); /* separator for each inner ring. Ideally we should probably triangulate and cut around as others do */ } } if (i < (psur->ngeoms - 1) ) { - ptr += sprintf(ptr, " -1 "); /* separator for each subgeom */ + stringbuffer_aprintf(sb, " -1 "); /* separator for each subgeom */ } } - return (ptr-output); + return LW_SUCCESS; } /** Return the linestring as an X3D LineSet */ -static char * -asx3d3_line(const LWLINE *line, char *srs, int precision, int opts, const char *defid) -{ - char *output; - int size; - - size = sizeof("") + asx3d3_line_size(line, srs, precision, opts, defid); - output = lwalloc(size); - asx3d3_line_buf(line, srs, output, precision, opts, defid); - return output; -} - -/** Compute the string space needed for the IndexedFaceSet representation of the polygon **/ -static size_t -asx3d3_poly_size(const LWPOLY *poly, char *srs, int precision, int opts, const char *defid) +static int +asx3d3_line_sb(const LWLINE *line, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb) { - size_t size; - size_t defidlen = strlen(defid); - int i; - - size = ( sizeof("") + (defidlen*3) ) * 2 + 6 * (poly->nrings - 1); - - for (i=0; inrings; i++) - size += pointArray_X3Dsize(poly->rings[i], precision); - return size; -} - -/** Compute the X3D coordinates of the polygon **/ -static size_t -asx3d3_poly_buf(const LWPOLY *poly, char *srs, char *output, int precision, int opts, int is_patch, const char *defid) -{ - int i; - char *ptr=output; + /* int dimension=2; */ + POINTARRAY *pa; - ptr += pointArray_toX3D3(poly->rings[0], ptr, precision, opts, 1); - for (i=1; inrings; i++) - { - ptr += sprintf(ptr, " "); /* inner ring points start */ - ptr += pointArray_toX3D3(poly->rings[i], ptr, precision, opts,1); - } - return (ptr-output); -} -static size_t -asx3d3_triangle_size(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid) -{ - size_t size; - size_t defidlen = strlen(defid); + /* if (FLAGS_GET_Z(line->flags)) dimension = 3; */ - /** 6 for the 3 sides and space to separate each side **/ - size = sizeof("") + defidlen + 6; - size += pointArray_X3Dsize(triangle->points, precision); + pa = line->points; + stringbuffer_aprintf(sb, "", defid, pa->npoints); - return size; -} + if ( X3D_USE_GEOCOORDS(opts) ) stringbuffer_aprintf(sb, "points, ptr, precision, opts, 1); + ptarray_to_x3d3_sb(line->points, precision, opts, lwline_is_closed((LWLINE *) line), sb); - return (ptr-output); -} -static char * -asx3d3_triangle(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid) -{ - char *output; - int size; + stringbuffer_aprintf(sb, "' />"); - size = asx3d3_triangle_size(triangle, srs, precision, opts, defid); - output = lwalloc(size); - asx3d3_triangle_buf(triangle, srs, output, precision, opts, defid); - return output; + return stringbuffer_aprintf(sb, ""); } - -/** - * Compute max size required for X3D version of this - * inspected geometry. Will recurse when needed. - * Don't call this with single-geoms inspected. - */ -static size_t -asx3d3_multi_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid) +/** Compute the X3D coordinates of the polygon and add to string buffer **/ +static int +asx3d3_poly_sb(const LWPOLY *poly, char *srs, int precision, int opts, int is_patch, const char *defid, stringbuffer_t *sb) { int i; - size_t size; - size_t defidlen = strlen(defid); - LWGEOM *subgeom; - - /* the longest possible multi version needs to hold DEF=defid and coordinate breakout */ - if ( X3D_USE_GEOCOORDS(opts) ) - size = sizeof(""); - else - size = sizeof("") + defidlen; - - - /* if ( srs ) size += strlen(srs) + sizeof(" srsName=.."); */ - - for (i=0; ingeoms; i++) + for (i=0; inrings; i++) { - subgeom = col->geoms[i]; - if (subgeom->type == POINTTYPE) - { - /* size += ( sizeof("point=''") + defidlen ) * 2; */ - size += asx3d3_point_size((LWPOINT*)subgeom, 0, precision, opts, defid); - } - else if (subgeom->type == LINETYPE) - { - /* size += ( sizeof("/") + defidlen ) * 2; */ - size += asx3d3_line_size((LWLINE*)subgeom, 0, precision, opts, defid); - } - else if (subgeom->type == POLYGONTYPE) - { - /* size += ( sizeof("/") + defidlen ) * 2; */ - size += asx3d3_poly_size((LWPOLY*)subgeom, 0, precision, opts, defid); - } + if (i) stringbuffer_aprintf(sb, " "); /* inner ring points start */ + ptarray_to_x3d3_sb(poly->rings[i], precision, opts, 1, sb); } + return LW_SUCCESS; +} - return size; +static int +asx3d3_triangle_sb(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb) +{ + return ptarray_to_x3d3_sb(triangle->points, precision, opts, 1, sb); } + /* * Don't call this with single-geoms inspected! */ -static size_t -asx3d3_multi_buf(const LWCOLLECTION *col, char *srs, char *output, int precision, int opts, const char *defid) +static int +asx3d3_multi_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb) { - char *ptr, *x3dtype; + char *x3dtype; int i; int dimension=2; if (FLAGS_GET_Z(col->flags)) dimension = 3; LWGEOM *subgeom; - ptr = output; x3dtype=""; @@ -429,23 +280,23 @@ asx3d3_multi_buf(const LWCOLLECTION *col, char *srs, char *output, int precision x3dtype = "PointSet"; if ( dimension == 2 ){ /** Use Polypoint2D instead **/ x3dtype = "Polypoint2D"; - ptr += sprintf(ptr, "<%s %s point='", x3dtype, defid); + stringbuffer_aprintf(sb, "<%s %s point='", x3dtype, defid); } else { - ptr += sprintf(ptr, "<%s %s>", x3dtype, defid); + stringbuffer_aprintf(sb, "<%s %s>", x3dtype, defid); } break; case MULTILINETYPE: x3dtype = "IndexedLineSet"; - ptr += sprintf(ptr, "<%s %s coordIndex='", x3dtype, defid); - ptr += asx3d3_mline_coordindex((const LWMLINE *)col, ptr); - ptr += sprintf(ptr, "'>"); + stringbuffer_aprintf(sb, "<%s %s coordIndex='", x3dtype, defid); + asx3d3_mline_coordindex_sb((const LWMLINE *)col, sb); + stringbuffer_aprintf(sb, "'>"); break; case MULTIPOLYGONTYPE: x3dtype = "IndexedFaceSet"; - ptr += sprintf(ptr, "<%s %s convex='false' coordIndex='", x3dtype, defid); - ptr += asx3d3_mpoly_coordindex((const LWMPOLY *)col, ptr); - ptr += sprintf(ptr, "'>"); + stringbuffer_aprintf(sb, "<%s %s convex='false' coordIndex='", x3dtype, defid); + asx3d3_mpoly_coordindex_sb((const LWMPOLY *)col, sb); + stringbuffer_aprintf(sb, "'>"); break; default: lwerror("asx3d3_multi_buf: '%s' geometry type not supported", lwtype_name(col->type)); @@ -453,9 +304,9 @@ asx3d3_multi_buf(const LWCOLLECTION *col, char *srs, char *output, int precision } if (dimension == 3){ if ( X3D_USE_GEOCOORDS(opts) ) - ptr += sprintf(ptr, "", x3dtype); + stringbuffer_aprintf(sb, "' />", x3dtype); } - else { ptr += sprintf(ptr, "' />"); } - return (ptr-output); -} + else { stringbuffer_aprintf(sb, "' />"); } + return LW_SUCCESS; -/* - * Don't call this with single-geoms inspected! - */ -static char * -asx3d3_multi(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid) -{ - char *x3d; - size_t size; - - size = asx3d3_multi_size(col, srs, precision, opts, defid); - x3d = lwalloc(size); - asx3d3_multi_buf(col, srs, x3d, precision, opts, defid); - return x3d; -} - - -static size_t -asx3d3_psurface_size(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid) -{ - int i; - size_t size; - size_t defidlen = strlen(defid); - - if ( X3D_USE_GEOCOORDS(opts) ) size = sizeof("") + defidlen; - else size = sizeof("") + defidlen; - - - for (i=0; ingeoms; i++) - { - size += asx3d3_poly_size(psur->geoms[i], 0, precision, opts, defid)*5; /** need to make space for coordIndex values too including -1 separating each poly**/ - } - - return size; } - /* * Don't call this with single-geoms inspected! */ -static size_t -asx3d3_psurface_buf(const LWPSURFACE *psur, char *srs, char *output, int precision, int opts, const char *defid) +static int +asx3d3_psurface_sb(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb) { - char *ptr; int i; int j; int k; int np; LWPOLY *patch; - ptr = output; - /* Open outmost tag */ - ptr += sprintf(ptr, ""); - - return (ptr-output); -} - -/* - * Don't call this with single-geoms inspected! - */ -static char * -asx3d3_psurface(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid) -{ - char *x3d; - size_t size; - - size = asx3d3_psurface_size(psur, srs, precision, opts, defid); - x3d = lwalloc(size); - asx3d3_psurface_buf(psur, srs, x3d, precision, opts, defid); - return x3d; -} - - -static size_t -asx3d3_tin_size(const LWTIN *tin, char *srs, int precision, int opts, const char *defid) -{ - int i; - size_t size; - size_t defidlen = strlen(defid); - /* int dimension=2; */ - - /** Need to make space for size of additional attributes, - ** the coordIndex has a value for each edge for each triangle plus a space to separate so we need at least that much extra room ***/ - size = sizeof("") + defidlen + tin->ngeoms*12; - - for (i=0; ingeoms; i++) - { - size += (asx3d3_triangle_size(tin->geoms[i], 0, precision, opts, defid) * 20); /** 3 is to make space for coordIndex **/ - } - - return size; + return stringbuffer_aprintf(sb, "' />"); } - /* - * Don't call this with single-geoms inspected! + * Computes X3D representation of TIN (as IndexedTriangleSet and adds to string buffer) */ -static size_t -asx3d3_tin_buf(const LWTIN *tin, char *srs, char *output, int precision, int opts, const char *defid) +static int +asx3d3_tin_sb(const LWTIN *tin, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb) { - char *ptr; int i; int k; /* int dimension=2; */ - ptr = output; - - ptr += sprintf(ptr, "ngeoms; i++) { - ptr += sprintf(ptr, "%d %d %d", k, (k+1), (k+2)); + stringbuffer_aprintf(sb, "%d %d %d", k, (k+1), (k+2)); if (i < (tin->ngeoms - 1) ) { - ptr += sprintf(ptr, " "); + stringbuffer_aprintf(sb, " "); } k += 3; } - if ( X3D_USE_GEOCOORDS(opts) ) ptr += sprintf(ptr, "'>"); - - return (ptr-output); + return stringbuffer_aprintf(sb, "'/>"); } -/* - * Don't call this with single-geoms inspected! - */ -static char * -asx3d3_tin(const LWTIN *tin, char *srs, int precision, int opts, const char *defid) -{ - char *x3d; - size_t size; - - size = asx3d3_tin_size(tin, srs, precision, opts, defid); - x3d = lwalloc(size); - asx3d3_tin_buf(tin, srs, x3d, precision, opts, defid); - return x3d; -} - -static size_t -asx3d3_collection_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid) +static int +asx3d3_collection_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb) { int i; - size_t size; - size_t defidlen = strlen(defid); LWGEOM *subgeom; - /* size = sizeof("") + defidlen*2; */ - size = defidlen*2; - - /** if ( srs ) - size += strlen(srs) + sizeof(" srsName=.."); **/ - - for (i=0; ingeoms; i++) - { - subgeom = col->geoms[i]; - size += ( sizeof("") + defidlen ) * 2; /** for collections we need to wrap each in a shape tag to make valid **/ - if ( subgeom->type == POINTTYPE ) - { - size += asx3d3_point_size((LWPOINT*)subgeom, 0, precision, opts, defid); - } - else if ( subgeom->type == LINETYPE ) - { - size += asx3d3_line_size((LWLINE*)subgeom, 0, precision, opts, defid); - } - else if ( subgeom->type == POLYGONTYPE ) - { - size += asx3d3_poly_size((LWPOLY*)subgeom, 0, precision, opts, defid); - } - else if ( subgeom->type == TINTYPE ) - { - size += asx3d3_tin_size((LWTIN*)subgeom, 0, precision, opts, defid); - } - else if ( subgeom->type == POLYHEDRALSURFACETYPE ) - { - size += asx3d3_psurface_size((LWPSURFACE*)subgeom, 0, precision, opts, defid); - } - else if ( lwgeom_is_collection(subgeom) ) - { - size += asx3d3_multi_size((LWCOLLECTION*)subgeom, 0, precision, opts, defid); - } - else - lwerror("asx3d3_collection_size: unknown geometry type"); - } - - return size; -} - -static size_t -asx3d3_collection_buf(const LWCOLLECTION *col, char *srs, char *output, int precision, int opts, const char *defid) -{ - char *ptr; - int i; - LWGEOM *subgeom; - - ptr = output; - /* Open outmost tag */ - /** @TODO: decide if we need outtermost tags, this one was just a copy from gml so is wrong **/ + /** @TODO: if collection should be grouped, we'll wrap in a group tag. Still needs cleanup + * like the shapes should really be in a transform **/ #ifdef PGIS_X3D_OUTERMOST_TAGS - if ( srs ) - { - ptr += sprintf(ptr, "<%sMultiGeometry srsName=\"%s\">", defid, srs); - } - else - { - ptr += sprintf(ptr, "<%sMultiGeometry>", defid); - } + stringbuffer_aprintf(sb, "<%sGroup>", defid); #endif for (i=0; ingeoms; i++) { subgeom = col->geoms[i]; - ptr += sprintf(ptr, "", defid); + stringbuffer_aprintf(sb, "", defid); if ( subgeom->type == POINTTYPE ) { - ptr += asx3d3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, defid); + asx3d3_point_sb((LWPOINT*)subgeom, 0, precision, opts, defid, sb); } else if ( subgeom->type == LINETYPE ) { - ptr += asx3d3_line_buf((LWLINE*)subgeom, 0, ptr, precision, opts, defid); + asx3d3_line_sb((LWLINE*)subgeom, 0, precision, opts, defid, sb); } else if ( subgeom->type == POLYGONTYPE ) { - ptr += asx3d3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, defid); + asx3d3_poly_sb((LWPOLY*)subgeom, 0, precision, opts, 0, defid, sb); } else if ( subgeom->type == TINTYPE ) { - ptr += asx3d3_tin_buf((LWTIN*)subgeom, srs, ptr, precision, opts, defid); + asx3d3_tin_sb((LWTIN*)subgeom, srs, precision, opts, defid, sb); } else if ( subgeom->type == POLYHEDRALSURFACETYPE ) { - ptr += asx3d3_psurface_buf((LWPSURFACE*)subgeom, srs, ptr, precision, opts, defid); + asx3d3_psurface_sb((LWPSURFACE*)subgeom, srs, precision, opts, defid, sb); } else if ( lwgeom_is_collection(subgeom) ) { if ( subgeom->type == COLLECTIONTYPE ) - ptr += asx3d3_collection_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, defid); + asx3d3_collection_sb((LWCOLLECTION*)subgeom, 0, precision, opts, defid, sb); else - ptr += asx3d3_multi_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, defid); + asx3d3_multi_sb((LWCOLLECTION*)subgeom, 0, precision, opts, defid, sb); } else lwerror("asx3d3_collection_buf: unknown geometry type"); - ptr += printf(ptr, ""); + stringbuffer_aprintf(sb, ""); } /* Close outmost tag */ #ifdef PGIS_X3D_OUTERMOST_TAGS - ptr += sprintf(ptr, "", defid); + stringbuffer_aprintf(sb, "", defid); #endif - return (ptr-output); + return LW_SUCCESS; } -/* - * Don't call this with single-geoms inspected! - */ -static char * -asx3d3_collection(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid) -{ - char *x3d; - size_t size; - - size = asx3d3_collection_size(col, srs, precision, opts, defid); - x3d = lwalloc(size); - asx3d3_collection_buf(col, srs, x3d, precision, opts, defid); - return x3d; -} - - /** In X3D3, coordinates are separated by a space separator */ -static size_t -pointArray_toX3D3(POINTARRAY *pa, char *output, int precision, int opts, int is_closed) +static int +ptarray_to_x3d3_sb(POINTARRAY *pa, int precision, int opts, int is_closed, stringbuffer_t *sb ) { int i; - char *ptr; char x[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1]; char y[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1]; char z[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1]; - ptr = output; - if ( ! FLAGS_GET_Z(pa->flags) ) { for (i=0; inpoints; i++) @@ -846,13 +524,12 @@ pointArray_toX3D3(POINTARRAY *pa, char *output, int precision, int opts, int is_ sprintf(y, "%g", pt.y); trim_trailing_zeros(y); - if ( i ) - ptr += sprintf(ptr, " "); + if ( i ) stringbuffer_append(sb," "); if ( ( opts & LW_X3D_FLIP_XY) ) - ptr += sprintf(ptr, "%s %s", y, x); + stringbuffer_aprintf(sb, "%s %s", y, x); else - ptr += sprintf(ptr, "%s %s", x, y); + stringbuffer_aprintf(sb, "%s %s", x, y); } } } @@ -884,31 +561,15 @@ pointArray_toX3D3(POINTARRAY *pa, char *output, int precision, int opts, int is_ sprintf(z, "%g", pt.z); trim_trailing_zeros(z); - if ( i ) - ptr += sprintf(ptr, " "); + if ( i ) stringbuffer_append(sb," "); if ( ( opts & LW_X3D_FLIP_XY) ) - ptr += sprintf(ptr, "%s %s %s", y, x, z); + stringbuffer_aprintf(sb, "%s %s %s", y, x, z); else - ptr += sprintf(ptr, "%s %s %s", x, y, z); + stringbuffer_aprintf(sb, "%s %s %s", x, y, z); } } } - return ptr-output; -} - - - -/** - * Returns maximum size of rendered pointarray in bytes. - */ -static size_t -pointArray_X3Dsize(POINTARRAY *pa, int precision) -{ - if (FLAGS_NDIMS(pa->flags) == 2) - return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(" ")) - * 2 * pa->npoints; - - return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(" ")) * 3 * pa->npoints; + return LW_SUCCESS; } diff --git a/liblwgeom/lwout_x3d.h b/liblwgeom/lwout_x3d.h index 6fcc208da..31a35151c 100644 --- a/liblwgeom/lwout_x3d.h +++ b/liblwgeom/lwout_x3d.h @@ -28,21 +28,19 @@ **********************************************************************/ #include #include "liblwgeom_internal.h" +#include "stringbuffer.h" /** defid is the id of the coordinate can be used to hold other elements DEF='abc' transform='' etc. **/ -static size_t asx3d3_point_size(const LWPOINT *point, char *srs, int precision, int opts, const char *defid); -static char *asx3d3_point(const LWPOINT *point, char *srs, int precision, int opts, const char *defid); -static size_t asx3d3_line_size(const LWLINE *line, char *srs, int precision, int opts, const char *defid); -static char *asx3d3_line(const LWLINE *line, char *srs, int precision, int opts, const char *defid); -static size_t asx3d3_poly_size(const LWPOLY *poly, char *srs, int precision, int opts, const char *defid); -static size_t asx3d3_triangle_size(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid); -static char *asx3d3_triangle(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid); -static size_t asx3d3_multi_size(const LWCOLLECTION *col, char *srs, int precisioSn, int opts, const char *defid); -static char *asx3d3_multi(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid); -static char *asx3d3_psurface(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid); -static char *asx3d3_tin(const LWTIN *tin, char *srs, int precision, int opts, const char *defid); -static size_t asx3d3_collection_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid); -static char *asx3d3_collection(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid); -static size_t pointArray_toX3D3(POINTARRAY *pa, char *buf, int precision, int opts, int is_closed); +static int lwgeom_to_x3d3_sb(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); -static size_t pointArray_X3Dsize(POINTARRAY *pa, int precision); +static int asx3d3_point_sb(const LWPOINT *point, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); +static int asx3d3_line_sb(const LWLINE *line, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); + +static int asx3d3_triangle_sb(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); + +static int asx3d3_multi_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); +static int asx3d3_psurface_sb(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); +static int asx3d3_tin_sb(const LWTIN *tin, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); + +static int asx3d3_collection_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); +static int ptarray_to_x3d3_sb(POINTARRAY *pa, int precision, int opts, int is_closed, stringbuffer_t *sb ); -- 2.40.0