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