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