PostGIS  2.1.10dev-r@@SVN_REVISION@@
geography_inout.c
Go to the documentation of this file.
1 /**********************************************************************
2  * $Id: geography_inout.c 13659 2015-06-11 19:47:14Z strk $
3  *
4  * PostGIS - Spatial Types for PostgreSQL
5  * Copyright 2009-2011 Paul Ramsey <pramsey@cleverelephant.ca>
6  *
7  * This is free software; you can redistribute and/or modify it under
8  * the terms of the GNU General Public Licence. See the COPYING file.
9  *
10  **********************************************************************/
11 
12 #include "postgres.h"
13 
14 #include "../postgis_config.h"
15 
16 #include <math.h>
17 #include <float.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include <errno.h>
21 
22 #include "utils/elog.h"
23 #include "utils/array.h"
24 #include "utils/builtins.h" /* for pg_atoi */
25 #include "lib/stringinfo.h" /* For binary input */
26 #include "catalog/pg_type.h" /* for CSTRINGOID */
27 
28 #include "liblwgeom.h" /* For standard geometry types. */
29 #include "lwgeom_pg.h" /* For debugging macros. */
30 #include "geography.h" /* For utility functions. */
31 #include "lwgeom_export.h" /* For export functions. */
32 #include "lwgeom_transform.h"
33 
34 Datum geography_in(PG_FUNCTION_ARGS);
35 Datum geography_out(PG_FUNCTION_ARGS);
36 
37 Datum geography_as_text(PG_FUNCTION_ARGS);
38 Datum geography_from_text(PG_FUNCTION_ARGS);
39 Datum geography_as_geojson(PG_FUNCTION_ARGS);
40 Datum geography_as_gml(PG_FUNCTION_ARGS);
41 Datum geography_as_kml(PG_FUNCTION_ARGS);
42 Datum geography_as_svg(PG_FUNCTION_ARGS);
43 Datum geography_from_binary(PG_FUNCTION_ARGS);
44 Datum geography_from_geometry(PG_FUNCTION_ARGS);
45 Datum geometry_from_geography(PG_FUNCTION_ARGS);
46 Datum geography_send(PG_FUNCTION_ARGS);
47 Datum geography_recv(PG_FUNCTION_ARGS);
48 
49 GSERIALIZED* gserialized_geography_from_lwgeom(LWGEOM *lwgeom, int32 geog_typmod);
50 
57 {
58  if ( ! (
59  type == POINTTYPE ||
60  type == LINETYPE ||
61  type == POLYGONTYPE ||
62  type == MULTIPOINTTYPE ||
63  type == MULTILINETYPE ||
64  type == MULTIPOLYGONTYPE ||
65  type == COLLECTIONTYPE
66  ) )
67  {
68  ereport(ERROR, (
69  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
70  errmsg("Geography type does not support %s", lwtype_name(type) )));
71 
72  }
73 }
74 
76 {
77  GSERIALIZED *g_ser = NULL;
78 
79  /* Set geodetic flag */
80  lwgeom_set_geodetic(lwgeom, true);
81 
82  /* Check that this is a type we can handle */
83  geography_valid_type(lwgeom->type);
84 
85  /* Force the geometry to have valid geodetic coordinate range. */
86  lwgeom_nudge_geodetic(lwgeom);
87  if ( lwgeom_force_geodetic(lwgeom) == LW_TRUE )
88  {
89  ereport(NOTICE, (
90  errmsg_internal("Coordinate values were coerced into range [-180 -90, 180 90] for GEOGRAPHY" ))
91  );
92  }
93 
94  /* Force default SRID to the default */
95  if ( (int)lwgeom->srid <= 0 )
96  lwgeom->srid = SRID_DEFAULT;
97 
98  /*
99  ** Serialize our lwgeom and set the geodetic flag so subsequent
100  ** functions do the right thing.
101  */
102  g_ser = geography_serialize(lwgeom);
103 
104  /* Check for typmod agreement */
105  if ( geog_typmod >= 0 )
106  {
107  g_ser = postgis_valid_typmod(g_ser, geog_typmod);
108  POSTGIS_DEBUG(3, "typmod and geometry were consistent");
109  }
110  else
111  {
112  POSTGIS_DEBUG(3, "typmod was -1");
113  }
114 
115  return g_ser;
116 }
117 
118 
119 /*
120 ** geography_in(cstring) returns *GSERIALIZED
121 */
123 Datum geography_in(PG_FUNCTION_ARGS)
124 {
125  char *str = PG_GETARG_CSTRING(0);
126  /* Datum geog_oid = PG_GETARG_OID(1); Not needed. */
127  int32 geog_typmod = -1;
128  LWGEOM_PARSER_RESULT lwg_parser_result;
129  LWGEOM *lwgeom = NULL;
130  GSERIALIZED *g_ser = NULL;
131 
132  if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) {
133  geog_typmod = PG_GETARG_INT32(2);
134  }
135 
136  lwgeom_parser_result_init(&lwg_parser_result);
137 
138  /* Empty string. */
139  if ( str[0] == '\0' )
140  ereport(ERROR,(errmsg("parse error - invalid geometry")));
141 
142  /* WKB? Let's find out. */
143  if ( str[0] == '0' )
144  {
145  /* TODO: 20101206: No parser checks! This is inline with current 1.5 behavior, but needs discussion */
147  /* Error out if something went sideways */
148  if ( ! lwgeom )
149  ereport(ERROR,(errmsg("parse error - invalid geometry")));
150  }
151  /* WKT then. */
152  else
153  {
154  if ( lwgeom_parse_wkt(&lwg_parser_result, str, LW_PARSER_CHECK_ALL) == LW_FAILURE )
155  PG_PARSER_ERROR(lwg_parser_result);
156 
157  lwgeom = lwg_parser_result.geom;
158  }
159 
160  /* Error on any SRID != default */
161  srid_is_latlong(fcinfo, lwgeom->srid);
162 
163  /* Convert to gserialized */
164  g_ser = gserialized_geography_from_lwgeom(lwgeom, geog_typmod);
165 
166  /* Clean up temporary object */
167  lwgeom_free(lwgeom);
168 
169 
170  PG_RETURN_POINTER(g_ser);
171 }
172 
173 /*
174 ** geography_out(*GSERIALIZED) returns cstring
175 */
177 Datum geography_out(PG_FUNCTION_ARGS)
178 {
179  LWGEOM *lwgeom = NULL;
180  GSERIALIZED *g = NULL;
181  char *hexwkb;
182 
183  g = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
184  lwgeom = lwgeom_from_gserialized(g);
185  hexwkb = lwgeom_to_hexwkb(lwgeom, WKB_EXTENDED, 0);
186  lwgeom_free(lwgeom);
187 
188  PG_RETURN_CSTRING(hexwkb);
189 }
190 
191 
192 /*
193 ** geography_as_gml(*GSERIALIZED) returns text
194 */
196 Datum geography_as_gml(PG_FUNCTION_ARGS)
197 {
198  LWGEOM *lwgeom = NULL;
199  GSERIALIZED *g = NULL;
200  char *gml;
201  text *result;
202  int version;
203  char *srs;
204  int srid = SRID_DEFAULT;
205  int precision = DBL_DIG;
206  int option=0;
207  int lwopts = LW_GML_IS_DIMS;
208  static const char *default_prefix = "gml:";
209  const char *prefix = default_prefix;
210  char *prefix_buf = "";
211  text *prefix_text, *id_text = NULL;
212  const char *id=NULL;
213  char *id_buf;
214 
215 
216  /* Get the version */
217  version = PG_GETARG_INT32(0);
218  if ( version != 2 && version != 3 )
219  {
220  elog(ERROR, "Only GML 2 and GML 3 are supported");
221  PG_RETURN_NULL();
222  }
223 
224  /* Get the geography */
225  if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
226  g = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
227 
228  /* Convert to lwgeom so we can run the old functions */
229  lwgeom = lwgeom_from_gserialized(g);
230 
231  /* Retrieve precision if any (default is max) */
232  if (PG_NARGS() >2 && !PG_ARGISNULL(2))
233  {
234  precision = PG_GETARG_INT32(2);
235  /* TODO: leave this to liblwgeom */
236  if ( precision > DBL_DIG )
237  precision = DBL_DIG;
238  else if ( precision < 0 ) precision = 0;
239  }
240 
241  /* retrieve option */
242  if (PG_NARGS() >3 && !PG_ARGISNULL(3))
243  option = PG_GETARG_INT32(3);
244 
245 
246  /* retrieve prefix */
247  if (PG_NARGS() >4 && !PG_ARGISNULL(4))
248  {
249  prefix_text = PG_GETARG_TEXT_P(4);
250  if ( VARSIZE(prefix_text)-VARHDRSZ == 0 )
251  {
252  prefix = "";
253  }
254  else
255  {
256  /* +2 is one for the ':' and one for term null */
257  prefix_buf = palloc(VARSIZE(prefix_text)-VARHDRSZ+2);
258  memcpy(prefix_buf, VARDATA(prefix_text),
259  VARSIZE(prefix_text)-VARHDRSZ);
260  /* add colon and null terminate */
261  prefix_buf[VARSIZE(prefix_text)-VARHDRSZ] = ':';
262  prefix_buf[VARSIZE(prefix_text)-VARHDRSZ+1] = '\0';
263  prefix = prefix_buf;
264  }
265  }
266 
267  /* retrieve id */
268  if (PG_NARGS() >5 && !PG_ARGISNULL(5))
269  {
270  id_text = PG_GETARG_TEXT_P(5);
271  if ( VARSIZE(id_text)-VARHDRSZ == 0 )
272  {
273  id = "";
274  }
275  else
276  {
277  id_buf = palloc(VARSIZE(id_text)-VARHDRSZ+1);
278  memcpy(id_buf, VARDATA(id_text), VARSIZE(id_text)-VARHDRSZ);
279  prefix_buf[VARSIZE(id_text)-VARHDRSZ+1] = '\0';
280  id = id_buf;
281  }
282  }
283 
284  if (option & 1) srs = getSRSbySRID(srid, false);
285  else srs = getSRSbySRID(srid, true);
286  if (!srs)
287  {
288  elog(ERROR, "SRID %d unknown in spatial_ref_sys table", SRID_DEFAULT);
289  PG_RETURN_NULL();
290  }
291 
292  /* Revert lat/lon only with long SRS */
293  if (option & 1) lwopts |= LW_GML_IS_DEGREE;
294  if (option & 2) lwopts &= ~LW_GML_IS_DIMS;
295 
296  if (version == 2)
297  gml = lwgeom_to_gml2(lwgeom, srs, precision, prefix);
298  else
299  gml = lwgeom_to_gml3(lwgeom, srs, precision, lwopts, prefix, id);
300 
301  lwgeom_free(lwgeom);
302  PG_FREE_IF_COPY(g, 1);
303 
304  /* Return null on null */
305  if ( ! gml )
306  PG_RETURN_NULL();
307 
308  /* Turn string result into text for return */
309  result = cstring2text(gml);
310  lwfree(gml);
311 
312  PG_RETURN_TEXT_P(result);
313 }
314 
315 
316 /*
317 ** geography_as_kml(*GSERIALIZED) returns text
318 */
320 Datum geography_as_kml(PG_FUNCTION_ARGS)
321 {
322  GSERIALIZED *g = NULL;
323  LWGEOM *lwgeom = NULL;
324  char *kml;
325  text *result;
326  int version;
327  int precision = DBL_DIG;
328  static const char *default_prefix = "";
329  char *prefixbuf;
330  const char* prefix = default_prefix;
331  text *prefix_text;
332 
333 
334  /* Get the version */
335  version = PG_GETARG_INT32(0);
336  if ( version != 2)
337  {
338  elog(ERROR, "Only KML 2 is supported");
339  PG_RETURN_NULL();
340  }
341 
342  /* Get the geometry */
343  if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
344  g = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
345 
346  /* Convert to lwgeom so we can run the old functions */
347  lwgeom = lwgeom_from_gserialized(g);
348 
349  /* Retrieve precision if any (default is max) */
350  if (PG_NARGS() >2 && !PG_ARGISNULL(2))
351  {
352  precision = PG_GETARG_INT32(2);
353  /* TODO: leave this to liblwgeom */
354  if ( precision > DBL_DIG )
355  precision = DBL_DIG;
356  else if ( precision < 0 ) precision = 0;
357  }
358 
359  /* retrieve prefix */
360  if (PG_NARGS() >3 && !PG_ARGISNULL(3))
361  {
362  prefix_text = PG_GETARG_TEXT_P(3);
363  if ( VARSIZE(prefix_text)-VARHDRSZ == 0 )
364  {
365  prefix = "";
366  }
367  else
368  {
369  /* +2 is one for the ':' and one for term null */
370  prefixbuf = palloc(VARSIZE(prefix_text)-VARHDRSZ+2);
371  memcpy(prefixbuf, VARDATA(prefix_text),
372  VARSIZE(prefix_text)-VARHDRSZ);
373  /* add colon and null terminate */
374  prefixbuf[VARSIZE(prefix_text)-VARHDRSZ] = ':';
375  prefixbuf[VARSIZE(prefix_text)-VARHDRSZ+1] = '\0';
376  prefix = prefixbuf;
377  }
378  }
379 
380  kml = lwgeom_to_kml2(lwgeom, precision, prefix);
381 
382  lwgeom_free(lwgeom);
383  PG_FREE_IF_COPY(g, 1);
384 
385  if ( ! kml )
386  PG_RETURN_NULL();
387 
388  result = cstring2text(kml);
389  lwfree(kml);
390 
391  PG_RETURN_TEXT_P(result);
392 }
393 
394 
395 /*
396 ** geography_as_svg(*GSERIALIZED) returns text
397 */
399 Datum geography_as_svg(PG_FUNCTION_ARGS)
400 {
401  GSERIALIZED *g = NULL;
402  LWGEOM *lwgeom = NULL;
403  char *svg;
404  text *result;
405  int relative = 0;
406  int precision=DBL_DIG;
407 
408  if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
409 
410  g = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
411 
412  /* Convert to lwgeom so we can run the old functions */
413  lwgeom = lwgeom_from_gserialized(g);
414 
415  /* check for relative path notation */
416  if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
417  relative = PG_GETARG_INT32(1) ? 1:0;
418 
419  if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
420  {
421  precision = PG_GETARG_INT32(2);
422  /* TODO: leave this to liblwgeom */
423  if ( precision > DBL_DIG )
424  precision = DBL_DIG;
425  else if ( precision < 0 ) precision = 0;
426  }
427 
428  svg = lwgeom_to_svg(lwgeom, precision, relative);
429 
430  lwgeom_free(lwgeom);
431  PG_FREE_IF_COPY(g, 0);
432 
433  result = cstring2text(svg);
434  lwfree(svg);
435 
436  PG_RETURN_TEXT_P(result);
437 }
438 
439 
440 /*
441 ** geography_as_geojson(*GSERIALIZED) returns text
442 */
444 Datum geography_as_geojson(PG_FUNCTION_ARGS)
445 {
446  LWGEOM *lwgeom = NULL;
447  GSERIALIZED *g = NULL;
448  char *geojson;
449  text *result;
450  int version;
451  int option = 0;
452  int has_bbox = 0;
453  int precision = DBL_DIG;
454  char * srs = NULL;
455 
456  /* Get the version */
457  version = PG_GETARG_INT32(0);
458  if ( version != 1)
459  {
460  elog(ERROR, "Only GeoJSON 1 is supported");
461  PG_RETURN_NULL();
462  }
463 
464  /* Get the geography */
465  if (PG_ARGISNULL(1) ) PG_RETURN_NULL();
466  g = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
467 
468  /* Convert to lwgeom so we can run the old functions */
469  lwgeom = lwgeom_from_gserialized(g);
470 
471  /* Retrieve precision if any (default is max) */
472  if (PG_NARGS() >2 && !PG_ARGISNULL(2))
473  {
474  precision = PG_GETARG_INT32(2);
475  /* TODO: leave this to liblwgeom */
476  if ( precision > DBL_DIG )
477  precision = DBL_DIG;
478  else if ( precision < 0 ) precision = 0;
479  }
480 
481  /* Retrieve output option
482  * 0 = without option (default)
483  * 1 = bbox
484  * 2 = short crs
485  * 4 = long crs
486  */
487  if (PG_NARGS() >3 && !PG_ARGISNULL(3))
488  option = PG_GETARG_INT32(3);
489 
490  if (option & 2 || option & 4)
491  {
492  /* Geography only handle srid SRID_DEFAULT */
493  if (option & 2) srs = getSRSbySRID(SRID_DEFAULT, true);
494  if (option & 4) srs = getSRSbySRID(SRID_DEFAULT, false);
495 
496  if (!srs)
497  {
498  elog(ERROR, "SRID SRID_DEFAULT unknown in spatial_ref_sys table");
499  PG_RETURN_NULL();
500  }
501  }
502 
503  if (option & 1) has_bbox = 1;
504 
505  geojson = lwgeom_to_geojson(lwgeom, srs, precision, has_bbox);
506  lwgeom_free(lwgeom);
507  PG_FREE_IF_COPY(g, 1);
508  if (srs) pfree(srs);
509 
510  result = cstring2text(geojson);
511  lwfree(geojson);
512 
513  PG_RETURN_TEXT_P(result);
514 }
515 
516 
517 /*
518 ** geography_from_text(*char) returns *GSERIALIZED
519 **
520 ** Convert text (varlena) to cstring and then call geography_in().
521 */
523 Datum geography_from_text(PG_FUNCTION_ARGS)
524 {
525  LWGEOM_PARSER_RESULT lwg_parser_result;
526  GSERIALIZED *g_ser = NULL;
527  text *wkt_text = PG_GETARG_TEXT_P(0);
528 
529  /* Extract the cstring from the varlena */
530  char *wkt = text2cstring(wkt_text);
531 
532  /* Pass the cstring to the input parser, and magic occurs! */
533  if ( lwgeom_parse_wkt(&lwg_parser_result, wkt, LW_PARSER_CHECK_ALL) == LW_FAILURE )
534  PG_PARSER_ERROR(lwg_parser_result);
535 
536  /* Clean up string */
537  pfree(wkt);
538  g_ser = gserialized_geography_from_lwgeom(lwg_parser_result.geom, -1);
539 
540  /* Clean up temporary object */
541  lwgeom_free(lwg_parser_result.geom);
542 
543  PG_RETURN_POINTER(g_ser);
544 }
545 
546 /*
547 ** geography_from_binary(*char) returns *GSERIALIZED
548 */
550 Datum geography_from_binary(PG_FUNCTION_ARGS)
551 {
552  char *wkb_bytea = (char*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
553  GSERIALIZED *gser = NULL;
554  size_t wkb_size = VARSIZE(wkb_bytea);
555  uint8_t *wkb = (uint8_t*)VARDATA(wkb_bytea);
556  LWGEOM *lwgeom = lwgeom_from_wkb(wkb, wkb_size, LW_PARSER_CHECK_NONE);
557 
558  if ( ! lwgeom )
559  lwerror("Unable to parse WKB");
560 
561  gser = gserialized_geography_from_lwgeom(lwgeom, -1);
562  lwgeom_free(lwgeom);
563  PG_RETURN_POINTER(gser);
564 }
565 
566 
568 Datum geography_from_geometry(PG_FUNCTION_ARGS)
569 {
570  GSERIALIZED *geom = (GSERIALIZED*)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
571  LWGEOM *lwgeom = NULL;
572  GSERIALIZED *g_ser = NULL;
573 
575 
576  lwgeom = lwgeom_from_gserialized(geom);
577 
578  /* Force default SRID */
579  if ( (int)lwgeom->srid <= 0 )
580  {
581  lwgeom->srid = SRID_DEFAULT;
582  }
583 
584  /* Error on any SRID != default */
585  srid_is_latlong(fcinfo, lwgeom->srid);
586 
587  /* Force the geometry to have valid geodetic coordinate range. */
588  lwgeom_nudge_geodetic(lwgeom);
589  if ( lwgeom_force_geodetic(lwgeom) == LW_TRUE )
590  {
591  ereport(NOTICE, (
592  errmsg_internal("Coordinate values were coerced into range [-180 -90, 180 90] for GEOGRAPHY" ))
593  );
594  }
595 
596  /*
597  ** Serialize our lwgeom and set the geodetic flag so subsequent
598  ** functions do the right thing.
599  */
600  lwgeom_set_geodetic(lwgeom, true);
601 
602  /* Recalculate the boxes after re-setting the geodetic bit */
603  lwgeom_drop_bbox(lwgeom);
604  lwgeom_add_bbox(lwgeom);
605 
606  g_ser = geography_serialize(lwgeom);
607 
608  /*
609  ** Replace the unaligned lwgeom with a new aligned one based on GSERIALIZED.
610  */
611  lwgeom_free(lwgeom);
612 
613  PG_FREE_IF_COPY(geom, 0);
614  PG_RETURN_POINTER(g_ser);
615 
616 }
617 
619 Datum geometry_from_geography(PG_FUNCTION_ARGS)
620 {
621  LWGEOM *lwgeom = NULL;
622  GSERIALIZED *ret = NULL;
623  GSERIALIZED *g_ser = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
624 
625  lwgeom = lwgeom_from_gserialized(g_ser);
626 
627  /* Recalculate the boxes after re-setting the geodetic bit */
628  lwgeom_set_geodetic(lwgeom, false);
629  lwgeom_drop_bbox(lwgeom);
630  lwgeom_add_bbox(lwgeom);
631 
632  /* We want "geometry" to think all our "geography" has an SRID, and the
633  implied SRID is the default, so we fill that in if our SRID is actually unknown. */
634  if ( (int)lwgeom->srid <= 0 )
635  lwgeom->srid = SRID_DEFAULT;
636 
637  ret = geometry_serialize(lwgeom);
638  lwgeom_free(lwgeom);
639 
640  PG_RETURN_POINTER(ret);
641 }
642 
644 Datum geography_recv(PG_FUNCTION_ARGS)
645 {
646  StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
647  int32 geog_typmod = -1;
648  LWGEOM *lwgeom = NULL;
649  GSERIALIZED *g_ser = NULL;
650 
651  if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) {
652  geog_typmod = PG_GETARG_INT32(2);
653  }
654 
655  lwgeom = lwgeom_from_wkb((uint8_t*)buf->data, buf->len, LW_PARSER_CHECK_ALL);
656 
657  /* Error on any SRID != default */
658  srid_is_latlong(fcinfo, lwgeom->srid);
659 
660  g_ser = gserialized_geography_from_lwgeom(lwgeom, geog_typmod);
661 
662  /* Clean up temporary object */
663  lwgeom_free(lwgeom);
664 
665  /* Set cursor to the end of buffer (so the backend is happy) */
666  buf->cursor = buf->len;
667 
668  PG_RETURN_POINTER(g_ser);
669 }
670 
671 
673 Datum geography_send(PG_FUNCTION_ARGS)
674 {
675  LWGEOM *lwgeom = NULL;
676  GSERIALIZED *g = NULL;
677  size_t size_result;
678  uint8_t *wkb;
679  bytea *result;
680 
681  g = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
682  lwgeom = lwgeom_from_gserialized(g);
683  wkb = lwgeom_to_wkb(lwgeom, WKB_EXTENDED, &size_result);
684  lwgeom_free(lwgeom);
685 
686  result = palloc(size_result + VARHDRSZ);
687  SET_VARSIZE(result, size_result + VARHDRSZ);
688  memcpy(VARDATA(result), wkb, size_result);
689  pfree(wkb);
690 
691  PG_RETURN_POINTER(result);
692 }
#define LINETYPE
Definition: liblwgeom.h:61
uint32_t gserialized_get_type(const GSERIALIZED *s)
Extract the geometry type from the serialized form (it hides in the anonymous data area...
Definition: g_serialized.c:56
char * lwgeom_to_hexwkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
Definition: lwout_wkb.c:776
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:211
GSERIALIZED * postgis_valid_typmod(GSERIALIZED *gser, int32_t typmod)
Check the consistency of the metadata we want to enforce in the typmod: srid, type and dimensionality...
void lwfree(void *mem)
Definition: lwutil.c:190
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:43
#define POLYGONTYPE
Definition: liblwgeom.h:62
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1006
#define MULTIPOINTTYPE
Definition: liblwgeom.h:63
#define SRID_DEFAULT
Definition: liblwgeom.h:161
Datum geography_as_geojson(PG_FUNCTION_ARGS)
Datum geography_recv(PG_FUNCTION_ARGS)
int lwgeom_nudge_geodetic(LWGEOM *geom)
Gently move coordinates of LWGEOM if they are close enough into geodetic range.
Definition: lwgeodetic.c:2988
PG_FUNCTION_INFO_V1(geography_in)
char ** result
Definition: liblwgeom.h:218
void lwgeom_drop_bbox(LWGEOM *lwgeom)
Call this function to drop BBOX and SRID from LWGEOM.
Definition: lwgeom.c:542
int32_t srid
Definition: liblwgeom.h:355
#define LW_FAILURE
Definition: liblwgeom.h:54
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:1706
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:164
uint8_t * lwgeom_to_wkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
Convert LWGEOM to a char* in WKB format.
Definition: lwout_wkb.c:692
int lwgeom_parse_wkt(LWGEOM_PARSER_RESULT *parser_result, char *wktstr, int parse_flags)
Parse a WKT geometry string into an LWGEOM structure.
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:51
Parser result structure: returns the result of attempting to convert (E)WKT/(E)WKB to LWGEOM...
Definition: liblwgeom.h:1713
int lwgeom_force_geodetic(LWGEOM *geom)
Force coordinates of LWGEOM into geodetic range (-180, -90, 180, 90)
Definition: lwgeodetic.c:2806
Datum geography_in(PG_FUNCTION_ARGS)
Datum geography_as_text(PG_FUNCTION_ARGS)
char * text2cstring(const text *textptr)
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:35
Datum geography_as_gml(PG_FUNCTION_ARGS)
Datum geometry_from_geography(PG_FUNCTION_ARGS)
Datum geography_as_svg(PG_FUNCTION_ARGS)
#define WKB_EXTENDED
Definition: liblwgeom.h:1769
void lwgeom_set_geodetic(LWGEOM *geom, int value)
Set the FLAGS geodetic bit on geometry an all sub-geometries and pointlists.
Definition: lwgeom.c:814
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:753
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:65
char * getSRSbySRID(int srid, bool short_crs)
Definition: lwgeom_export.c:39
Datum geography_from_geometry(PG_FUNCTION_ARGS)
#define LW_GML_IS_DIMS
Macros for specifying GML options.
Definition: liblwgeom.h:1358
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
Datum geography_out(PG_FUNCTION_ARGS)
void lwgeom_parser_result_init(LWGEOM_PARSER_RESULT *parser_result)
Definition: lwin_wkt.c:819
void geography_valid_type(uint8_t type)
The geography type only support POINT, LINESTRING, POLYGON, MULTI* variants of same, and GEOMETRYCOLLECTION.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:60
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
Definition: lwgeom.c:555
Datum geography_from_text(PG_FUNCTION_ARGS)
Datum geography_send(PG_FUNCTION_ARGS)
uint8_t type
Definition: liblwgeom.h:352
GSERIALIZED * gserialized_geography_from_lwgeom(LWGEOM *lwgeom, int32 geog_typmod)
Datum geography_from_binary(PG_FUNCTION_ARGS)
char * lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id)
Definition: lwout_gml.c:711
#define LW_PARSER_CHECK_ALL
Definition: liblwgeom.h:1707
LWGEOM * lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
WKB inputs must have a declared size, to prevent malformed WKB from reading off the end of the memory...
Definition: lwin_wkb.c:728
#define MULTILINETYPE
Definition: liblwgeom.h:64
#define COLLECTIONTYPE
Definition: liblwgeom.h:66
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:32
#define LW_GML_IS_DEGREE
For GML3 only, declare that datas are lat/lon.
Definition: liblwgeom.h:1360
Datum geography_as_kml(PG_FUNCTION_ARGS)