/*
* 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) )
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:
{
* 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;
{
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;
{
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) )
* 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="";
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));
}
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++)
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++)
{
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++)
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);
}
}
}
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;
}