source: trunk/postgis/lwgeom_gml.c @ 4535

Last change on this file since 4535 was 4535, checked in by colivier, 7 years ago

Add geography typmod support for export functions (ST_AsGML, ST_AsGeoJson, ST_KML, St_AsSVG). Create lwgeom_export.c and lwgeom_export.h to factorize common export functions routines.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
  • Property svn:mime-type set to text/plain
File size: 21.5 KB
Line 
1/**********************************************************************
2 * $Id: lwgeom_gml.c 4535 2009-09-28 18:16:21Z colivier $
3 *
4 * PostGIS - Spatial Types for PostgreSQL
5 * http://postgis.refractions.net
6 * Copyright 2001-2003 Refractions Research Inc.
7 *
8 * This is free software; you can redistribute and/or modify it under
9 * the terms of hte GNU General Public Licence. See the COPYING file.
10 *
11 **********************************************************************/
12
13/**
14* @file GML output routines.
15*
16**********************************************************************/
17
18
19#include "postgres.h"
20
21#include "lwgeom_pg.h"
22#include "liblwgeom.h"
23#include "lwgeom_export.h"
24
25
26Datum LWGEOM_asGML(PG_FUNCTION_ARGS);
27
28static size_t asgml2_point_size(LWPOINT *point, char *srs, int precision);
29static char *asgml2_point(LWPOINT *point, char *srs, int precision);
30static size_t asgml2_line_size(LWLINE *line, char *srs, int precision);
31static char *asgml2_line(LWLINE *line, char *srs, int precision);
32static size_t asgml2_poly_size(LWPOLY *poly, char *srs, int precision);
33static char *asgml2_poly(LWPOLY *poly, char *srs, int precision);
34static size_t asgml2_inspected_size(LWGEOM_INSPECTED *geom, char *srs, int precision);
35static char *asgml2_inspected(LWGEOM_INSPECTED *geom, char *srs, int precision);
36static size_t pointArray_toGML2(POINTARRAY *pa, char *buf, int precision);
37
38static size_t asgml3_point_size(LWPOINT *point, char *srs, int precision);
39static char *asgml3_point(LWPOINT *point, char *srs, int precision, bool is_deegree);
40static size_t asgml3_line_size(LWLINE *line, char *srs, int precision);
41static char *asgml3_line(LWLINE *line, char *srs, int precision, bool is_deegree);
42static size_t asgml3_poly_size(LWPOLY *poly, char *srs, int precision);
43static char *asgml3_poly(LWPOLY *poly, char *srs, int precision, bool is_deegree);
44static size_t asgml3_inspected_size(LWGEOM_INSPECTED *geom, char *srs, int precision);
45static char *asgml3_inspected(LWGEOM_INSPECTED *geom, char *srs, int precision, bool is_deegree);
46static size_t pointArray_toGML3(POINTARRAY *pa, char *buf, int precision, bool is_deegree);
47
48static size_t pointArray_GMLsize(POINTARRAY *pa, int precision);
49
50
51/**
52 * Encode feature in GML
53 */
54PG_FUNCTION_INFO_V1(LWGEOM_asGML);
55Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
56{
57        PG_LWGEOM *geom;
58        char *gml;
59        text *result;
60        int len;
61        int version;
62        char *srs;
63        int SRID;
64        int precision = MAX_DOUBLE_PRECISION;
65        int option=0;
66        bool is_deegree = false;
67
68        /* Get the version */
69        version = PG_GETARG_INT32(0);
70        if ( version != 2 && version != 3 )
71        {
72                elog(ERROR, "Only GML 2 and GML 3 are supported");
73                PG_RETURN_NULL();
74        }
75
76        /* Get the geometry */
77        if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
78        geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
79
80        /* Retrieve precision if any (default is max) */
81        if (PG_NARGS() >2 && !PG_ARGISNULL(2))
82        {
83                precision = PG_GETARG_INT32(2);
84                if ( precision > MAX_DOUBLE_PRECISION )
85                        precision = MAX_DOUBLE_PRECISION;
86                else if ( precision < 0 ) precision = 0;
87        }
88
89        /* retrieve option */
90        if (PG_NARGS() >3 && !PG_ARGISNULL(3))
91                option = PG_GETARG_INT32(3);
92
93        SRID = lwgeom_getsrid(SERIALIZED_FORM(geom));
94        if (SRID == -1) srs = NULL;
95        else if (option & 1) srs = getSRSbySRID(SRID, false);
96        else srs = getSRSbySRID(SRID, true);
97
98        if (option & 16) is_deegree = true;
99
100        if (version == 2)
101                gml = geometry_to_gml2(SERIALIZED_FORM(geom), srs, precision);
102        else
103                gml = geometry_to_gml3(SERIALIZED_FORM(geom), srs, precision, is_deegree);
104
105        PG_FREE_IF_COPY(geom, 1);
106
107        len = strlen(gml) + VARHDRSZ;
108
109        result = palloc(len);
110        SET_VARSIZE(result, len);
111
112        memcpy(VARDATA(result), gml, len-VARHDRSZ);
113
114        pfree(gml);
115
116        PG_RETURN_POINTER(result);
117}
118
119
120
121/**
122 *  @brief VERSION GML 2
123 *      takes a GEOMETRY and returns a GML@ representation
124 */
125char *
126geometry_to_gml2(uchar *geom, char *srs, int precision)
127{
128        int type;
129        LWPOINT *point;
130        LWLINE *line;
131        LWPOLY *poly;
132        LWGEOM_INSPECTED *inspected;
133
134        type = lwgeom_getType(geom[0]);
135
136        switch (type)
137        {
138        case POINTTYPE:
139                point = lwpoint_deserialize(geom);
140                return asgml2_point(point, srs, precision);
141
142        case LINETYPE:
143                line = lwline_deserialize(geom);
144                return asgml2_line(line, srs, precision);
145
146        case POLYGONTYPE:
147                poly = lwpoly_deserialize(geom);
148                return asgml2_poly(poly, srs, precision);
149
150        case MULTIPOINTTYPE:
151        case MULTILINETYPE:
152        case MULTIPOLYGONTYPE:
153        case COLLECTIONTYPE:
154                inspected = lwgeom_inspect(geom);
155                return asgml2_inspected(inspected, srs, precision);
156
157        default:
158                lwerror("geometry_to_gml2: '%s' geometry type not supported", lwgeom_typename(type));
159                return NULL;
160        }
161}
162
163static size_t
164asgml2_point_size(LWPOINT *point, char *srs, int precision)
165{
166        int size;
167        size = pointArray_GMLsize(point->point, precision);
168        size += sizeof("<gml:point><gml:coordinates>/") * 2;
169        if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
170        return size;
171}
172
173static size_t
174asgml2_point_buf(LWPOINT *point, char *srs, char *output, int precision)
175{
176        char *ptr = output;
177
178        if ( srs )
179        {
180                ptr += sprintf(ptr, "<gml:Point srsName=\"%s\">", srs);
181        }
182        else
183        {
184                ptr += sprintf(ptr, "<gml:Point>");
185        }
186        ptr += sprintf(ptr, "<gml:coordinates>");
187        ptr += pointArray_toGML2(point->point, ptr, precision);
188        ptr += sprintf(ptr, "</gml:coordinates></gml:Point>");
189
190        return (ptr-output);
191}
192
193static char *
194asgml2_point(LWPOINT *point, char *srs, int precision)
195{
196        char *output;
197        int size;
198
199        size = asgml2_point_size(point, srs, precision);
200        output = palloc(size);
201        asgml2_point_buf(point, srs, output, precision);
202        return output;
203}
204
205static size_t
206asgml2_line_size(LWLINE *line, char *srs, int precision)
207{
208        int size;
209        size = pointArray_GMLsize(line->points, precision);
210        size += sizeof("<gml:linestring><gml:coordinates>/") * 2;
211        if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
212        return size;
213}
214
215static size_t
216asgml2_line_buf(LWLINE *line, char *srs, char *output, int precision)
217{
218        char *ptr=output;
219
220        if ( srs )
221        {
222                ptr += sprintf(ptr, "<gml:LineString srsName=\"%s\">", srs);
223        }
224        else
225        {
226                ptr += sprintf(ptr, "<gml:LineString>");
227        }
228        ptr += sprintf(ptr, "<gml:coordinates>");
229        ptr += pointArray_toGML2(line->points, ptr, precision);
230        ptr += sprintf(ptr, "</gml:coordinates></gml:LineString>");
231
232        return (ptr-output);
233}
234
235static char *
236asgml2_line(LWLINE *line, char *srs, int precision)
237{
238        char *output;
239        int size;
240
241        size = asgml2_line_size(line, srs, precision);
242        output = palloc(size);
243        asgml2_line_buf(line, srs, output, precision);
244        return output;
245}
246
247static size_t
248asgml2_poly_size(LWPOLY *poly, char *srs, int precision)
249{
250        size_t size;
251        int i;
252
253        size = sizeof("<gml:polygon></gml:polygon>");
254        size += sizeof("<gml:outerboundaryis><gml:linearring><gml:coordinates>/") * 2;
255        size += sizeof("<gml:innerboundaryis><gml:linearring><gml:coordinates>/") * 2 *
256                poly->nrings;
257        if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
258
259        for (i=0; i<poly->nrings; i++)
260                size += pointArray_GMLsize(poly->rings[i], precision);
261
262        return size;
263}
264
265static size_t
266asgml2_poly_buf(LWPOLY *poly, char *srs, char *output, int precision)
267{
268        int i;
269        char *ptr=output;
270
271        if ( srs )
272        {
273                ptr += sprintf(ptr, "<gml:Polygon srsName=\"%s\">", srs);
274        }
275        else
276        {
277                ptr += sprintf(ptr, "<gml:Polygon>");
278        }
279        ptr += sprintf(ptr, "<gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>");
280        ptr += pointArray_toGML2(poly->rings[0], ptr, precision);
281        ptr += sprintf(ptr, "</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs>");
282        for (i=1; i<poly->nrings; i++)
283        {
284                ptr += sprintf(ptr, "<gml:innerBoundaryIs><gml:LinearRing><gml:coordinates>");
285                ptr += pointArray_toGML2(poly->rings[i], ptr, precision);
286                ptr += sprintf(ptr, "</gml:coordinates></gml:LinearRing></gml:innerBoundaryIs>");
287        }
288        ptr += sprintf(ptr, "</gml:Polygon>");
289
290        return (ptr-output);
291}
292
293static char *
294asgml2_poly(LWPOLY *poly, char *srs, int precision)
295{
296        char *output;
297        int size;
298
299        size = asgml2_poly_size(poly, srs, precision);
300        output = palloc(size);
301        asgml2_poly_buf(poly, srs, output, precision);
302        return output;
303}
304
305/*
306 * Compute max size required for GML version of this
307 * inspected geometry. Will recurse when needed.
308 * Don't call this with single-geoms inspected.
309 */
310static size_t
311asgml2_inspected_size(LWGEOM_INSPECTED *insp, char *srs, int precision)
312{
313        int i;
314        size_t size;
315
316        /* the longest possible multi version */
317        size = sizeof("<gml:MultiLineString></gml:MultiLineString>");
318
319        if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
320
321        for (i=0; i<insp->ngeometries; i++)
322        {
323                LWPOINT *point;
324                LWLINE *line;
325                LWPOLY *poly;
326                LWGEOM_INSPECTED *subinsp;
327                uchar *subgeom;
328
329                if ((point=lwgeom_getpoint_inspected(insp, i)))
330                {
331                        size += sizeof("<gml:pointMember>/") * 2;
332                        size += asgml2_point_size(point, 0, precision);
333                        lwpoint_release(point);
334                }
335                else if ((line=lwgeom_getline_inspected(insp, i)))
336                {
337                        size += sizeof("<gml:lineStringMember>/") * 2;
338                        size += asgml2_line_size(line, 0, precision);
339                        lwline_release(line);
340                }
341                else if ((poly=lwgeom_getpoly_inspected(insp, i)))
342                {
343                        size += sizeof("<gml:polygonMember>/") * 2;
344                        size += asgml2_poly_size(poly, 0, precision);
345                        lwpoly_release(poly);
346                }
347                else
348                {
349                        subgeom = lwgeom_getsubgeometry_inspected(insp, i);
350                        subinsp = lwgeom_inspect(subgeom);
351                        size += asgml2_inspected_size(subinsp, 0, precision);
352                        lwinspected_release(subinsp);
353                }
354        }
355
356        return size;
357}
358
359/*
360 * Don't call this with single-geoms inspected!
361 */
362static size_t
363asgml2_inspected_buf(LWGEOM_INSPECTED *insp, char *srs, char *output, int precision)
364{
365        int type = lwgeom_getType(insp->serialized_form[0]);
366        char *ptr, *gmltype;
367        int i;
368
369        ptr = output;
370
371        if (type == MULTIPOINTTYPE) gmltype = "MultiPoint";
372        else if (type == MULTILINETYPE) gmltype = "MultiLineString";
373        else if (type == MULTIPOLYGONTYPE) gmltype = "MultiPolygon";
374        else gmltype = "MultiGeometry";
375
376        /* Open outmost tag */
377        if ( srs )
378        {
379                ptr += sprintf(ptr, "<gml:%s srsName=\"%s\">", gmltype, srs);
380        }
381        else
382        {
383                ptr += sprintf(ptr, "<gml:%s>", gmltype);
384        }
385
386        for (i=0; i<insp->ngeometries; i++)
387        {
388                LWPOINT *point;
389                LWLINE *line;
390                LWPOLY *poly;
391                LWGEOM_INSPECTED *subinsp;
392                uchar *subgeom;
393
394                if ((point=lwgeom_getpoint_inspected(insp, i)))
395                {
396                        ptr += sprintf(ptr, "<gml:pointMember>");
397                        ptr += asgml2_point_buf(point, 0, ptr, precision);
398                        lwpoint_release(point);
399                        ptr += sprintf(ptr, "</gml:pointMember>");
400                }
401                else if ((line=lwgeom_getline_inspected(insp, i)))
402                {
403                        ptr += sprintf(ptr, "<gml:lineStringMember>");
404                        ptr += asgml2_line_buf(line, 0, ptr, precision);
405                        lwline_release(line);
406                        ptr += sprintf(ptr, "</gml:lineStringMember>");
407                }
408                else if ((poly=lwgeom_getpoly_inspected(insp, i)))
409                {
410                        ptr += sprintf(ptr, "<gml:polygonMember>");
411                        ptr += asgml2_poly_buf(poly, 0, ptr, precision);
412                        lwpoly_release(poly);
413                        ptr += sprintf(ptr, "</gml:polygonMember>");
414                }
415                else
416                {
417                        subgeom = lwgeom_getsubgeometry_inspected(insp, i);
418                        subinsp = lwgeom_inspect(subgeom);
419                        ptr += asgml2_inspected_buf(subinsp, 0, ptr, precision);
420                        lwinspected_release(subinsp);
421                }
422        }
423
424        /* Close outmost tag */
425        ptr += sprintf(ptr, "</gml:%s>", gmltype);
426
427        return (ptr-output);
428}
429
430/*
431 * Don't call this with single-geoms inspected!
432 */
433static char *
434asgml2_inspected(LWGEOM_INSPECTED *insp, char *srs, int precision)
435{
436        char *gml;
437        size_t size;
438
439        size = asgml2_inspected_size(insp, srs, precision);
440        gml = palloc(size);
441        asgml2_inspected_buf(insp, srs, gml, precision);
442        return gml;
443}
444
445static size_t
446pointArray_toGML2(POINTARRAY *pa, char *output, int precision)
447{
448        int i;
449        char *ptr;
450        char x[MAX_DIGS_DOUBLE+MAX_DOUBLE_PRECISION+1];
451        char y[MAX_DIGS_DOUBLE+MAX_DOUBLE_PRECISION+1];
452        char z[MAX_DIGS_DOUBLE+MAX_DOUBLE_PRECISION+1];
453
454        ptr = output;
455
456        if ( ! TYPE_HASZ(pa->dims) )
457        {
458                for (i=0; i<pa->npoints; i++)
459                {
460                        POINT2D pt;
461                        getPoint2d_p(pa, i, &pt);
462                        sprintf(x, "%.*f", precision, pt.x);
463                        trim_trailing_zeros(x);
464                        sprintf(y, "%.*f", precision, pt.y);
465                        trim_trailing_zeros(y);
466                        if ( i ) ptr += sprintf(ptr, " ");
467                        ptr += sprintf(ptr, "%s,%s", x, y);
468                }
469        }
470        else
471        {
472                for (i=0; i<pa->npoints; i++)
473                {
474                        POINT4D pt;
475                        getPoint4d_p(pa, i, &pt);
476                        sprintf(x, "%.*f", precision, pt.x);
477                        trim_trailing_zeros(x);
478                        sprintf(y, "%.*f", precision, pt.y);
479                        trim_trailing_zeros(y);
480                        sprintf(z, "%.*f", precision, pt.z);
481                        trim_trailing_zeros(z);
482                        if ( i ) ptr += sprintf(ptr, " ");
483                        ptr += sprintf(ptr, "%s,%s,%s", x, y, z);
484                }
485        }
486
487        return ptr-output;
488}
489
490
491/*
492 * VERSION GML 3.1.1
493 */
494
495
496/* takes a GEOMETRY and returns a GML representation */
497char *
498geometry_to_gml3(uchar *geom, char *srs, int precision, bool is_deegree)
499{
500        int type;
501        LWPOINT *point;
502        LWLINE *line;
503        LWPOLY *poly;
504        LWGEOM_INSPECTED *inspected;
505
506        type = lwgeom_getType(geom[0]);
507
508        switch (type)
509        {
510        case POINTTYPE:
511                point = lwpoint_deserialize(geom);
512                return asgml3_point(point, srs, precision, is_deegree);
513
514        case LINETYPE:
515                line = lwline_deserialize(geom);
516                return asgml3_line(line, srs, precision, is_deegree);
517
518        case POLYGONTYPE:
519                poly = lwpoly_deserialize(geom);
520                return asgml3_poly(poly, srs, precision, is_deegree);
521
522        default:
523                inspected = lwgeom_inspect(geom);
524                return asgml3_inspected(inspected, srs, precision, is_deegree);
525        }
526}
527
528static size_t
529asgml3_point_size(LWPOINT *point, char *srs, int precision)
530{
531        int size;
532        size = pointArray_GMLsize(point->point, precision);
533        size += sizeof("<gml:point><gml:pos>/") * 2;
534        if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
535        return size;
536}
537
538static size_t
539asgml3_point_buf(LWPOINT *point, char *srs, char *output, int precision, bool is_deegree)
540{
541        char *ptr = output;
542
543        if ( srs )
544        {
545                ptr += sprintf(ptr, "<gml:Point srsName=\"%s\">", srs);
546        }
547        else
548        {
549                ptr += sprintf(ptr, "<gml:Point>");
550        }
551        ptr += sprintf(ptr, "<gml:pos>");
552        ptr += pointArray_toGML3(point->point, ptr, precision, is_deegree);
553        ptr += sprintf(ptr, "</gml:pos></gml:Point>");
554
555        return (ptr-output);
556}
557
558static char *
559asgml3_point(LWPOINT *point, char *srs, int precision, bool is_deegree)
560{
561        char *output;
562        int size;
563
564        size = asgml3_point_size(point, srs, precision);
565        output = palloc(size);
566        asgml3_point_buf(point, srs, output, precision, is_deegree);
567        return output;
568}
569
570
571static size_t
572asgml3_line_size(LWLINE *line, char *srs, int precision)
573{
574        int size;
575        size = pointArray_GMLsize(line->points, precision);
576        size += sizeof("<gml:Curve><gml:segments><gml:LineStringSegment><gml:posList>/") * 2;
577        if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
578        return size;
579}
580
581static size_t
582asgml3_line_buf(LWLINE *line, char *srs, char *output, int precision, bool is_deegree)
583{
584        char *ptr=output;
585
586        if ( srs )
587        {
588                ptr += sprintf(ptr, "<gml:Curve srsName=\"%s\">", srs);
589        }
590        else
591        {
592                ptr += sprintf(ptr, "<gml:Curve>");
593        }
594        ptr += sprintf(ptr, "<gml:segments>");
595        ptr += sprintf(ptr, "<gml:LineStringSegment>");
596        ptr += sprintf(ptr, "<gml:posList>");
597        ptr += pointArray_toGML3(line->points, ptr, precision, is_deegree);
598        ptr += sprintf(ptr, "</gml:posList></gml:LineStringSegment>");
599        ptr += sprintf(ptr, "</gml:segments>");
600        ptr += sprintf(ptr, "</gml:Curve>");
601
602        return (ptr-output);
603}
604
605static char *
606asgml3_line(LWLINE *line, char *srs, int precision, bool is_deegree)
607{
608        char *output;
609        int size;
610
611        size = asgml3_line_size(line, srs, precision);
612        output = palloc(size);
613        asgml3_line_buf(line, srs, output, precision, is_deegree);
614        return output;
615}
616
617
618static size_t
619asgml3_poly_size(LWPOLY *poly, char *srs, int precision)
620{
621        size_t size;
622        int i;
623
624        size = sizeof("<gml:Polygon>");
625
626        size += sizeof("<gml:exterior><gml:LinearRing><gml:posList>");
627        size += sizeof("</gml:posList></gml:LinearRing></gml:exterior>");
628
629        size += sizeof("<gml:interior><gml:LinearRing><gml:posList>") * (poly->nrings - 1);
630        size += sizeof("</gml:posList></gml:LinearRing></gml:interior>") * (poly->nrings - 1);
631
632        size += sizeof("</gml:Polygon>");
633
634        if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
635
636        for (i=0; i<poly->nrings; i++)
637                size += pointArray_GMLsize(poly->rings[i], precision);
638
639        return size;
640}
641
642static size_t
643asgml3_poly_buf(LWPOLY *poly, char *srs, char *output, int precision, bool is_deegree)
644{
645        int i;
646        char *ptr=output;
647
648        if ( srs )
649        {
650                ptr += sprintf(ptr, "<gml:Polygon srsName=\"%s\">", srs);
651        }
652        else
653        {
654                ptr += sprintf(ptr, "<gml:Polygon>");
655        }
656        ptr += sprintf(ptr, "<gml:exterior><gml:LinearRing><gml:posList>");
657        ptr += pointArray_toGML3(poly->rings[0], ptr, precision, is_deegree);
658        ptr += sprintf(ptr, "</gml:posList></gml:LinearRing></gml:exterior>");
659        for (i=1; i<poly->nrings; i++)
660        {
661                ptr += sprintf(ptr, "<gml:interior><gml:LinearRing><gml:posList>");
662                ptr += pointArray_toGML3(poly->rings[i], ptr, precision, is_deegree);
663                ptr += sprintf(ptr, "</gml:posList></gml:LinearRing></gml:interior>");
664        }
665        ptr += sprintf(ptr, "</gml:Polygon>");
666
667        return (ptr-output);
668}
669
670static char *
671asgml3_poly(LWPOLY *poly, char *srs, int precision, bool is_deegree)
672{
673        char *output;
674        int size;
675
676        size = asgml3_poly_size(poly, srs, precision);
677        output = palloc(size);
678        asgml3_poly_buf(poly, srs, output, precision, is_deegree);
679        return output;
680}
681
682/*
683 * Compute max size required for GML version of this
684 * inspected geometry. Will recurse when needed.
685 * Don't call this with single-geoms inspected.
686 */
687static size_t
688asgml3_inspected_size(LWGEOM_INSPECTED *insp, char *srs, int precision)
689{
690        int i;
691        size_t size;
692
693        /* the longest possible multi version */
694        size = sizeof("<gml:MultiLineString></gml:MultiLineString>");
695
696        if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
697
698        for (i=0; i<insp->ngeometries; i++)
699        {
700                LWPOINT *point;
701                LWLINE *line;
702                LWPOLY *poly;
703                LWGEOM_INSPECTED *subinsp;
704                uchar *subgeom;
705
706                if ((point=lwgeom_getpoint_inspected(insp, i)))
707                {
708                        size += sizeof("<gml:pointMember>/") * 2;
709                        size += asgml3_point_size(point, 0, precision);
710                        lwpoint_release(point);
711                }
712                else if ((line=lwgeom_getline_inspected(insp, i)))
713                {
714                        size += sizeof("<gml:curveMember>/") * 2;
715                        size += asgml3_line_size(line, 0, precision);
716                        lwline_release(line);
717                }
718                else if ((poly=lwgeom_getpoly_inspected(insp, i)))
719                {
720                        size += sizeof("<gml:surfaceMember>/") * 2;
721                        size += asgml3_poly_size(poly, 0, precision);
722                        lwpoly_release(poly);
723                }
724                else
725                {
726                        subgeom = lwgeom_getsubgeometry_inspected(insp, i);
727                        subinsp = lwgeom_inspect(subgeom);
728                        size += asgml3_inspected_size(subinsp, 0, precision);
729                        lwinspected_release(subinsp);
730                }
731        }
732
733        return size;
734}
735
736/*
737 * Don't call this with single-geoms inspected!
738 */
739static size_t
740asgml3_inspected_buf(LWGEOM_INSPECTED *insp, char *srs, char *output, int precision, bool is_deegree)
741{
742        int type = lwgeom_getType(insp->serialized_form[0]);
743        char *ptr, *gmltype;
744        int i;
745
746        ptr = output;
747
748        if (type == MULTIPOINTTYPE) gmltype = "MultiPoint";
749        else if (type == MULTILINETYPE) gmltype = "MultiCurve";
750        else if (type == MULTIPOLYGONTYPE) gmltype = "MultiSurface";
751        else gmltype = "MultiGeometry";
752
753        /* Open outmost tag */
754        if ( srs )
755        {
756                ptr += sprintf(ptr, "<gml:%s srsName=\"%s\">", gmltype, srs);
757        }
758        else
759        {
760                ptr += sprintf(ptr, "<gml:%s>", gmltype);
761        }
762
763        for (i=0; i<insp->ngeometries; i++)
764        {
765                LWPOINT *point;
766                LWLINE *line;
767                LWPOLY *poly;
768                LWGEOM_INSPECTED *subinsp;
769                uchar *subgeom;
770
771                if ((point=lwgeom_getpoint_inspected(insp, i)))
772                {
773                        ptr += sprintf(ptr, "<gml:pointMember>");
774                        ptr += asgml3_point_buf(point, 0, ptr, precision, is_deegree);
775                        lwpoint_release(point);
776                        ptr += sprintf(ptr, "</gml:pointMember>");
777                }
778                else if ((line=lwgeom_getline_inspected(insp, i)))
779                {
780                        ptr += sprintf(ptr, "<gml:curveMember>");
781                        ptr += asgml3_line_buf(line, 0, ptr, precision, is_deegree);
782                        lwline_release(line);
783                        ptr += sprintf(ptr, "</gml:curveMember>");
784                }
785                else if ((poly=lwgeom_getpoly_inspected(insp, i)))
786                {
787                        ptr += sprintf(ptr, "<gml:surfaceMember>");
788                        ptr += asgml3_poly_buf(poly, 0, ptr, precision, is_deegree);
789                        lwpoly_release(poly);
790                        ptr += sprintf(ptr, "</gml:surfaceMember>");
791                }
792                else
793                {
794                        subgeom = lwgeom_getsubgeometry_inspected(insp, i);
795                        subinsp = lwgeom_inspect(subgeom);
796                        ptr += asgml3_inspected_buf(subinsp, 0, ptr, precision, is_deegree);
797                        lwinspected_release(subinsp);
798                }
799        }
800
801        /* Close outmost tag */
802        ptr += sprintf(ptr, "</gml:%s>", gmltype);
803
804        return (ptr-output);
805}
806
807/*
808 * Don't call this with single-geoms inspected!
809 */
810static char *
811asgml3_inspected(LWGEOM_INSPECTED *insp, char *srs, int precision, bool is_deegree)
812{
813        char *gml;
814        size_t size;
815
816        size = asgml3_inspected_size(insp, srs, precision);
817        gml = palloc(size);
818        asgml3_inspected_buf(insp, srs, gml, precision, is_deegree);
819        return gml;
820}
821
822/* In GML3, inside <posList> or <pos>, coordinates are separated by a space separator
823 * In GML3 also, lat/lon are reversed for geocentric data
824 */
825static size_t
826pointArray_toGML3(POINTARRAY *pa, char *output, int precision, bool is_deegree)
827{
828        int i;
829        char *ptr;
830        char x[MAX_DIGS_DOUBLE+MAX_DOUBLE_PRECISION+1];
831        char y[MAX_DIGS_DOUBLE+MAX_DOUBLE_PRECISION+1];
832        char z[MAX_DIGS_DOUBLE+MAX_DOUBLE_PRECISION+1];
833
834        ptr = output;
835
836        if ( ! TYPE_HASZ(pa->dims) )
837        {
838                for (i=0; i<pa->npoints; i++)
839                {
840                        POINT2D pt;
841                        getPoint2d_p(pa, i, &pt);
842                        sprintf(x, "%.*f", precision, pt.x);
843                        trim_trailing_zeros(x);
844                        sprintf(y, "%.*f", precision, pt.y);
845                        trim_trailing_zeros(y);
846                        if ( i ) ptr += sprintf(ptr, " ");
847                        if (is_deegree)
848                                ptr += sprintf(ptr, "%s %s", y, x);
849                        else
850                                ptr += sprintf(ptr, "%s %s", x, y);
851                }
852        }
853        else
854        {
855                for (i=0; i<pa->npoints; i++)
856                {
857                        POINT4D pt;
858                        getPoint4d_p(pa, i, &pt);
859                        sprintf(x, "%.*f", precision, pt.x);
860                        trim_trailing_zeros(x);
861                        sprintf(y, "%.*f", precision, pt.y);
862                        trim_trailing_zeros(y);
863                        sprintf(z, "%.*f", precision, pt.z);
864                        trim_trailing_zeros(z);
865                        if ( i ) ptr += sprintf(ptr, " ");
866                        if (is_deegree)
867                                ptr += sprintf(ptr, "%s %s %s", y, x, z);
868                        else
869                                ptr += sprintf(ptr, "%s %s %s", x, y, z);
870                }
871        }
872
873        return ptr-output;
874}
875
876
877
878/*
879 * Returns maximum size of rendered pointarray in bytes.
880 */
881static size_t
882pointArray_GMLsize(POINTARRAY *pa, int precision)
883{
884        if (TYPE_NDIMS(pa->dims) == 2)
885                return (MAX_DIGS_DOUBLE + precision + sizeof(", "))
886                       * 2 * pa->npoints;
887
888        return (MAX_DIGS_DOUBLE + precision + sizeof(", ")) * 3 * pa->npoints;
889}
Note: See TracBrowser for help on using the repository browser.