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