~ubuntu-branches/ubuntu/trusty/postgis/trusty-security

« back to all changes in this revision

Viewing changes to postgis/lwgeom_gml.c

  • Committer: Bazaar Package Importer
  • Author(s): Francesco Paolo Lovergine
  • Date: 2009-12-11 13:10:34 UTC
  • mfrom: (1.1.9 upstream) (5.2.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20091211131034-wmsz69wxvt95pe5r
Tags: 1.4.0-2
* Upload to unstable.
* Better parameterized debian/rules against postgis $(VERSION).
* Added dblatex and libcunit1-dev among build-deps.
* Added postgis_comments.sql to contrib/ SQL templates.
* Dropping 8.3 support, no more supported for squeeze.
  (closes: #559587)
* Do not stop on error in postrm if the target dir does not exist.
  (closes: #560409)

Show diffs side-by-side

added added

removed removed

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