PostGIS  2.3.7dev-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  int 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  int 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  int 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  int 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  int 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  int 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  int i;
665  char *ptr;
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 
679  if (fabs(pt->x) < OUT_MAX_DOUBLE)
680  sprintf(x, "%.*f", precision, pt->x);
681  else
682  sprintf(x, "%g", pt->x);
684 
685  if (fabs(pt->y) < OUT_MAX_DOUBLE)
686  sprintf(y, "%.*f", precision, pt->y);
687  else
688  sprintf(y, "%g", pt->y);
690 
691  if ( i ) ptr += sprintf(ptr, " ");
692  ptr += sprintf(ptr, "%s,%s", x, y);
693  }
694  }
695  else
696  {
697  for (i=0; i<pa->npoints; i++)
698  {
699  const POINT3DZ *pt;
700  pt = getPoint3dz_cp(pa, i);
701 
702  if (fabs(pt->x) < OUT_MAX_DOUBLE)
703  sprintf(x, "%.*f", precision, pt->x);
704  else
705  sprintf(x, "%g", pt->x);
707 
708  if (fabs(pt->y) < OUT_MAX_DOUBLE)
709  sprintf(y, "%.*f", precision, pt->y);
710  else
711  sprintf(y, "%g", pt->y);
713 
714  if (fabs(pt->z) < OUT_MAX_DOUBLE)
715  sprintf(z, "%.*f", precision, pt->z);
716  else
717  sprintf(z, "%g", pt->z);
719 
720  if ( i ) ptr += sprintf(ptr, " ");
721  ptr += sprintf(ptr, "%s,%s,%s", x, y, z);
722  }
723  }
724 
725  return ptr-output;
726 }
727 
728 
729 /*
730  * VERSION GML 3.1.1
731  */
732 
733 
734 /* takes a GEOMETRY and returns a GML representation */
735 extern char *
736 lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id)
737 {
738  int type = geom->type;
739 
740  /* Return null for empty (#1377) */
741  if ( lwgeom_is_empty(geom) )
742  return NULL;
743 
744  switch (type)
745  {
746  case POINTTYPE:
747  return asgml3_point((LWPOINT*)geom, srs, precision, opts, prefix, id);
748 
749  case LINETYPE:
750  return asgml3_line((LWLINE*)geom, srs, precision, opts, prefix, id);
751 
752  case CIRCSTRINGTYPE:
753  return asgml3_circstring((LWCIRCSTRING*)geom, srs, precision, opts, prefix, id );
754 
755  case POLYGONTYPE:
756  return asgml3_poly((LWPOLY*)geom, srs, precision, opts, 0, prefix, id);
757 
758  case CURVEPOLYTYPE:
759  return asgml3_curvepoly((LWCURVEPOLY*)geom, srs, precision, opts, prefix, id);
760 
761  case TRIANGLETYPE:
762  return asgml3_triangle((LWTRIANGLE*)geom, srs, precision, opts, prefix, id);
763 
764  case MULTIPOINTTYPE:
765  case MULTILINETYPE:
766  case MULTIPOLYGONTYPE:
767  return asgml3_multi((LWCOLLECTION*)geom, srs, precision, opts, prefix, id);
768 
770  return asgml3_psurface((LWPSURFACE*)geom, srs, precision, opts, prefix, id);
771 
772  case TINTYPE:
773  return asgml3_tin((LWTIN*)geom, srs, precision, opts, prefix, id);
774 
775  case COLLECTIONTYPE:
776  return asgml3_collection((LWCOLLECTION*)geom, srs, precision, opts, prefix, id);
777 
778  case COMPOUNDTYPE:
779  return asgml3_compound( (LWCOMPOUND*)geom, srs, precision, opts, prefix, id );
780 
781  case MULTICURVETYPE:
782  return asgml3_multicurve( (LWMCURVE*)geom, srs, precision, opts, prefix, id );
783 
784  case MULTISURFACETYPE:
785  return asgml3_multisurface( (LWMSURFACE*)geom, srs, precision, opts, prefix, id );
786 
787  default:
788  lwerror("lwgeom_to_gml3: '%s' geometry type not supported", lwtype_name(type));
789  return NULL;
790  }
791 }
792 
793 static size_t
794 asgml3_point_size(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id)
795 {
796  int size;
797  size_t prefixlen = strlen(prefix);
798 
799  size = pointArray_GMLsize(point->point, precision);
800  size += ( sizeof("<point><pos>/") + (prefixlen*2) ) * 2;
801  if (srs) size += strlen(srs) + sizeof(" srsName=..");
802  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
803  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'");
804  return size;
805 }
806 
807 static size_t
808 asgml3_point_buf(const LWPOINT *point, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
809 {
810  char *ptr = output;
811  int dimension=2;
812 
813  if (FLAGS_GET_Z(point->flags)) dimension = 3;
814 
815  ptr += sprintf(ptr, "<%sPoint", prefix);
816  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
817  if ( id ) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
818  if ( lwpoint_is_empty(point) )
819  {
820  ptr += sprintf(ptr, "/>");
821  return (ptr-output);
822  }
823 
824  ptr += sprintf(ptr, ">");
825  if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%spos srsDimension=\"%d\">", prefix, dimension);
826  else ptr += sprintf(ptr, "<%spos>", prefix);
827  ptr += pointArray_toGML3(point->point, ptr, precision, opts);
828  ptr += sprintf(ptr, "</%spos></%sPoint>", prefix, prefix);
829 
830  return (ptr-output);
831 }
832 
833 static char *
834 asgml3_point(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id)
835 {
836  char *output;
837  int size;
838 
839  size = asgml3_point_size(point, srs, precision, opts, prefix, id);
840  output = lwalloc(size);
841  asgml3_point_buf(point, srs, output, precision, opts, prefix, id);
842  return output;
843 }
844 
845 
846 static size_t
847 asgml3_line_size(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id)
848 {
849  int size;
850  size_t prefixlen = strlen(prefix);
851 
852  size = pointArray_GMLsize(line->points, precision);
853  if ( opts & LW_GML_SHORTLINE )
854  {
855  size += (
856  sizeof("<LineString><posList>/") +
857  ( prefixlen * 2 )
858  ) * 2;
859  }
860  else
861  {
862  size += (
863  sizeof("<Curve><segments><LineStringSegment><posList>/") +
864  ( prefixlen * 4 )
865  ) * 2;
866  }
867  if (srs) size += strlen(srs) + sizeof(" srsName=..");
868  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
869  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'");
870  return size;
871 }
872 
873 static size_t
874 asgml3_line_buf(const LWLINE *line, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
875 {
876  char *ptr=output;
877  int dimension=2;
878  int shortline = ( opts & LW_GML_SHORTLINE );
879 
880  if (FLAGS_GET_Z(line->flags)) dimension = 3;
881 
882  if ( shortline )
883  {
884  ptr += sprintf(ptr, "<%sLineString", prefix);
885  }
886  else
887  {
888  ptr += sprintf(ptr, "<%sCurve", prefix);
889  }
890 
891  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
892  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
893 
894  if ( lwline_is_empty(line) )
895  {
896  ptr += sprintf(ptr, "/>");
897  return (ptr-output);
898  }
899  ptr += sprintf(ptr, ">");
900 
901  if ( ! shortline )
902  {
903  ptr += sprintf(ptr, "<%ssegments>", prefix);
904  ptr += sprintf(ptr, "<%sLineStringSegment>", prefix);
905  }
906 
907  if (IS_DIMS(opts))
908  {
909  ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">",
910  prefix, dimension);
911  }
912  else
913  {
914  ptr += sprintf(ptr, "<%sposList>", prefix);
915  }
916 
917  ptr += pointArray_toGML3(line->points, ptr, precision, opts);
918 
919  ptr += sprintf(ptr, "</%sposList>", prefix);
920 
921  if ( shortline )
922  {
923  ptr += sprintf(ptr, "</%sLineString>", prefix);
924  }
925  else
926  {
927  ptr += sprintf(ptr, "</%sLineStringSegment>", prefix);
928  ptr += sprintf(ptr, "</%ssegments>", prefix);
929  ptr += sprintf(ptr, "</%sCurve>", prefix);
930  }
931 
932  return (ptr-output);
933 }
934 
935 static char *
936 asgml3_line(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id)
937 {
938  char *output;
939  int size;
940 
941  size = asgml3_line_size(line, srs, precision, opts, prefix, id);
942  output = lwalloc(size);
943  asgml3_line_buf(line, srs, output, precision, opts, prefix, id);
944  return output;
945 }
946 
947 
948 static size_t
949 asgml3_circstring_size(const LWCIRCSTRING *circ, const char *srs, int precision, int opts, const char *prefix, const char *id)
950 {
951  int size = pointArray_GMLsize( circ->points, precision );
952  size_t prefixlen = strlen(prefix);
953  size += 2 * ( sizeof( "<Curve><segments>/" ) + 2 * prefixlen );
954  size += 2 * ( sizeof( "<ArcString><posList>/" ) + 2 * prefixlen );
955  if (srs) size += strlen(srs) + sizeof(" srsName=..");
956  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
957  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'");
958  return size;
959 }
960 
961 static size_t
962 asgml3_circstring_buf(const LWCIRCSTRING *circ, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
963 {
964  char* ptr = output;
965  int dimension=2;
966 
967  if (FLAGS_GET_Z(circ->flags))
968  {
969  dimension = 3;
970  }
971 
972  ptr += sprintf(ptr, "<%sCurve", prefix);
973  if (srs)
974  {
975  ptr += sprintf(ptr, " srsName=\"%s\"", srs);
976  }
977  if (id)
978  {
979  ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
980  }
981  ptr += sprintf(ptr, ">");
982  ptr += sprintf(ptr, "<%ssegments>", prefix);
983  ptr += sprintf(ptr, "<%sArcString>", prefix);
984  ptr += sprintf(ptr, "<%sposList", prefix);
985 
986  if (IS_DIMS(opts))
987  {
988  ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension);
989  }
990  ptr += sprintf(ptr, ">");
991 
992  ptr += pointArray_toGML3(circ->points, ptr, precision, opts);
993  ptr += sprintf(ptr, "</%sposList>", prefix);
994  ptr += sprintf(ptr, "</%sArcString>", prefix);
995  ptr += sprintf(ptr, "</%ssegments>", prefix);
996  ptr += sprintf(ptr, "</%sCurve>", prefix);
997  return (ptr-output);
998 }
999 
1000 static char *
1001 asgml3_circstring( const LWCIRCSTRING *circ, const char *srs, int precision, int opts, const char *prefix, const char *id )
1002 {
1003  char *output;
1004  int size;
1005 
1006  size = asgml3_circstring_size(circ, srs, precision, opts, prefix, id);
1007  output = lwalloc( size );
1008  asgml3_circstring_buf(circ, srs, output, precision, opts, prefix, id);
1009  return output;
1010 }
1011 
1012 
1013 static size_t
1014 asgml3_poly_size(const LWPOLY *poly, const char *srs, int precision, int opts, const char *prefix, const char *id)
1015 {
1016  size_t size;
1017  size_t prefixlen = strlen(prefix);
1018  int i;
1019 
1020  size = ( sizeof("<PolygonPatch><exterior><LinearRing>///") + (prefixlen*3) ) * 2;
1021  size += ( sizeof("<interior><LinearRing>//") + (prefixlen*2) ) * 2 * (poly->nrings - 1);
1022  size += ( sizeof("<posList></posList>") + (prefixlen*2) ) * poly->nrings;
1023  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1024  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1025  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'") * poly->nrings;
1026 
1027  for (i=0; i<poly->nrings; i++)
1028  size += pointArray_GMLsize(poly->rings[i], precision);
1029 
1030  return size;
1031 }
1032 
1033 static size_t
1034 asgml3_poly_buf(const LWPOLY *poly, const char *srs, char *output, int precision, int opts, int is_patch, const char *prefix, const char *id)
1035 {
1036  int i;
1037  char *ptr=output;
1038  int dimension=2;
1039 
1040  if (FLAGS_GET_Z(poly->flags)) dimension = 3;
1041  if (is_patch)
1042  {
1043  ptr += sprintf(ptr, "<%sPolygonPatch", prefix);
1044 
1045  }
1046  else
1047  {
1048  ptr += sprintf(ptr, "<%sPolygon", prefix);
1049  }
1050 
1051  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1052  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1053 
1054  if ( lwpoly_is_empty(poly) )
1055  {
1056  ptr += sprintf(ptr, "/>");
1057  return (ptr-output);
1058  }
1059  ptr += sprintf(ptr, ">");
1060 
1061  ptr += sprintf(ptr, "<%sexterior><%sLinearRing>", prefix, prefix);
1062  if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">", prefix, dimension);
1063  else ptr += sprintf(ptr, "<%sposList>", prefix);
1064 
1065  ptr += pointArray_toGML3(poly->rings[0], ptr, precision, opts);
1066  ptr += sprintf(ptr, "</%sposList></%sLinearRing></%sexterior>",
1067  prefix, prefix, prefix);
1068  for (i=1; i<poly->nrings; i++)
1069  {
1070  ptr += sprintf(ptr, "<%sinterior><%sLinearRing>", prefix, prefix);
1071  if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">", prefix, dimension);
1072  else ptr += sprintf(ptr, "<%sposList>", prefix);
1073  ptr += pointArray_toGML3(poly->rings[i], ptr, precision, opts);
1074  ptr += sprintf(ptr, "</%sposList></%sLinearRing></%sinterior>",
1075  prefix, prefix, prefix);
1076  }
1077  if (is_patch) ptr += sprintf(ptr, "</%sPolygonPatch>", prefix);
1078  else ptr += sprintf(ptr, "</%sPolygon>", prefix);
1079 
1080  return (ptr-output);
1081 }
1082 
1083 static char *
1084 asgml3_poly(const LWPOLY *poly, const char *srs, int precision, int opts, int is_patch, const char *prefix, const char *id)
1085 {
1086  char *output;
1087  int size;
1088 
1089  size = asgml3_poly_size(poly, srs, precision, opts, prefix, id);
1090  output = lwalloc(size);
1091  asgml3_poly_buf(poly, srs, output, precision, opts, is_patch, prefix, id);
1092  return output;
1093 }
1094 
1095 static size_t
1096 asgml3_compound_size(const LWCOMPOUND *col, const char *srs, int precision, int opts, const char *prefix, const char *id )
1097 {
1098  int i;
1099  size_t size;
1100  LWGEOM *subgeom;
1101  size_t prefixlen = strlen(prefix);
1102 
1103  size = ( sizeof( "<Curve></Curve>" ) + 2 * prefixlen );
1104 
1105  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1106  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1107 
1108  size += ( sizeof("<segments></segments>") + 2 * prefixlen );
1109 
1110  for(i= 0; i < col->ngeoms; ++i )
1111  {
1112  subgeom = col->geoms[i];
1113  if ( subgeom->type == LINETYPE )
1114  {
1115 
1116  size += sizeof( "<LineStringSegment></LineStringSegment" ) + 2 * prefixlen;
1117  size += sizeof( "<posList></posList" ) + 2 * prefixlen;
1118  size += pointArray_GMLsize( ((LWLINE*)subgeom)->points, precision );
1119  }
1120  else if( subgeom->type == CIRCSTRINGTYPE )
1121  {
1122  size += sizeof( "<ArcString><posList></ArcString></posList>") + 4 * prefixlen;
1123  size += pointArray_GMLsize( ((LWCIRCSTRING*)subgeom)->points, precision );
1124  }
1125  else
1126  {
1127  continue;
1128  }
1129  if (IS_DIMS(opts))
1130  {
1131  size += sizeof(" srsDimension='x'");
1132  }
1133  }
1134  return size;
1135 }
1136 
1137 static size_t
1138 asgml3_compound_buf(const LWCOMPOUND *col, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1139 {
1140  LWGEOM *subgeom;
1141  int i;
1142  char* ptr = output;
1143  int dimension=2;
1144 
1145  if (FLAGS_GET_Z(col->flags))
1146  {
1147  dimension = 3;
1148  }
1149 
1150  ptr += sprintf( ptr, "<%sCurve", prefix );
1151  if (srs)
1152  {
1153  ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1154  }
1155  if (id)
1156  {
1157  ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id );
1158  }
1159  ptr += sprintf( ptr, ">" );
1160  ptr += sprintf( ptr, "<%ssegments>", prefix );
1161 
1162  for( i = 0; i < col->ngeoms; ++i )
1163  {
1164  subgeom = col->geoms[i];
1165  if( subgeom->type != LINETYPE && subgeom->type != CIRCSTRINGTYPE )
1166  {
1167  continue;
1168  }
1169 
1170  if ( subgeom->type == LINETYPE )
1171  {
1172  ptr += sprintf( ptr, "<%sLineStringSegment><%sposList", prefix, prefix );
1173  if (IS_DIMS(opts))
1174  {
1175  ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension);
1176  }
1177  ptr += sprintf(ptr, ">");
1178  ptr += pointArray_toGML3(((LWCIRCSTRING*)subgeom)->points, ptr, precision, opts);
1179  ptr += sprintf( ptr, "</%sposList></%sLineStringSegment>", prefix, prefix );
1180  }
1181  else if( subgeom->type == CIRCSTRINGTYPE )
1182  {
1183  ptr += sprintf( ptr, "<%sArcString><%sposList" , prefix, prefix );
1184  if (IS_DIMS(opts))
1185  {
1186  ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension);
1187  }
1188  ptr += sprintf(ptr, ">");
1189  ptr += pointArray_toGML3(((LWLINE*)subgeom)->points, ptr, precision, opts);
1190  ptr += sprintf( ptr, "</%sposList></%sArcString>", prefix, prefix );
1191  }
1192  }
1193 
1194  ptr += sprintf( ptr, "</%ssegments>", prefix );
1195  ptr += sprintf( ptr, "</%sCurve>", prefix );
1196  return ( ptr - output );
1197 }
1198 
1199 static char *
1200 asgml3_compound(const LWCOMPOUND *col, const char *srs, int precision, int opts, const char *prefix, const char *id )
1201 {
1202  char* gml;
1203  size_t size;
1204 
1205  size = asgml3_compound_size( col, srs, precision, opts, prefix, id );
1206  gml = lwalloc( size );
1207  asgml3_compound_buf( col, srs, gml, precision, opts, prefix, id );
1208  return gml;
1209 }
1210 
1211 static size_t asgml3_curvepoly_size(const LWCURVEPOLY* poly, const char *srs, int precision, int opts, const char *prefix, const char *id)
1212 {
1213  size_t prefixlen = strlen(prefix);
1214  LWGEOM* subgeom;
1215  size_t size = sizeof( "<Polygon></Polygon" ) + 2 * prefixlen;
1216  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1217  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1218  int i;
1219 
1220  for( i = 0; i < poly->nrings; ++i )
1221  {
1222  if( i == 0 )
1223  {
1224  size += sizeof( "<exterior></exterior>" ) + 2 * prefixlen;
1225  }
1226  else
1227  {
1228  size += sizeof( "<interior></interior>" ) + 2 * prefixlen;
1229  }
1230  subgeom = poly->rings[i];
1231 
1232  if ( subgeom->type == LINETYPE )
1233  {
1234  size += sizeof("<LinearRing></LinearRing>") + 2 * prefixlen;
1235  size += sizeof("<posList></posList") + 2 * prefixlen;
1236  if (IS_DIMS(opts))
1237  {
1238  size += sizeof(" srsDimension='x'");
1239  }
1240  size += pointArray_GMLsize( ((LWLINE*)subgeom)->points, precision );
1241  }
1242  else if( subgeom->type == CIRCSTRINGTYPE )
1243  {
1244  size += sizeof("<Ring></Ring>") + 2 * prefixlen;
1245  size += sizeof("<CurveMember></CurveMember>") + 2 * prefixlen;
1246  size += asgml3_circstring_size((LWCIRCSTRING*)subgeom, srs, precision, opts, prefix, id);
1247  }
1248  else if( subgeom->type == COMPOUNDTYPE )
1249  {
1250  size += sizeof("<Ring></Ring>") + 2 * prefixlen;
1251  size += sizeof("<curveMember></curveMember>") + 2 * prefixlen;
1252  size += asgml3_compound_size( (LWCOMPOUND*)subgeom, srs, precision, opts, prefix, id );
1253  }
1254  }
1255  return size;
1256 }
1257 
1258 static size_t asgml3_curvepoly_buf(const LWCURVEPOLY* poly, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1259 {
1260  int i;
1261  LWGEOM* subgeom;
1262  char *ptr=output;
1263  int dimension=2;
1264 
1265  if (FLAGS_GET_Z(poly->flags))
1266  {
1267  dimension = 3;
1268  }
1269 
1270  ptr += sprintf( ptr, "<%sPolygon", prefix );
1271  if (srs)
1272  {
1273  ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1274  }
1275  if (id)
1276  {
1277  ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id );
1278  }
1279  ptr += sprintf(ptr, ">");
1280 
1281  for( i = 0; i < poly->nrings; ++i )
1282  {
1283  if( i == 0 )
1284  {
1285  ptr += sprintf( ptr, "<%sexterior>", prefix);
1286  }
1287  else
1288  {
1289  ptr += sprintf( ptr, "<%sinterior>", prefix);
1290  }
1291 
1292  subgeom = poly->rings[i];
1293  if ( subgeom->type == LINETYPE )
1294  {
1295  ptr += sprintf( ptr, "<%sLinearRing>", prefix );
1296  ptr += sprintf( ptr, "<%sposList", prefix );
1297  if (IS_DIMS(opts))
1298  {
1299  ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension);
1300  }
1301  ptr += sprintf( ptr, ">" );
1302  ptr += pointArray_toGML3(((LWLINE*)subgeom)->points, ptr, precision, opts);
1303  ptr += sprintf( ptr, "</%sposList>", prefix );
1304  ptr += sprintf( ptr, "</%sLinearRing>", prefix );
1305  }
1306  else if( subgeom->type == CIRCSTRINGTYPE )
1307  {
1308  ptr += sprintf( ptr, "<%sRing>", prefix );
1309  ptr += sprintf( ptr, "<%scurveMember>", prefix );
1310  ptr += asgml3_circstring_buf( (LWCIRCSTRING*)subgeom, srs, ptr, precision, opts, prefix, id );
1311  ptr += sprintf( ptr, "</%scurveMember>", prefix );
1312  ptr += sprintf( ptr, "</%sRing>", prefix );
1313  }
1314  else if( subgeom->type == COMPOUNDTYPE )
1315  {
1316  ptr += sprintf( ptr, "<%sRing>", prefix );
1317  ptr += sprintf( ptr, "<%scurveMember>", prefix );
1318  ptr += asgml3_compound_buf( (LWCOMPOUND*)subgeom, srs, ptr, precision, opts, prefix, id );
1319  ptr += sprintf( ptr, "</%scurveMember>", prefix );
1320  ptr += sprintf( ptr, "</%sRing>", prefix );
1321  }
1322 
1323  if( i == 0 )
1324  {
1325  ptr += sprintf( ptr, "</%sexterior>", prefix);
1326  }
1327  else
1328  {
1329  ptr += sprintf( ptr, "</%sinterior>", prefix);
1330  }
1331  }
1332 
1333  ptr += sprintf( ptr, "</%sPolygon>", prefix );
1334  return (ptr - output);
1335 }
1336 
1337 static char* asgml3_curvepoly(const LWCURVEPOLY* poly, const char *srs, int precision, int opts, const char *prefix, const char *id)
1338 {
1339  char* gml;
1340  size_t size;
1341 
1342  size = asgml3_curvepoly_size( poly, srs, precision, opts, prefix, id );
1343  gml = lwalloc( size );
1344  asgml3_curvepoly_buf( poly, srs, gml, precision, opts, prefix, id );
1345  return gml;
1346 }
1347 
1348 
1349 static size_t
1350 asgml3_triangle_size(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id)
1351 {
1352  size_t size;
1353  size_t prefixlen = strlen(prefix);
1354 
1355  size = ( sizeof("<Triangle><exterior><LinearRing>///") + (prefixlen*3) ) * 2;
1356  size += sizeof("<posList></posList>") + (prefixlen*2);
1357  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1358  if (id) size += strlen(prefix) + strlen(id) + sizeof(" id=..");
1359  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'");
1360 
1361  size += pointArray_GMLsize(triangle->points, precision);
1362 
1363  return size;
1364 }
1365 
1366 static size_t
1367 asgml3_triangle_buf(const LWTRIANGLE *triangle, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1368 {
1369  char *ptr=output;
1370  int dimension=2;
1371 
1372  if (FLAGS_GET_Z(triangle->flags)) dimension = 3;
1373  ptr += sprintf(ptr, "<%sTriangle", prefix);
1374  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1375  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1376  ptr += sprintf(ptr, ">");
1377 
1378  ptr += sprintf(ptr, "<%sexterior><%sLinearRing>", prefix, prefix);
1379  if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">", prefix, dimension);
1380  else ptr += sprintf(ptr, "<%sposList>", prefix);
1381 
1382  ptr += pointArray_toGML3(triangle->points, ptr, precision, opts);
1383  ptr += sprintf(ptr, "</%sposList></%sLinearRing></%sexterior>",
1384  prefix, prefix, prefix);
1385 
1386  ptr += sprintf(ptr, "</%sTriangle>", prefix);
1387 
1388  return (ptr-output);
1389 }
1390 
1391 static char *
1392 asgml3_triangle(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id)
1393 {
1394  char *output;
1395  int size;
1396 
1397  size = asgml3_triangle_size(triangle, srs, precision, opts, prefix, id);
1398  output = lwalloc(size);
1399  asgml3_triangle_buf(triangle, srs, output, precision, opts, prefix, id);
1400  return output;
1401 }
1402 
1403 
1404 /*
1405  * Compute max size required for GML version of this
1406  * inspected geometry. Will recurse when needed.
1407  * Don't call this with single-geoms inspected.
1408  */
1409 static size_t
1410 asgml3_multi_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
1411 {
1412  int i;
1413  size_t size;
1414  size_t prefixlen = strlen(prefix);
1415  LWGEOM *subgeom;
1416 
1417  /* the longest possible multi version */
1418  size = sizeof("<MultiLineString></MultiLineString>") + prefixlen*2;
1419 
1420  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1421  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1422 
1423  for (i=0; i<col->ngeoms; i++)
1424  {
1425  subgeom = col->geoms[i];
1426  if (subgeom->type == POINTTYPE)
1427  {
1428  size += ( sizeof("<pointMember>/") + prefixlen ) * 2;
1429  size += asgml3_point_size((LWPOINT*)subgeom, 0, precision, opts, prefix, id);
1430  }
1431  else if (subgeom->type == LINETYPE)
1432  {
1433  size += ( sizeof("<curveMember>/") + prefixlen ) * 2;
1434  size += asgml3_line_size((LWLINE*)subgeom, 0, precision, opts, prefix, id);
1435  }
1436  else if (subgeom->type == POLYGONTYPE)
1437  {
1438  size += ( sizeof("<surfaceMember>/") + prefixlen ) * 2;
1439  size += asgml3_poly_size((LWPOLY*)subgeom, 0, precision, opts, prefix, id);
1440  }
1441  }
1442 
1443  return size;
1444 }
1445 
1446 /*
1447  * Don't call this with single-geoms inspected!
1448  */
1449 static size_t
1450 asgml3_multi_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1451 {
1452  int type = col->type;
1453  char *ptr, *gmltype;
1454  int i;
1455  LWGEOM *subgeom;
1456 
1457  ptr = output;
1458  gmltype="";
1459 
1460  if (type == MULTIPOINTTYPE) gmltype = "MultiPoint";
1461  else if (type == MULTILINETYPE) gmltype = "MultiCurve";
1462  else if (type == MULTIPOLYGONTYPE) gmltype = "MultiSurface";
1463 
1464  /* Open outmost tag */
1465  ptr += sprintf(ptr, "<%s%s", prefix, gmltype);
1466  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1467  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1468 
1469  if (!col->ngeoms)
1470  {
1471  ptr += sprintf(ptr, "/>");
1472  return (ptr-output);
1473  }
1474  ptr += sprintf(ptr, ">");
1475 
1476  for (i=0; i<col->ngeoms; i++)
1477  {
1478  subgeom = col->geoms[i];
1479  if (subgeom->type == POINTTYPE)
1480  {
1481  ptr += sprintf(ptr, "<%spointMember>", prefix);
1482  ptr += asgml3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, prefix, id);
1483  ptr += sprintf(ptr, "</%spointMember>", prefix);
1484  }
1485  else if (subgeom->type == LINETYPE)
1486  {
1487  ptr += sprintf(ptr, "<%scurveMember>", prefix);
1488  ptr += asgml3_line_buf((LWLINE*)subgeom, 0, ptr, precision, opts, prefix, id);
1489  ptr += sprintf(ptr, "</%scurveMember>", prefix);
1490  }
1491  else if (subgeom->type == POLYGONTYPE)
1492  {
1493  ptr += sprintf(ptr, "<%ssurfaceMember>", prefix);
1494  ptr += asgml3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, prefix, id);
1495  ptr += sprintf(ptr, "</%ssurfaceMember>", prefix);
1496  }
1497  }
1498 
1499  /* Close outmost tag */
1500  ptr += sprintf(ptr, "</%s%s>", prefix, gmltype);
1501 
1502  return (ptr-output);
1503 }
1504 
1505 /*
1506  * Don't call this with single-geoms inspected!
1507  */
1508 static char *
1509 asgml3_multi(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
1510 {
1511  char *gml;
1512  size_t size;
1513 
1514  size = asgml3_multi_size(col, srs, precision, opts, prefix, id);
1515  gml = lwalloc(size);
1516  asgml3_multi_buf(col, srs, gml, precision, opts, prefix, id);
1517  return gml;
1518 }
1519 
1520 
1521 static size_t
1522 asgml3_psurface_size(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *prefix, const char *id)
1523 {
1524  int i;
1525  size_t size;
1526  size_t prefixlen = strlen(prefix);
1527 
1528  size = (sizeof("<PolyhedralSurface><polygonPatches>/") + prefixlen*2) * 2;
1529  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1530  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1531 
1532  for (i=0; i<psur->ngeoms; i++)
1533  {
1534  size += asgml3_poly_size(psur->geoms[i], 0, precision, opts, prefix, id);
1535  }
1536 
1537  return size;
1538 }
1539 
1540 
1541 /*
1542  * Don't call this with single-geoms inspected!
1543  */
1544 static size_t
1545 asgml3_psurface_buf(const LWPSURFACE *psur, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1546 {
1547  char *ptr;
1548  int i;
1549 
1550  ptr = output;
1551 
1552  /* Open outmost tag */
1553  ptr += sprintf(ptr, "<%sPolyhedralSurface", prefix);
1554  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1555  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1556  ptr += sprintf(ptr, "><%spolygonPatches>", prefix);
1557 
1558  for (i=0; i<psur->ngeoms; i++)
1559  {
1560  ptr += asgml3_poly_buf(psur->geoms[i], 0, ptr, precision, opts, 1, prefix, id);
1561  }
1562 
1563  /* Close outmost tag */
1564  ptr += sprintf(ptr, "</%spolygonPatches></%sPolyhedralSurface>",
1565  prefix, prefix);
1566 
1567  return (ptr-output);
1568 }
1569 
1570 /*
1571  * Don't call this with single-geoms inspected!
1572  */
1573 static char *
1574 asgml3_psurface(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *prefix, const char *id)
1575 {
1576  char *gml;
1577  size_t size;
1578 
1579  size = asgml3_psurface_size(psur, srs, precision, opts, prefix, id);
1580  gml = lwalloc(size);
1581  asgml3_psurface_buf(psur, srs, gml, precision, opts, prefix, id);
1582  return gml;
1583 }
1584 
1585 
1586 static size_t
1587 asgml3_tin_size(const LWTIN *tin, const char *srs, int precision, int opts, const char *prefix, const char *id)
1588 {
1589  int i;
1590  size_t size;
1591  size_t prefixlen = strlen(prefix);
1592 
1593  size = (sizeof("<Tin><trianglePatches>/") + prefixlen*2) * 2;
1594  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1595  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1596 
1597  for (i=0; i<tin->ngeoms; i++)
1598  {
1599  size += asgml3_triangle_size(tin->geoms[i], 0, precision, opts, prefix, id);
1600  }
1601 
1602  return size;
1603 }
1604 
1605 
1606 /*
1607  * Don't call this with single-geoms inspected!
1608  */
1609 static size_t
1610 asgml3_tin_buf(const LWTIN *tin, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1611 {
1612  char *ptr;
1613  int i;
1614 
1615  ptr = output;
1616 
1617  /* Open outmost tag */
1618  ptr += sprintf(ptr, "<%sTin", prefix);
1619  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1620  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1621  else ptr += sprintf(ptr, "><%strianglePatches>", prefix);
1622 
1623  for (i=0; i<tin->ngeoms; i++)
1624  {
1625  ptr += asgml3_triangle_buf(tin->geoms[i], 0, ptr, precision,
1626  opts, prefix, id);
1627  }
1628 
1629  /* Close outmost tag */
1630  ptr += sprintf(ptr, "</%strianglePatches></%sTin>", prefix, prefix);
1631 
1632  return (ptr-output);
1633 }
1634 
1635 /*
1636  * Don't call this with single-geoms inspected!
1637  */
1638 static char *
1639 asgml3_tin(const LWTIN *tin, const char *srs, int precision, int opts, const char *prefix, const char *id)
1640 {
1641  char *gml;
1642  size_t size;
1643 
1644  size = asgml3_tin_size(tin, srs, precision, opts, prefix, id);
1645  gml = lwalloc(size);
1646  asgml3_tin_buf(tin, srs, gml, precision, opts, prefix, id);
1647  return gml;
1648 }
1649 
1650 static size_t
1651 asgml3_collection_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
1652 {
1653  int i;
1654  size_t size;
1655  size_t prefixlen = strlen(prefix);
1656  LWGEOM *subgeom;
1657 
1658  size = sizeof("<MultiGeometry></MultiGeometry>") + prefixlen*2;
1659 
1660  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1661  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1662 
1663  for (i=0; i<col->ngeoms; i++)
1664  {
1665  subgeom = col->geoms[i];
1666  size += ( sizeof("<geometryMember>/") + prefixlen ) * 2;
1667  if ( subgeom->type == POINTTYPE )
1668  {
1669  size += asgml3_point_size((LWPOINT*)subgeom, 0, precision, opts, prefix, id);
1670  }
1671  else if ( subgeom->type == LINETYPE )
1672  {
1673  size += asgml3_line_size((LWLINE*)subgeom, 0, precision, opts, prefix, id);
1674  }
1675  else if ( subgeom->type == POLYGONTYPE )
1676  {
1677  size += asgml3_poly_size((LWPOLY*)subgeom, 0, precision, opts, prefix, id);
1678  }
1679  else if ( lwgeom_is_collection(subgeom) )
1680  {
1681  size += asgml3_multi_size((LWCOLLECTION*)subgeom, 0, precision, opts, prefix, id);
1682  }
1683  else
1684  lwerror("asgml3_collection_size: unknown geometry type");
1685  }
1686 
1687  return size;
1688 }
1689 
1690 static size_t
1691 asgml3_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1692 {
1693  char *ptr;
1694  int i;
1695  LWGEOM *subgeom;
1696 
1697  ptr = output;
1698 
1699  /* Open outmost tag */
1700  ptr += sprintf(ptr, "<%sMultiGeometry", prefix);
1701  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1702  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1703 
1704  if (!col->ngeoms)
1705  {
1706  ptr += sprintf(ptr, "/>");
1707  return (ptr-output);
1708  }
1709  ptr += sprintf(ptr, ">");
1710 
1711  for (i=0; i<col->ngeoms; i++)
1712  {
1713  subgeom = col->geoms[i];
1714  ptr += sprintf(ptr, "<%sgeometryMember>", prefix);
1715  if ( subgeom->type == POINTTYPE )
1716  {
1717  ptr += asgml3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, prefix, id);
1718  }
1719  else if ( subgeom->type == LINETYPE )
1720  {
1721  ptr += asgml3_line_buf((LWLINE*)subgeom, 0, ptr, precision, opts, prefix, id);
1722  }
1723  else if ( subgeom->type == POLYGONTYPE )
1724  {
1725  ptr += asgml3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, prefix, id);
1726  }
1727  else if ( lwgeom_is_collection(subgeom) )
1728  {
1729  if ( subgeom->type == COLLECTIONTYPE )
1730  ptr += asgml3_collection_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, prefix, id);
1731  else
1732  ptr += asgml3_multi_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, prefix, id);
1733  }
1734  else
1735  lwerror("asgml3_collection_buf: unknown geometry type");
1736 
1737  ptr += sprintf(ptr, "</%sgeometryMember>", prefix);
1738  }
1739 
1740  /* Close outmost tag */
1741  ptr += sprintf(ptr, "</%sMultiGeometry>", prefix);
1742 
1743  return (ptr-output);
1744 }
1745 
1746 /*
1747  * Don't call this with single-geoms inspected!
1748  */
1749 static char *
1750 asgml3_collection(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
1751 {
1752  char *gml;
1753  size_t size;
1754 
1755  size = asgml3_collection_size(col, srs, precision, opts, prefix, id);
1756  gml = lwalloc(size);
1757  asgml3_collection_buf(col, srs, gml, precision, opts, prefix, id);
1758  return gml;
1759 }
1760 
1761 static size_t asgml3_multicurve_size( const LWMCURVE* cur, const char *srs, int precision, int opts, const char *prefix, const char *id )
1762 {
1763  size_t prefixlen = strlen(prefix);
1764  size_t size = sizeof( "<MultiCurve></MultiCurve>" ) + 2 * prefixlen;
1765  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1766  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1767  LWGEOM* subgeom;
1768  int i;
1769 
1770  for( i = 0; i < cur->ngeoms; ++i )
1771  {
1772  size += sizeof( "<curveMember></curveMember>" ) + 2 * prefixlen;
1773  subgeom = cur->geoms[i];
1774  if ( subgeom->type == LINETYPE )
1775  {
1776  size += asgml3_line_size( (LWLINE*)subgeom, srs, precision, opts, prefix, id );
1777  }
1778  else if( subgeom->type == CIRCSTRINGTYPE )
1779  {
1780  size += asgml3_circstring_size( (LWCIRCSTRING*)subgeom, srs, precision, opts, prefix, id );
1781  }
1782  else if( subgeom->type == COMPOUNDTYPE )
1783  {
1784  size += asgml3_compound_size( (LWCOMPOUND*)subgeom, srs, precision, opts, prefix, id );
1785  }
1786  }
1787  return size;
1788 }
1789 
1790 static size_t asgml3_multicurve_buf( const LWMCURVE* cur, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id )
1791 {
1792  char* ptr = output;
1793  LWGEOM* subgeom;
1794  int i;
1795 
1796  ptr += sprintf(ptr, "<%sMultiCurve", prefix );
1797  if (srs)
1798  {
1799  ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1800  }
1801  if (id)
1802  {
1803  ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id );
1804  }
1805  ptr += sprintf( ptr, ">");
1806 
1807  for( i = 0; i < cur->ngeoms; ++i )
1808  {
1809  ptr += sprintf(ptr, "<%scurveMember>", prefix );
1810  subgeom = cur->geoms[i];
1811  if ( subgeom->type == LINETYPE )
1812  {
1813  ptr += asgml3_line_buf( (LWLINE*)subgeom, srs, ptr, precision, opts, prefix, id );
1814  }
1815  else if( subgeom->type == CIRCSTRINGTYPE )
1816  {
1817  ptr += asgml3_circstring_buf( (LWCIRCSTRING*)subgeom, srs, ptr, precision, opts, prefix, id );
1818  }
1819  else if( subgeom->type == COMPOUNDTYPE )
1820  {
1821  ptr += asgml3_compound_buf( (LWCOMPOUND*)subgeom, srs, ptr, precision, opts, prefix, id );
1822  }
1823  ptr += sprintf(ptr, "</%scurveMember>", prefix );
1824  }
1825  ptr += sprintf(ptr, "</%sMultiCurve>", prefix );
1826  return (ptr - output);
1827 }
1828 
1829 static char *asgml3_multicurve( const LWMCURVE* cur, const char *srs, int precision, int opts, const char *prefix, const char *id )
1830 {
1831  char* gml;
1832  size_t size =asgml3_multicurve_size( cur, srs, precision, opts, prefix, id );
1833  gml = lwalloc( size );
1834  asgml3_multicurve_buf( cur, srs, gml, precision, opts, prefix, id );
1835  return gml;
1836 }
1837 
1838 static size_t asgml3_multisurface_size(const LWMSURFACE *sur, const char *srs, int precision, int opts, const char *prefix, const char *id)
1839 {
1840  size_t prefixlen = strlen(prefix);
1841  size_t size = sizeof( "<MultiSurface></MultiSurface>" ) + 2 * prefixlen;
1842  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1843  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1844  LWGEOM* subgeom;
1845  int i;
1846 
1847  for( i = 0; i < sur->ngeoms; ++i )
1848  {
1849  subgeom = sur->geoms[i];
1850  if( subgeom->type == POLYGONTYPE )
1851  {
1852  size += asgml3_poly_size( (LWPOLY*)sur->geoms[i], srs, precision, opts, prefix, id );
1853  }
1854  else if( subgeom->type == CURVEPOLYTYPE )
1855  {
1856  size += asgml3_curvepoly_size( (LWCURVEPOLY*)sur->geoms[i], srs, precision, opts, prefix, id );
1857  }
1858  }
1859  return size;
1860 }
1861 
1862 static size_t asgml3_multisurface_buf(const LWMSURFACE *sur, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1863 {
1864  char* ptr = output;
1865  int i;
1866  LWGEOM* subgeom;
1867 
1868  ptr += sprintf( ptr, "<%sMultiSurface", prefix );
1869  if (srs)
1870  {
1871  ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1872  }
1873  if (id)
1874  {
1875  ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id );
1876  }
1877  ptr += sprintf( ptr, ">" );
1878 
1879  for( i = 0; i < sur->ngeoms; ++i )
1880  {
1881  subgeom = sur->geoms[i];
1882  if( subgeom->type == POLYGONTYPE )
1883  {
1884  ptr += asgml3_poly_buf( (LWPOLY*)sur->geoms[i], srs, ptr, precision, opts, 0, prefix, id );
1885  }
1886  else if( subgeom->type == CURVEPOLYTYPE )
1887  {
1888  ptr += asgml3_curvepoly_buf( (LWCURVEPOLY*)sur->geoms[i], srs, ptr, precision, opts, prefix, id );
1889  }
1890  }
1891  ptr += sprintf( ptr, "</%sMultiSurface>", prefix );
1892  return ptr - output;
1893 }
1894 
1895 static char *asgml3_multisurface(const LWMSURFACE *sur, const char *srs, int precision, int opts, const char *prefix, const char *id)
1896 {
1897  char* gml;
1898  size_t size = asgml3_multisurface_size( sur, srs, precision, opts, prefix, id );
1899  gml = lwalloc( size );
1900  asgml3_multisurface_buf( sur, srs, gml, precision, opts, prefix, id );
1901  return gml;
1902 }
1903 
1904 
1905 /* In GML3, inside <posList> or <pos>, coordinates are separated by a space separator
1906  * In GML3 also, lat/lon are reversed for geocentric data
1907  */
1908 static size_t
1909 pointArray_toGML3(POINTARRAY *pa, char *output, int precision, int opts)
1910 {
1911  int i;
1912  char *ptr;
1916 
1917  ptr = output;
1918 
1919  if ( ! FLAGS_GET_Z(pa->flags) )
1920  {
1921  for (i=0; i<pa->npoints; i++)
1922  {
1923  const POINT2D *pt;
1924  pt = getPoint2d_cp(pa, i);
1925 
1926  if (fabs(pt->x) < OUT_MAX_DOUBLE)
1927  sprintf(x, "%.*f", precision, pt->x);
1928  else
1929  sprintf(x, "%g", pt->x);
1931 
1932  if (fabs(pt->y) < OUT_MAX_DOUBLE)
1933  sprintf(y, "%.*f", precision, pt->y);
1934  else
1935  sprintf(y, "%g", pt->y);
1937 
1938  if ( i ) ptr += sprintf(ptr, " ");
1939  if (IS_DEGREE(opts))
1940  ptr += sprintf(ptr, "%s %s", y, x);
1941  else
1942  ptr += sprintf(ptr, "%s %s", x, y);
1943  }
1944  }
1945  else
1946  {
1947  for (i=0; i<pa->npoints; i++)
1948  {
1949  const POINT3DZ *pt;
1950  pt = getPoint3dz_cp(pa, i);
1951 
1952  if (fabs(pt->x) < OUT_MAX_DOUBLE)
1953  sprintf(x, "%.*f", precision, pt->x);
1954  else
1955  sprintf(x, "%g", pt->x);
1957 
1958  if (fabs(pt->y) < OUT_MAX_DOUBLE)
1959  sprintf(y, "%.*f", precision, pt->y);
1960  else
1961  sprintf(y, "%g", pt->y);
1963 
1964  if (fabs(pt->z) < OUT_MAX_DOUBLE)
1965  sprintf(z, "%.*f", precision, pt->z);
1966  else
1967  sprintf(z, "%g", pt->z);
1969 
1970  if ( i ) ptr += sprintf(ptr, " ");
1971  if (IS_DEGREE(opts))
1972  ptr += sprintf(ptr, "%s %s %s", y, x, z);
1973  else
1974  ptr += sprintf(ptr, "%s %s %s", x, y, z);
1975  }
1976  }
1977 
1978  return ptr-output;
1979 }
1980 
1981 
1982 
1983 /*
1984  * Returns maximum size of rendered pointarray in bytes.
1985  */
1986 static size_t
1988 {
1989  if (FLAGS_NDIMS(pa->flags) == 2)
1990  return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(", ")) * 2 * pa->npoints;
1991 
1992  return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(", ")) * 3 * pa->npoints;
1993 }
int ngeoms
Definition: liblwgeom.h:545
double x
Definition: liblwgeom.h:351
#define LINETYPE
Definition: liblwgeom.h:85
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:1838
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
#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:1517
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:1691
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:1004
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:1392
LWGEOM ** rings
Definition: liblwgeom.h:534
int npoints
Definition: liblwgeom.h:370
uint8_t type
Definition: liblwgeom.h:502
#define OUT_MAX_DOUBLE_PRECISION
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:1790
void trim_trailing_zeros(char *num)
Definition: lwutil.c:252
#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:330
#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:1096
#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:808
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:1014
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:847
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:96
#define IS_DEGREE(x)
Definition: liblwgeom.h:1523
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:1211
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:1574
static char * asgml3_point(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:834
LWGEOM ** geoms
Definition: liblwgeom.h:521
uint8_t flags
Definition: liblwgeom.h:516
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
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:1862
static char * asgml2_collection(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:648
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:1587
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:1651
int ngeoms
Definition: liblwgeom.h:584
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:1138
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:1350
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:216
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:1610
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:1522
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
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, int n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
Definition: lwgeom_api.c:485
static char * asgml3_compound(const LWCOMPOUND *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1200
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:962
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:794
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:1084
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:75
#define IS_DIMS(x)
Definition: liblwgeom.h:1522
LWGEOM ** geoms
Definition: liblwgeom.h:508
#define TINTYPE
Definition: liblwgeom.h:98
LWTRIANGLE ** geoms
Definition: liblwgeom.h:586
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:653
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:1509
uint8_t precision
Definition: cu_in_twkb.c:25
int lwpoly_is_empty(const LWPOLY *poly)
Definition: lwpoly.c:403
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:1034
int nrings
Definition: liblwgeom.h:454
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:1450
static char * asgml3_multisurface(const LWMSURFACE *sur, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1895
static char * asgml3_multicurve(const LWMCURVE *cur, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1829
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:936
uint8_t flags
Definition: liblwgeom.h:290
static size_t pointArray_GMLsize(POINTARRAY *pa, int precision)
Definition: lwout_gml.c:1987
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:1367
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:89
#define OUT_MAX_DOUBLE
uint8_t flags
Definition: liblwgeom.h:407
int lwline_is_empty(const LWLINE *line)
Definition: lwline.c:525
static char * asgml3_collection(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1750
static size_t asgml2_point_buf(const LWPOINT *point, const char *srs, char *output, int precision, const char *prefix)
Definition: lwout_gml.c:283
int ngeoms
Definition: liblwgeom.h:558
char * lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:736
const POINT3DZ * getPoint3dz_cp(const POINTARRAY *pa, int n)
Returns a POINT3DZ pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
Definition: lwgeom_api.c:499
#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:1258
LWGEOM ** geoms
Definition: liblwgeom.h:560
int ptarray_remove_point(POINTARRAY *pa, int where)
Remove a point from an existing POINTARRAY.
Definition: ptarray.c:261
static char * asgml2_point(const LWPOINT *point, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:303
int ngeoms
Definition: liblwgeom.h:519
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:1909
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:84
int lwpoint_is_empty(const LWPOINT *point)
Definition: lwpoint.c:273
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:949
POINTARRAY * points
Definition: liblwgeom.h:443
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:227
#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:1310
static size_t asgml2_line_buf(const LWLINE *line, const char *srs, char *output, int precision, const char *prefix)
Definition: lwout_gml.c:327
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
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:1337
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:151
int ngeoms
Definition: liblwgeom.h:571
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:1761
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:102
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:1410
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:874
static char * asgml3_tin(const LWTIN *tin, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1639
#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:1001
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:1545
uint8_t flags
Definition: liblwgeom.h:429
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