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