PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwgeom_export.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 2009-2011 Olivier Courtin <olivier.courtin@oslandia.com>
22 *
23 **********************************************************************/
24
25
26
31#include "postgres.h"
32#include "catalog/pg_type.h" /* for INT4OID */
33#include "executor/spi.h"
34#include "utils/builtins.h"
35#include "utils/jsonb.h"
36
37#include "../postgis_config.h"
38#include "lwgeom_cache.h"
39#include "lwgeom_pg.h"
40#include "liblwgeom.h"
41#include "liblwgeom_internal.h"
42
43Datum LWGEOM_asGML(PG_FUNCTION_ARGS);
44Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS);
45Datum LWGEOM_asGeoJson_old(PG_FUNCTION_ARGS);
46Datum LWGEOM_asSVG(PG_FUNCTION_ARGS);
47Datum LWGEOM_asX3D(PG_FUNCTION_ARGS);
48Datum LWGEOM_asEncodedPolyline(PG_FUNCTION_ARGS);
49Datum geometry_to_json(PG_FUNCTION_ARGS);
50Datum geometry_to_jsonb(PG_FUNCTION_ARGS);
51
56Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
57{
58 GSERIALIZED *geom;
59 LWGEOM *lwgeom;
60 lwvarlena_t *v = NULL;
61 int version;
62 const char *srs;
63 int32_t srid;
64 int option = 0;
65 int lwopts = LW_GML_IS_DIMS;
67 static const char* default_prefix = "gml:"; /* default prefix */
68 const char* prefix = default_prefix;
69 const char* gml_id = NULL;
70 size_t len;
71 char *gml_id_buf, *prefix_buf;
72 text *prefix_text, *gml_id_text;
73
74 /*
75 * Two potential callers, one starts with GML version,
76 * one starts with geometry, and we check for initial
77 * argument type and then dynamically change what args
78 * we read based on presence/absence
79 */
80 Oid first_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
81 int argnum = 0;
82 if (first_type != INT4OID)
83 {
84 version = 2;
85 }
86 else
87 {
88 /* Get the version */
89 version = PG_GETARG_INT32(argnum++);
90 if (version != 2 && version != 3)
91 {
92 elog(ERROR, "Only GML 2 and GML 3 are supported");
93 PG_RETURN_NULL();
94 }
95 }
96
97 /* Get the geometry */
98 if (PG_ARGISNULL(argnum))
99 PG_RETURN_NULL();
100 geom = PG_GETARG_GSERIALIZED_P(argnum++);
101
102 /* Retrieve precision if any (default is max) */
103 if (PG_NARGS() > argnum && !PG_ARGISNULL(argnum))
104 {
105 precision = PG_GETARG_INT32(argnum);
106 }
107 argnum++;
108
109 /* retrieve option */
110 if (PG_NARGS() > argnum && !PG_ARGISNULL(argnum))
111 option = PG_GETARG_INT32(argnum);
112 argnum++;
113
114 /* retrieve prefix */
115 if (PG_NARGS() > argnum && !PG_ARGISNULL(argnum))
116 {
117 prefix_text = PG_GETARG_TEXT_P(argnum);
118 if ( VARSIZE(prefix_text) == VARHDRSZ )
119 {
120 prefix = "";
121 }
122 else
123 {
124 len = VARSIZE_ANY_EXHDR(prefix_text);
125 prefix_buf = palloc(len + 2); /* +2 is one for the ':' and one for term null */
126 memcpy(prefix_buf, VARDATA(prefix_text), len);
127 /* add colon and null terminate */
128 prefix_buf[len] = ':';
129 prefix_buf[len+1] = '\0';
130 prefix = prefix_buf;
131 }
132 }
133 argnum++;
134
135 if (PG_NARGS() > argnum && !PG_ARGISNULL(argnum))
136 {
137 gml_id_text = PG_GETARG_TEXT_P(argnum);
138 if ( VARSIZE(gml_id_text) == VARHDRSZ )
139 {
140 gml_id = "";
141 }
142 else
143 {
144 len = VARSIZE_ANY_EXHDR(gml_id_text);
145 gml_id_buf = palloc(len+1);
146 memcpy(gml_id_buf, VARDATA(gml_id_text), len);
147 gml_id_buf[len] = '\0';
148 gml_id = gml_id_buf;
149 }
150 }
151 argnum++;
152
153 srid = gserialized_get_srid(geom);
154 if (srid == SRID_UNKNOWN) srs = NULL;
155 else if (option & 1)
156 srs = GetSRSCacheBySRID(fcinfo, srid, false);
157 else
158 srs = GetSRSCacheBySRID(fcinfo, srid, true);
159
160 if (option & 2) lwopts &= ~LW_GML_IS_DIMS;
161 if (option & 4) lwopts |= LW_GML_SHORTLINE;
162 if (option & 8)
163 {
164 elog(ERROR,
165 "Options %d passed to ST_AsGML(geometry) sets "
166 "unsupported value 8",
167 option);
168 PG_RETURN_NULL();
169 }
170 if (option & 16) lwopts |= LW_GML_IS_DEGREE;
171 if (option & 32) lwopts |= LW_GML_EXTENT;
172
173 lwgeom = lwgeom_from_gserialized(geom);
174
175 if (version == 2)
176 {
177 if (lwopts & LW_GML_EXTENT)
178 v = lwgeom_extent_to_gml2(lwgeom, srs, precision, prefix);
179 else
180 v = lwgeom_to_gml2(lwgeom, srs, precision, prefix);
181 }
182 if (version == 3)
183 {
184 if (lwopts & LW_GML_EXTENT)
185 v = lwgeom_extent_to_gml3(lwgeom, srs, precision, lwopts, prefix);
186 else
187 v = lwgeom_to_gml3(lwgeom, srs, precision, lwopts, prefix, gml_id);
188 }
189
190 if (!v)
191 PG_RETURN_NULL();
192 PG_RETURN_TEXT_P(v);
193}
194
195
200Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
201{
202 GSERIALIZED *geom;
203 LWGEOM *lwgeom;
205 int output_bbox = LW_FALSE;
206 int output_long_crs = LW_FALSE;
207 int output_short_crs = LW_FALSE;
208 int output_guess_short_srid = LW_FALSE;
209 const char *srs = NULL;
210 int32_t srid;
211
212 /* Get the geometry */
213 if (PG_ARGISNULL(0))
214 PG_RETURN_NULL();
215
216 geom = PG_GETARG_GSERIALIZED_P(0);
217 srid = gserialized_get_srid(geom);
218
219 /* Retrieve precision if any (default is max) */
220 if ( PG_NARGS() > 1 && !PG_ARGISNULL(1) )
221 {
222 precision = PG_GETARG_INT32(1);
223 }
224
225 /* Retrieve output option
226 * 0 = without option
227 * 1 = bbox
228 * 2 = short crs
229 * 4 = long crs
230 * 8 = guess if CRS is needed (default)
231 */
232 if (PG_NARGS() > 2 && !PG_ARGISNULL(2))
233 {
234 int option = PG_GETARG_INT32(2);
235 output_guess_short_srid = (option & 8) ? LW_TRUE : LW_FALSE;
236 output_short_crs = (option & 2) ? LW_TRUE : LW_FALSE;
237 output_long_crs = (option & 4) ? LW_TRUE : LW_FALSE;
238 output_bbox = (option & 1) ? LW_TRUE : LW_FALSE;
239 }
240 else
241 output_guess_short_srid = LW_TRUE;
242
243 if (output_guess_short_srid && srid != WGS84_SRID && srid != SRID_UNKNOWN)
244 output_short_crs = LW_TRUE;
245
246 if (srid != SRID_UNKNOWN && (output_short_crs || output_long_crs))
247 {
248 srs = GetSRSCacheBySRID(fcinfo, srid, !output_long_crs);
249
250 if (!srs)
251 {
252 elog(ERROR, "SRID %i unknown in spatial_ref_sys table", srid);
253 PG_RETURN_NULL();
254 }
255 }
256
257 lwgeom = lwgeom_from_gserialized(geom);
258 PG_RETURN_TEXT_P(lwgeom_to_geojson(lwgeom, srs, precision, output_bbox));
259}
260
261
266Datum geometry_to_json(PG_FUNCTION_ARGS)
267{
268 GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
269 LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
270 const char *srs = NULL;
271 lwvarlena_t *geojson;
272 if (lwgeom->srid != SRID_UNKNOWN)
273 {
274 const int short_crs = LW_TRUE;
275 srs = GetSRSCacheBySRID(fcinfo, lwgeom->srid, short_crs);
276 }
277 geojson = lwgeom_to_geojson(lwgeom, srs, 15, 0);
278 lwgeom_free(lwgeom);
279 PG_FREE_IF_COPY(geom, 0);
280 PG_RETURN_TEXT_P(geojson);
281}
282
284Datum geometry_to_jsonb(PG_FUNCTION_ARGS)
285{
286 GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
287 LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
288 const char *srs = NULL;
289 char *cstr;
290 lwvarlena_t *geojson;
291 if (lwgeom->srid != SRID_UNKNOWN)
292 {
293 const int short_crs = LW_TRUE;
294 srs = GetSRSCacheBySRID(fcinfo, lwgeom->srid, short_crs);
295 }
296 geojson = lwgeom_to_geojson(lwgeom, srs, 15, 0);
297 lwgeom_free(lwgeom);
298 cstr = palloc0(VARSIZE_ANY_EXHDR(geojson) + 1);
299 memcpy(cstr, VARDATA(geojson), VARSIZE_ANY_EXHDR(geojson));
300 PG_RETURN_DATUM(DirectFunctionCall1(jsonb_in, PointerGetDatum(cstr)));
301}
302
303
308Datum LWGEOM_asSVG(PG_FUNCTION_ARGS)
309{
310 GSERIALIZED *geom;
311 LWGEOM *lwgeom;
312 int relative = 0;
314
315 if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
316
317 geom = PG_GETARG_GSERIALIZED_P(0);
318
319 /* check for relative path notation */
320 if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
321 relative = PG_GETARG_INT32(1) ? 1:0;
322
323 if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
324 {
325 precision = PG_GETARG_INT32(2);
326 }
327
328 lwgeom = lwgeom_from_gserialized(geom);
329 PG_RETURN_TEXT_P(lwgeom_to_svg(lwgeom, precision, relative));
330}
331
336Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
337{
338 GSERIALIZED *geom;
339 LWGEOM *lwgeom;
340 int version;
341 int option = 0;
343 static const char* default_defid = "x3d:"; /* default defid */
344 char *defidbuf;
345 const char* defid = default_defid;
346 text *defid_text;
347
348 /* Get the version */
349 version = PG_GETARG_INT32(0);
350 if ( version != 3 )
351 {
352 elog(ERROR, "Only X3D version 3 are supported");
353 PG_RETURN_NULL();
354 }
355
356 /* Get the geometry */
357 if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
358 geom = PG_GETARG_GSERIALIZED_P(1);
359
360 /* Retrieve precision if any (default is max) */
361 if (PG_NARGS() >2 && !PG_ARGISNULL(2))
362 {
363 precision = PG_GETARG_INT32(2);
364 }
365
366 /* retrieve option */
367 if (PG_NARGS() >3 && !PG_ARGISNULL(3))
368 option = PG_GETARG_INT32(3);
369
370
371 /* retrieve defid */
372 if (PG_NARGS() >4 && !PG_ARGISNULL(4))
373 {
374 defid_text = PG_GETARG_TEXT_P(4);
375 if ( VARSIZE_ANY_EXHDR(defid_text) == 0 )
376 {
377 defid = "";
378 }
379 else
380 {
381 /* +2 is one for the ':' and one for term null */
382 defidbuf = palloc(VARSIZE_ANY_EXHDR(defid_text)+2);
383 memcpy(defidbuf, VARDATA(defid_text),
384 VARSIZE_ANY_EXHDR(defid_text));
385 /* add colon and null terminate */
386 defidbuf[VARSIZE_ANY_EXHDR(defid_text)] = ':';
387 defidbuf[VARSIZE_ANY_EXHDR(defid_text)+1] = '\0';
388 defid = defidbuf;
389 }
390 }
391
392 lwgeom = lwgeom_from_gserialized(geom);
393
394 if (option & LW_X3D_USE_GEOCOORDS) {
395 if (lwgeom->srid != 4326)
396 {
397 PG_FREE_IF_COPY(geom, 1);
400 elog(ERROR, "Only SRID 4326 is supported for geocoordinates.");
401 PG_RETURN_NULL();
402 }
403 }
404
405 PG_RETURN_TEXT_P(lwgeom_to_x3d3(lwgeom, precision, option, defid));
406}
407
412Datum LWGEOM_asEncodedPolyline(PG_FUNCTION_ARGS)
413{
414 GSERIALIZED *geom;
415 LWGEOM *lwgeom;
416 int precision = 5;
417
418 if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
419
420 geom = PG_GETARG_GSERIALIZED_P(0);
421 if (gserialized_get_srid(geom) != 4326) {
422 PG_FREE_IF_COPY(geom, 0);
423 elog(ERROR, "Only SRID 4326 is supported.");
424 PG_RETURN_NULL();
425 }
426 lwgeom = lwgeom_from_gserialized(geom);
427
428 if (PG_NARGS() > 1 && !PG_ARGISNULL(1))
429 {
430 precision = PG_GETARG_INT32(1);
431 if ( precision < 0 ) precision = 5;
432 }
433
434 PG_RETURN_TEXT_P(lwgeom_to_encoded_polyline(lwgeom, precision));
435}
static uint8_t precision
Definition cu_in_twkb.c:25
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
lwvarlena_t * lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix)
Definition lwout_gml.c:1081
#define WGS84_SRID
Definition liblwgeom.h:149
lwvarlena_t * lwgeom_to_x3d3(const LWGEOM *geom, int precision, int opts, const char *defid)
Definition lwout_x3d.c:37
#define LW_FALSE
Definition liblwgeom.h:94
#define LW_GML_IS_DEGREE
For GML3 only, declare that data are lat/lon.
Definition liblwgeom.h:1714
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1246
#define LW_GML_SHORTLINE
For GML3, use <LineString> rather than <Curve> for lines.
Definition liblwgeom.h:1716
lwvarlena_t * lwgeom_to_svg(const LWGEOM *geom, int precision, int relative)
Takes a GEOMETRY and returns a SVG representation.
Definition lwout_svg.c:559
lwvarlena_t * lwgeom_to_geojson(const LWGEOM *geo, const char *srs, int precision, int has_bbox)
Takes a GEOMETRY and returns a GeoJson representation.
#define LW_GML_EXTENT
For GML2 and GML3, output only extent of geometry.
Definition liblwgeom.h:1718
lwvarlena_t * lwgeom_to_encoded_polyline(const LWGEOM *geom, int precision)
lwvarlena_t * lwgeom_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix)
Definition lwout_gml.c:920
#define LW_GML_IS_DIMS
Macros for specifying GML options.
Definition liblwgeom.h:1712
lwvarlena_t * lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix)
Definition lwout_gml.c:1063
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:978
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:93
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:215
#define LW_X3D_USE_GEOCOORDS
Definition liblwgeom.h:1731
This library is the generic geometry handling section of PostGIS.
#define OUT_DEFAULT_DECIMAL_DIGITS
Datum geometry_to_json(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(LWGEOM_asGML)
Encode feature in GML.
Datum LWGEOM_asGeoJson_old(PG_FUNCTION_ARGS)
Datum LWGEOM_asEncodedPolyline(PG_FUNCTION_ARGS)
Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
Datum LWGEOM_asSVG(PG_FUNCTION_ARGS)
Datum geometry_to_jsonb(PG_FUNCTION_ARGS)
Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
int32_t srid
Definition liblwgeom.h:460