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