PostGIS  2.5.7dev-r@@SVN_REVISION@@
lwout_x3d.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * PostGIS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * PostGIS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18  *
19  **********************************************************************
20  *
21  * Copyright 2011-2017 Arrival 3D, Regina Obe
22  *
23  **********************************************************************/
24 
29 #include "lwout_x3d.h"
30 
31 /*
32  * VERSION X3D 3.0.2 http://www.web3d.org/specifications/x3d-3.0.dtd
33  */
34 /* takes a GEOMETRY and returns a X3D representation */
35 char*
36 lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid)
37 {
38  stringbuffer_t *sb;
39  int rv;
40  char *result;
41 
42  /* Empty string for empties */
43  if( lwgeom_is_empty(geom) )
44  {
45  char *ret = NULL;
46  ret = lwalloc(1);
47  ret[0] = '\0';
48  return ret;
49  }
50 
51  sb = stringbuffer_create();
52  rv = lwgeom_to_x3d3_sb(geom, srs, precision, opts, defid, sb);
53 
54  if ( rv == LW_FAILURE )
55  {
57  return NULL;
58  }
59 
60  result = stringbuffer_getstringcopy(sb);
62 
63  return result;
64 }
65 /* takes a GEOMETRY and appends to string buffer the x3d output */
66 static int
67 lwgeom_to_x3d3_sb(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
68 {
69  int type = geom->type;
70 
71  switch (type)
72  {
73  case POINTTYPE:
74  return asx3d3_point_sb((LWPOINT*)geom, srs, precision, opts, defid, sb);
75 
76  case LINETYPE:
77  return asx3d3_line_sb((LWLINE*)geom, srs, precision, opts, defid, sb);
78 
79  case POLYGONTYPE:
80  {
85  asx3d3_multi_sb(tmp, srs, precision, opts, defid, sb);
86  lwcollection_free(tmp);
87  return LW_SUCCESS;
88  }
89 
90  case TRIANGLETYPE:
91  return asx3d3_triangle_sb((LWTRIANGLE*)geom, srs, precision, opts, defid, sb);
92 
93  case MULTIPOINTTYPE:
94  case MULTILINETYPE:
95  case MULTIPOLYGONTYPE:
96  return asx3d3_multi_sb((LWCOLLECTION*)geom, srs, precision, opts, defid, sb);
97 
99  return asx3d3_psurface_sb((LWPSURFACE*)geom, srs, precision, opts, defid, sb);
100 
101  case TINTYPE:
102  return asx3d3_tin_sb((LWTIN*)geom, srs, precision, opts, defid, sb);
103 
104  case COLLECTIONTYPE:
105  return asx3d3_collection_sb((LWCOLLECTION*)geom, srs, precision, opts, defid, sb);
106 
107  default:
108  lwerror("lwgeom_to_x3d3: '%s' geometry type not supported", lwtype_name(type));
109  return LW_FAILURE;
110  }
111 }
112 
113 static int
114 asx3d3_point_sb(const LWPOINT *point, __attribute__((__unused__)) char *srs, int precision,
115  int opts, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
116 {
118  return ptarray_to_x3d3_sb(point->point, precision, opts, 0, sb);
119 }
120 
121 static int
123 {
124  return ptarray_to_x3d3_sb(line->points, precision, opts, lwline_is_closed(line), sb);
125 }
126 
127 /* Calculate the coordIndex property of the IndexedLineSet for the multilinestring
128 and add to string buffer */
129 static int
131 {
132  LWLINE *geom;
133  uint32_t i, j, k, si;
134  POINTARRAY *pa;
135  uint32_t np;
136 
137  j = 0;
138  for (i=0; i < mgeom->ngeoms; i++)
139  {
140  geom = (LWLINE *) mgeom->geoms[i];
141  pa = geom->points;
142  np = pa->npoints;
143  si = j; /* start index of first point of linestring */
144  for (k=0; k < np ; k++)
145  {
146  if (k)
147  {
148  stringbuffer_aprintf(sb, " ");
149  }
153  if (!lwline_is_closed(geom) || k < (np -1) )
154  {
155  stringbuffer_aprintf(sb, "%u", j);
156  j += 1;
157  }
158  else
159  {
160  stringbuffer_aprintf(sb,"%u", si);
161  }
162  }
163  if (i < (mgeom->ngeoms - 1) )
164  {
165  stringbuffer_aprintf(sb, " -1 "); /* separator for each linestring */
166  }
167  }
168  return LW_SUCCESS;
169 }
170 
171 /* Calculate the coordIndex property of the IndexedLineSet for a multipolygon
172  This is not ideal -- would be really nice to just share this function with psurf,
173  but I'm not smart enough to do that yet*/
174 static int
176 {
177  LWPOLY *patch;
178  uint32_t i, j, k, l;
179  uint32_t np;
180  j = 0;
181  for (i=0; i<psur->ngeoms; i++)
182  {
183  patch = (LWPOLY *) psur->geoms[i];
184  for (l=0; l < patch->nrings; l++)
185  {
186  np = patch->rings[l]->npoints - 1;
187  for (k=0; k < np ; k++)
188  {
189  if (k)
190  {
191  stringbuffer_aprintf(sb, " ");
192  }
193  stringbuffer_aprintf(sb, "%d", (j + k));
194  }
195  j += k;
196  if (l < (patch->nrings - 1) )
197  {
206  stringbuffer_aprintf(sb, " -1 "); /* separator for each inner ring. Ideally we should probably triangulate and cut around as others do */
207  }
208  }
209  if (i < (psur->ngeoms - 1) )
210  {
211  stringbuffer_aprintf(sb, " -1 "); /* separator for each subgeom */
212  }
213  }
214  return LW_SUCCESS;
215 }
216 
218 static int
219 asx3d3_line_sb(const LWLINE *line, __attribute__((__unused__)) char *srs, int precision,
220  int opts, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
221 {
222 
223  /* int dimension=2; */
224  POINTARRAY *pa;
225 
226 
227  /* if (FLAGS_GET_Z(line->flags)) dimension = 3; */
228 
229  pa = line->points;
230  stringbuffer_aprintf(sb, "<LineSet %s vertexCount='%d'>", defid, pa->npoints);
231 
232  if ( X3D_USE_GEOCOORDS(opts) ) stringbuffer_aprintf(sb, "<GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
233  else
234  stringbuffer_aprintf(sb, "<Coordinate point='");
235 
237 
238 
239  stringbuffer_aprintf(sb, "' />");
240 
241  return stringbuffer_aprintf(sb, "</LineSet>");
242 }
243 
245 static int
246 asx3d3_poly_sb(const LWPOLY *poly, __attribute__((__unused__)) char *srs, int precision,
247  int opts, __attribute__((__unused__)) int is_patch, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
248 {
249  uint32_t i;
250  for (i=0; i<poly->nrings; i++)
251  {
252  if (i) stringbuffer_aprintf(sb, " "); /* inner ring points start */
253  ptarray_to_x3d3_sb(poly->rings[i], precision, opts, 1, sb);
254  }
255  return LW_SUCCESS;
256 }
257 
258 static int
259 asx3d3_triangle_sb(const LWTRIANGLE *triangle, __attribute__((__unused__)) char *srs, int precision,
260  int opts, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
261 {
262  return ptarray_to_x3d3_sb(triangle->points, precision, opts, 1, sb);
263 }
264 
265 
266 /*
267  * Don't call this with single-geoms inspected!
268  */
269 static int
270 asx3d3_multi_sb(const LWCOLLECTION *col, __attribute__((__unused__)) char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
271 {
272  char *x3dtype;
273  uint32_t i;
274  int dimension=2;
275 
276  if (FLAGS_GET_Z(col->flags)) dimension = 3;
277  LWGEOM *subgeom;
278  x3dtype="";
279 
280 
281  switch (col->type)
282  {
283  case MULTIPOINTTYPE:
284  x3dtype = "PointSet";
285  if ( dimension == 2 ){
286  x3dtype = "Polypoint2D";
287  stringbuffer_aprintf(sb, "<%s %s point='", x3dtype, defid);
288  }
289  else {
290  stringbuffer_aprintf(sb, "<%s %s>", x3dtype, defid);
291  }
292  break;
293  case MULTILINETYPE:
294  x3dtype = "IndexedLineSet";
295  stringbuffer_aprintf(sb, "<%s %s coordIndex='", x3dtype, defid);
296  asx3d3_mline_coordindex_sb((const LWMLINE *)col, sb);
297  stringbuffer_aprintf(sb, "'>");
298  break;
299  case MULTIPOLYGONTYPE:
300  x3dtype = "IndexedFaceSet";
301  stringbuffer_aprintf(sb, "<%s %s convex='false' coordIndex='", x3dtype, defid);
302  asx3d3_mpoly_coordindex_sb((const LWMPOLY *)col, sb);
303  stringbuffer_aprintf(sb, "'>");
304  break;
305  default:
306  lwerror("asx3d3_multi_buf: '%s' geometry type not supported", lwtype_name(col->type));
307  return 0;
308  }
309  if (dimension == 3){
310  if ( X3D_USE_GEOCOORDS(opts) )
311  stringbuffer_aprintf(sb, "<GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ((opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
312  else
313  stringbuffer_aprintf(sb, "<Coordinate point='");
314  }
315 
316  for (i=0; i<col->ngeoms; i++)
317  {
318  subgeom = col->geoms[i];
319  if (subgeom->type == POINTTYPE)
320  {
321  asx3d3_point_sb((LWPOINT*)subgeom, 0, precision, opts, defid, sb);
322  stringbuffer_aprintf(sb, " ");
323  }
324  else if (subgeom->type == LINETYPE)
325  {
326  asx3d3_line_coords_sb((LWLINE*)subgeom, precision, opts, sb);
327  stringbuffer_aprintf(sb, " ");
328  }
329  else if (subgeom->type == POLYGONTYPE)
330  {
331  asx3d3_poly_sb((LWPOLY*)subgeom, 0, precision, opts, 0, defid, sb);
332  stringbuffer_aprintf(sb, " ");
333  }
334  }
335 
336  /* Close outmost tag */
337  if (dimension == 3){
338  stringbuffer_aprintf(sb, "' /></%s>", x3dtype);
339  }
340  else { stringbuffer_aprintf(sb, "' />"); }
341  return LW_SUCCESS;
342 
343 }
344 
345 /*
346  * Don't call this with single-geoms inspected!
347  */
348 static int
349 asx3d3_psurface_sb(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
350 {
351  uint32_t i;
352  uint32_t j;
353  uint32_t k;
354  uint32_t np;
355  LWPOLY *patch;
356 
357  /* Open outmost tag */
358  stringbuffer_aprintf(sb, "<IndexedFaceSet convex='false' %s coordIndex='",defid);
359 
360  j = 0;
361  for (i=0; i<psur->ngeoms; i++)
362  {
363  patch = (LWPOLY *) psur->geoms[i];
364  np = patch->rings[0]->npoints - 1;
365  for (k=0; k < np ; k++)
366  {
367  if (k)
368  {
369  stringbuffer_aprintf(sb, " ");
370  }
371  stringbuffer_aprintf(sb,"%d", (j + k));
372  }
373  if (i < (psur->ngeoms - 1) )
374  {
375  stringbuffer_aprintf(sb, " -1 "); /* separator for each subgeom */
376  }
377  j += k;
378  }
379 
380  if ( X3D_USE_GEOCOORDS(opts) )
381  stringbuffer_aprintf(sb, "'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='",
382  ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
383  else stringbuffer_aprintf(sb, "'><Coordinate point='");
384 
385  for (i=0; i<psur->ngeoms; i++)
386  {
387  asx3d3_poly_sb(psur->geoms[i], srs, precision, opts, 1, defid, sb);
388  if (i < (psur->ngeoms - 1) )
389  {
390  stringbuffer_aprintf(sb, " "); /* only add a trailing space if its not the last polygon in the set */
391  }
392  }
393 
394  /* Close outmost tag */
395  return stringbuffer_aprintf(sb, "' /></IndexedFaceSet>");
396 }
397 
398 /*
399  * Computes X3D representation of TIN (as IndexedTriangleSet and adds to string buffer)
400  */
401 static int
402 asx3d3_tin_sb(const LWTIN *tin, __attribute__((__unused__)) char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
403 {
404  uint32_t i;
405  uint32_t k;
406  /* int dimension=2; */
407 
408  stringbuffer_aprintf(sb,"<IndexedTriangleSet %s index='",defid);
409  k = 0;
411  for (i=0; i<tin->ngeoms; i++)
412  {
413  stringbuffer_aprintf(sb, "%d %d %d", k, (k+1), (k+2));
414  if (i < (tin->ngeoms - 1) )
415  {
416  stringbuffer_aprintf(sb, " ");
417  }
418  k += 3;
419  }
420 
421  if ( X3D_USE_GEOCOORDS(opts) ) stringbuffer_aprintf(sb, "'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
422  else stringbuffer_aprintf(sb, "'><Coordinate point='");
423 
424  for (i=0; i<tin->ngeoms; i++)
425  {
426  asx3d3_triangle_sb(tin->geoms[i], 0, precision,
427  opts, defid, sb);
428  if (i < (tin->ngeoms - 1) )
429  {
430  stringbuffer_aprintf(sb, " ");
431  }
432  }
433 
434  /* Close outmost tag */
435 
436  return stringbuffer_aprintf(sb, "'/></IndexedTriangleSet>");
437 }
438 
439 static int
440 asx3d3_collection_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
441 {
442  uint32_t i;
443  LWGEOM *subgeom;
444 
445  /* Open outmost tag */
448 #ifdef PGIS_X3D_OUTERMOST_TAGS
449  stringbuffer_aprintf(sb, "<%sGroup>", defid);
450 #endif
451 
452  for (i=0; i<col->ngeoms; i++)
453  {
454  subgeom = col->geoms[i];
455  stringbuffer_aprintf(sb, "<Shape%s>", defid);
456  if ( subgeom->type == POINTTYPE )
457  {
458  asx3d3_point_sb((LWPOINT*)subgeom, 0, precision, opts, defid, sb);
459  }
460  else if ( subgeom->type == LINETYPE )
461  {
462  asx3d3_line_sb((LWLINE*)subgeom, 0, precision, opts, defid, sb);
463  }
464  else if ( subgeom->type == POLYGONTYPE )
465  {
466  asx3d3_poly_sb((LWPOLY*)subgeom, 0, precision, opts, 0, defid, sb);
467  }
468  else if ( subgeom->type == TINTYPE )
469  {
470  asx3d3_tin_sb((LWTIN*)subgeom, srs, precision, opts, defid, sb);
471 
472  }
473  else if ( subgeom->type == POLYHEDRALSURFACETYPE )
474  {
475  asx3d3_psurface_sb((LWPSURFACE*)subgeom, srs, precision, opts, defid, sb);
476 
477  }
478  else if ( lwgeom_is_collection(subgeom) )
479  {
480  if ( subgeom->type == COLLECTIONTYPE )
481  asx3d3_collection_sb((LWCOLLECTION*)subgeom, 0, precision, opts, defid, sb);
482  else
483  asx3d3_multi_sb((LWCOLLECTION*)subgeom, 0, precision, opts, defid, sb);
484  }
485  else
486  lwerror("asx3d3_collection_buf: unknown geometry type");
487 
488  stringbuffer_aprintf(sb, "</Shape>");
489  }
490 
491  /* Close outmost tag */
492 #ifdef PGIS_X3D_OUTERMOST_TAGS
493  stringbuffer_aprintf(sb, "</%sGroup>", defid);
494 #endif
495 
496  return LW_SUCCESS;
497 }
498 
501 static int
502 ptarray_to_x3d3_sb(POINTARRAY *pa, int precision, int opts, int is_closed, stringbuffer_t *sb )
503 {
504  uint32_t i;
507  char z[OUT_DOUBLE_BUFFER_SIZE];
508 
509  if ( ! FLAGS_GET_Z(pa->flags) )
510  {
511  for (i=0; i<pa->npoints; i++)
512  {
514  if ( !is_closed || i < (pa->npoints - 1) )
515  {
516  POINT2D pt;
517  getPoint2d_p(pa, i, &pt);
518 
523 
524  if ( i ) stringbuffer_append(sb," ");
525 
526  if ( ( opts & LW_X3D_FLIP_XY) )
527  stringbuffer_aprintf(sb, "%s %s", y, x);
528  else
529  stringbuffer_aprintf(sb, "%s %s", x, y);
530  }
531  }
532  }
533  else
534  {
535  for (i=0; i<pa->npoints; i++)
536  {
538  if ( !is_closed || i < (pa->npoints - 1) )
539  {
540  POINT4D pt;
541  getPoint4d_p(pa, i, &pt);
542 
549 
550  if ( i ) stringbuffer_append(sb," ");
551 
552  if ( ( opts & LW_X3D_FLIP_XY) )
553  stringbuffer_aprintf(sb, "%s %s %s", y, x, z);
554  else
555  stringbuffer_aprintf(sb, "%s %s %s", x, y, z);
556  }
557  }
558  }
559 
560  return LW_SUCCESS;
561 }
static uint8_t precision
Definition: cu_in_twkb.c:25
#define COLLECTIONTYPE
Definition: liblwgeom.h:91
#define LW_FAILURE
Definition: liblwgeom.h:79
#define MULTILINETYPE
Definition: liblwgeom.h:89
LWGEOM * lwgeom_as_multi(const LWGEOM *lwgeom)
Create a new LWGEOM of the appropriate MULTI* type.
Definition: lwgeom.c:371
#define LINETYPE
Definition: liblwgeom.h:86
#define LW_SUCCESS
Definition: liblwgeom.h:80
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
int getPoint2d_p(const POINTARRAY *pa, uint32_t n, POINT2D *point)
Definition: lwgeom_api.c:348
#define LW_X3D_FLIP_XY
Macros for specifying X3D options.
Definition: liblwgeom.h:1560
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:140
#define TINTYPE
Definition: liblwgeom.h:99
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:90
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1085
#define POLYGONTYPE
Definition: liblwgeom.h:87
#define __attribute__(x)
Definition: liblwgeom.h:201
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:97
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:356
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwgeom.c:1393
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:123
#define TRIANGLETYPE
Definition: liblwgeom.h:98
void * lwalloc(size_t size)
Definition: lwutil.c:229
#define X3D_USE_GEOCOORDS(x)
Definition: liblwgeom.h:1562
int lwline_is_closed(const LWLINE *line)
Definition: lwline.c:454
#define OUT_DOUBLE_BUFFER_SIZE
int lwprint_double(double d, int maxdd, char *buf, size_t bufsize)
Definition: lwprint.c:490
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
static int asx3d3_tin_sb(const LWTIN *tin, __attribute__((__unused__)) char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
Definition: lwout_x3d.c:402
static int asx3d3_psurface_sb(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
Definition: lwout_x3d.c:349
static int asx3d3_triangle_sb(const LWTRIANGLE *triangle, __attribute__((__unused__)) char *srs, int precision, int opts, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
Definition: lwout_x3d.c:259
char * lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:36
static int lwgeom_to_x3d3_sb(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
Definition: lwout_x3d.c:67
static int ptarray_to_x3d3_sb(POINTARRAY *pa, int precision, int opts, int is_closed, stringbuffer_t *sb)
In X3D3, coordinates are separated by a space separator.
Definition: lwout_x3d.c:502
static int asx3d3_collection_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
Definition: lwout_x3d.c:440
static int asx3d3_mpoly_coordindex_sb(const LWMPOLY *psur, stringbuffer_t *sb)
Definition: lwout_x3d.c:175
static int asx3d3_line_coords_sb(const LWLINE *line, int precision, int opts, stringbuffer_t *sb)
Definition: lwout_x3d.c:122
static int asx3d3_point_sb(const LWPOINT *point, __attribute__((__unused__)) char *srs, int precision, int opts, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
Definition: lwout_x3d.c:114
static int asx3d3_mline_coordindex_sb(const LWMLINE *mgeom, stringbuffer_t *sb)
Definition: lwout_x3d.c:130
static int asx3d3_poly_sb(const LWPOLY *poly, __attribute__((__unused__)) char *srs, int precision, int opts, __attribute__((__unused__)) int is_patch, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
Compute the X3D coordinates of the polygon and add to string buffer.
Definition: lwout_x3d.c:246
static int asx3d3_multi_sb(const LWCOLLECTION *col, __attribute__((__unused__)) char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb)
Definition: lwout_x3d.c:270
static int asx3d3_line_sb(const LWLINE *line, __attribute__((__unused__)) char *srs, int precision, int opts, __attribute__((__unused__)) const char *defid, stringbuffer_t *sb)
Return the linestring as an X3D LineSet.
Definition: lwout_x3d.c:219
opts
Definition: ovdump.py:44
type
Definition: ovdump.py:41
int stringbuffer_aprintf(stringbuffer_t *s, const char *fmt,...)
Appends a formatted string to the current string buffer, using the format and argument list provided.
Definition: stringbuffer.c:253
stringbuffer_t * stringbuffer_create(void)
Allocate a new stringbuffer_t.
Definition: stringbuffer.c:35
void stringbuffer_append(stringbuffer_t *s, const char *a)
Append the specified string to the stringbuffer_t.
Definition: stringbuffer.c:134
void stringbuffer_destroy(stringbuffer_t *s)
Free the stringbuffer_t and all memory managed within it.
Definition: stringbuffer.c:78
char * stringbuffer_getstringcopy(stringbuffer_t *s)
Returns a newly allocated string large enough to contain the current state of the string.
Definition: stringbuffer.c:160
uint32_t ngeoms
Definition: liblwgeom.h:510
uint8_t type
Definition: liblwgeom.h:506
uint8_t flags
Definition: liblwgeom.h:507
LWGEOM ** geoms
Definition: liblwgeom.h:512
uint8_t type
Definition: liblwgeom.h:399
POINTARRAY * points
Definition: liblwgeom.h:425
LWLINE ** geoms
Definition: liblwgeom.h:486
uint8_t type
Definition: liblwgeom.h:480
uint32_t ngeoms
Definition: liblwgeom.h:484
uint32_t ngeoms
Definition: liblwgeom.h:497
LWPOLY ** geoms
Definition: liblwgeom.h:499
POINTARRAY * point
Definition: liblwgeom.h:414
POINTARRAY ** rings
Definition: liblwgeom.h:460
uint32_t nrings
Definition: liblwgeom.h:458
LWPOLY ** geoms
Definition: liblwgeom.h:577
uint32_t ngeoms
Definition: liblwgeom.h:575
uint32_t ngeoms
Definition: liblwgeom.h:588
LWTRIANGLE ** geoms
Definition: liblwgeom.h:590
POINTARRAY * points
Definition: liblwgeom.h:436
double y
Definition: liblwgeom.h:331
double x
Definition: liblwgeom.h:331
double x
Definition: liblwgeom.h:355
double z
Definition: liblwgeom.h:355
double y
Definition: liblwgeom.h:355
uint32_t npoints
Definition: liblwgeom.h:374
uint8_t flags
Definition: liblwgeom.h:372
unsigned int uint32_t
Definition: uthash.h:78