]> granicus.if.org Git - postgis/commitdiff
Rewrite to use stringbuffer instead of the mess of sprintfs
authorRegina Obe <lr@pcorp.us>
Mon, 8 Jan 2018 17:09:09 +0000 (17:09 +0000)
committerRegina Obe <lr@pcorp.us>
Mon, 8 Jan 2018 17:09:09 +0000 (17:09 +0000)
Closes #3974

git-svn-id: http://svn.osgeo.org/postgis/trunk@16224 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/lwout_x3d.c
liblwgeom/lwout_x3d.h

index 9010a710c7f56596a2b1ea01e51761ca7ee0c717..e66f838224008f0a6cca30e517950b97f18985ee 100644 (file)
 /*
  * 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("<point><pos>/") + (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, "</%spos></%sPoint>", 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("<LineSet vertexCount=''><GeoCoordinate geoSystem='\"GD\" \"WE\" \"longitude_first\"' point='' /></LineSet>")  + defidlen
-               ) * 2;
-       }
-       else {
-               size += (
-                           sizeof("<LineSet vertexCount=''><Coordinate point='' /></LineSet>")  + 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, "<LineSet %s vertexCount='%d'>", defid, pa->npoints);
-
-       if ( X3D_USE_GEOCOORDS(opts) ) ptr += sprintf(ptr, "<GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
-       else
-               ptr += sprintf(ptr, "<Coordinate point='");
-       ptr += pointArray_toX3D3(line->points, ptr, precision, opts, lwline_is_closed((LWLINE *) line));
-
-       ptr += sprintf(ptr, "' />");
-
-       ptr += sprintf(ptr, "</LineSet>");
-       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("<LineSet><CoordIndex ='' /></LineSet>") + 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("<IndexedFaceSet></IndexedFaceSet>") + (defidlen*3) ) * 2 + 6 * (poly->nrings - 1);
-
-       for (i=0; i<poly->nrings; 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; i<poly->nrings; 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("<IndexedTriangleSet index=''></IndexedTriangleSet>") + defidlen + 6;
-       size += pointArray_X3Dsize(triangle->points, precision);
+       pa = line->points;
+       stringbuffer_aprintf(sb, "<LineSet %s vertexCount='%d'>", defid, pa->npoints);
 
-       return size;
-}
+       if ( X3D_USE_GEOCOORDS(opts) ) stringbuffer_aprintf(sb, "<GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
+       else
+               stringbuffer_aprintf(sb, "<Coordinate point='");
 
-static size_t
-asx3d3_triangle_buf(const LWTRIANGLE *triangle, char *srs, char *output, int precision, int opts, const char *defid)
-{
-       char *ptr=output;
-       ptr += pointArray_toX3D3(triangle->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, "</LineSet>");
 }
 
-
-/**
- * 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("<PointSet><GeoCoordinate geoSystem='\"GD\" \"WE\" \"longitude_first\"' point='' /></PointSet>");
-       else
-               size = sizeof("<PointSet><Coordinate point='' /></PointSet>") + defidlen;
-
-
-       /* if ( srs ) size += strlen(srs) + sizeof(" srsName=.."); */
-
-       for (i=0; i<col->ngeoms; i++)
+       for (i=0; i<poly->nrings; 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("<curveMember>/") + defidlen ) * 2; */
-                       size += asx3d3_line_size((LWLINE*)subgeom, 0, precision, opts, defid);
-               }
-               else if (subgeom->type == POLYGONTYPE)
-               {
-                       /* size += ( sizeof("<surfaceMember>/") + 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, "<GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ((opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
+                       stringbuffer_aprintf(sb, "<GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ((opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
                else
-               ptr += sprintf(ptr, "<Coordinate point='");
+               stringbuffer_aprintf(sb, "<Coordinate point='");
     }
 
        for (i=0; i<col->ngeoms; i++)
@@ -463,82 +314,44 @@ asx3d3_multi_buf(const LWCOLLECTION *col, char *srs, char *output, int precision
                subgeom = col->geoms[i];
                if (subgeom->type == POINTTYPE)
                {
-                       ptr += asx3d3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, defid);
-                       ptr += sprintf(ptr, " ");
+                       asx3d3_point_sb((LWPOINT*)subgeom, 0, precision, opts, defid, sb);
+                       stringbuffer_aprintf(sb, " ");
                }
                else if (subgeom->type == LINETYPE)
                {
-                       ptr += asx3d3_line_coords((LWLINE*)subgeom, ptr, precision, opts);
-                       ptr += sprintf(ptr, " ");
+                       asx3d3_line_coords_sb((LWLINE*)subgeom, precision, opts, sb);
+                       stringbuffer_aprintf(sb, " ");
                }
                else if (subgeom->type == POLYGONTYPE)
                {
-                       ptr += asx3d3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, defid);
-                       ptr += sprintf(ptr, " ");
+                       asx3d3_poly_sb((LWPOLY*)subgeom, 0, precision, opts, 0, defid, sb);
+                       stringbuffer_aprintf(sb, " ");
                }
        }
 
        /* Close outmost tag */
        if (dimension == 3){
-           ptr += sprintf(ptr, "' /></%s>", x3dtype);
+               stringbuffer_aprintf(sb, "' /></%s>", 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("<IndexedFaceSet convex='false' coordIndex=''><GeoCoordinate geoSystem='\"GD\" \"WE\" \"longitude_first\"' point='' />") + defidlen;
-       else size = sizeof("<IndexedFaceSet convex='false' coordIndex=''><Coordinate point='' />") + defidlen;
-
-
-       for (i=0; i<psur->ngeoms; 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, "<IndexedFaceSet convex='false' %s coordIndex='",defid);
+       stringbuffer_aprintf(sb, "<IndexedFaceSet convex='false' %s coordIndex='",defid);
 
        j = 0;
        for (i=0; i<psur->ngeoms; i++)
@@ -549,281 +362,146 @@ asx3d3_psurface_buf(const LWPSURFACE *psur, char *srs, char *output, int precisi
                {
                        if (k)
                        {
-                               ptr += sprintf(ptr, " ");
+                               stringbuffer_aprintf(sb, " ");
                        }
-                       ptr += sprintf(ptr, "%d", (j + k));
+                       stringbuffer_aprintf(sb,"%d", (j + k));
                }
                if (i < (psur->ngeoms - 1) )
                {
-                       ptr += sprintf(ptr, " -1 "); /* separator for each subgeom */
+                       stringbuffer_aprintf(sb, " -1 "); /* separator for each subgeom */
                }
                j += k;
        }
 
        if ( X3D_USE_GEOCOORDS(opts) )
-               ptr += sprintf(ptr, "'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
-       else ptr += sprintf(ptr, "'><Coordinate point='");
+               stringbuffer_aprintf(sb, "'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='",
+                       ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
+       else stringbuffer_aprintf(sb, "'><Coordinate point='");
 
        for (i=0; i<psur->ngeoms; i++)
        {
-               ptr += asx3d3_poly_buf(psur->geoms[i], 0, ptr, precision, opts, 1, defid);
+               asx3d3_poly_sb(psur->geoms[i], srs, precision, opts, 1, defid, sb);
                if (i < (psur->ngeoms - 1) )
                {
-                       ptr += sprintf(ptr, " "); /* only add a trailing space if its not the last polygon in the set */
+                       stringbuffer_aprintf(sb, " "); /* only add a trailing space if its not the last polygon in the set */
                }
        }
 
        /* Close outmost tag */
-       ptr += sprintf(ptr, "' /></IndexedFaceSet>");
-
-       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("<IndexedTriangleSet coordIndex=''></IndexedTriangleSet>") + defidlen + tin->ngeoms*12;
-
-       for (i=0; i<tin->ngeoms; 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, "' /></IndexedFaceSet>");
 }
 
-
 /*
- * 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, "<IndexedTriangleSet %s index='",defid);
+       stringbuffer_aprintf(sb,"<IndexedTriangleSet %s index='",defid);
        k = 0;
        /** Fill in triangle index **/
        for (i=0; i<tin->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, "'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
-       else ptr += sprintf(ptr, "'><Coordinate point='");
+       if ( X3D_USE_GEOCOORDS(opts) ) stringbuffer_aprintf(sb, "'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
+       else stringbuffer_aprintf(sb, "'><Coordinate point='");
 
        for (i=0; i<tin->ngeoms; i++)
        {
-               ptr += asx3d3_triangle_buf(tin->geoms[i], 0, ptr, precision,
-                                          opts, defid);
+               asx3d3_triangle_sb(tin->geoms[i], 0, precision,
+                                          opts, defid, sb);
                if (i < (tin->ngeoms - 1) )
                {
-                       ptr += sprintf(ptr, " ");
+                       stringbuffer_aprintf(sb, " ");
                }
        }
 
        /* Close outmost tag */
 
-       ptr += sprintf(ptr, "'/></IndexedTriangleSet>");
-
-       return (ptr-output);
+       return stringbuffer_aprintf(sb, "'/></IndexedTriangleSet>");
 }
 
-/*
- * 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("<MultiGeometry></MultiGeometry>") + defidlen*2; */
-       size = defidlen*2;
-
-       /** if ( srs )
-               size += strlen(srs) + sizeof(" srsName=.."); **/
-
-       for (i=0; i<col->ngeoms; i++)
-       {
-               subgeom = col->geoms[i];
-               size += ( sizeof("<Shape />") + 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; i<col->ngeoms; i++)
        {
                subgeom = col->geoms[i];
-               ptr += sprintf(ptr, "<Shape%s>", defid);
+               stringbuffer_aprintf(sb, "<Shape%s>", 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, "</Shape>");
+               stringbuffer_aprintf(sb, "</Shape>");
        }
 
        /* Close outmost tag */
 #ifdef PGIS_X3D_OUTERMOST_TAGS
-       ptr += sprintf(ptr, "</%sMultiGeometry>", defid);
+       stringbuffer_aprintf(sb,  "</%sGroup>", 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; i<pa->npoints; 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;
 }
index 6fcc208dacaf62737b25c69f9bf2aca2480c215b..31a35151cc4aafde72f977cdadb24e843f5c910c 100644 (file)
 **********************************************************************/
 #include <string.h>
 #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 );