PostGIS  2.1.10dev-r@@SVN_REVISION@@
lwout_gml.c
Go to the documentation of this file.
1 /**********************************************************************
2  * $Id: lwout_gml.c 13252 2015-02-20 17:48:52Z pramsey $
3  *
4  * PostGIS - Spatial Types for PostgreSQL
5  * http://postgis.net
6  *
7  * Copyright 2011 Sandro Santilli <strk@keybit.net>
8  * Copyright 2010-2012 Oslandia
9  * Copyright 2001-2003 Refractions Research Inc.
10  *
11  * This is free software; you can redistribute and/or modify it under
12  * the terms of the GNU General Public Licence. See the COPYING file.
13  *
14  **********************************************************************/
15 
22 #include <string.h>
23 #include "liblwgeom_internal.h"
24 
25 
26 static size_t asgml2_point_size(const LWPOINT *point, const char *srs, int precision, const char *prefix);
27 static char *asgml2_point(const LWPOINT *point, const char *srs, int precision, const char *prefix);
28 static size_t asgml2_line_size(const LWLINE *line, const char *srs, int precision, const char *prefix);
29 static char *asgml2_line(const LWLINE *line, const char *srs, int precision, const char *prefix);
30 static size_t asgml2_poly_size(const LWPOLY *poly, const char *srs, int precision, const char *prefix);
31 static char *asgml2_poly(const LWPOLY *poly, const char *srs, int precision, const char *prefix);
32 static size_t asgml2_multi_size(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix);
33 static char *asgml2_multi(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix);
34 static size_t asgml2_collection_size(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix);
35 static char *asgml2_collection(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix);
36 static size_t pointArray_toGML2(POINTARRAY *pa, char *buf, int precision);
37 
38 static size_t asgml3_point_size(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id);
39 static char *asgml3_point(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id);
40 static size_t asgml3_line_size(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id);
41 static char *asgml3_line(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id);
42 static size_t asgml3_poly_size(const LWPOLY *poly, const char *srs, int precision, int opts, const char *prefix, const char *id);
43 static char *asgml3_poly(const LWPOLY *poly, const char *srs, int precision, int opts, int is_patch, const char *prefix, const char *id);
44 static size_t asgml3_triangle_size(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id);
45 static char *asgml3_triangle(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id);
46 static size_t asgml3_multi_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id);
47 static char *asgml3_multi(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id);
48 static char *asgml3_psurface(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *prefix, const char *id);
49 static char *asgml3_tin(const LWTIN *tin, const char *srs, int precision, int opts, const char *prefix, const char *id);
50 static size_t asgml3_collection_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id);
51 static char *asgml3_collection(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id);
52 static size_t pointArray_toGML3(POINTARRAY *pa, char *buf, int precision, int opts);
53 
54 static size_t pointArray_GMLsize(POINTARRAY *pa, int precision);
55 
56 static char *
57 gbox_to_gml2(const GBOX *bbox, const char *srs, int precision, const char *prefix)
58 {
59  int size;
60  POINT4D pt;
61  POINTARRAY *pa;
62  char *ptr, *output;
63  size_t prefixlen = strlen(prefix);
64 
65  if ( ! bbox ) {
66  size = ( sizeof("<Box>/") + (prefixlen*2) ) * 2;
67  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
68 
69  ptr = output = lwalloc(size);
70 
71  ptr += sprintf(ptr, "<%sBox", prefix);
72 
73  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
74 
75  ptr += sprintf(ptr, "/>");
76 
77  return output;
78  }
79 
80  pa = ptarray_construct_empty(FLAGS_GET_Z(bbox->flags), 0, 2);
81 
82  pt.x = bbox->xmin;
83  pt.y = bbox->ymin;
84  if (FLAGS_GET_Z(bbox->flags)) pt.z = bbox->zmin;
85  ptarray_append_point(pa, &pt, LW_TRUE);
86 
87  pt.x = bbox->xmax;
88  pt.y = bbox->ymax;
89  if (FLAGS_GET_Z(bbox->flags)) pt.z = bbox->zmax;
90  ptarray_append_point(pa, &pt, LW_TRUE);
91 
92  size = pointArray_GMLsize(pa, precision);
93  size += ( sizeof("<Box><coordinates>/") + (prefixlen*2) ) * 2;
94  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
95 
96  ptr = output = lwalloc(size);
97 
98  if ( srs ) ptr += sprintf(ptr, "<%sBox srsName=\"%s\">", prefix, srs);
99  else ptr += sprintf(ptr, "<%sBox>", prefix);
100 
101  ptr += sprintf(ptr, "<%scoordinates>", prefix);
102  ptr += pointArray_toGML2(pa, ptr, precision);
103  ptr += sprintf(ptr, "</%scoordinates></%sBox>", prefix, prefix);
104 
105  ptarray_free(pa);
106 
107  return output;
108 }
109 
110 static char *
111 gbox_to_gml3(const GBOX *bbox, const char *srs, int precision, int opts, const char *prefix)
112 {
113  int size;
114  POINT4D pt;
115  POINTARRAY *pa;
116  char *ptr, *output;
117  size_t prefixlen = strlen(prefix);
118  int dimension = 2;
119 
120  if ( ! bbox ) {
121  size = ( sizeof("<Envelope>/") + (prefixlen*2) ) * 2;
122  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
123 
124  ptr = output = lwalloc(size);
125 
126  ptr += sprintf(ptr, "<%sEnvelope", prefix);
127  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
128 
129  ptr += sprintf(ptr, "/>");
130 
131  return output;
132  }
133 
134  if (FLAGS_GET_Z(bbox->flags)) dimension = 3;
135 
136  pa = ptarray_construct_empty(FLAGS_GET_Z(bbox->flags), 0, 1);
137 
138  pt.x = bbox->xmin;
139  pt.y = bbox->ymin;
140  if (FLAGS_GET_Z(bbox->flags)) pt.z = bbox->zmin;
141  ptarray_append_point(pa, &pt, LW_TRUE);
142 
143  size = pointArray_GMLsize(pa, precision) * 2;
144  size += ( sizeof("<Envelope><lowerCorner><upperCorner>//") + (prefixlen*3) ) * 2;
145  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
146  if ( IS_DIMS(opts) ) size += sizeof(" srsDimension=. .");
147 
148  ptr = output = lwalloc(size);
149 
150  ptr += sprintf(ptr, "<%sEnvelope", prefix);
151  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
152  if ( IS_DIMS(opts) ) ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension);
153  ptr += sprintf(ptr, ">");
154 
155  ptr += sprintf(ptr, "<%slowerCorner>", prefix);
156  ptr += pointArray_toGML3(pa, ptr, precision, opts);
157  ptr += sprintf(ptr, "</%slowerCorner>", prefix);
158 
159  ptarray_remove_point(pa, 0);
160  pt.x = bbox->xmax;
161  pt.y = bbox->ymax;
162  if (FLAGS_GET_Z(bbox->flags)) pt.z = bbox->zmax;
163  ptarray_append_point(pa, &pt, LW_TRUE);
164 
165  ptr += sprintf(ptr, "<%supperCorner>", prefix);
166  ptr += pointArray_toGML3(pa, ptr, precision, opts);
167  ptr += sprintf(ptr, "</%supperCorner>", prefix);
168 
169  ptr += sprintf(ptr, "</%sEnvelope>", prefix);
170 
171  ptarray_free(pa);
172 
173  return output;
174 }
175 
176 
177 extern char *
178 lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix)
179 {
180  const GBOX* bbox = lwgeom_get_bbox(geom);
181 /*
182  if ( ! bbox ) {
183  lwerror("lwgeom_extent_to_gml2: empty geometry doesn't have a bounding box");
184  return NULL;
185  }
186 */
187  char *ret = gbox_to_gml2(bbox, srs, precision, prefix);
188  return ret;
189 }
190 
191 
192 extern char *
193 lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix)
194 {
195  const GBOX* bbox = lwgeom_get_bbox(geom);
196 /*
197  if ( ! bbox ) {
198  lwerror("lwgeom_extent_to_gml3: empty geometry doesn't have a bounding box");
199  return NULL;
200  }
201 */
202  return gbox_to_gml3(bbox, srs, precision, opts, prefix);
203 }
204 
205 
210 extern char *
211 lwgeom_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char* prefix)
212 {
213  int type = geom->type;
214 
215  /* Return null for empty (#1377) */
216  if ( lwgeom_is_empty(geom) )
217  return NULL;
218 
219  switch (type)
220  {
221  case POINTTYPE:
222  return asgml2_point((LWPOINT*)geom, srs, precision, prefix);
223 
224  case LINETYPE:
225  return asgml2_line((LWLINE*)geom, srs, precision, prefix);
226 
227  case POLYGONTYPE:
228  return asgml2_poly((LWPOLY*)geom, srs, precision, prefix);
229 
230  case MULTIPOINTTYPE:
231  case MULTILINETYPE:
232  case MULTIPOLYGONTYPE:
233  return asgml2_multi((LWCOLLECTION*)geom, srs, precision, prefix);
234 
235  case COLLECTIONTYPE:
236  return asgml2_collection((LWCOLLECTION*)geom, srs, precision, prefix);
237 
238  case TRIANGLETYPE:
240  case TINTYPE:
241  lwerror("Cannot convert %s to GML2. Try ST_AsGML(3, <geometry>) to generate GML3.", lwtype_name(type));
242  return NULL;
243 
244  default:
245  lwerror("lwgeom_to_gml2: '%s' geometry type not supported", lwtype_name(type));
246  return NULL;
247  }
248 }
249 
250 static size_t
251 asgml2_point_size(const LWPOINT *point, const char *srs, int precision, const char* prefix)
252 {
253  int size;
254  size_t prefixlen = strlen(prefix);
255 
256  size = pointArray_GMLsize(point->point, precision);
257  size += ( sizeof("<point><coordinates>/") + (prefixlen*2) ) * 2;
258  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
259  return size;
260 }
261 
262 static size_t
263 asgml2_point_buf(const LWPOINT *point, const char *srs, char *output, int precision, const char* prefix)
264 {
265  char *ptr = output;
266 
267  ptr += sprintf(ptr, "<%sPoint", prefix);
268  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
269  if ( lwpoint_is_empty(point) ) {
270  ptr += sprintf(ptr, "/>");
271  return (ptr-output);
272  }
273  ptr += sprintf(ptr, ">");
274  ptr += sprintf(ptr, "<%scoordinates>", prefix);
275  ptr += pointArray_toGML2(point->point, ptr, precision);
276  ptr += sprintf(ptr, "</%scoordinates></%sPoint>", prefix, prefix);
277 
278  return (ptr-output);
279 }
280 
281 static char *
282 asgml2_point(const LWPOINT *point, const char *srs, int precision, const char *prefix)
283 {
284  char *output;
285  int size;
286 
287  size = asgml2_point_size(point, srs, precision, prefix);
288  output = lwalloc(size);
289  asgml2_point_buf(point, srs, output, precision, prefix);
290  return output;
291 }
292 
293 static size_t
294 asgml2_line_size(const LWLINE *line, const char *srs, int precision, const char *prefix)
295 {
296  int size;
297  size_t prefixlen = strlen(prefix);
298 
299  size = pointArray_GMLsize(line->points, precision);
300  size += ( sizeof("<linestring><coordinates>/") + (prefixlen*2) ) * 2;
301  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
302  return size;
303 }
304 
305 static size_t
306 asgml2_line_buf(const LWLINE *line, const char *srs, char *output, int precision,
307  const char *prefix)
308 {
309  char *ptr=output;
310 
311  ptr += sprintf(ptr, "<%sLineString", prefix);
312  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
313 
314  if ( lwline_is_empty(line) ) {
315  ptr += sprintf(ptr, "/>");
316  return (ptr-output);
317  }
318  ptr += sprintf(ptr, ">");
319 
320  ptr += sprintf(ptr, "<%scoordinates>", prefix);
321  ptr += pointArray_toGML2(line->points, ptr, precision);
322  ptr += sprintf(ptr, "</%scoordinates></%sLineString>", prefix, prefix);
323 
324  return (ptr-output);
325 }
326 
327 static char *
328 asgml2_line(const LWLINE *line, const char *srs, int precision, const char *prefix)
329 {
330  char *output;
331  int size;
332 
333  size = asgml2_line_size(line, srs, precision, prefix);
334  output = lwalloc(size);
335  asgml2_line_buf(line, srs, output, precision, prefix);
336  return output;
337 }
338 
339 static size_t
340 asgml2_poly_size(const LWPOLY *poly, const char *srs, int precision, const char *prefix)
341 {
342  size_t size;
343  int i;
344  size_t prefixlen = strlen(prefix);
345 
346  size = sizeof("<polygon></polygon>") + prefixlen*2;
347  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
348  if ( lwpoly_is_empty(poly) )
349  return size;
350  size += ( sizeof("<outerboundaryis><linearring><coordinates>/") + ( prefixlen*3) ) * 2;
351  size += ( sizeof("<innerboundaryis><linearring><coordinates>/") + ( prefixlen*2) ) * 2 * poly->nrings;
352 
353  for (i=0; i<poly->nrings; i++)
354  size += pointArray_GMLsize(poly->rings[i], precision);
355 
356  return size;
357 }
358 
359 static size_t
360 asgml2_poly_buf(const LWPOLY *poly, const char *srs, char *output, int precision,
361  const char *prefix)
362 {
363  int i;
364  char *ptr=output;
365 
366  ptr += sprintf(ptr, "<%sPolygon", prefix);
367  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
368  if ( lwpoly_is_empty(poly) ) {
369  ptr += sprintf(ptr, "/>");
370  return (ptr-output);
371  }
372  ptr += sprintf(ptr, ">");
373  ptr += sprintf(ptr, "<%souterBoundaryIs><%sLinearRing><%scoordinates>",
374  prefix, prefix, prefix);
375  ptr += pointArray_toGML2(poly->rings[0], ptr, precision);
376  ptr += sprintf(ptr, "</%scoordinates></%sLinearRing></%souterBoundaryIs>", prefix, prefix, prefix);
377  for (i=1; i<poly->nrings; i++)
378  {
379  ptr += sprintf(ptr, "<%sinnerBoundaryIs><%sLinearRing><%scoordinates>", prefix, prefix, prefix);
380  ptr += pointArray_toGML2(poly->rings[i], ptr, precision);
381  ptr += sprintf(ptr, "</%scoordinates></%sLinearRing></%sinnerBoundaryIs>", prefix, prefix, prefix);
382  }
383  ptr += sprintf(ptr, "</%sPolygon>", prefix);
384 
385  return (ptr-output);
386 }
387 
388 static char *
389 asgml2_poly(const LWPOLY *poly, const char *srs, int precision, const char *prefix)
390 {
391  char *output;
392  int size;
393 
394  size = asgml2_poly_size(poly, srs, precision, prefix);
395  output = lwalloc(size);
396  asgml2_poly_buf(poly, srs, output, precision, prefix);
397  return output;
398 }
399 
400 /*
401  * Compute max size required for GML version of this
402  * inspected geometry. Will recurse when needed.
403  * Don't call this with single-geoms inspected.
404  */
405 static size_t
406 asgml2_multi_size(const LWCOLLECTION *col, const char *srs, int precision,
407  const char *prefix)
408 {
409  int i;
410  size_t size;
411  size_t prefixlen = strlen(prefix);
412  LWGEOM *subgeom;
413 
414  /* the longest possible multi version */
415  size = sizeof("<MultiLineString></MultiLineString>");
416  size += 2*prefixlen;
417 
418  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
419 
420  for (i=0; i<col->ngeoms; i++)
421  {
422  subgeom = col->geoms[i];
423  if (subgeom->type == POINTTYPE)
424  {
425  size += ( sizeof("<pointMember>/") + prefixlen ) * 2;
426  size += asgml2_point_size((LWPOINT*)subgeom, 0, precision, prefix);
427  }
428  else if (subgeom->type == LINETYPE)
429  {
430  size += ( sizeof("<lineStringMember>/") + prefixlen ) * 2;
431  size += asgml2_line_size((LWLINE*)subgeom, 0, precision, prefix);
432  }
433  else if (subgeom->type == POLYGONTYPE)
434  {
435  size += ( sizeof("<polygonMember>/") + prefixlen ) * 2;
436  size += asgml2_poly_size((LWPOLY*)subgeom, 0, precision, prefix);
437  }
438  }
439 
440  return size;
441 }
442 
443 /*
444  * Don't call this with single-geoms inspected!
445  */
446 static size_t
447 asgml2_multi_buf(const LWCOLLECTION *col, const char *srs, char *output,
448  int precision, const char *prefix)
449 {
450  int type = col->type;
451  char *ptr, *gmltype;
452  int i;
453  LWGEOM *subgeom;
454 
455  ptr = output;
456  gmltype="";
457 
458  if (type == MULTIPOINTTYPE) gmltype = "MultiPoint";
459  else if (type == MULTILINETYPE) gmltype = "MultiLineString";
460  else if (type == MULTIPOLYGONTYPE) gmltype = "MultiPolygon";
461 
462  /* Open outmost tag */
463  ptr += sprintf(ptr, "<%s%s", prefix, gmltype);
464  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
465 
466  if (!col->ngeoms) {
467  ptr += sprintf(ptr, "/>");
468  return (ptr-output);
469  }
470  ptr += sprintf(ptr, ">");
471 
472  for (i=0; i<col->ngeoms; i++)
473  {
474  subgeom = col->geoms[i];
475  if (subgeom->type == POINTTYPE)
476  {
477  ptr += sprintf(ptr, "<%spointMember>", prefix);
478  ptr += asgml2_point_buf((LWPOINT*)subgeom, 0, ptr, precision, prefix);
479  ptr += sprintf(ptr, "</%spointMember>", prefix);
480  }
481  else if (subgeom->type == LINETYPE)
482  {
483  ptr += sprintf(ptr, "<%slineStringMember>", prefix);
484  ptr += asgml2_line_buf((LWLINE*)subgeom, 0, ptr, precision, prefix);
485  ptr += sprintf(ptr, "</%slineStringMember>", prefix);
486  }
487  else if (subgeom->type == POLYGONTYPE)
488  {
489  ptr += sprintf(ptr, "<%spolygonMember>", prefix);
490  ptr += asgml2_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, prefix);
491  ptr += sprintf(ptr, "</%spolygonMember>", prefix);
492  }
493  }
494 
495  /* Close outmost tag */
496  ptr += sprintf(ptr, "</%s%s>", prefix, gmltype);
497 
498  return (ptr-output);
499 }
500 
501 /*
502  * Don't call this with single-geoms inspected!
503  */
504 static char *
505 asgml2_multi(const LWCOLLECTION *col, const char *srs, int precision,
506  const char *prefix)
507 {
508  char *gml;
509  size_t size;
510 
511  size = asgml2_multi_size(col, srs, precision, prefix);
512  gml = lwalloc(size);
513  asgml2_multi_buf(col, srs, gml, precision, prefix);
514  return gml;
515 }
516 
517 
518 /*
519  * Don't call this with single-geoms!
520  */
521 static size_t
522 asgml2_collection_size(const LWCOLLECTION *col, const char *srs, int precision,
523  const char *prefix)
524 {
525  int i;
526  size_t size;
527  size_t prefixlen = strlen(prefix);
528  LWGEOM *subgeom;
529 
530  size = sizeof("<MultiGeometry></MultiGeometry>");
531  size += (prefixlen * 2);
532 
533  if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
534 
535  for (i=0; i<col->ngeoms; i++)
536  {
537  subgeom = col->geoms[i];
538 
539  size += ( sizeof("<geometryMember>/") + prefixlen ) * 2;
540  if ( subgeom->type == POINTTYPE)
541  {
542  size += asgml2_point_size((LWPOINT*)subgeom, 0, precision, prefix);
543  }
544  else if ( subgeom->type == LINETYPE)
545  {
546  size += asgml2_line_size((LWLINE*)subgeom, 0, precision, prefix);
547  }
548  else if ( subgeom->type == POLYGONTYPE)
549  {
550  size += asgml2_poly_size((LWPOLY*)subgeom, 0, precision, prefix);
551  }
552  else if ( lwgeom_is_collection(subgeom) )
553  {
554  size += asgml2_collection_size((LWCOLLECTION*)subgeom, 0, precision, prefix);
555  }
556  else
557  lwerror("asgml2_collection_size: Unable to process geometry type!");
558  }
559 
560 
561  return size;
562 }
563 
564 /*
565  * Don't call this with single-geoms inspected!
566  */
567 static size_t
568 asgml2_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, const char *prefix)
569 {
570  char *ptr;
571  int i;
572  LWGEOM *subgeom;
573 
574  ptr = output;
575 
576  /* Open outmost tag */
577  ptr += sprintf(ptr, "<%sMultiGeometry", prefix);
578  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
579 
580  if (!col->ngeoms) {
581  ptr += sprintf(ptr, "/>");
582  return (ptr-output);
583  }
584  ptr += sprintf(ptr, ">");
585 
586  for (i=0; i<col->ngeoms; i++)
587  {
588  subgeom = col->geoms[i];
589 
590  ptr += sprintf(ptr, "<%sgeometryMember>", prefix);
591  if (subgeom->type == POINTTYPE)
592  {
593  ptr += asgml2_point_buf((LWPOINT*)subgeom, 0, ptr, precision, prefix);
594  }
595  else if (subgeom->type == LINETYPE)
596  {
597  ptr += asgml2_line_buf((LWLINE*)subgeom, 0, ptr, precision, prefix);
598  }
599  else if (subgeom->type == POLYGONTYPE)
600  {
601  ptr += asgml2_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, prefix);
602  }
603  else if (lwgeom_is_collection(subgeom))
604  {
605  if (subgeom->type == COLLECTIONTYPE)
606  ptr += asgml2_collection_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, prefix);
607  else
608  ptr += asgml2_multi_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, prefix);
609  }
610  ptr += sprintf(ptr, "</%sgeometryMember>", prefix);
611  }
612 
613  /* Close outmost tag */
614  ptr += sprintf(ptr, "</%sMultiGeometry>", prefix);
615 
616  return (ptr-output);
617 }
618 
619 /*
620  * Don't call this with single-geoms inspected!
621  */
622 static char *
623 asgml2_collection(const LWCOLLECTION *col, const char *srs, int precision,
624  const char *prefix)
625 {
626  char *gml;
627  size_t size;
628 
629  size = asgml2_collection_size(col, srs, precision, prefix);
630  gml = lwalloc(size);
631  asgml2_collection_buf(col, srs, gml, precision, prefix);
632  return gml;
633 }
634 
635 
636 static size_t
637 pointArray_toGML2(POINTARRAY *pa, char *output, int precision)
638 {
639  int i;
640  char *ptr;
644 
645  ptr = output;
646 
647  if ( ! FLAGS_GET_Z(pa->flags) )
648  {
649  for (i=0; i<pa->npoints; i++)
650  {
651  const POINT2D *pt;
652  pt = getPoint2d_cp(pa, i);
653 
654  if (fabs(pt->x) < OUT_MAX_DOUBLE)
655  sprintf(x, "%.*f", precision, pt->x);
656  else
657  sprintf(x, "%g", pt->x);
659 
660  if (fabs(pt->y) < OUT_MAX_DOUBLE)
661  sprintf(y, "%.*f", precision, pt->y);
662  else
663  sprintf(y, "%g", pt->y);
665 
666  if ( i ) ptr += sprintf(ptr, " ");
667  ptr += sprintf(ptr, "%s,%s", x, y);
668  }
669  }
670  else
671  {
672  for (i=0; i<pa->npoints; i++)
673  {
674  const POINT3DZ *pt;
675  pt = getPoint3dz_cp(pa, i);
676 
677  if (fabs(pt->x) < OUT_MAX_DOUBLE)
678  sprintf(x, "%.*f", precision, pt->x);
679  else
680  sprintf(x, "%g", pt->x);
682 
683  if (fabs(pt->y) < OUT_MAX_DOUBLE)
684  sprintf(y, "%.*f", precision, pt->y);
685  else
686  sprintf(y, "%g", pt->y);
688 
689  if (fabs(pt->z) < OUT_MAX_DOUBLE)
690  sprintf(z, "%.*f", precision, pt->z);
691  else
692  sprintf(z, "%g", pt->z);
694 
695  if ( i ) ptr += sprintf(ptr, " ");
696  ptr += sprintf(ptr, "%s,%s,%s", x, y, z);
697  }
698  }
699 
700  return ptr-output;
701 }
702 
703 
704 /*
705  * VERSION GML 3.1.1
706  */
707 
708 
709 /* takes a GEOMETRY and returns a GML representation */
710 extern char *
711 lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id)
712 {
713  int type = geom->type;
714 
715  /* Return null for empty (#1377) */
716  if ( lwgeom_is_empty(geom) )
717  return NULL;
718 
719  switch (type)
720  {
721  case POINTTYPE:
722  return asgml3_point((LWPOINT*)geom, srs, precision, opts, prefix, id);
723 
724  case LINETYPE:
725  return asgml3_line((LWLINE*)geom, srs, precision, opts, prefix, id);
726 
727  case POLYGONTYPE:
728  return asgml3_poly((LWPOLY*)geom, srs, precision, opts, 0, prefix, id);
729 
730  case TRIANGLETYPE:
731  return asgml3_triangle((LWTRIANGLE*)geom, srs, precision, opts, prefix, id);
732 
733  case MULTIPOINTTYPE:
734  case MULTILINETYPE:
735  case MULTIPOLYGONTYPE:
736  return asgml3_multi((LWCOLLECTION*)geom, srs, precision, opts, prefix, id);
737 
739  return asgml3_psurface((LWPSURFACE*)geom, srs, precision, opts, prefix, id);
740 
741  case TINTYPE:
742  return asgml3_tin((LWTIN*)geom, srs, precision, opts, prefix, id);
743 
744  case COLLECTIONTYPE:
745  return asgml3_collection((LWCOLLECTION*)geom, srs, precision, opts, prefix, id);
746 
747  default:
748  lwerror("lwgeom_to_gml3: '%s' geometry type not supported", lwtype_name(type));
749  return NULL;
750  }
751 }
752 
753 static size_t
754 asgml3_point_size(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id)
755 {
756  int size;
757  size_t prefixlen = strlen(prefix);
758 
759  size = pointArray_GMLsize(point->point, precision);
760  size += ( sizeof("<point><pos>/") + (prefixlen*2) ) * 2;
761  if (srs) size += strlen(srs) + sizeof(" srsName=..");
762  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
763  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'");
764  return size;
765 }
766 
767 static size_t
768 asgml3_point_buf(const LWPOINT *point, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
769 {
770  char *ptr = output;
771  int dimension=2;
772 
773  if (FLAGS_GET_Z(point->flags)) dimension = 3;
774 
775  ptr += sprintf(ptr, "<%sPoint", prefix);
776  if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
777  if ( id ) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
778  if ( lwpoint_is_empty(point) ) {
779  ptr += sprintf(ptr, "/>");
780  return (ptr-output);
781  }
782 
783  ptr += sprintf(ptr, ">");
784  if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%spos srsDimension=\"%d\">", prefix, dimension);
785  else ptr += sprintf(ptr, "<%spos>", prefix);
786  ptr += pointArray_toGML3(point->point, ptr, precision, opts);
787  ptr += sprintf(ptr, "</%spos></%sPoint>", prefix, prefix);
788 
789  return (ptr-output);
790 }
791 
792 static char *
793 asgml3_point(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id)
794 {
795  char *output;
796  int size;
797 
798  size = asgml3_point_size(point, srs, precision, opts, prefix, id);
799  output = lwalloc(size);
800  asgml3_point_buf(point, srs, output, precision, opts, prefix, id);
801  return output;
802 }
803 
804 
805 static size_t
806 asgml3_line_size(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id)
807 {
808  int size;
809  size_t prefixlen = strlen(prefix);
810 
811  size = pointArray_GMLsize(line->points, precision);
812  if ( opts & LW_GML_SHORTLINE )
813  {
814  size += (
815  sizeof("<LineString><posList>/") +
816  ( prefixlen * 2 )
817  ) * 2;
818  }
819  else
820  {
821  size += (
822  sizeof("<Curve><segments><LineStringSegment><posList>/") +
823  ( prefixlen * 4 )
824  ) * 2;
825  }
826  if (srs) size += strlen(srs) + sizeof(" srsName=..");
827  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
828  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'");
829  return size;
830 }
831 
832 static size_t
833 asgml3_line_buf(const LWLINE *line, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
834 {
835  char *ptr=output;
836  int dimension=2;
837  int shortline = ( opts & LW_GML_SHORTLINE );
838 
839  if (FLAGS_GET_Z(line->flags)) dimension = 3;
840 
841  if ( shortline ) {
842  ptr += sprintf(ptr, "<%sLineString", prefix);
843  } else {
844  ptr += sprintf(ptr, "<%sCurve", prefix);
845  }
846 
847  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
848  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
849 
850  if ( lwline_is_empty(line) ) {
851  ptr += sprintf(ptr, "/>");
852  return (ptr-output);
853  }
854  ptr += sprintf(ptr, ">");
855 
856  if ( ! shortline ) {
857  ptr += sprintf(ptr, "<%ssegments>", prefix);
858  ptr += sprintf(ptr, "<%sLineStringSegment>", prefix);
859  }
860 
861  if (IS_DIMS(opts)) {
862  ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">",
863  prefix, dimension);
864  } else {
865  ptr += sprintf(ptr, "<%sposList>", prefix);
866  }
867 
868  ptr += pointArray_toGML3(line->points, ptr, precision, opts);
869 
870  ptr += sprintf(ptr, "</%sposList>", prefix);
871 
872  if ( shortline ) {
873  ptr += sprintf(ptr, "</%sLineString>", prefix);
874  } else {
875  ptr += sprintf(ptr, "</%sLineStringSegment>", prefix);
876  ptr += sprintf(ptr, "</%ssegments>", prefix);
877  ptr += sprintf(ptr, "</%sCurve>", prefix);
878  }
879 
880  return (ptr-output);
881 }
882 
883 static char *
884 asgml3_line(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id)
885 {
886  char *output;
887  int size;
888 
889  size = asgml3_line_size(line, srs, precision, opts, prefix, id);
890  output = lwalloc(size);
891  asgml3_line_buf(line, srs, output, precision, opts, prefix, id);
892  return output;
893 }
894 
895 
896 static size_t
897 asgml3_poly_size(const LWPOLY *poly, const char *srs, int precision, int opts, const char *prefix, const char *id)
898 {
899  size_t size;
900  size_t prefixlen = strlen(prefix);
901  int i;
902 
903  size = ( sizeof("<PolygonPatch><exterior><LinearRing>///") + (prefixlen*3) ) * 2;
904  size += ( sizeof("<interior><LinearRing>//") + (prefixlen*2) ) * 2 * (poly->nrings - 1);
905  size += ( sizeof("<posList></posList>") + (prefixlen*2) ) * poly->nrings;
906  if (srs) size += strlen(srs) + sizeof(" srsName=..");
907  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
908  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'") * poly->nrings;
909 
910  for (i=0; i<poly->nrings; i++)
911  size += pointArray_GMLsize(poly->rings[i], precision);
912 
913  return size;
914 }
915 
916 static size_t
917 asgml3_poly_buf(const LWPOLY *poly, const char *srs, char *output, int precision, int opts, int is_patch, const char *prefix, const char *id)
918 {
919  int i;
920  char *ptr=output;
921  int dimension=2;
922 
923  if (FLAGS_GET_Z(poly->flags)) dimension = 3;
924  if (is_patch)
925  {
926  ptr += sprintf(ptr, "<%sPolygonPatch", prefix);
927 
928  }
929  else
930  {
931  ptr += sprintf(ptr, "<%sPolygon", prefix);
932  }
933 
934  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
935  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
936 
937  if ( lwpoly_is_empty(poly) ) {
938  ptr += sprintf(ptr, "/>");
939  return (ptr-output);
940  }
941  ptr += sprintf(ptr, ">");
942 
943  ptr += sprintf(ptr, "<%sexterior><%sLinearRing>", prefix, prefix);
944  if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">", prefix, dimension);
945  else ptr += sprintf(ptr, "<%sposList>", prefix);
946 
947  ptr += pointArray_toGML3(poly->rings[0], ptr, precision, opts);
948  ptr += sprintf(ptr, "</%sposList></%sLinearRing></%sexterior>",
949  prefix, prefix, prefix);
950  for (i=1; i<poly->nrings; i++)
951  {
952  ptr += sprintf(ptr, "<%sinterior><%sLinearRing>", prefix, prefix);
953  if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">", prefix, dimension);
954  else ptr += sprintf(ptr, "<%sposList>", prefix);
955  ptr += pointArray_toGML3(poly->rings[i], ptr, precision, opts);
956  ptr += sprintf(ptr, "</%sposList></%sLinearRing></%sinterior>",
957  prefix, prefix, prefix);
958  }
959  if (is_patch) ptr += sprintf(ptr, "</%sPolygonPatch>", prefix);
960  else ptr += sprintf(ptr, "</%sPolygon>", prefix);
961 
962  return (ptr-output);
963 }
964 
965 static char *
966 asgml3_poly(const LWPOLY *poly, const char *srs, int precision, int opts, int is_patch, const char *prefix, const char *id)
967 {
968  char *output;
969  int size;
970 
971  size = asgml3_poly_size(poly, srs, precision, opts, prefix, id);
972  output = lwalloc(size);
973  asgml3_poly_buf(poly, srs, output, precision, opts, is_patch, prefix, id);
974  return output;
975 }
976 
977 
978 static size_t
979 asgml3_triangle_size(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id)
980 {
981  size_t size;
982  size_t prefixlen = strlen(prefix);
983 
984  size = ( sizeof("<Triangle><exterior><LinearRing>///") + (prefixlen*3) ) * 2;
985  size += sizeof("<posList></posList>") + (prefixlen*2);
986  if (srs) size += strlen(srs) + sizeof(" srsName=..");
987  if (id) size += strlen(prefix) + strlen(id) + sizeof(" id=..");
988  if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'");
989 
990  size += pointArray_GMLsize(triangle->points, precision);
991 
992  return size;
993 }
994 
995 static size_t
996 asgml3_triangle_buf(const LWTRIANGLE *triangle, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
997 {
998  char *ptr=output;
999  int dimension=2;
1000 
1001  if (FLAGS_GET_Z(triangle->flags)) dimension = 3;
1002  ptr += sprintf(ptr, "<%sTriangle", prefix);
1003  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1004  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1005  ptr += sprintf(ptr, ">");
1006 
1007  ptr += sprintf(ptr, "<%sexterior><%sLinearRing>", prefix, prefix);
1008  if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">", prefix, dimension);
1009  else ptr += sprintf(ptr, "<%sposList>", prefix);
1010 
1011  ptr += pointArray_toGML3(triangle->points, ptr, precision, opts);
1012  ptr += sprintf(ptr, "</%sposList></%sLinearRing></%sexterior>",
1013  prefix, prefix, prefix);
1014 
1015  ptr += sprintf(ptr, "</%sTriangle>", prefix);
1016 
1017  return (ptr-output);
1018 }
1019 
1020 static char *
1021 asgml3_triangle(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id)
1022 {
1023  char *output;
1024  int size;
1025 
1026  size = asgml3_triangle_size(triangle, srs, precision, opts, prefix, id);
1027  output = lwalloc(size);
1028  asgml3_triangle_buf(triangle, srs, output, precision, opts, prefix, id);
1029  return output;
1030 }
1031 
1032 
1033 /*
1034  * Compute max size required for GML version of this
1035  * inspected geometry. Will recurse when needed.
1036  * Don't call this with single-geoms inspected.
1037  */
1038 static size_t
1039 asgml3_multi_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
1040 {
1041  int i;
1042  size_t size;
1043  size_t prefixlen = strlen(prefix);
1044  LWGEOM *subgeom;
1045 
1046  /* the longest possible multi version */
1047  size = sizeof("<MultiLineString></MultiLineString>") + prefixlen*2;
1048 
1049  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1050  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1051 
1052  for (i=0; i<col->ngeoms; i++)
1053  {
1054  subgeom = col->geoms[i];
1055  if (subgeom->type == POINTTYPE)
1056  {
1057  size += ( sizeof("<pointMember>/") + prefixlen ) * 2;
1058  size += asgml3_point_size((LWPOINT*)subgeom, 0, precision, opts, prefix, id);
1059  }
1060  else if (subgeom->type == LINETYPE)
1061  {
1062  size += ( sizeof("<curveMember>/") + prefixlen ) * 2;
1063  size += asgml3_line_size((LWLINE*)subgeom, 0, precision, opts, prefix, id);
1064  }
1065  else if (subgeom->type == POLYGONTYPE)
1066  {
1067  size += ( sizeof("<surfaceMember>/") + prefixlen ) * 2;
1068  size += asgml3_poly_size((LWPOLY*)subgeom, 0, precision, opts, prefix, id);
1069  }
1070  }
1071 
1072  return size;
1073 }
1074 
1075 /*
1076  * Don't call this with single-geoms inspected!
1077  */
1078 static size_t
1079 asgml3_multi_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1080 {
1081  int type = col->type;
1082  char *ptr, *gmltype;
1083  int i;
1084  LWGEOM *subgeom;
1085 
1086  ptr = output;
1087  gmltype="";
1088 
1089  if (type == MULTIPOINTTYPE) gmltype = "MultiPoint";
1090  else if (type == MULTILINETYPE) gmltype = "MultiCurve";
1091  else if (type == MULTIPOLYGONTYPE) gmltype = "MultiSurface";
1092 
1093  /* Open outmost tag */
1094  ptr += sprintf(ptr, "<%s%s", prefix, gmltype);
1095  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1096  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1097 
1098  if (!col->ngeoms) {
1099  ptr += sprintf(ptr, "/>");
1100  return (ptr-output);
1101  }
1102  ptr += sprintf(ptr, ">");
1103 
1104  for (i=0; i<col->ngeoms; i++)
1105  {
1106  subgeom = col->geoms[i];
1107  if (subgeom->type == POINTTYPE)
1108  {
1109  ptr += sprintf(ptr, "<%spointMember>", prefix);
1110  ptr += asgml3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, prefix, id);
1111  ptr += sprintf(ptr, "</%spointMember>", prefix);
1112  }
1113  else if (subgeom->type == LINETYPE)
1114  {
1115  ptr += sprintf(ptr, "<%scurveMember>", prefix);
1116  ptr += asgml3_line_buf((LWLINE*)subgeom, 0, ptr, precision, opts, prefix, id);
1117  ptr += sprintf(ptr, "</%scurveMember>", prefix);
1118  }
1119  else if (subgeom->type == POLYGONTYPE)
1120  {
1121  ptr += sprintf(ptr, "<%ssurfaceMember>", prefix);
1122  ptr += asgml3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, prefix, id);
1123  ptr += sprintf(ptr, "</%ssurfaceMember>", prefix);
1124  }
1125  }
1126 
1127  /* Close outmost tag */
1128  ptr += sprintf(ptr, "</%s%s>", prefix, gmltype);
1129 
1130  return (ptr-output);
1131 }
1132 
1133 /*
1134  * Don't call this with single-geoms inspected!
1135  */
1136 static char *
1137 asgml3_multi(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
1138 {
1139  char *gml;
1140  size_t size;
1141 
1142  size = asgml3_multi_size(col, srs, precision, opts, prefix, id);
1143  gml = lwalloc(size);
1144  asgml3_multi_buf(col, srs, gml, precision, opts, prefix, id);
1145  return gml;
1146 }
1147 
1148 
1149 static size_t
1150 asgml3_psurface_size(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *prefix, const char *id)
1151 {
1152  int i;
1153  size_t size;
1154  size_t prefixlen = strlen(prefix);
1155 
1156  size = (sizeof("<PolyhedralSurface><polygonPatches>/") + prefixlen*2) * 2;
1157  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1158  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1159 
1160  for (i=0; i<psur->ngeoms; i++)
1161  {
1162  size += asgml3_poly_size(psur->geoms[i], 0, precision, opts, prefix, id);
1163  }
1164 
1165  return size;
1166 }
1167 
1168 
1169 /*
1170  * Don't call this with single-geoms inspected!
1171  */
1172 static size_t
1173 asgml3_psurface_buf(const LWPSURFACE *psur, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1174 {
1175  char *ptr;
1176  int i;
1177 
1178  ptr = output;
1179 
1180  /* Open outmost tag */
1181  ptr += sprintf(ptr, "<%sPolyhedralSurface", prefix);
1182  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1183  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1184  ptr += sprintf(ptr, "><%spolygonPatches>", prefix);
1185 
1186  for (i=0; i<psur->ngeoms; i++)
1187  {
1188  ptr += asgml3_poly_buf(psur->geoms[i], 0, ptr, precision, opts, 1, prefix, id);
1189  }
1190 
1191  /* Close outmost tag */
1192  ptr += sprintf(ptr, "</%spolygonPatches></%sPolyhedralSurface>",
1193  prefix, prefix);
1194 
1195  return (ptr-output);
1196 }
1197 
1198 /*
1199  * Don't call this with single-geoms inspected!
1200  */
1201 static char *
1202 asgml3_psurface(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *prefix, const char *id)
1203 {
1204  char *gml;
1205  size_t size;
1206 
1207  size = asgml3_psurface_size(psur, srs, precision, opts, prefix, id);
1208  gml = lwalloc(size);
1209  asgml3_psurface_buf(psur, srs, gml, precision, opts, prefix, id);
1210  return gml;
1211 }
1212 
1213 
1214 static size_t
1215 asgml3_tin_size(const LWTIN *tin, const char *srs, int precision, int opts, const char *prefix, const char *id)
1216 {
1217  int i;
1218  size_t size;
1219  size_t prefixlen = strlen(prefix);
1220 
1221  size = (sizeof("<Tin><trianglePatches>/") + prefixlen*2) * 2;
1222  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1223  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1224 
1225  for (i=0; i<tin->ngeoms; i++)
1226  {
1227  size += asgml3_triangle_size(tin->geoms[i], 0, precision, opts, prefix, id);
1228  }
1229 
1230  return size;
1231 }
1232 
1233 
1234 /*
1235  * Don't call this with single-geoms inspected!
1236  */
1237 static size_t
1238 asgml3_tin_buf(const LWTIN *tin, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1239 {
1240  char *ptr;
1241  int i;
1242 
1243  ptr = output;
1244 
1245  /* Open outmost tag */
1246  ptr += sprintf(ptr, "<%sTin", prefix);
1247  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1248  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1249  else ptr += sprintf(ptr, "><%strianglePatches>", prefix);
1250 
1251  for (i=0; i<tin->ngeoms; i++)
1252  {
1253  ptr += asgml3_triangle_buf(tin->geoms[i], 0, ptr, precision,
1254  opts, prefix, id);
1255  }
1256 
1257  /* Close outmost tag */
1258  ptr += sprintf(ptr, "</%strianglePatches></%sTin>", prefix, prefix);
1259 
1260  return (ptr-output);
1261 }
1262 
1263 /*
1264  * Don't call this with single-geoms inspected!
1265  */
1266 static char *
1267 asgml3_tin(const LWTIN *tin, const char *srs, int precision, int opts, const char *prefix, const char *id)
1268 {
1269  char *gml;
1270  size_t size;
1271 
1272  size = asgml3_tin_size(tin, srs, precision, opts, prefix, id);
1273  gml = lwalloc(size);
1274  asgml3_tin_buf(tin, srs, gml, precision, opts, prefix, id);
1275  return gml;
1276 }
1277 
1278 static size_t
1279 asgml3_collection_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
1280 {
1281  int i;
1282  size_t size;
1283  size_t prefixlen = strlen(prefix);
1284  LWGEOM *subgeom;
1285 
1286  size = sizeof("<MultiGeometry></MultiGeometry>") + prefixlen*2;
1287 
1288  if (srs) size += strlen(srs) + sizeof(" srsName=..");
1289  if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=..");
1290 
1291  for (i=0; i<col->ngeoms; i++)
1292  {
1293  subgeom = col->geoms[i];
1294  size += ( sizeof("<geometryMember>/") + prefixlen ) * 2;
1295  if ( subgeom->type == POINTTYPE )
1296  {
1297  size += asgml3_point_size((LWPOINT*)subgeom, 0, precision, opts, prefix, id);
1298  }
1299  else if ( subgeom->type == LINETYPE )
1300  {
1301  size += asgml3_line_size((LWLINE*)subgeom, 0, precision, opts, prefix, id);
1302  }
1303  else if ( subgeom->type == POLYGONTYPE )
1304  {
1305  size += asgml3_poly_size((LWPOLY*)subgeom, 0, precision, opts, prefix, id);
1306  }
1307  else if ( lwgeom_is_collection(subgeom) )
1308  {
1309  size += asgml3_multi_size((LWCOLLECTION*)subgeom, 0, precision, opts, prefix, id);
1310  }
1311  else
1312  lwerror("asgml3_collection_size: unknown geometry type");
1313  }
1314 
1315  return size;
1316 }
1317 
1318 static size_t
1319 asgml3_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id)
1320 {
1321  char *ptr;
1322  int i;
1323  LWGEOM *subgeom;
1324 
1325  ptr = output;
1326 
1327  /* Open outmost tag */
1328  ptr += sprintf(ptr, "<%sMultiGeometry", prefix);
1329  if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs);
1330  if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id);
1331 
1332  if (!col->ngeoms) {
1333  ptr += sprintf(ptr, "/>");
1334  return (ptr-output);
1335  }
1336  ptr += sprintf(ptr, ">");
1337 
1338  for (i=0; i<col->ngeoms; i++)
1339  {
1340  subgeom = col->geoms[i];
1341  ptr += sprintf(ptr, "<%sgeometryMember>", prefix);
1342  if ( subgeom->type == POINTTYPE )
1343  {
1344  ptr += asgml3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, prefix, id);
1345  }
1346  else if ( subgeom->type == LINETYPE )
1347  {
1348  ptr += asgml3_line_buf((LWLINE*)subgeom, 0, ptr, precision, opts, prefix, id);
1349  }
1350  else if ( subgeom->type == POLYGONTYPE )
1351  {
1352  ptr += asgml3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, prefix, id);
1353  }
1354  else if ( lwgeom_is_collection(subgeom) )
1355  {
1356  if ( subgeom->type == COLLECTIONTYPE )
1357  ptr += asgml3_collection_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, prefix, id);
1358  else
1359  ptr += asgml3_multi_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, prefix, id);
1360  }
1361  else
1362  lwerror("asgml3_collection_buf: unknown geometry type");
1363 
1364  ptr += sprintf(ptr, "</%sgeometryMember>", prefix);
1365  }
1366 
1367  /* Close outmost tag */
1368  ptr += sprintf(ptr, "</%sMultiGeometry>", prefix);
1369 
1370  return (ptr-output);
1371 }
1372 
1373 /*
1374  * Don't call this with single-geoms inspected!
1375  */
1376 static char *
1377 asgml3_collection(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
1378 {
1379  char *gml;
1380  size_t size;
1381 
1382  size = asgml3_collection_size(col, srs, precision, opts, prefix, id);
1383  gml = lwalloc(size);
1384  asgml3_collection_buf(col, srs, gml, precision, opts, prefix, id);
1385  return gml;
1386 }
1387 
1388 
1389 /* In GML3, inside <posList> or <pos>, coordinates are separated by a space separator
1390  * In GML3 also, lat/lon are reversed for geocentric data
1391  */
1392 static size_t
1393 pointArray_toGML3(POINTARRAY *pa, char *output, int precision, int opts)
1394 {
1395  int i;
1396  char *ptr;
1400 
1401  ptr = output;
1402 
1403  if ( ! FLAGS_GET_Z(pa->flags) )
1404  {
1405  for (i=0; i<pa->npoints; i++)
1406  {
1407  const POINT2D *pt;
1408  pt = getPoint2d_cp(pa, i);
1409 
1410  if (fabs(pt->x) < OUT_MAX_DOUBLE)
1411  sprintf(x, "%.*f", precision, pt->x);
1412  else
1413  sprintf(x, "%g", pt->x);
1415 
1416  if (fabs(pt->y) < OUT_MAX_DOUBLE)
1417  sprintf(y, "%.*f", precision, pt->y);
1418  else
1419  sprintf(y, "%g", pt->y);
1421 
1422  if ( i ) ptr += sprintf(ptr, " ");
1423  if (IS_DEGREE(opts))
1424  ptr += sprintf(ptr, "%s %s", y, x);
1425  else
1426  ptr += sprintf(ptr, "%s %s", x, y);
1427  }
1428  }
1429  else
1430  {
1431  for (i=0; i<pa->npoints; i++)
1432  {
1433  const POINT3DZ *pt;
1434  pt = getPoint3dz_cp(pa, i);
1435 
1436  if (fabs(pt->x) < OUT_MAX_DOUBLE)
1437  sprintf(x, "%.*f", precision, pt->x);
1438  else
1439  sprintf(x, "%g", pt->x);
1441 
1442  if (fabs(pt->y) < OUT_MAX_DOUBLE)
1443  sprintf(y, "%.*f", precision, pt->y);
1444  else
1445  sprintf(y, "%g", pt->y);
1447 
1448  if (fabs(pt->z) < OUT_MAX_DOUBLE)
1449  sprintf(z, "%.*f", precision, pt->z);
1450  else
1451  sprintf(z, "%g", pt->z);
1453 
1454  if ( i ) ptr += sprintf(ptr, " ");
1455  if (IS_DEGREE(opts))
1456  ptr += sprintf(ptr, "%s %s %s", y, x, z);
1457  else
1458  ptr += sprintf(ptr, "%s %s %s", x, y, z);
1459  }
1460  }
1461 
1462  return ptr-output;
1463 }
1464 
1465 
1466 
1467 /*
1468  * Returns maximum size of rendered pointarray in bytes.
1469  */
1470 static size_t
1471 pointArray_GMLsize(POINTARRAY *pa, int precision)
1472 {
1473  if (FLAGS_NDIMS(pa->flags) == 2)
1474  return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(", ")) * 2 * pa->npoints;
1475 
1476  return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(", ")) * 3 * pa->npoints;
1477 }
double x
Definition: liblwgeom.h:308
#define LINETYPE
Definition: liblwgeom.h:61
static size_t asgml2_point_size(const LWPOINT *point, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:251
double z
Definition: liblwgeom.h:290
double y
Definition: liblwgeom.h:290
POINTARRAY * points
Definition: liblwgeom.h:389
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:211
#define LW_GML_SHORTLINE
For GML3, use rather than for lines.
Definition: liblwgeom.h:1362
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:1319
static char * asgml2_line(const LWLINE *line, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:328
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:947
double x
Definition: liblwgeom.h:290
static char * asgml3_triangle(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1021
int npoints
Definition: liblwgeom.h:327
uint8_t type
Definition: liblwgeom.h:459
#define OUT_MAX_DOUBLE_PRECISION
void trim_trailing_zeros(char *num)
Definition: lwutil.c:200
#define POLYGONTYPE
Definition: liblwgeom.h:62
double xmax
Definition: liblwgeom.h:249
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:57
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:315
#define MULTIPOINTTYPE
Definition: liblwgeom.h:63
static size_t asgml2_line_size(const LWLINE *line, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:294
#define TRIANGLETYPE
Definition: liblwgeom.h:73
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:768
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:897
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:806
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:72
#define IS_DEGREE(x)
Definition: liblwgeom.h:1368
LWPOLY ** geoms
Definition: liblwgeom.h:530
static char * asgml3_psurface(const LWPSURFACE *psur, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1202
static char * asgml3_point(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:793
char * lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix)
Definition: lwout_gml.c:193
POINTARRAY * point
Definition: liblwgeom.h:367
static size_t asgml2_multi_size(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:406
static size_t asgml2_poly_size(const LWPOLY *poly, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:340
static char * asgml2_collection(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:623
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
double x
Definition: liblwgeom.h:284
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:1215
static size_t asgml2_multi_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, const char *prefix)
Definition: lwout_gml.c:447
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:1279
int ngeoms
Definition: liblwgeom.h:541
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:979
double zmax
Definition: liblwgeom.h:253
double ymin
Definition: liblwgeom.h:250
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:164
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:1238
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:1150
double xmin
Definition: liblwgeom.h:248
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_TRUE, then a duplicate point will not be added.
Definition: ptarray.c:141
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:458
uint8_t flags
Definition: liblwgeom.h:325
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:754
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:966
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:51
#define IS_DIMS(x)
Definition: liblwgeom.h:1367
LWGEOM ** geoms
Definition: liblwgeom.h:465
#define TINTYPE
Definition: liblwgeom.h:74
LWTRIANGLE ** geoms
Definition: liblwgeom.h:543
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:596
POINTARRAY ** rings
Definition: liblwgeom.h:413
static char * asgml3_multi(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1137
int lwpoly_is_empty(const LWPOLY *poly)
Definition: lwpoly.c:327
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:917
int nrings
Definition: liblwgeom.h:411
double ymax
Definition: liblwgeom.h:251
double y
Definition: liblwgeom.h:284
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:106
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:1079
double z
Definition: liblwgeom.h:308
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:884
uint8_t flags
Definition: liblwgeom.h:247
static size_t pointArray_GMLsize(POINTARRAY *pa, int precision)
Definition: lwout_gml.c:1471
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:996
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:65
#define OUT_MAX_DOUBLE
uint8_t flags
Definition: liblwgeom.h:364
int lwline_is_empty(const LWLINE *line)
Definition: lwline.c:464
static char * asgml3_collection(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1377
static size_t asgml2_point_buf(const LWPOINT *point, const char *srs, char *output, int precision, const char *prefix)
Definition: lwout_gml.c:263
char * lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:711
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:472
int ptarray_remove_point(POINTARRAY *pa, int where)
Remove a point from an existing POINTARRAY.
Definition: ptarray.c:246
static char * asgml2_point(const LWPOINT *point, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:282
double zmin
Definition: liblwgeom.h:252
static size_t asgml2_poly_buf(const LWPOLY *poly, const char *srs, char *output, int precision, const char *prefix)
Definition: lwout_gml.c:360
static size_t pointArray_toGML3(POINTARRAY *pa, char *buf, int precision, int opts)
Definition: lwout_gml.c:1393
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:60
int lwpoint_is_empty(const LWPOINT *point)
Definition: lwpoint.c:258
static size_t asgml2_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, int precision, const char *prefix)
Definition: lwout_gml.c:568
uint8_t type
Definition: liblwgeom.h:352
static size_t asgml2_collection_size(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:522
uint8_t flags
Definition: liblwgeom.h:408
static size_t pointArray_toGML2(POINTARRAY *pa, char *buf, int precision)
Definition: lwout_gml.c:637
void * lwalloc(size_t size)
Definition: lwutil.c:175
#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:1229
static size_t asgml2_line_buf(const LWLINE *line, const char *srs, char *output, int precision, const char *prefix)
Definition: lwout_gml.c:306
static char * asgml2_multi(const LWCOLLECTION *col, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:505
double y
Definition: liblwgeom.h:308
#define MULTILINETYPE
Definition: liblwgeom.h:64
uint8_t flags
Definition: liblwgeom.h:375
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:118
int ngeoms
Definition: liblwgeom.h:528
char * lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:178
static char * asgml2_poly(const LWPOLY *poly, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:389
static char * gbox_to_gml2(const GBOX *bbox, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:57
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:1039
if(!(yy_init))
Definition: lwin_wkt_lex.c:860
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:833
static char * asgml3_tin(const LWTIN *tin, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:1267
#define COLLECTIONTYPE
Definition: liblwgeom.h:66
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:1173
uint8_t flags
Definition: liblwgeom.h:386
POINTARRAY * points
Definition: liblwgeom.h:378
static char * gbox_to_gml3(const GBOX *bbox, const char *srs, int precision, int opts, const char *prefix)
Definition: lwout_gml.c:111