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