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