PostGIS  2.4.9dev-r@@SVN_REVISION@@
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 "float.h" /* for DBL_DIG */
32 
33 #include "postgres.h"
34 #include "catalog/pg_type.h" /* for CSTRINGOID */
35 #include "executor/spi.h"
36 
37 #include "../postgis_config.h"
38 #include "lwgeom_pg.h"
39 #include "liblwgeom.h"
40 #include "lwgeom_export.h"
41 
42 Datum LWGEOM_asGML(PG_FUNCTION_ARGS);
43 Datum LWGEOM_asKML(PG_FUNCTION_ARGS);
44 Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS);
45 Datum LWGEOM_asGeoJson_old(PG_FUNCTION_ARGS);
46 Datum LWGEOM_asSVG(PG_FUNCTION_ARGS);
47 Datum LWGEOM_asX3D(PG_FUNCTION_ARGS);
48 Datum LWGEOM_asEncodedPolyline(PG_FUNCTION_ARGS);
49 
50 /*
51  * Retrieve an SRS from a given SRID
52  * Require valid spatial_ref_sys table entry
53  *
54  * Could return SRS as short one (i.e EPSG:4326)
55  * or as long one: (i.e urn:ogc:def:crs:EPSG::4326)
56  */
57 char * getSRSbySRID(int srid, bool short_crs)
58 {
59  char query[256];
60  char *srs, *srscopy;
61  int size, err;
62 
63  if (SPI_OK_CONNECT != SPI_connect ())
64  {
65  elog(NOTICE, "getSRSbySRID: could not connect to SPI manager");
66  SPI_finish();
67  return NULL;
68  }
69 
70  if (short_crs)
71  snprintf(query, 256, "SELECT auth_name||':'||auth_srid \
72  FROM spatial_ref_sys WHERE srid='%d'", srid);
73  else
74  snprintf(query, 256, "SELECT 'urn:ogc:def:crs:'||auth_name||'::'||auth_srid \
75  FROM spatial_ref_sys WHERE srid='%d'", srid);
76 
77  err = SPI_exec(query, 1);
78  if ( err < 0 )
79  {
80  elog(NOTICE, "getSRSbySRID: error executing query %d", err);
81  SPI_finish();
82  return NULL;
83  }
84 
85  /* no entry in spatial_ref_sys */
86  if (SPI_processed <= 0)
87  {
88  SPI_finish();
89  return NULL;
90  }
91 
92  /* get result */
93  srs = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
94 
95  /* NULL result */
96  if ( ! srs )
97  {
98  SPI_finish();
99  return NULL;
100  }
101 
102  /* copy result to upper executor context */
103  size = strlen(srs)+1;
104  srscopy = SPI_palloc(size);
105  memcpy(srscopy, srs, size);
106 
107  /* disconnect from SPI */
108  SPI_finish();
109 
110  return srscopy;
111 }
112 
113 
114 /*
115 * Retrieve an SRID from a given SRS
116 * Require valid spatial_ref_sys table entry
117 *
118 */
119 int getSRIDbySRS(const char* srs)
120 {
121  char *query =
122  "SELECT srid "
123  "FROM spatial_ref_sys, "
124  "regexp_matches($1::text, E'([a-z]+):([0-9]+)', 'gi') AS re "
125  "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid";
126  Oid argtypes[] = {CSTRINGOID};
127  Datum values[] = {CStringGetDatum(srs)};
128  int32_t srid, err;
129 
130  if (srs == NULL)
131  return 0;
132 
133  if (SPI_OK_CONNECT != SPI_connect())
134  {
135  elog(NOTICE, "getSRIDbySRS: could not connect to SPI manager");
136  return 0;
137  }
138 
139  err = SPI_execute_with_args(query, 1, argtypes, values, NULL, true, 1);
140  if (err < 0)
141  {
142  elog(NOTICE, "getSRIDbySRS: error executing query %d", err);
143  SPI_finish();
144  return 0;
145  }
146 
147  /* no entry in spatial_ref_sys */
148  if (SPI_processed <= 0)
149  {
150  query =
151  "SELECT srid "
152  "FROM spatial_ref_sys, "
153  "regexp_matches($1::text, E'urn:ogc:def:crs:([a-z]+):.*:([0-9]+)', 'gi') AS re "
154  "WHERE re[1] ILIKE auth_name AND int4(re[2]) = auth_srid";
155 
156  err = SPI_execute_with_args(query, 1, argtypes, values, NULL, true, 1);
157  if (err < 0)
158  {
159  elog(NOTICE, "getSRIDbySRS: error executing query %d", err);
160  SPI_finish();
161  return 0;
162  }
163 
164  if (SPI_processed <= 0)
165  {
166  SPI_finish();
167  return 0;
168  }
169  }
170 
171  srid = atoi(SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1));
172  if ( ! srs )
173  {
174  SPI_finish();
175  return 0;
176  }
177 
178  SPI_finish();
179 
180  return srid;
181 }
182 
183 
188 Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
189 {
190  GSERIALIZED *geom;
191  LWGEOM *lwgeom;
192  char *gml = NULL;
193  text *result;
194  int version;
195  char *srs;
196  int srid;
197  int option = 0;
198  int lwopts = LW_GML_IS_DIMS;
199  int precision = DBL_DIG;
200  static const char* default_prefix = "gml:"; /* default prefix */
201  const char* prefix = default_prefix;
202  const char* gml_id = NULL;
203  size_t len;
204  char *gml_id_buf, *prefix_buf;
205  text *prefix_text, *gml_id_text;
206 
207 
208  /* Get the version */
209  version = PG_GETARG_INT32(0);
210  if ( version != 2 && version != 3 )
211  {
212  elog(ERROR, "Only GML 2 and GML 3 are supported");
213  PG_RETURN_NULL();
214  }
215 
216  /* Get the geometry */
217  if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
218  geom = PG_GETARG_GSERIALIZED_P(1);
219 
220  /* Retrieve precision if any (default is max) */
221  if (PG_NARGS() >2 && !PG_ARGISNULL(2))
222  {
223  precision = PG_GETARG_INT32(2);
224  /* TODO: leave this to liblwgeom ? */
225  if ( precision > DBL_DIG )
226  precision = DBL_DIG;
227  else if ( precision < 0 ) precision = 0;
228  }
229 
230  /* retrieve option */
231  if (PG_NARGS() >3 && !PG_ARGISNULL(3))
232  option = PG_GETARG_INT32(3);
233 
234  /* retrieve prefix */
235  if (PG_NARGS() >4 && !PG_ARGISNULL(4))
236  {
237  prefix_text = PG_GETARG_TEXT_P(4);
238  if ( VARSIZE(prefix_text) == VARHDRSZ )
239  {
240  prefix = "";
241  }
242  else
243  {
244  len = VARSIZE(prefix_text)-VARHDRSZ;
245  prefix_buf = palloc(len + 2); /* +2 is one for the ':' and one for term null */
246  memcpy(prefix_buf, VARDATA(prefix_text), len);
247  /* add colon and null terminate */
248  prefix_buf[len] = ':';
249  prefix_buf[len+1] = '\0';
250  prefix = prefix_buf;
251  }
252  }
253 
254  if (PG_NARGS() >5 && !PG_ARGISNULL(5))
255  {
256  gml_id_text = PG_GETARG_TEXT_P(5);
257  if ( VARSIZE(gml_id_text) == VARHDRSZ )
258  {
259  gml_id = "";
260  }
261  else
262  {
263  len = VARSIZE(gml_id_text)-VARHDRSZ;
264  gml_id_buf = palloc(len+1);
265  memcpy(gml_id_buf, VARDATA(gml_id_text), len);
266  gml_id_buf[len] = '\0';
267  gml_id = gml_id_buf;
268  }
269  }
270 
271  srid = gserialized_get_srid(geom);
272  if (srid == SRID_UNKNOWN) srs = NULL;
273  else if (option & 1) srs = getSRSbySRID(srid, false);
274  else srs = getSRSbySRID(srid, true);
275 
276  if (option & 2) lwopts &= ~LW_GML_IS_DIMS;
277  if (option & 4) lwopts |= LW_GML_SHORTLINE;
278  if (option & 16) lwopts |= LW_GML_IS_DEGREE;
279  if (option & 32) lwopts |= LW_GML_EXTENT;
280 
281  lwgeom = lwgeom_from_gserialized(geom);
282 
283  if (version == 2 && lwopts & LW_GML_EXTENT)
284  gml = lwgeom_extent_to_gml2(lwgeom, srs, precision, prefix);
285  else if (version == 2)
286  gml = lwgeom_to_gml2(lwgeom, srs, precision, prefix);
287  else if (version == 3 && lwopts & LW_GML_EXTENT)
288  gml = lwgeom_extent_to_gml3(lwgeom, srs, precision, lwopts, prefix);
289  else if (version == 3)
290  gml = lwgeom_to_gml3(lwgeom, srs, precision, lwopts, prefix, gml_id);
291 
292  lwgeom_free(lwgeom);
293  PG_FREE_IF_COPY(geom, 1);
294 
295  /* Return null on null */
296  if ( ! gml )
297  PG_RETURN_NULL();
298 
299  result = cstring2text(gml);
300  lwfree(gml);
301  PG_RETURN_TEXT_P(result);
302 }
303 
304 
309 Datum LWGEOM_asKML(PG_FUNCTION_ARGS)
310 {
311  GSERIALIZED *geom;
312  LWGEOM *lwgeom;
313  char *kml;
314  text *result;
315  int version;
316  int precision = DBL_DIG;
317  static const char* default_prefix = ""; /* default prefix */
318  char *prefixbuf;
319  const char* prefix = default_prefix;
320  text *prefix_text;
321 
322 
323  /* Get the version */
324  version = PG_GETARG_INT32(0);
325  if ( version != 2)
326  {
327  elog(ERROR, "Only KML 2 is supported");
328  PG_RETURN_NULL();
329  }
330 
331  /* Get the geometry */
332  if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
333  geom = PG_GETARG_GSERIALIZED_P(1);
334 
335  /* Retrieve precision if any (default is max) */
336  if (PG_NARGS() >2 && !PG_ARGISNULL(2))
337  {
338  /* TODO: leave this to liblwgeom ? */
339  precision = PG_GETARG_INT32(2);
340  if ( precision > DBL_DIG )
341  precision = DBL_DIG;
342  else if ( precision < 0 ) precision = 0;
343  }
344 
345  /* retrieve prefix */
346  if (PG_NARGS() >3 && !PG_ARGISNULL(3))
347  {
348  prefix_text = PG_GETARG_TEXT_P(3);
349  if ( VARSIZE(prefix_text)-VARHDRSZ == 0 )
350  {
351  prefix = "";
352  }
353  else
354  {
355  /* +2 is one for the ':' and one for term null */
356  prefixbuf = palloc(VARSIZE(prefix_text)-VARHDRSZ+2);
357  memcpy(prefixbuf, VARDATA(prefix_text),
358  VARSIZE(prefix_text)-VARHDRSZ);
359  /* add colon and null terminate */
360  prefixbuf[VARSIZE(prefix_text)-VARHDRSZ] = ':';
361  prefixbuf[VARSIZE(prefix_text)-VARHDRSZ+1] = '\0';
362  prefix = prefixbuf;
363  }
364  }
365 
366  lwgeom = lwgeom_from_gserialized(geom);
367  kml = lwgeom_to_kml2(lwgeom, precision, prefix);
368  lwgeom_free(lwgeom);
369  PG_FREE_IF_COPY(geom, 1);
370 
371  if( ! kml )
372  PG_RETURN_NULL();
373 
374  result = cstring2text(kml);
375  lwfree(kml);
376 
377  PG_RETURN_POINTER(result);
378 }
379 
380 
388 Datum LWGEOM_asGeoJson_old(PG_FUNCTION_ARGS)
389 {
390  switch( PG_NARGS() )
391  {
392  case 2:
393  return DirectFunctionCall1(LWGEOM_asGeoJson, PG_GETARG_DATUM(1));
394  case 3:
395  return DirectFunctionCall2(LWGEOM_asGeoJson, PG_GETARG_DATUM(1), PG_GETARG_DATUM(2));
396  case 4:
397  return DirectFunctionCall3(LWGEOM_asGeoJson, PG_GETARG_DATUM(1), PG_GETARG_DATUM(2), PG_GETARG_DATUM(3));
398  default:
399  elog(ERROR, "bad call in %s", __func__);
400  }
401  PG_RETURN_NULL();
402 }
403 
408 Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
409 {
410  GSERIALIZED *geom;
411  LWGEOM *lwgeom;
412  char *geojson;
413  text *result;
414  int has_bbox = 0;
415  int precision = DBL_DIG;
416  char *srs = NULL;
417 
418  /* Get the geometry */
419  if ( PG_ARGISNULL(0) )
420  PG_RETURN_NULL();
421 
422  geom = PG_GETARG_GSERIALIZED_P(0);
423 
424  /* Retrieve precision if any (default is max) */
425  if ( PG_NARGS() > 1 && !PG_ARGISNULL(1) )
426  {
427  precision = PG_GETARG_INT32(1);
428  if ( precision > DBL_DIG )
429  precision = DBL_DIG;
430  else if ( precision < 0 )
431  precision = 0;
432  }
433 
434  /* Retrieve output option
435  * 0 = without option (default)
436  * 1 = bbox
437  * 2 = short crs
438  * 4 = long crs
439  */
440  if ( PG_NARGS() > 2 && !PG_ARGISNULL(2) )
441  {
442  int option = PG_GETARG_INT32(2);
443 
444  if ( option & 2 || option & 4 )
445  {
446  int srid = gserialized_get_srid(geom);
447  if ( srid != SRID_UNKNOWN )
448  {
449  if ( option & 2 )
450  srs = getSRSbySRID(srid, true);
451 
452  if ( option & 4 )
453  srs = getSRSbySRID(srid, false);
454 
455  if ( !srs )
456  {
457  elog(ERROR,
458  "SRID %i unknown in spatial_ref_sys table",
459  srid);
460  PG_RETURN_NULL();
461  }
462  }
463  }
464 
465  if (option & 1)
466  has_bbox = 1;
467  }
468 
469  lwgeom = lwgeom_from_gserialized(geom);
470  geojson = lwgeom_to_geojson(lwgeom, srs, precision, has_bbox);
471  lwgeom_free(lwgeom);
472 
473  if (srs) pfree(srs);
474 
475  result = cstring2text(geojson);
476  lwfree(geojson);
477 
478  PG_FREE_IF_COPY(geom, 0);
479  PG_RETURN_TEXT_P(result);
480 }
481 
482 
487 Datum LWGEOM_asSVG(PG_FUNCTION_ARGS)
488 {
489  GSERIALIZED *geom;
490  LWGEOM *lwgeom;
491  char *svg;
492  text *result;
493  int relative = 0;
494  int precision=DBL_DIG;
495 
496  if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
497 
498  geom = PG_GETARG_GSERIALIZED_P(0);
499 
500  /* check for relative path notation */
501  if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
502  relative = PG_GETARG_INT32(1) ? 1:0;
503 
504  if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
505  {
506  precision = PG_GETARG_INT32(2);
507  /* TODO: leave this to liblwgeom ? */
508  if ( precision > DBL_DIG )
509  precision = DBL_DIG;
510  else if ( precision < 0 ) precision = 0;
511  }
512 
513  lwgeom = lwgeom_from_gserialized(geom);
514  svg = lwgeom_to_svg(lwgeom, precision, relative);
515  result = cstring2text(svg);
516  lwgeom_free(lwgeom);
517  pfree(svg);
518  PG_FREE_IF_COPY(geom, 0);
519 
520  PG_RETURN_TEXT_P(result);
521 }
522 
527 Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
528 {
529  GSERIALIZED *geom;
530  LWGEOM *lwgeom;
531  char *x3d;
532  text *result;
533  int version;
534  char *srs;
535  int srid;
536  int option = 0;
537  int precision = DBL_DIG;
538  static const char* default_defid = "x3d:"; /* default defid */
539  char *defidbuf;
540  const char* defid = default_defid;
541  text *defid_text;
542 
543  /* Get the version */
544  version = PG_GETARG_INT32(0);
545  if ( version != 3 )
546  {
547  elog(ERROR, "Only X3D version 3 are supported");
548  PG_RETURN_NULL();
549  }
550 
551  /* Get the geometry */
552  if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
553  geom = PG_GETARG_GSERIALIZED_P(1);
554 
555  /* Retrieve precision if any (default is max) */
556  if (PG_NARGS() >2 && !PG_ARGISNULL(2))
557  {
558  precision = PG_GETARG_INT32(2);
559  /* TODO: leave this to liblwgeom ? */
560  if ( precision > DBL_DIG )
561  precision = DBL_DIG;
562  else if ( precision < 0 ) precision = 0;
563  }
564 
565  /* retrieve option */
566  if (PG_NARGS() >3 && !PG_ARGISNULL(3))
567  option = PG_GETARG_INT32(3);
568 
569 
570 
571  /* retrieve defid */
572  if (PG_NARGS() >4 && !PG_ARGISNULL(4))
573  {
574  defid_text = PG_GETARG_TEXT_P(4);
575  if ( VARSIZE(defid_text)-VARHDRSZ == 0 )
576  {
577  defid = "";
578  }
579  else
580  {
581  /* +2 is one for the ':' and one for term null */
582  defidbuf = palloc(VARSIZE(defid_text)-VARHDRSZ+2);
583  memcpy(defidbuf, VARDATA(defid_text),
584  VARSIZE(defid_text)-VARHDRSZ);
585  /* add colon and null terminate */
586  defidbuf[VARSIZE(defid_text)-VARHDRSZ] = ':';
587  defidbuf[VARSIZE(defid_text)-VARHDRSZ+1] = '\0';
588  defid = defidbuf;
589  }
590  }
591 
592  lwgeom = lwgeom_from_gserialized(geom);
593  srid = gserialized_get_srid(geom);
594  if (srid == SRID_UNKNOWN) srs = NULL;
595  else if (option & 1) srs = getSRSbySRID(srid, false);
596  else srs = getSRSbySRID(srid, true);
597 
598  if (option & LW_X3D_USE_GEOCOORDS) {
599  if (srid != 4326) {
600  PG_FREE_IF_COPY(geom, 0);
603  elog(ERROR, "Only SRID 4326 is supported for geocoordinates.");
604  PG_RETURN_NULL();
605  }
606  }
607 
608 
609  x3d = lwgeom_to_x3d3(lwgeom, srs, precision,option, defid);
610 
611  lwgeom_free(lwgeom);
612  PG_FREE_IF_COPY(geom, 1);
613 
614  result = cstring2text(x3d);
615  lwfree(x3d);
616 
617  PG_RETURN_TEXT_P(result);
618 }
619 
624 Datum LWGEOM_asEncodedPolyline(PG_FUNCTION_ARGS)
625 {
626  GSERIALIZED *geom;
627  LWGEOM *lwgeom;
628  char *encodedpolyline;
629  int precision = 5;
630  text *result;
631 
632  if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
633 
634  geom = PG_GETARG_GSERIALIZED_P(0);
635  if (gserialized_get_srid(geom) != 4326) {
636  PG_FREE_IF_COPY(geom, 0);
637  elog(ERROR, "Only SRID 4326 is supported.");
638  PG_RETURN_NULL();
639  }
640  lwgeom = lwgeom_from_gserialized(geom);
641 
642  if (PG_NARGS() > 1 && !PG_ARGISNULL(1))
643  {
644  precision = PG_GETARG_INT32(1);
645  if ( precision < 0 ) precision = 5;
646  }
647 
648  encodedpolyline = lwgeom_to_encoded_polyline(lwgeom, precision);
649  lwgeom_free(lwgeom);
650  PG_FREE_IF_COPY(geom, 0);
651 
652  result = cstring2text(encodedpolyline);
653  lwfree(encodedpolyline);
654 
655  PG_RETURN_TEXT_P(result);
656 }
char * lwgeom_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix)
VERSION GML 2 takes a GEOMETRY and returns a GML2 representation.
Definition: lwout_gml.c:231
Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
#define LW_GML_SHORTLINE
For GML3, use <LineString> rather than <Curve> for lines.
Definition: liblwgeom.h:1539
char * lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:60
void lwfree(void *mem)
Definition: lwutil.c:244
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
char * lwgeom_to_svg(const LWGEOM *geom, int precision, int relative)
Takes a GEOMETRY and returns a SVG representation.
Definition: lwout_svg.c:56
PG_FUNCTION_INFO_V1(LWGEOM_asGML)
Encode feature in GML.
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1099
Datum LWGEOM_asSVG(PG_FUNCTION_ARGS)
char * lwgeom_to_encoded_polyline(const LWGEOM *geom, int precision)
#define LW_X3D_USE_GEOCOORDS
Definition: liblwgeom.h:1554
LWGEOM * geom
Datum LWGEOM_asGeoJson_old(PG_FUNCTION_ARGS)
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:188
char * lwgeom_to_geojson(const LWGEOM *geo, char *srs, int precision, int has_bbox)
Takes a GEOMETRY and returns a GeoJson representation.
Definition: lwout_geojson.c:48
#define LW_GML_EXTENT
For GML2 and GML3, output only extent of geometry.
Definition: liblwgeom.h:1541
uint8_t precision
Definition: cu_in_twkb.c:25
Datum LWGEOM_asEncodedPolyline(PG_FUNCTION_ARGS)
Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
char * lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix)
Definition: lwout_gml.c:198
int getSRIDbySRS(const char *srs)
char * lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix)
Definition: lwout_gml.c:213
Datum LWGEOM_asKML(PG_FUNCTION_ARGS)
char * getSRSbySRID(int srid, bool short_crs)
Definition: lwgeom_export.c:57
#define LW_GML_IS_DIMS
Macros for specifying GML options.
Definition: liblwgeom.h:1535
char * lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:736
Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: g_serialized.c:100
This library is the generic geometry handling section of PostGIS.
char * lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix)
Definition: lwout_kml.c:43
#define LW_GML_IS_DEGREE
For GML3 only, declare that datas are lat/lon.
Definition: liblwgeom.h:1537