PostGIS  2.5.0dev-r@@SVN_REVISION@@
lwout_gml.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 Sandro Santilli <strk@kbt.io>
22  * Copyright 2010-2012 Oslandia
23  * Copyright 2001-2003 Refractions Research Inc.
24  *
25  **********************************************************************/
26 
27 
34 #include <string.h>
35 #include "liblwgeom_internal.h"
36 
37 
38 static size_t asgml2_point_size(const LWPOINT *point, const char *srs, int precision, const char *prefix);
39 static char *asgml2_point(const LWPOINT *point, const char *srs, int precision, const char *prefix);
40 static size_t asgml2_line_size(const LWLINE *line, const char *srs, int precision, const char *prefix);
41 static char *asgml2_line(const LWLINE *line, const char *srs, int precision, const char *prefix);
42 static size_t asgml2_poly_size(const LWPOLY *poly, const char *srs, int precision, const char *prefix);
43 static char *asgml2_poly(const LWPOLY *poly, const char *srs, int precision, const char *prefix);
44 static size_t asgml2_multi_size(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix);
45 static char *asgml2_multi(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix);
46 static size_t asgml2_collection_size(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix);
47 static char *asgml2_collection(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix);
48 static size_t pointArray_toGML2(POINTARRAY *pa, char *buf, int precision);
49 
50 static size_t asgml3_point_size(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id);
51 static char *asgml3_point(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id);
52 static size_t asgml3_line_size(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id);
53 static char *asgml3_line(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id);
54 static char *asgml3_circstring( const LWCIRCSTRING *circ, const char *srs, int precision, int opts, const char *prefix, const char *id );
55 static size_t asgml3_poly_size(const LWPOLY *poly, const char *srs, int precision, int opts, const char *prefix, const char *id);
56 static char *asgml3_poly(const LWPOLY *poly, const char *srs, int precision, int opts, int is_patch, const char *prefix, const char *id);
57 static char * asgml3_curvepoly(const LWCURVEPOLY* poly, const char *srs, int precision, int opts, const char *prefix, const char *id);
58 static size_t asgml3_triangle_size(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id);
59 static char *asgml3_triangle(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id);
60 static size_t asgml3_multi_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id);
61 static char *asgml3_multi(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id);
62 static char *asgml3_psurface(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *prefix, const char *id);
63 static char *asgml3_tin(const LWTIN *tin, const char *srs, int precision, int opts, const char *prefix, const char *id);
64 static size_t asgml3_collection_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id);
65 static char *asgml3_collection(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id);
66 static char *asgml3_compound(const LWCOMPOUND *col, const char *srs, int precision, int opts, const char *prefix, const char *id );
67 static char *asgml3_multicurve( const LWMCURVE* cur, const char *srs, int precision, int opts, const char *prefix, const char *id );
68 static char *asgml3_multisurface(const LWMSURFACE *sur, const char *srs, int precision, int opts, const char *prefix, const char *id);
69 static size_t pointArray_toGML3(POINTARRAY *pa, char *buf, int precision, int opts);
70 
71 
72 static size_t pointArray_GMLsize(POINTARRAY *pa, int precision);
73 
74 static char *
75 gbox_to_gml2(const GBOX *bbox, const char *srs, int precision, const char *prefix)
76 {
77  int size;
78  POINT4D pt;
79  POINTARRAY *pa;
80  char *ptr, *output;
81  size_t prefixlen = strlen(prefix);
82 
83  if ( ! bbox )
84  {
85  size = ( sizeof("<Box>/") + (prefixlen*2) ) * 2;
86  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
87 
88  ptr = output = lwalloc(size);
89 
90  ptr += sprintf(ptr, "<%sBox", prefix);
91 
92  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
93 
94  ptr += sprintf(ptr, "/>");
95 
96  return output;
97  }
98 
99  pa = ptarray_construct_empty(FLAGS_GET_Z(bbox->flags), 0, 2);
100 
101  pt.x = bbox->xmin;
102  pt.y = bbox->ymin;
103  if (FLAGS_GET_Z(bbox->flags)) pt.z = bbox->zmin;
104  ptarray_append_point(pa, &pt, LW_TRUE);
105 
106  pt.x = bbox->xmax;
107  pt.y = bbox->ymax;
108  if (FLAGS_GET_Z(bbox->flags)) pt.z = bbox->zmax;
109  ptarray_append_point(pa, &pt, LW_TRUE);
110 
111  size = pointArray_GMLsize(pa, precision);
112  size += ( sizeof("<Box><coordinates>/") + (prefixlen*2) ) * 2;
113  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
114 
115  ptr = output = lwalloc(size);
116 
117  if ( srs ) ptr += sprintf(ptr, "<%sBox srsName=\"%s\">", prefix, srs);
118  else ptr += sprintf(ptr, "<%sBox>", prefix);
119 
120  ptr += sprintf(ptr, "<%scoordinates>", prefix);
121  ptr += pointArray_toGML2(pa, ptr, precision);
122  ptr += sprintf(ptr, "</%scoordinates></%sBox>", prefix, prefix);
123 
124  ptarray_free(pa);
125 
126  return output;
127 }
128 
129 static char *
130 gbox_to_gml3(const GBOX *bbox, const char *srs, int precision, int opts, const char *prefix)
131 {
132  int size;
133  POINT4D pt;
134  POINTARRAY *pa;
135  char *ptr, *output;
136  size_t prefixlen = strlen(prefix);
137  int dimension = 2;
138 
139  if ( ! bbox )
140  {
141  size = ( sizeof("<Envelope>/") + (prefixlen*2) ) * 2;
142  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
143 
144  ptr = output = lwalloc(size);
145 
146  ptr += sprintf(ptr, "<%sEnvelope", prefix);
147  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
148 
149  ptr += sprintf(ptr, "/>");
150 
151  return output;
152  }
153 
154  if (FLAGS_GET_Z(bbox->flags)) dimension = 3;
155 
156  pa = ptarray_construct_empty(FLAGS_GET_Z(bbox->flags), 0, 1);
157 
158  pt.x = bbox->xmin;
159  pt.y = bbox->ymin;
160  if (FLAGS_GET_Z(bbox->flags)) pt.z = bbox->zmin;
161  ptarray_append_point(pa, &pt, LW_TRUE);
162 
163  size = pointArray_GMLsize(pa, precision) * 2;
164  size += ( sizeof("<Envelope><lowerCorner><upperCorner>//") + (prefixlen*3) ) * 2;
165  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
166  if ( IS_DIMS(opts) ) size += sizeof(" srsDimension=. .");
167 
168  ptr = output = lwalloc(size);
169 
170  ptr += sprintf(ptr, "<%sEnvelope", prefix);
171  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
172  if ( IS_DIMS(opts) ) ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension);
173  ptr += sprintf(ptr, ">");
174 
175  ptr += sprintf(ptr, "<%slowerCorner>", prefix);
176  ptr += pointArray_toGML3(pa, ptr, precision, opts);
177  ptr += sprintf(ptr, "</%slowerCorner>", prefix);
178 
179  ptarray_remove_point(pa, 0);
180  pt.x = bbox->xmax;
181  pt.y = bbox->ymax;
182  if (FLAGS_GET_Z(bbox->flags)) pt.z = bbox->zmax;
183  ptarray_append_point(pa, &pt, LW_TRUE);
184 
185  ptr += sprintf(ptr, "<%supperCorner>", prefix);
186  ptr += pointArray_toGML3(pa, ptr, precision, opts);
187  ptr += sprintf(ptr, "</%supperCorner>", prefix);
188 
189  ptr += sprintf(ptr, "</%sEnvelope>", prefix);
190 
191  ptarray_free(pa);
192 
193  return output;
194 }
195 
196 
197 extern char *
198 lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix)
199 {
200  const GBOX* bbox = lwgeom_get_bbox(geom);
201  /*
202  if ( ! bbox ) {
203  lwerror("lwgeom_extent_to_gml2: empty geometry doesn't have a bounding box");
204  return NULL;
205  }
206  */
207  char *ret = gbox_to_gml2(bbox, srs, precision, prefix);
208  return ret;
209 }
210 
211 
212 extern char *
213 lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix)
214 {
215  const GBOX* bbox = lwgeom_get_bbox(geom);
216  /*
217  if ( ! bbox ) {
218  lwerror("lwgeom_extent_to_gml3: empty geometry doesn't have a bounding box");
219  return NULL;
220  }
221  */
222  return gbox_to_gml3(bbox, srs, precision, opts, prefix);
223 }
224 
225 
230 extern char *
231 lwgeom_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char* prefix)
232 {
233  int type = geom->type;
234 
235  /* Return null for empty (#1377) */
236  if ( lwgeom_is_empty(geom) )
237  return NULL;
238 
239  switch (type)
240  {
241  case POINTTYPE:
242  return asgml2_point((LWPOINT*)geom, srs, precision, prefix);
243 
244  case LINETYPE:
245  return asgml2_line((LWLINE*)geom, srs, precision, prefix);
246 
247  case POLYGONTYPE:
248  return asgml2_poly((LWPOLY*)geom, srs, precision, prefix);
249 
250  case MULTIPOINTTYPE:
251  case MULTILINETYPE:
252  case MULTIPOLYGONTYPE:
253  return asgml2_multi((LWCOLLECTION*)geom, srs, precision, prefix);
254 
255  case COLLECTIONTYPE:
256  return asgml2_collection((LWCOLLECTION*)geom, srs, precision, prefix);
257 
258  case TRIANGLETYPE:
260  case TINTYPE:
261  lwerror("Cannot convert %s to GML2. Try ST_AsGML(3, <geometry>) to generate GML3.", lwtype_name(type));
262  return NULL;
263 
264  default:
265  lwerror("lwgeom_to_gml2: '%s' geometry type not supported", lwtype_name(type));
266  return NULL;
267  }
268 }
269 
270 static size_t
271 asgml2_point_size(const LWPOINT *point, const char *srs, int precision, const char* prefix)
272 {
273  int size;
274  size_t prefixlen = strlen(prefix);
275 
276  size = pointArray_GMLsize(point->point, precision);
277  size += ( sizeof("<point><coordinates>/") + (prefixlen*2) ) * 2;
278  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
279  return size;
280 }
281 
282 static size_t
283 asgml2_point_buf(const LWPOINT *point, const char *srs, char *output, int precision, const char* prefix)
284 {
285  char *ptr = output;
286 
287  ptr += sprintf(ptr, "<%sPoint", prefix);
288  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
289  if ( lwpoint_is_empty(point) )
290  {
291  ptr += sprintf(ptr, "/>");
292  return (ptr-output);
293  }
294  ptr += sprintf(ptr, ">");
295  ptr += sprintf(ptr, "<%scoordinates>", prefix);
296  ptr += pointArray_toGML2(point->point, ptr, precision);
297  ptr += sprintf(ptr, "</%scoordinates></%sPoint>", prefix, prefix);
298 
299  return (ptr-output);
300 }
301 
302 static char *
303 asgml2_point(const LWPOINT *point, const char *srs, int precision, const char *prefix)
304 {
305  char *output;
306  int size;
307 
308  size = asgml2_point_size(point, srs, precision, prefix);
309  output = lwalloc(size);
310  asgml2_point_buf(point, srs, output, precision, prefix);
311  return output;
312 }
313 
314 static size_t
315 asgml2_line_size(const LWLINE *line, const char *srs, int precision, const char *prefix)
316 {
317  int size;
318  size_t prefixlen = strlen(prefix);
319 
320  size = pointArray_GMLsize(line->points, precision);
321  size += ( sizeof("<linestring><coordinates>/") + (prefixlen*2) ) * 2;
322  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
323  return size;
324 }
325 
326 static size_t
327 asgml2_line_buf(const LWLINE *line, const char *srs, char *output, int precision,
328  const char *prefix)
329 {
330  char *ptr=output;
331 
332  ptr += sprintf(ptr, "<%sLineString", prefix);
333  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
334 
335  if ( lwline_is_empty(line) )
336  {
337  ptr += sprintf(ptr, "/>");
338  return (ptr-output);
339  }
340  ptr += sprintf(ptr, ">");
341 
342  ptr += sprintf(ptr, "<%scoordinates>", prefix);
343  ptr += pointArray_toGML2(line->points, ptr, precision);
344  ptr += sprintf(ptr, "</%scoordinates></%sLineString>", prefix, prefix);
345 
346  return (ptr-output);
347 }
348 
349 static char *
350 asgml2_line(const LWLINE *line, const char *srs, int precision, const char *prefix)
351 {
352  char *output;
353  int size;
354 
355  size = asgml2_line_size(line, srs, precision, prefix);
356  output = lwalloc(size);
357  asgml2_line_buf(line, srs, output, precision, prefix);
358  return output;
359 }
360 
361 static size_t
362 asgml2_poly_size(const LWPOLY *poly, const char *srs, int precision, const char *prefix)
363 {
364  size_t size;
365  uint32_t i;
366  size_t prefixlen = strlen(prefix);
367 
368  size = sizeof("<polygon></polygon>") + prefixlen*2;
369  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
370  if ( lwpoly_is_empty(poly) )
371  return size;
372  size += ( sizeof("<outerboundaryis><linearring><coordinates>/") + ( prefixlen*3) ) * 2;
373  size += ( sizeof("<innerboundaryis><linearring><coordinates>/") + ( prefixlen*2) ) * 2 * poly->nrings;
374 
375  for (i=0; i<poly->nrings; i++)
376  size += pointArray_GMLsize(poly->rings[i], precision);
377 
378  return size;
379 }
380 
381 static size_t
382 asgml2_poly_buf(const LWPOLY *poly, const char *srs, char *output, int precision,
383  const char *prefix)
384 {
385  uint32_t i;
386  char *ptr=output;
387 
388  ptr += sprintf(ptr, "<%sPolygon", prefix);
389  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
390  if ( lwpoly_is_empty(poly) )
391  {
392  ptr += sprintf(ptr, "/>");
393  return (ptr-output);
394  }
395  ptr += sprintf(ptr, ">");
396  ptr += sprintf(ptr, "<%souterBoundaryIs><%sLinearRing><%scoordinates>",
397  prefix, prefix, prefix);
398  ptr += pointArray_toGML2(poly->rings[0], ptr, precision);
399  ptr += sprintf(ptr, "</%scoordinates></%sLinearRing></%souterBoundaryIs>", prefix, prefix, prefix);
400  for (i=1; i<poly->nrings; i++)
401  {
402  ptr += sprintf(ptr, "<%sinnerBoundaryIs><%sLinearRing><%scoordinates>", prefix, prefix, prefix);
403  ptr += pointArray_toGML2(poly->rings[i], ptr, precision);
404  ptr += sprintf(ptr, "</%scoordinates></%sLinearRing></%sinnerBoundaryIs>", prefix, prefix, prefix);
405  }
406  ptr += sprintf(ptr, "</%sPolygon>", prefix);
407 
408  return (ptr-output);
409 }
410 
411 static char *
412 asgml2_poly(const LWPOLY *poly, const char *srs, int precision, const char *prefix)
413 {
414  char *output;
415  int size;
416 
417  size = asgml2_poly_size(poly, srs, precision, prefix);
418  output = lwalloc(size);
419  asgml2_poly_buf(poly, srs, output, precision, prefix);
420  return output;
421 }
422 
423 /*
424  * Compute max size required for GML version of this
425  * inspected geometry. Will recurse when needed.
426  * Don't call this with single-geoms inspected.
427  */
428 static size_t
429 asgml2_multi_size(const LWCOLLECTION *col, const char *srs, int precision,
430  const char *prefix)
431 {
432  uint32_t i;
433  size_t size;
434  size_t prefixlen = strlen(prefix);
435  LWGEOM *subgeom;
436 
437  /* the longest possible multi version */
438  size = sizeof("<MultiLineString></MultiLineString>");
439  size += 2*prefixlen;
440 
441  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
442 
443  for (i=0; i<col->ngeoms; i++)
444  {
445  subgeom = col->geoms[i];
446  if (subgeom->type == POINTTYPE)
447  {
448  size += ( sizeof("<pointMember>/") + prefixlen ) * 2;
449  size += asgml2_point_size((LWPOINT*)subgeom, 0, precision, prefix);
450  }
451  else if (subgeom->type == LINETYPE)
452  {
453  size += ( sizeof("<lineStringMember>/") + prefixlen ) * 2;
454  size += asgml2_line_size((LWLINE*)subgeom, 0, precision, prefix);
455  }
456  else if (subgeom->type == POLYGONTYPE)
457  {
458  size += ( sizeof("<polygonMember>/") + prefixlen ) * 2;
459  size += asgml2_poly_size((LWPOLY*)subgeom, 0, precision, prefix);
460  }
461  }
462 
463  return size;
464 }
465 
466 /*
467  * Don't call this with single-geoms inspected!
468  */
469 static size_t
470 asgml2_multi_buf(const LWCOLLECTION *col, const char *srs, char *output,
471  int precision, const char *prefix)
472 {
473  int type = col->type;
474  char *ptr, *gmltype;
475  uint32_t i;
476  LWGEOM *subgeom;
477 
478  ptr = output;
479  gmltype="";
480 
481  if (type == MULTIPOINTTYPE) gmltype = "MultiPoint";
482  else if (type == MULTILINETYPE) gmltype = "MultiLineString";
483  else if (type == MULTIPOLYGONTYPE) gmltype = "MultiPolygon";
484 
485  /* Open outmost tag */
486  ptr += sprintf(ptr, "<%s%s", prefix, gmltype);
487  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
488 
489  if (!col->ngeoms)
490  {
491  ptr += sprintf(ptr, "/>");
492  return (ptr-output);
493  }
494  ptr += sprintf(ptr, ">");
495 
496  for (i=0; i<col->ngeoms; i++)
497  {
498  subgeom = col->geoms[i];
499  if (subgeom->type == POINTTYPE)
500  {
501  ptr += sprintf(ptr, "<%spointMember>", prefix);
502  ptr += asgml2_point_buf((LWPOINT*)subgeom, 0, ptr, precision, prefix);
503  ptr += sprintf(ptr, "</%spointMember>", prefix);
504  }
505  else if (subgeom->type == LINETYPE)
506  {
507  ptr += sprintf(ptr, "<%slineStringMember>", prefix);
508  ptr += asgml2_line_buf((LWLINE*)subgeom, 0, ptr, precision, prefix);
509  ptr += sprintf(ptr, "</%slineStringMember>", prefix);
510  }
511  else if (subgeom->type == POLYGONTYPE)
512  {
513  ptr += sprintf(ptr, "<%spolygonMember>", prefix);
514  ptr += asgml2_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, prefix);
515  ptr += sprintf(ptr, "</%spolygonMember>", prefix);
516  }
517  }
518 
519  /* Close outmost tag */
520  ptr += sprintf(ptr, "</%s%s>", prefix, gmltype);
521 
522  return (ptr-output);
523 }
524 
525 /*
526  * Don't call this with single-geoms inspected!
527  */
528 static char *
529 asgml2_multi(const LWCOLLECTION *col, const char *srs, int precision,
530  const char *prefix)
531 {
532  char *gml;
533  size_t size;
534 
535  size = asgml2_multi_size(col, srs, precision, prefix);
536  gml = lwalloc(size);
537  asgml2_multi_buf(col, srs, gml, precision, prefix);
538  return gml;
539 }
540 
541 
542 /*
543  * Don't call this with single-geoms!
544  */
545 static size_t
546 asgml2_collection_size(const LWCOLLECTION *col, const char *srs, int precision,
547  const char *prefix)
548 {
549  uint32_t i;
550  size_t size;
551  size_t prefixlen = strlen(prefix);
552  LWGEOM *subgeom;
553 
554  size = sizeof("<MultiGeometry></MultiGeometry>");
555  size += (prefixlen * 2);
556 
557  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
558 
559  for (i=0; i<col->ngeoms; i++)
560  {
561  subgeom = col->geoms[i];
562 
563  size += ( sizeof("<geometryMember>/") + prefixlen ) * 2;
564  if ( subgeom->type == POINTTYPE)
565  {
566  size += asgml2_point_size((LWPOINT*)subgeom, 0, precision, prefix);
567  }
568  else if ( subgeom->type == LINETYPE)
569  {
570  size += asgml2_line_size((LWLINE*)subgeom, 0, precision, prefix);
571  }
572  else if ( subgeom->type == POLYGONTYPE)
573  {
574  size += asgml2_poly_size((LWPOLY*)subgeom, 0, precision, prefix);
575  }
576  else if ( lwgeom_is_collection(subgeom) )
577  {
578  size += asgml2_collection_size((LWCOLLECTION*)subgeom, 0, precision, prefix);
579  }
580  else
581  lwerror("asgml2_collection_size: Unable to process geometry type!");
582  }
583 
584 
585  return size;
586 }
587 
588 /*
589  * Don't call this with single-geoms inspected!
590  */
591 static size_t
592 asgml2_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, const char *prefix)
593 {
594  char *ptr;
595  uint32_t i;
596  LWGEOM *subgeom;
597 
598  ptr = output;
599 
600  /* Open outmost tag */
601  ptr += sprintf(ptr, "<%sMultiGeometry", prefix);
602  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
603 
604  if (!col->ngeoms)
605  {
606  ptr += sprintf(ptr, "/>");
607  return (ptr-output);
608  }
609  ptr += sprintf(ptr, ">");
610 
611  for (i=0; i<col->ngeoms; i++)
612  {
613  subgeom = col->geoms[i];
614 
615  ptr += sprintf(ptr, "<%sgeometryMember>", prefix);
616  if (subgeom->type == POINTTYPE)
617  {
618  ptr += asgml2_point_buf((LWPOINT*)subgeom, 0, ptr, precision, prefix);
619  }
620  else if (subgeom->type == LINETYPE)
621  {
622  ptr += asgml2_line_buf((LWLINE*)subgeom, 0, ptr, precision, prefix);
623  }
624  else if (subgeom->type == POLYGONTYPE)
625  {
626  ptr += asgml2_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, prefix);
627  }
628  else if (lwgeom_is_collection(subgeom))
629  {
630  if (subgeom->type == COLLECTIONTYPE)
631  ptr += asgml2_collection_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, prefix);
632  else
633  ptr += asgml2_multi_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, prefix);
634  }
635  ptr += sprintf(ptr, "</%sgeometryMember>", prefix);
636  }
637 
638  /* Close outmost tag */
639  ptr += sprintf(ptr, "</%sMultiGeometry>", prefix);
640 
641  return (ptr-output);
642 }
643 
644 /*
645  * Don't call this with single-geoms inspected!
646  */
647 static char *
648 asgml2_collection(const LWCOLLECTION *col, const char *srs, int precision,
649  const char *prefix)
650 {
651  char *gml;
652  size_t size;
653 
654  size = asgml2_collection_size(col, srs, precision, prefix);
655  gml = lwalloc(size);
656  asgml2_collection_buf(col, srs, gml, precision, prefix);
657  return gml;
658 }
659 
660 
661 static size_t
662 pointArray_toGML2(POINTARRAY *pa, char *output, int precision)
663 {
664  uint32_t i;
665  char *ptr;
668  char z[OUT_DOUBLE_BUFFER_SIZE];
669 
670  ptr = output;
671 
672  if ( ! FLAGS_GET_Z(pa->flags) )
673  {
674  for (i=0; i<pa->npoints; i++)
675  {
676  const POINT2D *pt;
677  pt = getPoint2d_cp(pa, i);
678 
680  pt->x, precision, x, OUT_DOUBLE_BUFFER_SIZE);
682  pt->y, precision, y, OUT_DOUBLE_BUFFER_SIZE);
683 
684  if ( i ) ptr += sprintf(ptr, " ");
685  ptr += sprintf(ptr, "%s,%s", x, y);
686  }
687  }
688  else
689  {
690  for (i=0; i<pa->npoints; i++)
691  {
692  const POINT3DZ *pt;
693  pt = getPoint3dz_cp(pa, i);
695  pt->x, precision, x, OUT_DOUBLE_BUFFER_SIZE);
697  pt->y, precision, y, OUT_DOUBLE_BUFFER_SIZE);
699  pt->z, precision, z, OUT_DOUBLE_BUFFER_SIZE);
700 
701  if ( i ) ptr += sprintf(ptr, " ");
702  ptr += sprintf(ptr, "%s,%s,%s", x, y, z);
703  }
704  }
705 
706  return ptr-output;
707 }
708 
709 
710 /*
711  * VERSION GML 3.1.1
712  */
713 
714 
715 /* takes a GEOMETRY and returns a GML representation */
716 extern char *
717 lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id)
718 {
719  int type = geom->type;
720 
721  /* Return null for empty (#1377) */
722  if ( lwgeom_is_empty(geom) )
723  return NULL;
724 
725  switch (type)
726  {
727  case POINTTYPE:
728  return asgml3_point((LWPOINT*)geom, srs, precision, opts, prefix, id);
729 
730  case LINETYPE:
731  return asgml3_line((LWLINE*)geom, srs, precision, opts, prefix, id);
732 
733  case CIRCSTRINGTYPE:
734  return asgml3_circstring((LWCIRCSTRING*)geom, srs, precision, opts, prefix, id );
735 
736  case POLYGONTYPE:
737  return asgml3_poly((LWPOLY*)geom, srs, precision, opts, 0, prefix, id);
738 
739  case CURVEPOLYTYPE:
740  return asgml3_curvepoly((LWCURVEPOLY*)geom, srs, precision, opts, prefix, id);
741 
742  case TRIANGLETYPE:
743  return asgml3_triangle((LWTRIANGLE*)geom, srs, precision, opts, prefix, id);
744 
745  case MULTIPOINTTYPE:
746  case MULTILINETYPE:
747  case MULTIPOLYGONTYPE:
748  return asgml3_multi((LWCOLLECTION*)geom, srs, precision, opts, prefix, id);
749 
751  return asgml3_psurface((LWPSURFACE*)geom, srs, precision, opts, prefix, id);
752 
753  case TINTYPE:
754  return asgml3_tin((LWTIN*)geom, srs, precision, opts, prefix, id);
755 
756  case COLLECTIONTYPE:
757  return asgml3_collection((LWCOLLECTION*)geom, srs, precision, opts, prefix, id);
758 
759  case COMPOUNDTYPE:
760  return asgml3_compound( (LWCOMPOUND*)geom, srs, precision, opts, prefix, id );
761 
762  case MULTICURVETYPE:
763  return asgml3_multicurve( (LWMCURVE*)geom, srs, precision, opts, prefix, id );
764 
765  case MULTISURFACETYPE:
766  return asgml3_multisurface( (LWMSURFACE*)geom, srs, precision, opts, prefix, id );
767 
768  default:
769  lwerror("lwgeom_to_gml3: '%s' geometry type not supported", lwtype_name(type));
770  return NULL;
771  }
772 }
773 
774 static size_t
775 asgml3_point_size(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id)
776 {
777  int size;
778  size_t prefixlen = strlen(prefix);
779 
780  size = pointArray_GMLsize(point->point, precision);
781  size += ( sizeof("<point><pos>/") + (prefixlen*2) ) * 2;
782  if (srs) size += strlen(srs) + sizeof(" srsName=..");
783  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
784  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'");
785  return size;
786 }
787 
788 static size_t
789 asgml3_point_buf(const LWPOINT *point, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
790 {
791  char *ptr = output;
792  int dimension=2;
793 
794  if (FLAGS_GET_Z(point->flags)) dimension = 3;
795 
796  ptr += sprintf(ptr, "<%sPoint", prefix);
797  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
798  if ( id ) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
799  if ( lwpoint_is_empty(point) )
800  {
801  ptr += sprintf(ptr, "/>");
802  return (ptr-output);
803  }
804 
805  ptr += sprintf(ptr, ">");
806  if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%spos srsDimension=\"%d\">", prefix, dimension);
807  else ptr += sprintf(ptr, "<%spos>", prefix);
808  ptr += pointArray_toGML3(point->point, ptr, precision, opts);
809  ptr += sprintf(ptr, "</%spos></%sPoint>", prefix, prefix);
810 
811  return (ptr-output);
812 }
813 
814 static char *
815 asgml3_point(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id)
816 {
817  char *output;
818  int size;
819 
820  size = asgml3_point_size(point, srs, precision, opts, prefix, id);
821  output = lwalloc(size);
822  asgml3_point_buf(point, srs, output, precision, opts, prefix, id);
823  return output;
824 }
825 
826 
827 static size_t
828 asgml3_line_size(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id)
829 {
830  int size;
831  size_t prefixlen = strlen(prefix);
832 
833  size = pointArray_GMLsize(line->points, precision);
834  if ( opts & LW_GML_SHORTLINE )
835  {
836  size += (
837  sizeof("<LineString><posList>/") +
838  ( prefixlen * 2 )
839  ) * 2;
840  }
841  else
842  {
843  size += (
844  sizeof("<Curve><segments><LineStringSegment><posList>/") +
845  ( prefixlen * 4 )
846  ) * 2;
847  }
848  if (srs) size += strlen(srs) + sizeof(" srsName=..");
849  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
850  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'");
851  return size;
852 }
853 
854 static size_t
855 asgml3_line_buf(const LWLINE *line, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
856 {
857  char *ptr=output;
858  int dimension=2;
859  int shortline = ( opts & LW_GML_SHORTLINE );
860 
861  if (FLAGS_GET_Z(line->flags)) dimension = 3;
862 
863  if ( shortline )
864  {
865  ptr += sprintf(ptr, "<%sLineString", prefix);
866  }
867  else
868  {
869  ptr += sprintf(ptr, "<%sCurve", prefix);
870  }
871 
872  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
873  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
874 
875  if ( lwline_is_empty(line) )
876  {
877  ptr += sprintf(ptr, "/>");
878  return (ptr-output);
879  }
880  ptr += sprintf(ptr, ">");
881 
882  if ( ! shortline )
883  {
884  ptr += sprintf(ptr, "<%ssegments>", prefix);
885  ptr += sprintf(ptr, "<%sLineStringSegment>", prefix);
886  }
887 
888  if (IS_DIMS(opts))
889  {
890  ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">",
891  prefix, dimension);
892  }
893  else
894  {
895  ptr += sprintf(ptr, "<%sposList>", prefix);
896  }
897 
898  ptr += pointArray_toGML3(line->points, ptr, precision, opts);
899 
900  ptr += sprintf(ptr, "</%sposList>", prefix);
901 
902  if ( shortline )
903  {
904  ptr += sprintf(ptr, "</%sLineString>", prefix);
905  }
906  else
907  {
908  ptr += sprintf(ptr, "</%sLineStringSegment>", prefix);
909  ptr += sprintf(ptr, "</%ssegments>", prefix);
910  ptr += sprintf(ptr, "</%sCurve>", prefix);
911  }
912 
913  return (ptr-output);
914 }
915 
916 static char *
917 asgml3_line(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id)
918 {
919  char *output;
920  int size;
921 
922  size = asgml3_line_size(line, srs, precision, opts, prefix, id);
923  output = lwalloc(size);
924  asgml3_line_buf(line, srs, output, precision, opts, prefix, id);
925  return output;
926 }
927 
928 
929 static size_t
930 asgml3_circstring_size(const LWCIRCSTRING *circ, const char *srs, int precision, int opts, const char *prefix, const char *id)
931 {
932  int size = pointArray_GMLsize( circ->points, precision );
933  size_t prefixlen = strlen(prefix);
934  size += 2 * ( sizeof( "<Curve><segments>/" ) + 2 * prefixlen );
935  size += 2 * ( sizeof( "<ArcString><posList>/" ) + 2 * prefixlen );
936  if (srs) size += strlen(srs) + sizeof(" srsName=..");
937  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
938  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'");
939  return size;
940 }
941 
942 static size_t
943 asgml3_circstring_buf(const LWCIRCSTRING *circ, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
944 {
945  char* ptr = output;
946  int dimension=2;
947 
948  if (FLAGS_GET_Z(circ->flags))
949  {
950  dimension = 3;
951  }
952 
953  ptr += sprintf(ptr, "<%sCurve", prefix);
954  if (srs)
955  {
956  ptr += sprintf(ptr, " srsName=\"%s\"", srs);
957  }
958  if (id)
959  {
960  ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
961  }
962  ptr += sprintf(ptr, ">");
963  ptr += sprintf(ptr, "<%ssegments>", prefix);
964  ptr += sprintf(ptr, "<%sArcString>", prefix);
965  ptr += sprintf(ptr, "<%sposList", prefix);
966 
967  if (IS_DIMS(opts))
968  {
969  ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension);
970  }
971  ptr += sprintf(ptr, ">");
972 
973  ptr += pointArray_toGML3(circ->points, ptr, precision, opts);
974  ptr += sprintf(ptr, "</%sposList>", prefix);
975  ptr += sprintf(ptr, "</%sArcString>", prefix);
976  ptr += sprintf(ptr, "</%ssegments>", prefix);
977  ptr += sprintf(ptr, "</%sCurve>", prefix);
978  return (ptr-output);
979 }
980 
981 static char *
982 asgml3_circstring( const LWCIRCSTRING *circ, const char *srs, int precision, int opts, const char *prefix, const char *id )
983 {
984  char *output;
985  int size;
986 
987  size = asgml3_circstring_size(circ, srs, precision, opts, prefix, id);
988  output = lwalloc( size );
989  asgml3_circstring_buf(circ, srs, output, precision, opts, prefix, id);
990  return output;
991 }
992 
993 
994 static size_t
995 asgml3_poly_size(const LWPOLY *poly, const char *srs, int precision, int opts, const char *prefix, const char *id)
996 {
997  size_t size;
998  size_t prefixlen = strlen(prefix);
999  uint32_t i;
1000 
1001  size = ( sizeof("<PolygonPatch><exterior><LinearRing>///") + (prefixlen*3) ) * 2;
1002  size += ( sizeof("<interior><LinearRing>//") + (prefixlen*2) ) * 2 * (poly->nrings - 1);
1003  size += ( sizeof("<posList></posList>") + (prefixlen*2) ) * poly->nrings;
1004  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1005  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1006  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'") * poly->nrings;
1007 
1008  for (i=0; i<poly->nrings; i++)
1009  size += pointArray_GMLsize(poly->rings[i], precision);
1010 
1011  return size;
1012 }
1013 
1014 static size_t
1015 asgml3_poly_buf(const LWPOLY *poly, const char *srs, char *output, int precision, int opts, int is_patch, const char *prefix, const char *id)
1016 {
1017  uint32_t i;
1018  char *ptr=output;
1019  int dimension=2;
1020 
1021  if (FLAGS_GET_Z(poly->flags)) dimension = 3;
1022  if (is_patch)
1023  {
1024  ptr += sprintf(ptr, "<%sPolygonPatch", prefix);
1025 
1026  }
1027  else
1028  {
1029  ptr += sprintf(ptr, "<%sPolygon", prefix);
1030  }
1031 
1032  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1033  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1034 
1035  if ( lwpoly_is_empty(poly) )
1036  {
1037  ptr += sprintf(ptr, "/>");
1038  return (ptr-output);
1039  }
1040  ptr += sprintf(ptr, ">");
1041 
1042  ptr += sprintf(ptr, "<%sexterior><%sLinearRing>", prefix, prefix);
1043  if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">", prefix, dimension);
1044  else ptr += sprintf(ptr, "<%sposList>", prefix);
1045 
1046  ptr += pointArray_toGML3(poly->rings[0], ptr, precision, opts);
1047  ptr += sprintf(ptr, "</%sposList></%sLinearRing></%sexterior>",
1048  prefix, prefix, prefix);
1049  for (i=1; i<poly->nrings; i++)
1050  {
1051  ptr += sprintf(ptr, "<%sinterior><%sLinearRing>", prefix, prefix);
1052  if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">", prefix, dimension);
1053  else ptr += sprintf(ptr, "<%sposList>", prefix);
1054  ptr += pointArray_toGML3(poly->rings[i], ptr, precision, opts);
1055  ptr += sprintf(ptr, "</%sposList></%sLinearRing></%sinterior>",
1056  prefix, prefix, prefix);
1057  }
1058  if (is_patch) ptr += sprintf(ptr, "</%sPolygonPatch>", prefix);
1059  else ptr += sprintf(ptr, "</%sPolygon>", prefix);
1060 
1061  return (ptr-output);
1062 }
1063 
1064 static char *
1065 asgml3_poly(const LWPOLY *poly, const char *srs, int precision, int opts, int is_patch, const char *prefix, const char *id)
1066 {
1067  char *output;
1068  int size;
1069 
1070  size = asgml3_poly_size(poly, srs, precision, opts, prefix, id);
1071  output = lwalloc(size);
1072  asgml3_poly_buf(poly, srs, output, precision, opts, is_patch, prefix, id);
1073  return output;
1074 }
1075 
1076 static size_t
1077 asgml3_compound_size(const LWCOMPOUND *col, const char *srs, int precision, int opts, const char *prefix, const char *id )
1078 {
1079  uint32_t i;
1080  size_t size;
1081  LWGEOM *subgeom;
1082  size_t prefixlen = strlen(prefix);
1083 
1084  size = ( sizeof( "<Curve></Curve>" ) + 2 * prefixlen );
1085 
1086  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1087  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1088 
1089  size += ( sizeof("<segments></segments>") + 2 * prefixlen );
1090 
1091  for(i= 0; i < col->ngeoms; ++i )
1092  {
1093  subgeom = col->geoms[i];
1094  if ( subgeom->type == LINETYPE )
1095  {
1096 
1097  size += sizeof( "<LineStringSegment></LineStringSegment" ) + 2 * prefixlen;
1098  size += sizeof( "<posList></posList" ) + 2 * prefixlen;
1099  size += pointArray_GMLsize( ((LWLINE*)subgeom)->points, precision );
1100  }
1101  else if( subgeom->type == CIRCSTRINGTYPE )
1102  {
1103  size += sizeof( "<ArcString><posList></ArcString></posList>") + 4 * prefixlen;
1104  size += pointArray_GMLsize( ((LWCIRCSTRING*)subgeom)->points, precision );
1105  }
1106  else
1107  {
1108  continue;
1109  }
1110  if (IS_DIMS(opts))
1111  {
1112  size += sizeof(" srsDimension='x'");
1113  }
1114  }
1115  return size;
1116 }
1117 
1118 static size_t
1119 asgml3_compound_buf(const LWCOMPOUND *col, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1120 {
1121  LWGEOM *subgeom;
1122  uint32_t i;
1123  char* ptr = output;
1124  int dimension=2;
1125 
1126  if (FLAGS_GET_Z(col->flags))
1127  {
1128  dimension = 3;
1129  }
1130 
1131  ptr += sprintf( ptr, "<%sCurve", prefix );
1132  if (srs)
1133  {
1134  ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1135  }
1136  if (id)
1137  {
1138  ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id );
1139  }
1140  ptr += sprintf( ptr, ">" );
1141  ptr += sprintf( ptr, "<%ssegments>", prefix );
1142 
1143  for( i = 0; i < col->ngeoms; ++i )
1144  {
1145  subgeom = col->geoms[i];
1146  if( subgeom->type != LINETYPE && subgeom->type != CIRCSTRINGTYPE )
1147  {
1148  continue;
1149  }
1150 
1151  if ( subgeom->type == LINETYPE )
1152  {
1153  ptr += sprintf( ptr, "<%sLineStringSegment><%sposList", prefix, prefix );
1154  if (IS_DIMS(opts))
1155  {
1156  ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension);
1157  }
1158  ptr += sprintf(ptr, ">");
1159  ptr += pointArray_toGML3(((LWCIRCSTRING*)subgeom)->points, ptr, precision, opts);
1160  ptr += sprintf( ptr, "</%sposList></%sLineStringSegment>", prefix, prefix );
1161  }
1162  else if( subgeom->type == CIRCSTRINGTYPE )
1163  {
1164  ptr += sprintf( ptr, "<%sArcString><%sposList" , prefix, prefix );
1165  if (IS_DIMS(opts))
1166  {
1167  ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension);
1168  }
1169  ptr += sprintf(ptr, ">");
1170  ptr += pointArray_toGML3(((LWLINE*)subgeom)->points, ptr, precision, opts);
1171  ptr += sprintf( ptr, "</%sposList></%sArcString>", prefix, prefix );
1172  }
1173  }
1174 
1175  ptr += sprintf( ptr, "</%ssegments>", prefix );
1176  ptr += sprintf( ptr, "</%sCurve>", prefix );
1177  return ( ptr - output );
1178 }
1179 
1180 static char *
1181 asgml3_compound(const LWCOMPOUND *col, const char *srs, int precision, int opts, const char *prefix, const char *id )
1182 {
1183  char* gml;
1184  size_t size;
1185 
1186  size = asgml3_compound_size( col, srs, precision, opts, prefix, id );
1187  gml = lwalloc( size );
1188  asgml3_compound_buf( col, srs, gml, precision, opts, prefix, id );
1189  return gml;
1190 }
1191 
1192 static size_t asgml3_curvepoly_size(const LWCURVEPOLY* poly, const char *srs, int precision, int opts, const char *prefix, const char *id)
1193 {
1194  size_t prefixlen = strlen(prefix);
1195  LWGEOM* subgeom;
1196  size_t size = sizeof( "<Polygon></Polygon" ) + 2 * prefixlen;
1197  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1198  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1199  uint32_t i;
1200 
1201  for( i = 0; i < poly->nrings; ++i )
1202  {
1203  if( i == 0 )
1204  {
1205  size += sizeof( "<exterior></exterior>" ) + 2 * prefixlen;
1206  }
1207  else
1208  {
1209  size += sizeof( "<interior></interior>" ) + 2 * prefixlen;
1210  }
1211  subgeom = poly->rings[i];
1212 
1213  if ( subgeom->type == LINETYPE )
1214  {
1215  size += sizeof("<LinearRing></LinearRing>") + 2 * prefixlen;
1216  size += sizeof("<posList></posList") + 2 * prefixlen;
1217  if (IS_DIMS(opts))
1218  {
1219  size += sizeof(" srsDimension='x'");
1220  }
1221  size += pointArray_GMLsize( ((LWLINE*)subgeom)->points, precision );
1222  }
1223  else if( subgeom->type == CIRCSTRINGTYPE )
1224  {
1225  size += sizeof("<Ring></Ring>") + 2 * prefixlen;
1226  size += sizeof("<CurveMember></CurveMember>") + 2 * prefixlen;
1227  size += asgml3_circstring_size((LWCIRCSTRING*)subgeom, srs, precision, opts, prefix, id);
1228  }
1229  else if( subgeom->type == COMPOUNDTYPE )
1230  {
1231  size += sizeof("<Ring></Ring>") + 2 * prefixlen;
1232  size += sizeof("<curveMember></curveMember>") + 2 * prefixlen;
1233  size += asgml3_compound_size( (LWCOMPOUND*)subgeom, srs, precision, opts, prefix, id );
1234  }
1235  }
1236  return size;
1237 }
1238 
1239 static size_t asgml3_curvepoly_buf(const LWCURVEPOLY* poly, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1240 {
1241  uint32_t i;
1242  LWGEOM* subgeom;
1243  char *ptr=output;
1244  int dimension=2;
1245 
1246  if (FLAGS_GET_Z(poly->flags))
1247  {
1248  dimension = 3;
1249  }
1250 
1251  ptr += sprintf( ptr, "<%sPolygon", prefix );
1252  if (srs)
1253  {
1254  ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1255  }
1256  if (id)
1257  {
1258  ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id );
1259  }
1260  ptr += sprintf(ptr, ">");
1261 
1262  for( i = 0; i < poly->nrings; ++i )
1263  {
1264  if( i == 0 )
1265  {
1266  ptr += sprintf( ptr, "<%sexterior>", prefix);
1267  }
1268  else
1269  {
1270  ptr += sprintf( ptr, "<%sinterior>", prefix);
1271  }
1272 
1273  subgeom = poly->rings[i];
1274  if ( subgeom->type == LINETYPE )
1275  {
1276  ptr += sprintf( ptr, "<%sLinearRing>", prefix );
1277  ptr += sprintf( ptr, "<%sposList", prefix );
1278  if (IS_DIMS(opts))
1279  {
1280  ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension);
1281  }
1282  ptr += sprintf( ptr, ">" );
1283  ptr += pointArray_toGML3(((LWLINE*)subgeom)->points, ptr, precision, opts);
1284  ptr += sprintf( ptr, "</%sposList>", prefix );
1285  ptr += sprintf( ptr, "</%sLinearRing>", prefix );
1286  }
1287  else if( subgeom->type == CIRCSTRINGTYPE )
1288  {
1289  ptr += sprintf( ptr, "<%sRing>", prefix );
1290  ptr += sprintf( ptr, "<%scurveMember>", prefix );
1291  ptr += asgml3_circstring_buf( (LWCIRCSTRING*)subgeom, srs, ptr, precision, opts, prefix, id );
1292  ptr += sprintf( ptr, "</%scurveMember>", prefix );
1293  ptr += sprintf( ptr, "</%sRing>", prefix );
1294  }
1295  else if( subgeom->type == COMPOUNDTYPE )
1296  {
1297  ptr += sprintf( ptr, "<%sRing>", prefix );
1298  ptr += sprintf( ptr, "<%scurveMember>", prefix );
1299  ptr += asgml3_compound_buf( (LWCOMPOUND*)subgeom, srs, ptr, precision, opts, prefix, id );
1300  ptr += sprintf( ptr, "</%scurveMember>", prefix );
1301  ptr += sprintf( ptr, "</%sRing>", prefix );
1302  }
1303 
1304  if( i == 0 )
1305  {
1306  ptr += sprintf( ptr, "</%sexterior>", prefix);
1307  }
1308  else
1309  {
1310  ptr += sprintf( ptr, "</%sinterior>", prefix);
1311  }
1312  }
1313 
1314  ptr += sprintf( ptr, "</%sPolygon>", prefix );
1315  return (ptr - output);
1316 }
1317 
1318 static char* asgml3_curvepoly(const LWCURVEPOLY* poly, const char *srs, int precision, int opts, const char *prefix, const char *id)
1319 {
1320  char* gml;
1321  size_t size;
1322 
1323  size = asgml3_curvepoly_size( poly, srs, precision, opts, prefix, id );
1324  gml = lwalloc( size );
1325  asgml3_curvepoly_buf( poly, srs, gml, precision, opts, prefix, id );
1326  return gml;
1327 }
1328 
1329 
1330 static size_t
1331 asgml3_triangle_size(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id)
1332 {
1333  size_t size;
1334  size_t prefixlen = strlen(prefix);
1335 
1336  size = ( sizeof("<Triangle><exterior><LinearRing>///") + (prefixlen*3) ) * 2;
1337  size += sizeof("<posList></posList>") + (prefixlen*2);
1338  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1339  if (id) size += strlen(prefix) + strlen(id) + sizeof(" id=..");
1340  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'");
1341 
1342  size += pointArray_GMLsize(triangle->points, precision);
1343 
1344  return size;
1345 }
1346 
1347 static size_t
1348 asgml3_triangle_buf(const LWTRIANGLE *triangle, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1349 {
1350  char *ptr=output;
1351  int dimension=2;
1352 
1353  if (FLAGS_GET_Z(triangle->flags)) dimension = 3;
1354  ptr += sprintf(ptr, "<%sTriangle", prefix);
1355  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1356  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1357  ptr += sprintf(ptr, ">");
1358 
1359  ptr += sprintf(ptr, "<%sexterior><%sLinearRing>", prefix, prefix);
1360  if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">", prefix, dimension);
1361  else ptr += sprintf(ptr, "<%sposList>", prefix);
1362 
1363  ptr += pointArray_toGML3(triangle->points, ptr, precision, opts);
1364  ptr += sprintf(ptr, "</%sposList></%sLinearRing></%sexterior>",
1365  prefix, prefix, prefix);
1366 
1367  ptr += sprintf(ptr, "</%sTriangle>", prefix);
1368 
1369  return (ptr-output);
1370 }
1371 
1372 static char *
1373 asgml3_triangle(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id)
1374 {
1375  char *output;
1376  int size;
1377 
1378  size = asgml3_triangle_size(triangle, srs, precision, opts, prefix, id);
1379  output = lwalloc(size);
1380  asgml3_triangle_buf(triangle, srs, output, precision, opts, prefix, id);
1381  return output;
1382 }
1383 
1384 
1385 /*
1386  * Compute max size required for GML version of this
1387  * inspected geometry. Will recurse when needed.
1388  * Don't call this with single-geoms inspected.
1389  */
1390 static size_t
1391 asgml3_multi_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
1392 {
1393  uint32_t i;
1394  size_t size;
1395  size_t prefixlen = strlen(prefix);
1396  LWGEOM *subgeom;
1397 
1398  /* the longest possible multi version */
1399  size = sizeof("<MultiLineString></MultiLineString>") + prefixlen*2;
1400 
1401  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1402  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1403 
1404  for (i=0; i<col->ngeoms; i++)
1405  {
1406  subgeom = col->geoms[i];
1407  if (subgeom->type == POINTTYPE)
1408  {
1409  size += ( sizeof("<pointMember>/") + prefixlen ) * 2;
1410  size += asgml3_point_size((LWPOINT*)subgeom, 0, precision, opts, prefix, id);
1411  }
1412  else if (subgeom->type == LINETYPE)
1413  {
1414  size += ( sizeof("<curveMember>/") + prefixlen ) * 2;
1415  size += asgml3_line_size((LWLINE*)subgeom, 0, precision, opts, prefix, id);
1416  }
1417  else if (subgeom->type == POLYGONTYPE)
1418  {
1419  size += ( sizeof("<surfaceMember>/") + prefixlen ) * 2;
1420  size += asgml3_poly_size((LWPOLY*)subgeom, 0, precision, opts, prefix, id);
1421  }
1422  }
1423 
1424  return size;
1425 }
1426 
1427 /*
1428  * Don't call this with single-geoms inspected!
1429  */
1430 static size_t
1431 asgml3_multi_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1432 {
1433  int type = col->type;
1434  char *ptr, *gmltype;
1435  uint32_t i;
1436  LWGEOM *subgeom;
1437 
1438  ptr = output;
1439  gmltype="";
1440 
1441  if (type == MULTIPOINTTYPE) gmltype = "MultiPoint";
1442  else if (type == MULTILINETYPE) gmltype = "MultiCurve";
1443  else if (type == MULTIPOLYGONTYPE) gmltype = "MultiSurface";
1444 
1445  /* Open outmost tag */
1446  ptr += sprintf(ptr, "<%s%s", prefix, gmltype);
1447  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1448  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1449 
1450  if (!col->ngeoms)
1451  {
1452  ptr += sprintf(ptr, "/>");
1453  return (ptr-output);
1454  }
1455  ptr += sprintf(ptr, ">");
1456 
1457  for (i=0; i<col->ngeoms; i++)
1458  {
1459  subgeom = col->geoms[i];
1460  if (subgeom->type == POINTTYPE)
1461  {
1462  ptr += sprintf(ptr, "<%spointMember>", prefix);
1463  ptr += asgml3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, prefix, id);
1464  ptr += sprintf(ptr, "</%spointMember>", prefix);
1465  }
1466  else if (subgeom->type == LINETYPE)
1467  {
1468  ptr += sprintf(ptr, "<%scurveMember>", prefix);
1469  ptr += asgml3_line_buf((LWLINE*)subgeom, 0, ptr, precision, opts, prefix, id);
1470  ptr += sprintf(ptr, "</%scurveMember>", prefix);
1471  }
1472  else if (subgeom->type == POLYGONTYPE)
1473  {
1474  ptr += sprintf(ptr, "<%ssurfaceMember>", prefix);
1475  ptr += asgml3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, prefix, id);
1476  ptr += sprintf(ptr, "</%ssurfaceMember>", prefix);
1477  }
1478  }
1479 
1480  /* Close outmost tag */
1481  ptr += sprintf(ptr, "</%s%s>", prefix, gmltype);
1482 
1483  return (ptr-output);
1484 }
1485 
1486 /*
1487  * Don't call this with single-geoms inspected!
1488  */
1489 static char *
1490 asgml3_multi(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
1491 {
1492  char *gml;
1493  size_t size;
1494 
1495  size = asgml3_multi_size(col, srs, precision, opts, prefix, id);
1496  gml = lwalloc(size);
1497  asgml3_multi_buf(col, srs, gml, precision, opts, prefix, id);
1498  return gml;
1499 }
1500 
1501 
1502 static size_t
1503 asgml3_psurface_size(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *prefix, const char *id)
1504 {
1505  uint32_t i;
1506  size_t size;
1507  size_t prefixlen = strlen(prefix);
1508 
1509  size = (sizeof("<PolyhedralSurface><polygonPatches>/") + prefixlen*2) * 2;
1510  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1511  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1512 
1513  for (i=0; i<psur->ngeoms; i++)
1514  {
1515  size += asgml3_poly_size(psur->geoms[i], 0, precision, opts, prefix, id);
1516  }
1517 
1518  return size;
1519 }
1520 
1521 
1522 /*
1523  * Don't call this with single-geoms inspected!
1524  */
1525 static size_t
1526 asgml3_psurface_buf(const LWPSURFACE *psur, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1527 {
1528  char *ptr;
1529  uint32_t i;
1530 
1531  ptr = output;
1532 
1533  /* Open outmost tag */
1534  ptr += sprintf(ptr, "<%sPolyhedralSurface", prefix);
1535  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1536  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1537  ptr += sprintf(ptr, "><%spolygonPatches>", prefix);
1538 
1539  for (i=0; i<psur->ngeoms; i++)
1540  {
1541  ptr += asgml3_poly_buf(psur->geoms[i], 0, ptr, precision, opts, 1, prefix, id);
1542  }
1543 
1544  /* Close outmost tag */
1545  ptr += sprintf(ptr, "</%spolygonPatches></%sPolyhedralSurface>",
1546  prefix, prefix);
1547 
1548  return (ptr-output);
1549 }
1550 
1551 /*
1552  * Don't call this with single-geoms inspected!
1553  */
1554 static char *
1555 asgml3_psurface(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *prefix, const char *id)
1556 {
1557  char *gml;
1558  size_t size;
1559 
1560  size = asgml3_psurface_size(psur, srs, precision, opts, prefix, id);
1561  gml = lwalloc(size);
1562  asgml3_psurface_buf(psur, srs, gml, precision, opts, prefix, id);
1563  return gml;
1564 }
1565 
1566 
1567 static size_t
1568 asgml3_tin_size(const LWTIN *tin, const char *srs, int precision, int opts, const char *prefix, const char *id)
1569 {
1570  uint32_t i;
1571  size_t size;
1572  size_t prefixlen = strlen(prefix);
1573 
1574  size = (sizeof("<Tin><trianglePatches>/") + prefixlen*2) * 2;
1575  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1576  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1577 
1578  for (i=0; i<tin->ngeoms; i++)
1579  {
1580  size += asgml3_triangle_size(tin->geoms[i], 0, precision, opts, prefix, id);
1581  }
1582 
1583  return size;
1584 }
1585 
1586 
1587 /*
1588  * Don't call this with single-geoms inspected!
1589  */
1590 static size_t
1591 asgml3_tin_buf(const LWTIN *tin, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1592 {
1593  char *ptr;
1594  uint32_t i;
1595 
1596  ptr = output;
1597 
1598  /* Open outmost tag */
1599  ptr += sprintf(ptr, "<%sTin", prefix);
1600  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1601  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1602  else ptr += sprintf(ptr, "><%strianglePatches>", prefix);
1603 
1604  for (i=0; i<tin->ngeoms; i++)
1605  {
1606  ptr += asgml3_triangle_buf(tin->geoms[i], 0, ptr, precision,
1607  opts, prefix, id);
1608  }
1609 
1610  /* Close outmost tag */
1611  ptr += sprintf(ptr, "</%strianglePatches></%sTin>", prefix, prefix);
1612 
1613  return (ptr-output);
1614 }
1615 
1616 /*
1617  * Don't call this with single-geoms inspected!
1618  */
1619 static char *
1620 asgml3_tin(const LWTIN *tin, const char *srs, int precision, int opts, const char *prefix, const char *id)
1621 {
1622  char *gml;
1623  size_t size;
1624 
1625  size = asgml3_tin_size(tin, srs, precision, opts, prefix, id);
1626  gml = lwalloc(size);
1627  asgml3_tin_buf(tin, srs, gml, precision, opts, prefix, id);
1628  return gml;
1629 }
1630 
1631 static size_t
1632 asgml3_collection_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
1633 {
1634  uint32_t i;
1635  size_t size;
1636  size_t prefixlen = strlen(prefix);
1637  LWGEOM *subgeom;
1638 
1639  size = sizeof("<MultiGeometry></MultiGeometry>") + prefixlen*2;
1640 
1641  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1642  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1643 
1644  for (i=0; i<col->ngeoms; i++)
1645  {
1646  subgeom = col->geoms[i];
1647  size += ( sizeof("<geometryMember>/") + prefixlen ) * 2;
1648  if ( subgeom->type == POINTTYPE )
1649  {
1650  size += asgml3_point_size((LWPOINT*)subgeom, 0, precision, opts, prefix, id);
1651  }
1652  else if ( subgeom->type == LINETYPE )
1653  {
1654  size += asgml3_line_size((LWLINE*)subgeom, 0, precision, opts, prefix, id);
1655  }
1656  else if ( subgeom->type == POLYGONTYPE )
1657  {
1658  size += asgml3_poly_size((LWPOLY*)subgeom, 0, precision, opts, prefix, id);
1659  }
1660  else if ( lwgeom_is_collection(subgeom) )
1661  {
1662  size += asgml3_multi_size((LWCOLLECTION*)subgeom, 0, precision, opts, prefix, id);
1663  }
1664  else
1665  lwerror("asgml3_collection_size: unknown geometry type");
1666  }
1667 
1668  return size;
1669 }
1670 
1671 static size_t
1672 asgml3_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1673 {
1674  char *ptr;
1675  uint32_t i;
1676  LWGEOM *subgeom;
1677 
1678  ptr = output;
1679 
1680  /* Open outmost tag */
1681  ptr += sprintf(ptr, "<%sMultiGeometry", prefix);
1682  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1683  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1684 
1685  if (!col->ngeoms)
1686  {
1687  ptr += sprintf(ptr, "/>");
1688  return (ptr-output);
1689  }
1690  ptr += sprintf(ptr, ">");
1691 
1692  for (i=0; i<col->ngeoms; i++)
1693  {
1694  subgeom = col->geoms[i];
1695  ptr += sprintf(ptr, "<%sgeometryMember>", prefix);
1696  if ( subgeom->type == POINTTYPE )
1697  {
1698  ptr += asgml3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, prefix, id);
1699  }
1700  else if ( subgeom->type == LINETYPE )
1701  {
1702  ptr += asgml3_line_buf((LWLINE*)subgeom, 0, ptr, precision, opts, prefix, id);
1703  }
1704  else if ( subgeom->type == POLYGONTYPE )
1705  {
1706  ptr += asgml3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, prefix, id);
1707  }
1708  else if ( lwgeom_is_collection(subgeom) )
1709  {
1710  if ( subgeom->type == COLLECTIONTYPE )
1711  ptr += asgml3_collection_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, prefix, id);
1712  else
1713  ptr += asgml3_multi_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, prefix, id);
1714  }
1715  else
1716  lwerror("asgml3_collection_buf: unknown geometry type");
1717 
1718  ptr += sprintf(ptr, "</%sgeometryMember>", prefix);
1719  }
1720 
1721  /* Close outmost tag */
1722  ptr += sprintf(ptr, "</%sMultiGeometry>", prefix);
1723 
1724  return (ptr-output);
1725 }
1726 
1727 /*
1728  * Don't call this with single-geoms inspected!
1729  */
1730 static char *
1731 asgml3_collection(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
1732 {
1733  char *gml;
1734  size_t size;
1735 
1736  size = asgml3_collection_size(col, srs, precision, opts, prefix, id);
1737  gml = lwalloc(size);
1738  asgml3_collection_buf(col, srs, gml, precision, opts, prefix, id);
1739  return gml;
1740 }
1741 
1742 static size_t asgml3_multicurve_size( const LWMCURVE* cur, const char *srs, int precision, int opts, const char *prefix, const char *id )
1743 {
1744  size_t prefixlen = strlen(prefix);
1745  size_t size = sizeof( "<MultiCurve></MultiCurve>" ) + 2 * prefixlen;
1746  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1747  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1748  LWGEOM* subgeom;
1749  uint32_t i;
1750 
1751  for( i = 0; i < cur->ngeoms; ++i )
1752  {
1753  size += sizeof( "<curveMember></curveMember>" ) + 2 * prefixlen;
1754  subgeom = cur->geoms[i];
1755  if ( subgeom->type == LINETYPE )
1756  {
1757  size += asgml3_line_size( (LWLINE*)subgeom, srs, precision, opts, prefix, id );
1758  }
1759  else if( subgeom->type == CIRCSTRINGTYPE )
1760  {
1761  size += asgml3_circstring_size( (LWCIRCSTRING*)subgeom, srs, precision, opts, prefix, id );
1762  }
1763  else if( subgeom->type == COMPOUNDTYPE )
1764  {
1765  size += asgml3_compound_size( (LWCOMPOUND*)subgeom, srs, precision, opts, prefix, id );
1766  }
1767  }
1768  return size;
1769 }
1770 
1771 static size_t asgml3_multicurve_buf( const LWMCURVE* cur, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id )
1772 {
1773  char* ptr = output;
1774  LWGEOM* subgeom;
1775  uint32_t i;
1776 
1777  ptr += sprintf(ptr, "<%sMultiCurve", prefix );
1778  if (srs)
1779  {
1780  ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1781  }
1782  if (id)
1783  {
1784  ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id );
1785  }
1786  ptr += sprintf( ptr, ">");
1787 
1788  for( i = 0; i < cur->ngeoms; ++i )
1789  {
1790  ptr += sprintf(ptr, "<%scurveMember>", prefix );
1791  subgeom = cur->geoms[i];
1792  if ( subgeom->type == LINETYPE )
1793  {
1794  ptr += asgml3_line_buf( (LWLINE*)subgeom, srs, ptr, precision, opts, prefix, id );
1795  }
1796  else if( subgeom->type == CIRCSTRINGTYPE )
1797  {
1798  ptr += asgml3_circstring_buf( (LWCIRCSTRING*)subgeom, srs, ptr, precision, opts, prefix, id );
1799  }
1800  else if( subgeom->type == COMPOUNDTYPE )
1801  {
1802  ptr += asgml3_compound_buf( (LWCOMPOUND*)subgeom, srs, ptr, precision, opts, prefix, id );
1803  }
1804  ptr += sprintf(ptr, "</%scurveMember>", prefix );
1805  }
1806  ptr += sprintf(ptr, "</%sMultiCurve>", prefix );
1807  return (ptr - output);
1808 }
1809 
1810 static char *asgml3_multicurve( const LWMCURVE* cur, const char *srs, int precision, int opts, const char *prefix, const char *id )
1811 {
1812  char* gml;
1813  size_t size =asgml3_multicurve_size( cur, srs, precision, opts, prefix, id );
1814  gml = lwalloc( size );
1815  asgml3_multicurve_buf( cur, srs, gml, precision, opts, prefix, id );
1816  return gml;
1817 }
1818 
1819 static size_t asgml3_multisurface_size(const LWMSURFACE *sur, const char *srs, int precision, int opts, const char *prefix, const char *id)
1820 {
1821  size_t prefixlen = strlen(prefix);
1822  size_t size = sizeof( "<MultiSurface></MultiSurface>" ) + 2 * prefixlen;
1823  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1824  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1825  LWGEOM* subgeom;
1826  uint32_t i;
1827 
1828  for( i = 0; i < sur->ngeoms; ++i )
1829  {
1830  subgeom = sur->geoms[i];
1831  if( subgeom->type == POLYGONTYPE )
1832  {
1833  size += asgml3_poly_size( (LWPOLY*)sur->geoms[i], srs, precision, opts, prefix, id );
1834  }
1835  else if( subgeom->type == CURVEPOLYTYPE )
1836  {
1837  size += asgml3_curvepoly_size( (LWCURVEPOLY*)sur->geoms[i], srs, precision, opts, prefix, id );
1838  }
1839  }
1840  return size;
1841 }
1842 
1843 static size_t asgml3_multisurface_buf(const LWMSURFACE *sur, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1844 {
1845  char* ptr = output;
1846  uint32_t i;
1847  LWGEOM* subgeom;
1848 
1849  ptr += sprintf( ptr, "<%sMultiSurface", prefix );
1850  if (srs)
1851  {
1852  ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1853  }
1854  if (id)
1855  {
1856  ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id );
1857  }
1858  ptr += sprintf( ptr, ">" );
1859 
1860  for( i = 0; i < sur->ngeoms; ++i )
1861  {
1862  subgeom = sur->geoms[i];
1863  if( subgeom->type == POLYGONTYPE )
1864  {
1865  ptr += asgml3_poly_buf( (LWPOLY*)sur->geoms[i], srs, ptr, precision, opts, 0, prefix, id );
1866  }
1867  else if( subgeom->type == CURVEPOLYTYPE )
1868  {
1869  ptr += asgml3_curvepoly_buf( (LWCURVEPOLY*)sur->geoms[i], srs, ptr, precision, opts, prefix, id );
1870  }
1871  }
1872  ptr += sprintf( ptr, "</%sMultiSurface>", prefix );
1873  return ptr - output;
1874 }
1875 
1876 static char *asgml3_multisurface(const LWMSURFACE *sur, const char *srs, int precision, int opts, const char *prefix, const char *id)
1877 {
1878  char* gml;
1879  size_t size = asgml3_multisurface_size( sur, srs, precision, opts, prefix, id );
1880  gml = lwalloc( size );
1881  asgml3_multisurface_buf( sur, srs, gml, precision, opts, prefix, id );
1882  return gml;
1883 }
1884 
1885 
1886 /* In GML3, inside <posList> or <pos>, coordinates are separated by a space separator
1887  * In GML3 also, lat/lon are reversed for geocentric data
1888  */
1889 static size_t
1890 pointArray_toGML3(POINTARRAY *pa, char *output, int precision, int opts)
1891 {
1892  uint32_t i;
1893  char *ptr;
1894  char x[OUT_DOUBLE_BUFFER_SIZE];
1895  char y[OUT_DOUBLE_BUFFER_SIZE];
1896  char z[OUT_DOUBLE_BUFFER_SIZE];
1897 
1898  ptr = output;
1899 
1900  if ( ! FLAGS_GET_Z(pa->flags) )
1901  {
1902  for (i=0; i<pa->npoints; i++)
1903  {
1904  const POINT2D *pt;
1905  pt = getPoint2d_cp(pa, i);
1907  pt->x, precision, x, OUT_DOUBLE_BUFFER_SIZE);
1909  pt->y, precision, y, OUT_DOUBLE_BUFFER_SIZE);
1910 
1911  if ( i ) ptr += sprintf(ptr, " ");
1912  if (IS_DEGREE(opts))
1913  ptr += sprintf(ptr, "%s %s", y, x);
1914  else
1915  ptr += sprintf(ptr, "%s %s", x, y);
1916  }
1917  }
1918  else
1919  {
1920  for (i=0; i<pa->npoints; i++)
1921  {
1922  const POINT3DZ *pt;
1923  pt = getPoint3dz_cp(pa, i);
1924 
1926  pt->x, precision, x, OUT_DOUBLE_BUFFER_SIZE);
1928  pt->y, precision, y, OUT_DOUBLE_BUFFER_SIZE);
1930  pt->z, precision, z, OUT_DOUBLE_BUFFER_SIZE);
1931 
1932  if ( i ) ptr += sprintf(ptr, " ");
1933  if (IS_DEGREE(opts))
1934  ptr += sprintf(ptr, "%s %s %s", y, x, z);
1935  else
1936  ptr += sprintf(ptr, "%s %s %s", x, y, z);
1937  }
1938  }
1939 
1940  return ptr-output;
1941 }
1942 
1943 
1944 
1945 /*
1946  * Returns maximum size of rendered pointarray in bytes.
1947  */
1948 static size_t
1950 {
1951  if (FLAGS_NDIMS(pa->flags) == 2)
1952  return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(", ")) * 2 * pa->npoints;
1953 
1954  return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(", ")) * 3 * pa->npoints;
1955 }
double x
Definition: liblwgeom.h:351
#define LINETYPE
Definition: liblwgeom.h:85
int lwprint_double(double d, int maxdd, char *buf, size_t bufsize)
Definition: lwprint.c:488
static size_t asgml2_point_size(const LWPOINT *point, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:271
static size_t asgml3_multisurface_size(const LWMSURFACE *sur, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1819
double z
Definition: liblwgeom.h:333
double y
Definition: liblwgeom.h:333
uint8_t flags
Definition: liblwgeom.h:440
POINTARRAY * points
Definition: liblwgeom.h:432
uint32_t ngeoms
Definition: liblwgeom.h:558
#define MULTICURVETYPE
Definition: liblwgeom.h:94
char * lwgeom_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix)
VERSION GML 2 takes a GEOMETRY and returns a GML2 representation.
Definition: lwout_gml.c:231
#define LW_GML_SHORTLINE
For GML3, use rather than for lines.
Definition: liblwgeom.h:1539
static size_t asgml3_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1672
static char * asgml2_line(const LWLINE *line, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:350
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1078
double x
Definition: liblwgeom.h:333
static char * asgml3_triangle(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1373
LWGEOM ** rings
Definition: liblwgeom.h:534
uint8_t type
Definition: liblwgeom.h:502
static size_t asgml3_multicurve_buf(const LWMCURVE *cur, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1771
#define POLYGONTYPE
Definition: liblwgeom.h:86
double xmax
Definition: liblwgeom.h:292
#define CURVEPOLYTYPE
Definition: liblwgeom.h:93
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:70
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:328
#define COMPOUNDTYPE
Definition: liblwgeom.h:92
#define MULTIPOINTTYPE
Definition: liblwgeom.h:87
static size_t asgml2_line_size(const LWLINE *line, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:315
static size_t asgml3_compound_size(const LWCOMPOUND *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1077
#define TRIANGLETYPE
Definition: liblwgeom.h:97
static size_t asgml3_point_buf(const LWPOINT *point, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:789
static size_t asgml3_poly_size(const LWPOLY *poly, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:995
static size_t asgml3_line_size(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:828
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:96
#define IS_DEGREE(x)
Definition: liblwgeom.h:1545
static size_t asgml3_curvepoly_size(const LWCURVEPOLY *poly, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1192
LWPOLY ** geoms
Definition: liblwgeom.h:573
static char * asgml3_psurface(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1555
uint32_t ngeoms
Definition: liblwgeom.h:571
static char * asgml3_point(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:815
LWGEOM ** geoms
Definition: liblwgeom.h:521
uint8_t flags
Definition: liblwgeom.h:516
uint32_t ngeoms
Definition: liblwgeom.h:506
char * lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix)
Definition: lwout_gml.c:213
POINTARRAY * point
Definition: liblwgeom.h:410
static size_t asgml2_multi_size(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:429
uint32_t nrings
Definition: liblwgeom.h:454
static size_t asgml2_poly_size(const LWPOLY *poly, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:362
static size_t asgml3_multisurface_buf(const LWMSURFACE *sur, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1843
static char * asgml2_collection(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:648
unsigned int uint32_t
Definition: uthash.h:78
double x
Definition: liblwgeom.h:327
static size_t asgml3_tin_size(const LWTIN *tin, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1568
static size_t asgml2_multi_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, const char *prefix)
Definition: lwout_gml.c:470
static size_t asgml3_collection_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1632
static size_t asgml3_compound_buf(const LWCOMPOUND *col, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1119
const POINT3DZ * getPoint3dz_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT3DZ pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
Definition: lwgeom_api.c:378
static size_t asgml3_triangle_size(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1331
double zmax
Definition: liblwgeom.h:296
double ymin
Definition: liblwgeom.h:293
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
static size_t asgml3_tin_buf(const LWTIN *tin, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1591
static size_t asgml3_psurface_size(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1503
double xmin
Definition: liblwgeom.h:291
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE, then a duplicate point will not be added.
Definition: ptarray.c:156
static char * asgml3_compound(const LWCOMPOUND *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1181
static size_t asgml3_circstring_buf(const LWCIRCSTRING *circ, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:943
uint8_t flags
Definition: liblwgeom.h:368
static size_t asgml3_point_size(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:775
static char * asgml3_poly(const LWPOLY *poly, const char *srs, int precision, int opts, int is_patch, const char *prefix, const char *id)
Definition: lwout_gml.c:1065
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:75
#define IS_DIMS(x)
Definition: liblwgeom.h:1544
LWGEOM ** geoms
Definition: liblwgeom.h:508
#define TINTYPE
Definition: liblwgeom.h:98
LWTRIANGLE ** geoms
Definition: liblwgeom.h:586
uint32_t ngeoms
Definition: liblwgeom.h:519
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
Definition: lwgeom.c:727
POINTARRAY ** rings
Definition: liblwgeom.h:456
static char * asgml3_multi(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1490
uint8_t precision
Definition: cu_in_twkb.c:25
int lwpoly_is_empty(const LWPOLY *poly)
Definition: lwpoly.c:416
static size_t asgml3_poly_buf(const LWPOLY *poly, const char *srs, char *output, int precision, int opts, int is_patch, const char *prefix, const char *id)
Definition: lwout_gml.c:1015
double ymax
Definition: liblwgeom.h:294
double y
Definition: liblwgeom.h:327
uint8_t flags
Definition: liblwgeom.h:529
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:139
static size_t asgml3_multi_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1431
static char * asgml3_multisurface(const LWMSURFACE *sur, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1876
static char * asgml3_multicurve(const LWMCURVE *cur, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1810
double z
Definition: liblwgeom.h:351
tuple x
Definition: pixval.py:53
static char * asgml3_line(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:917
uint8_t flags
Definition: liblwgeom.h:290
static size_t pointArray_GMLsize(POINTARRAY *pa, int precision)
Definition: lwout_gml.c:1949
static size_t asgml3_triangle_buf(const LWTRIANGLE *triangle, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1348
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:89
uint8_t flags
Definition: liblwgeom.h:407
int lwline_is_empty(const LWLINE *line)
Definition: lwline.c:511
static char * asgml3_collection(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1731
static size_t asgml2_point_buf(const LWPOINT *point, const char *srs, char *output, int precision, const char *prefix)
Definition: lwout_gml.c:283
char * lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:717
#define MULTISURFACETYPE
Definition: liblwgeom.h:95
static size_t asgml3_curvepoly_buf(const LWCURVEPOLY *poly, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1239
LWGEOM ** geoms
Definition: liblwgeom.h:560
static char * asgml2_point(const LWPOINT *point, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:303
double zmin
Definition: liblwgeom.h:295
static size_t asgml2_poly_buf(const LWPOLY *poly, const char *srs, char *output, int precision, const char *prefix)
Definition: lwout_gml.c:382
LWGEOM ** geoms
Definition: liblwgeom.h:547
static size_t pointArray_toGML3(POINTARRAY *pa, char *buf, int precision, int opts)
Definition: lwout_gml.c:1890
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:84
int ptarray_remove_point(POINTARRAY *pa, uint32_t where)
Remove a point from an existing POINTARRAY.
Definition: ptarray.c:261
int lwpoint_is_empty(const LWPOINT *point)
Definition: lwpoint.c:291
static size_t asgml2_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, const char *prefix)
Definition: lwout_gml.c:592
uint8_t type
Definition: liblwgeom.h:395
static size_t asgml3_circstring_size(const LWCIRCSTRING *circ, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:930
POINTARRAY * points
Definition: liblwgeom.h:443
uint32_t nrings
Definition: liblwgeom.h:532
#define OUT_DOUBLE_BUFFER_SIZE
static size_t asgml2_collection_size(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:546
uint8_t flags
Definition: liblwgeom.h:451
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:91
static size_t pointArray_toGML2(POINTARRAY *pa, char *buf, int precision)
Definition: lwout_gml.c:662
void * lwalloc(size_t size)
Definition: lwutil.c:229
#define OUT_MAX_DIGS_DOUBLE
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:1386
static size_t asgml2_line_buf(const LWLINE *line, const char *srs, char *output, int precision, const char *prefix)
Definition: lwout_gml.c:327
uint32_t ngeoms
Definition: liblwgeom.h:545
static char * asgml2_multi(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:529
double y
Definition: liblwgeom.h:351
#define MULTILINETYPE
Definition: liblwgeom.h:88
uint32_t ngeoms
Definition: liblwgeom.h:584
uint8_t flags
Definition: liblwgeom.h:418
static char * asgml3_curvepoly(const LWCURVEPOLY *poly, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1318
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:151
char * lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:198
static char * asgml2_poly(const LWPOLY *poly, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:412
static char * gbox_to_gml2(const GBOX *bbox, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:75
static size_t asgml3_multicurve_size(const LWMCURVE *cur, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1742
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
tuple y
Definition: pixval.py:54
static size_t asgml3_multi_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1391
if(!(yy_init))
Definition: lwin_wkt_lex.c:888
static size_t asgml3_line_buf(const LWLINE *line, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:855
static char * asgml3_tin(const LWTIN *tin, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1620
#define COLLECTIONTYPE
Definition: liblwgeom.h:90
static char * asgml3_circstring(const LWCIRCSTRING *circ, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:982
static size_t asgml3_psurface_buf(const LWPSURFACE *psur, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1526
uint8_t flags
Definition: liblwgeom.h:429
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
Definition: lwgeom_api.c:364
POINTARRAY * points
Definition: liblwgeom.h:421
static char * gbox_to_gml3(const GBOX *bbox, const char *srs, int precision, int opts, const char *prefix)
Definition: lwout_gml.c:130
uint32_t npoints
Definition: liblwgeom.h:370