PostGIS  3.4.0dev-r@@SVN_REVISION@@
lwgeom_ogc.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 2001-2005 Refractions Research Inc.
22  *
23  **********************************************************************/
24 
25 
26 #include "postgres.h"
27 
28 #include <math.h>
29 #include <float.h>
30 #include <string.h>
31 #include <stdio.h>
32 
33 #include "access/gist.h"
34 #include "access/itup.h"
35 
36 #include "fmgr.h"
37 #include "utils/builtins.h"
38 #include "utils/elog.h"
39 
40 #include "../postgis_config.h"
41 
42 #include "liblwgeom.h"
43 #include "liblwgeom_internal.h"
44 #include "lwgeom_pg.h"
45 
46 
47 /* ---- SRID(geometry) */
48 Datum LWGEOM_get_srid(PG_FUNCTION_ARGS);
49 /* ---- SetSRID(geometry, integer) */
50 Datum LWGEOM_set_srid(PG_FUNCTION_ARGS);
51 /* ---- GeometryType(geometry) */
52 Datum LWGEOM_getTYPE(PG_FUNCTION_ARGS);
53 Datum geometry_geometrytype(PG_FUNCTION_ARGS);
54 /* ---- NumPoints(geometry) */
55 Datum LWGEOM_numpoints_linestring(PG_FUNCTION_ARGS);
56 /* ---- NumGeometries(geometry) */
57 Datum LWGEOM_numgeometries_collection(PG_FUNCTION_ARGS);
58 /* ---- GeometryN(geometry, integer) */
59 Datum LWGEOM_geometryn_collection(PG_FUNCTION_ARGS);
60 /* ---- Dimension(geometry) */
61 Datum LWGEOM_dimension(PG_FUNCTION_ARGS);
62 /* ---- ExteriorRing(geometry) */
63 Datum LWGEOM_exteriorring_polygon(PG_FUNCTION_ARGS);
64 /* ---- InteriorRingN(geometry, integer) */
65 Datum LWGEOM_interiorringn_polygon(PG_FUNCTION_ARGS);
66 /* ---- NumInteriorRings(geometry) */
67 Datum LWGEOM_numinteriorrings_polygon(PG_FUNCTION_ARGS);
68 /* ---- PointN(geometry, integer) */
69 Datum LWGEOM_pointn_linestring(PG_FUNCTION_ARGS);
70 /* ---- X(geometry) */
71 Datum LWGEOM_x_point(PG_FUNCTION_ARGS);
72 /* ---- Y(geometry) */
73 Datum LWGEOM_y_point(PG_FUNCTION_ARGS);
74 /* ---- Z(geometry) */
75 Datum LWGEOM_z_point(PG_FUNCTION_ARGS);
76 /* ---- M(geometry) */
77 Datum LWGEOM_m_point(PG_FUNCTION_ARGS);
78 /* ---- StartPoint(geometry) */
79 Datum LWGEOM_startpoint_linestring(PG_FUNCTION_ARGS);
80 /* ---- EndPoint(geometry) */
81 Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS);
82 /* ---- AsText(geometry) */
83 Datum LWGEOM_asText(PG_FUNCTION_ARGS);
84 /* ---- AsBinary(geometry, [XDR|NDR]) */
85 Datum LWGEOM_asBinary(PG_FUNCTION_ARGS);
86 /* ---- GeometryFromText(text, integer) */
87 Datum LWGEOM_from_text(PG_FUNCTION_ARGS);
88 /* ---- GeomFromWKB(bytea, integer) */
89 Datum LWGEOM_from_WKB(PG_FUNCTION_ARGS);
90 /* ---- IsClosed(geometry) */
91 Datum LWGEOM_isclosed(PG_FUNCTION_ARGS);
92 
93 /*------------------------------------------------------------------*/
94 
95 /* getSRID(lwgeom) :: int4 */
97 Datum LWGEOM_get_srid(PG_FUNCTION_ARGS)
98 {
99  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_HEADER(0);
100  int32_t srid = gserialized_get_srid(geom);
101  PG_FREE_IF_COPY(geom,0);
102  PG_RETURN_INT32(srid);
103 }
104 
105 /* setSRID(lwgeom, int4) :: lwgeom */
107 Datum LWGEOM_set_srid(PG_FUNCTION_ARGS)
108 {
109  GSERIALIZED *g = (GSERIALIZED *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
110  int32_t srid = PG_GETARG_INT32(1);
111  gserialized_set_srid(g, srid);
112  PG_RETURN_POINTER(g);
113 }
114 
115 /* returns a string representation of this geometry's type */
117 Datum LWGEOM_getTYPE(PG_FUNCTION_ARGS)
118 {
119  GSERIALIZED *gser;
120  text *text_ob;
121  char *result;
122  uint8_t type;
123  static int maxtyplen = 20;
124 
125  gser = PG_GETARG_GSERIALIZED_HEADER(0);
126  text_ob = palloc0(VARHDRSZ + maxtyplen);
127  result = VARDATA(text_ob);
128 
129  type = gserialized_get_type(gser);
130 
131  if (type == POINTTYPE)
132  strcpy(result,"POINT");
133  else if (type == MULTIPOINTTYPE)
134  strcpy(result,"MULTIPOINT");
135  else if (type == LINETYPE)
136  strcpy(result,"LINESTRING");
137  else if (type == CIRCSTRINGTYPE)
138  strcpy(result,"CIRCULARSTRING");
139  else if (type == COMPOUNDTYPE)
140  strcpy(result, "COMPOUNDCURVE");
141  else if (type == MULTILINETYPE)
142  strcpy(result,"MULTILINESTRING");
143  else if (type == MULTICURVETYPE)
144  strcpy(result, "MULTICURVE");
145  else if (type == POLYGONTYPE)
146  strcpy(result,"POLYGON");
147  else if (type == TRIANGLETYPE)
148  strcpy(result,"TRIANGLE");
149  else if (type == CURVEPOLYTYPE)
150  strcpy(result,"CURVEPOLYGON");
151  else if (type == MULTIPOLYGONTYPE)
152  strcpy(result,"MULTIPOLYGON");
153  else if (type == MULTISURFACETYPE)
154  strcpy(result, "MULTISURFACE");
155  else if (type == COLLECTIONTYPE)
156  strcpy(result,"GEOMETRYCOLLECTION");
157  else if (type == POLYHEDRALSURFACETYPE)
158  strcpy(result,"POLYHEDRALSURFACE");
159  else if (type == TINTYPE)
160  strcpy(result,"TIN");
161  else
162  strcpy(result,"UNKNOWN");
163 
164  if ( gserialized_has_m(gser) && ! gserialized_has_z(gser) )
165  strcat(result, "M");
166 
167  SET_VARSIZE(text_ob, strlen(result) + VARHDRSZ); /* size of string */
168 
169  PG_FREE_IF_COPY(gser, 0);
170 
171  PG_RETURN_TEXT_P(text_ob);
172 }
173 
174 /* Matches lwutil.c::lwgeomTypeName */
175 static char *stTypeName[] = {"Unknown",
176  "ST_Point",
177  "ST_LineString",
178  "ST_Polygon",
179  "ST_MultiPoint",
180  "ST_MultiLineString",
181  "ST_MultiPolygon",
182  "ST_GeometryCollection",
183  "ST_CircularString",
184  "ST_CompoundCurve",
185  "ST_CurvePolygon",
186  "ST_MultiCurve",
187  "ST_MultiSurface",
188  "ST_PolyhedralSurface",
189  "ST_Triangle",
190  "ST_Tin"};
191 
192 /* returns a string representation of this geometry's type */
194 Datum geometry_geometrytype(PG_FUNCTION_ARGS)
195 {
196  GSERIALIZED *gser;
197  text *type_text;
198 
199  /* Read just the header from the toasted tuple */
200  gser = PG_GETARG_GSERIALIZED_HEADER(0);
201 
202  /* Build a text type to store things in */
203  type_text = cstring_to_text(stTypeName[gserialized_get_type(gser)]);
204 
205  PG_FREE_IF_COPY(gser, 0);
206  PG_RETURN_TEXT_P(type_text);
207 }
208 
209 
210 
216 Datum LWGEOM_numpoints_linestring(PG_FUNCTION_ARGS)
217 {
218  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
219  LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
220  int count = -1;
221  int type = lwgeom->type;
222 
223  if ( type == LINETYPE || type == CIRCSTRINGTYPE || type == COMPOUNDTYPE )
224  count = lwgeom_count_vertices(lwgeom);
225 
226  lwgeom_free(lwgeom);
227  PG_FREE_IF_COPY(geom, 0);
228 
229  /* OGC says this functions is only valid on LINESTRING */
230  if ( count < 0 )
231  PG_RETURN_NULL();
232 
233  PG_RETURN_INT32(count);
234 }
235 
237 Datum LWGEOM_numgeometries_collection(PG_FUNCTION_ARGS)
238 {
239  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
240  LWGEOM *lwgeom;
241  int32 ret = 1;
242 
243  lwgeom = lwgeom_from_gserialized(geom);
244  if (lwgeom_is_empty(lwgeom))
245  {
246  ret = 0;
247  }
248  else if (lwgeom_is_collection(lwgeom))
249  {
250  LWCOLLECTION *col = lwgeom_as_lwcollection(lwgeom);
251  ret = col->ngeoms;
252  }
253  lwgeom_free(lwgeom);
254  PG_FREE_IF_COPY(geom, 0);
255  PG_RETURN_INT32(ret);
256 }
257 
260 Datum LWGEOM_geometryn_collection(PG_FUNCTION_ARGS)
261 {
262  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
264  int type = gserialized_get_type(geom);
265  int32 idx;
266  LWCOLLECTION *coll;
267  LWGEOM *subgeom;
268 
269  POSTGIS_DEBUG(2, "LWGEOM_geometryn_collection called.");
270 
271  /* elog(NOTICE, "GeometryN called"); */
272 
273  idx = PG_GETARG_INT32(1);
274  idx -= 1; /* index is 1-based */
275 
276  if (gserialized_is_empty(geom))
277  {
278  PG_RETURN_NULL();
279  }
280 
281  /* call is valid on multi* geoms only */
285  {
286  if ( idx == 0 ) PG_RETURN_POINTER(geom);
287  PG_RETURN_NULL();
288  }
289 
291 
292  if ( idx < 0 ) PG_RETURN_NULL();
293  if ( idx >= (int32) coll->ngeoms ) PG_RETURN_NULL();
294 
295  subgeom = coll->geoms[idx];
296  subgeom->srid = coll->srid;
297 
298  /* COMPUTE_BBOX==TAINTING */
299  if ( coll->bbox ) lwgeom_add_bbox(subgeom);
300 
301  result = geometry_serialize(subgeom);
302 
303  lwcollection_free(coll);
304  PG_FREE_IF_COPY(geom, 0);
305 
306  PG_RETURN_POINTER(result);
307 
308 }
309 
310 
316 Datum LWGEOM_dimension(PG_FUNCTION_ARGS)
317 {
318  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
319  LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
320  int dimension = -1;
321 
322  dimension = lwgeom_dimension(lwgeom);
323  lwgeom_free(lwgeom);
324  PG_FREE_IF_COPY(geom, 0);
325 
326  if ( dimension < 0 )
327  {
328  elog(NOTICE, "Could not compute geometry dimensions");
329  PG_RETURN_NULL();
330  }
331 
332  PG_RETURN_INT32(dimension);
333 }
334 
335 
342 Datum LWGEOM_exteriorring_polygon(PG_FUNCTION_ARGS)
343 {
344  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
346  POINTARRAY *extring;
347  LWGEOM *lwgeom;
348  LWLINE *line;
349  GBOX *bbox=NULL;
350  int type = gserialized_get_type(geom);
351 
352  POSTGIS_DEBUG(2, "LWGEOM_exteriorring_polygon called.");
353 
354  if ( (type != POLYGONTYPE) &&
355  (type != CURVEPOLYTYPE) &&
356  (type != TRIANGLETYPE))
357  {
358  PG_RETURN_NULL();
359  }
360 
361  lwgeom = lwgeom_from_gserialized(geom);
362 
363  if( lwgeom_is_empty(lwgeom) )
364  {
365  line = lwline_construct_empty(lwgeom->srid,
366  lwgeom_has_z(lwgeom),
367  lwgeom_has_m(lwgeom));
368  result = geometry_serialize(lwline_as_lwgeom(line));
369  }
370  else if ( type == POLYGONTYPE )
371  {
372  LWPOLY *poly = lwgeom_as_lwpoly(lwgeom);
373 
374  /* Ok, now we have a polygon. Here is its exterior ring. */
375  extring = poly->rings[0];
376 
377  /*
378  * This is a LWLINE constructed by exterior ring POINTARRAY
379  * If the input geom has a bbox, use it for
380  * the output geom, as exterior ring makes it up !
381  */
382  if ( poly->bbox )
383  bbox = gbox_copy(poly->bbox);
384 
385  line = lwline_construct(poly->srid, bbox, extring);
386  result = geometry_serialize((LWGEOM *)line);
387 
388  lwgeom_release((LWGEOM *)line);
389  }
390  else if ( type == TRIANGLETYPE )
391  {
392  LWTRIANGLE *triangle = lwgeom_as_lwtriangle(lwgeom);
393 
394  /*
395  * This is a LWLINE constructed by exterior ring POINTARRAY
396  * If the input geom has a bbox, use it for
397  * the output geom, as exterior ring makes it up !
398  */
399  if ( triangle->bbox )
400  bbox = gbox_copy(triangle->bbox);
401  line = lwline_construct(triangle->srid, bbox, triangle->points);
402 
403  result = geometry_serialize((LWGEOM *)line);
404 
405  lwgeom_release((LWGEOM *)line);
406  }
407  else
408  {
409  LWCURVEPOLY *curvepoly = lwgeom_as_lwcurvepoly(lwgeom);
410  result = geometry_serialize(curvepoly->rings[0]);
411  }
412 
413  lwgeom_free(lwgeom);
414  PG_FREE_IF_COPY(geom, 0);
415  PG_RETURN_POINTER(result);
416 }
417 
425 Datum LWGEOM_numinteriorrings_polygon(PG_FUNCTION_ARGS)
426 {
427  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
428  int type = gserialized_get_type(geom);
429  LWGEOM *lwgeom;
430  int result = -1;
431 
432  if ( (type != POLYGONTYPE) &&
433  (type != CURVEPOLYTYPE) &&
434  (type != TRIANGLETYPE))
435  {
436  PG_RETURN_NULL();
437  }
438 
439  lwgeom = lwgeom_from_gserialized(geom);
440  if ( lwgeom_is_empty(lwgeom) )
441  {
442  result = 0;
443  }
444  else
445  {
446  const LWPOLY *poly = (LWPOLY*)lwgeom;
447  result = poly->nrings - 1;
448  }
449 
450  lwgeom_free(lwgeom);
451  PG_FREE_IF_COPY(geom, 0);
452 
453  if ( result < 0 )
454  PG_RETURN_NULL();
455 
456  PG_RETURN_INT32(result);
457 }
458 
466 Datum LWGEOM_interiorringn_polygon(PG_FUNCTION_ARGS)
467 {
468  GSERIALIZED *geom;
469  int32 wanted_index;
470  LWCURVEPOLY *curvepoly = NULL;
471  LWPOLY *poly = NULL;
472  POINTARRAY *ring;
473  LWLINE *line;
474  LWGEOM *lwgeom;
476  GBOX *bbox = NULL;
477  int type;
478 
479  POSTGIS_DEBUG(2, "LWGEOM_interiorringn_polygon called.");
480 
481  wanted_index = PG_GETARG_INT32(1);
482  if ( wanted_index < 1 )
483  {
484  PG_RETURN_NULL(); /* index out of range */
485  }
486 
487  geom = PG_GETARG_GSERIALIZED_P(0);
488  type = gserialized_get_type(geom);
489 
490  if ( (type != POLYGONTYPE) && (type != CURVEPOLYTYPE) )
491  {
492  PG_FREE_IF_COPY(geom, 0);
493  PG_RETURN_NULL();
494  }
495 
496  lwgeom = lwgeom_from_gserialized(geom);
497  if( lwgeom_is_empty(lwgeom) )
498  {
499  lwpoly_free(poly);
500  PG_FREE_IF_COPY(geom, 0);
501  PG_RETURN_NULL();
502  }
503 
504  if ( type == POLYGONTYPE)
505  {
507 
508  /* Ok, now we have a polygon. Let's see if it has enough holes */
509  if ( wanted_index >= (int32)poly->nrings )
510  {
511  lwpoly_free(poly);
512  PG_FREE_IF_COPY(geom, 0);
513  PG_RETURN_NULL();
514  }
515 
516  ring = poly->rings[wanted_index];
517 
518  /* COMPUTE_BBOX==TAINTING */
519  if ( poly->bbox )
520  {
521  bbox = lwalloc(sizeof(GBOX));
523  }
524 
525  /* This is a LWLINE constructed by interior ring POINTARRAY */
526  line = lwline_construct(poly->srid, bbox, ring);
527 
528 
529  result = geometry_serialize((LWGEOM *)line);
530  lwline_release(line);
531  lwpoly_free(poly);
532  }
533  else
534  {
536 
537  if (wanted_index >= (int32)curvepoly->nrings)
538  {
539  PG_FREE_IF_COPY(geom, 0);
540  lwgeom_release((LWGEOM *)curvepoly);
541  PG_RETURN_NULL();
542  }
543 
544  result = geometry_serialize(curvepoly->rings[wanted_index]);
545  lwgeom_free((LWGEOM*)curvepoly);
546  }
547 
548  PG_FREE_IF_COPY(geom, 0);
549  PG_RETURN_POINTER(result);
550 }
551 
558 Datum LWGEOM_pointn_linestring(PG_FUNCTION_ARGS)
559 {
560  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
561  int where = PG_GETARG_INT32(1);
562  LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
563  LWPOINT *lwpoint = NULL;
564  int type = lwgeom->type;
565 
566  /* If index is negative, count backward */
567  if( where < 1 )
568  {
569  int count = -1;
570  if ( type == LINETYPE || type == CIRCSTRINGTYPE || type == COMPOUNDTYPE )
571  count = lwgeom_count_vertices(lwgeom);
572  if(count >0)
573  {
574  /* only work if we found the total point number */
575  /* converting where to positive backward indexing, +1 because 1 indexing */
576  where = where + count + 1;
577  }
578  if (where < 1)
579  PG_RETURN_NULL();
580  }
581 
582  if ( type == LINETYPE || type == CIRCSTRINGTYPE )
583  {
584  /* OGC index starts at one, so we substract first. */
585  lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, where - 1);
586  }
587  else if ( type == COMPOUNDTYPE )
588  {
589  lwpoint = lwcompound_get_lwpoint((LWCOMPOUND*)lwgeom, where - 1);
590  }
591 
592  lwgeom_free(lwgeom);
593  PG_FREE_IF_COPY(geom, 0);
594 
595  if ( ! lwpoint )
596  PG_RETURN_NULL();
597 
598  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(lwpoint)));
599 }
600 
606 Datum LWGEOM_x_point(PG_FUNCTION_ARGS)
607 {
608  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
609  POINT4D pt;
610 
611  if (gserialized_get_type(geom) != POINTTYPE)
612  lwpgerror("Argument to ST_X() must have type POINT");
613 
614  if (gserialized_peek_first_point(geom, &pt) == LW_FAILURE)
615  {
616  PG_RETURN_NULL();
617  }
618  PG_RETURN_FLOAT8(pt.x);
619 }
620 
626 Datum LWGEOM_y_point(PG_FUNCTION_ARGS)
627 {
628  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
629  POINT4D pt;
630 
631  if (gserialized_get_type(geom) != POINTTYPE)
632  lwpgerror("Argument to ST_Y() must have type POINT");
633 
634  if (gserialized_peek_first_point(geom, &pt) == LW_FAILURE)
635  {
636  PG_RETURN_NULL();
637  }
638  PG_RETURN_FLOAT8(pt.y);
639 }
640 
647 Datum LWGEOM_z_point(PG_FUNCTION_ARGS)
648 {
649  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
650  POINT4D pt;
651 
652  if (gserialized_get_type(geom) != POINTTYPE)
653  lwpgerror("Argument to ST_Z() must have type POINT");
654 
655  if (!gserialized_has_z(geom) || (gserialized_peek_first_point(geom, &pt) == LW_FAILURE))
656  {
657  PG_RETURN_NULL();
658  }
659  PG_RETURN_FLOAT8(pt.z);
660 }
661 
667 Datum LWGEOM_m_point(PG_FUNCTION_ARGS)
668 {
669  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
670  POINT4D pt;
671 
672  if (gserialized_get_type(geom) != POINTTYPE)
673  lwpgerror("Argument to ST_M() must have type POINT");
674 
675  if (!gserialized_has_m(geom) || (gserialized_peek_first_point(geom, &pt) == LW_FAILURE))
676  {
677  PG_RETURN_NULL();
678  }
679  PG_RETURN_FLOAT8(pt.m);
680 }
681 
687 Datum LWGEOM_startpoint_linestring(PG_FUNCTION_ARGS)
688 {
689  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
690  GSERIALIZED *ret;
691  LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
692  LWGEOM *lwpoint = NULL;
693  POINT4D pt;
694 
695  if (lwgeom_startpoint(lwgeom, &pt) == LW_FAILURE)
696  {
697  PG_RETURN_NULL();
698  }
699 
700  lwpoint = (LWGEOM *)lwpoint_make(lwgeom->srid, lwgeom_has_z(lwgeom), lwgeom_has_m(lwgeom), &pt);
701  ret = geometry_serialize(lwpoint);
702 
703  lwgeom_free(lwgeom);
704  lwgeom_free(lwpoint);
705 
706  PG_FREE_IF_COPY(geom, 0);
707  PG_RETURN_POINTER(ret);
708 }
709 
715 Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS)
716 {
717  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
718  LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
719  LWPOINT *lwpoint = NULL;
720  int type = lwgeom->type;
721 
722  if ( type == LINETYPE || type == CIRCSTRINGTYPE )
723  {
724  LWLINE *line = (LWLINE*)lwgeom;
725  if ( line->points )
726  lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, line->points->npoints - 1);
727  }
728  else if ( type == COMPOUNDTYPE )
729  {
730  lwpoint = lwcompound_get_endpoint((LWCOMPOUND*)lwgeom);
731  }
732 
733  lwgeom_free(lwgeom);
734  PG_FREE_IF_COPY(geom, 0);
735 
736  if ( ! lwpoint )
737  PG_RETURN_NULL();
738 
739  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(lwpoint)));
740 }
741 
750 Datum LWGEOM_from_text(PG_FUNCTION_ARGS)
751 {
752  text *wkttext = PG_GETARG_TEXT_P(0);
753  char *wkt = text_to_cstring(wkttext);
754  LWGEOM_PARSER_RESULT lwg_parser_result;
755  GSERIALIZED *geom_result = NULL;
756  LWGEOM *lwgeom;
757 
758  POSTGIS_DEBUG(2, "LWGEOM_from_text");
759  POSTGIS_DEBUGF(3, "wkt: [%s]", wkt);
760 
761  if (lwgeom_parse_wkt(&lwg_parser_result, wkt, LW_PARSER_CHECK_ALL) == LW_FAILURE )
762  PG_PARSER_ERROR(lwg_parser_result);
763 
764  lwgeom = lwg_parser_result.geom;
765 
766  if ( lwgeom->srid != SRID_UNKNOWN )
767  {
768  elog(WARNING, "OGC WKT expected, EWKT provided - use GeomFromEWKT() for this");
769  }
770 
771  /* read user-requested SRID if any */
772  if ( PG_NARGS() > 1 )
773  lwgeom_set_srid(lwgeom, PG_GETARG_INT32(1));
774 
775  geom_result = geometry_serialize(lwgeom);
776  lwgeom_parser_result_free(&lwg_parser_result);
777 
778  PG_RETURN_POINTER(geom_result);
779 }
780 
791 Datum LWGEOM_from_WKB(PG_FUNCTION_ARGS)
792 {
793  bytea *bytea_wkb = PG_GETARG_BYTEA_P(0);
794  int32 srid = 0;
795  GSERIALIZED *geom;
796  LWGEOM *lwgeom;
797  uint8_t *wkb = (uint8_t*)VARDATA(bytea_wkb);
798 
799  lwgeom = lwgeom_from_wkb(wkb, VARSIZE_ANY_EXHDR(bytea_wkb), LW_PARSER_CHECK_ALL);
800  if (!lwgeom)
801  lwpgerror("Unable to parse WKB");
802 
803  geom = geometry_serialize(lwgeom);
804  lwgeom_free(lwgeom);
805  PG_FREE_IF_COPY(bytea_wkb, 0);
806 
807  if ( gserialized_get_srid(geom) != SRID_UNKNOWN )
808  {
809  elog(WARNING, "OGC WKB expected, EWKB provided - use GeometryFromEWKB() for this");
810  }
811 
812  if ( PG_NARGS() > 1 )
813  {
814  srid = PG_GETARG_INT32(1);
815  if ( srid != gserialized_get_srid(geom) )
816  gserialized_set_srid(geom, srid);
817  }
818 
819  PG_RETURN_POINTER(geom);
820 }
821 
824 Datum LWGEOM_asText(PG_FUNCTION_ARGS)
825 {
826  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
827  LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
828 
829  int dbl_dig_for_wkt = OUT_DEFAULT_DECIMAL_DIGITS;
830  if (PG_NARGS() > 1) dbl_dig_for_wkt = PG_GETARG_INT32(1);
831 
832  PG_RETURN_TEXT_P(lwgeom_to_wkt_varlena(lwgeom, WKT_ISO, dbl_dig_for_wkt));
833 }
834 
835 
838 Datum LWGEOM_asBinary(PG_FUNCTION_ARGS)
839 {
840  GSERIALIZED *geom;
841  LWGEOM *lwgeom;
842  uint8_t variant = WKB_ISO;
843 
844  if (PG_ARGISNULL(0))
845  PG_RETURN_NULL();
846 
847  /* Get a 2D version of the geometry */
848  geom = PG_GETARG_GSERIALIZED_P(0);
849  lwgeom = lwgeom_from_gserialized(geom);
850 
851 
852  /* If user specified endianness, respect it */
853  if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) )
854  {
855  text *wkb_endian = PG_GETARG_TEXT_P(1);
856 
857  if ( ! strncmp(VARDATA(wkb_endian), "xdr", 3) ||
858  ! strncmp(VARDATA(wkb_endian), "XDR", 3) )
859  {
860  variant = variant | WKB_XDR;
861  }
862  else
863  {
864  variant = variant | WKB_NDR;
865  }
866  }
867 
868  /* Write to WKB and free the geometry */
869  PG_RETURN_BYTEA_P(lwgeom_to_wkb_varlena(lwgeom, variant));
870 }
871 
872 
873 
881 Datum LWGEOM_isclosed(PG_FUNCTION_ARGS)
882 {
883  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
884  LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
885  int closed = lwgeom_is_closed(lwgeom);
886 
887  lwgeom_free(lwgeom);
888  PG_FREE_IF_COPY(geom, 0);
889  PG_RETURN_BOOL(closed);
890 }
static uint8_t variant
Definition: cu_in_twkb.c:26
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition: cu_print.c:262
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
Definition: gbox.c:426
int ptarray_calculate_gbox_cartesian(const POINTARRAY *pa, GBOX *gbox)
Calculate box (x/y) and add values to gbox.
Definition: gbox.c:601
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: gserialized.c:126
int gserialized_has_m(const GSERIALIZED *g)
Check if a GSERIALIZED has an M ordinate.
Definition: gserialized.c:185
int gserialized_peek_first_point(const GSERIALIZED *g, POINT4D *out_point)
Pull the first point values of a GSERIALIZED.
Definition: gserialized.c:257
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
Definition: gserialized.c:239
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: gserialized.c:152
void gserialized_set_srid(GSERIALIZED *g, int32_t srid)
Write the SRID into the serialized form (it is packed into three bytes so this is a handy function).
Definition: gserialized.c:138
int gserialized_has_z(const GSERIALIZED *g)
Check if a GSERIALIZED has a Z ordinate.
Definition: gserialized.c:174
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
Definition: gserialized.c:89
int lwgeom_is_closed(const LWGEOM *geom)
Return true or false depending on whether a geometry is a linear feature that closes on itself.
Definition: lwgeom.c:1053
#define LW_PARSER_CHECK_ALL
Definition: liblwgeom.h:2115
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:339
#define COLLECTIONTYPE
Definition: liblwgeom.h:108
#define COMPOUNDTYPE
Definition: liblwgeom.h:110
int lwgeom_startpoint(const LWGEOM *lwgeom, POINT4D *pt)
Definition: lwgeom.c:2135
#define WKB_ISO
Definition: liblwgeom.h:2175
void lwgeom_set_srid(LWGEOM *geom, int32_t srid)
Set the SRID on an LWGEOM For collections, only the parent gets an SRID, all the children get SRID_UN...
Definition: lwgeom.c:1547
#define LW_FAILURE
Definition: liblwgeom.h:96
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1155
#define CURVEPOLYTYPE
Definition: liblwgeom.h:111
#define MULTILINETYPE
Definition: liblwgeom.h:106
LWPOINT * lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, uint32_t where)
Definition: lwcompound.c:213
#define MULTISURFACETYPE
Definition: liblwgeom.h:113
#define LINETYPE
Definition: liblwgeom.h:103
void lwline_release(LWLINE *lwline)
Definition: lwline.c:125
#define MULTIPOINTTYPE
Definition: liblwgeom.h:105
int lwgeom_parse_wkt(LWGEOM_PARSER_RESULT *parser_result, char *wktstr, int parse_flags)
Parse a WKT geometry string into an LWGEOM structure.
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:934
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:102
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
LWTRIANGLE * lwgeom_as_lwtriangle(const LWGEOM *lwgeom)
Definition: lwgeom.c:224
#define TINTYPE
Definition: liblwgeom.h:116
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:107
uint32_t lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition: lwgeom.c:1246
int lwgeom_dimension(const LWGEOM *geom)
For an LWGEOM, returns 0 for points, 1 for lines, 2 for polygons, 3 for volume, and the max dimension...
Definition: lwgeom.c:1298
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:344
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1097
#define POLYGONTYPE
Definition: liblwgeom.h:104
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:114
LWCURVEPOLY * lwgeom_as_lwcurvepoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:206
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:109
#define WKT_ISO
Definition: liblwgeom.h:2184
#define WKB_NDR
Definition: liblwgeom.h:2178
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:357
#define MULTICURVETYPE
Definition: liblwgeom.h:112
#define TRIANGLETYPE
Definition: liblwgeom.h:115
void * lwalloc(size_t size)
Definition: lwutil.c:227
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition: lwgeom.c:233
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:175
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:215
void lwgeom_release(LWGEOM *lwgeom)
Free the containing LWGEOM and the associated BOX.
Definition: lwgeom.c:468
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:215
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:834
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:941
lwvarlena_t * lwgeom_to_wkb_varlena(const LWGEOM *geom, uint8_t variant)
Definition: lwout_wkb.c:851
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
Definition: lwgeom.c:695
LWLINE * lwline_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwline.c:55
void lwgeom_parser_result_free(LWGEOM_PARSER_RESULT *parser_result)
Definition: lwin_wkt.c:886
LWPOINT * lwcompound_get_endpoint(const LWCOMPOUND *lwcmp)
Definition: lwcompound.c:254
#define WKB_XDR
Definition: liblwgeom.h:2179
LWPOINT * lwpoint_make(int32_t srid, int hasz, int hasm, const POINT4D *p)
Definition: lwpoint.c:206
lwvarlena_t * lwgeom_to_wkt_varlena(const LWGEOM *geom, uint8_t variant, int precision)
Definition: lwout_wkt.c:721
LWPOINT * lwline_get_lwpoint(const LWLINE *line, uint32_t where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition: lwline.c:309
This library is the generic geometry handling section of PostGIS.
#define OUT_DEFAULT_DECIMAL_DIGITS
Datum LWGEOM_asBinary(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:838
Datum LWGEOM_exteriorring_polygon(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:342
Datum LWGEOM_from_WKB(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:791
Datum LWGEOM_dimension(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:316
PG_FUNCTION_INFO_V1(LWGEOM_get_srid)
Datum LWGEOM_get_srid(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:97
Datum LWGEOM_isclosed(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:881
Datum LWGEOM_asText(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:824
static char * stTypeName[]
Definition: lwgeom_ogc.c:175
Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:715
Datum LWGEOM_startpoint_linestring(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:687
Datum LWGEOM_from_text(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:750
Datum LWGEOM_pointn_linestring(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:558
Datum LWGEOM_numpoints_linestring(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:216
Datum LWGEOM_geometryn_collection(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:260
Datum geometry_geometrytype(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:194
Datum LWGEOM_x_point(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:606
Datum LWGEOM_interiorringn_polygon(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:466
Datum LWGEOM_y_point(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:626
Datum LWGEOM_m_point(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:667
Datum LWGEOM_numinteriorrings_polygon(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:425
Datum LWGEOM_numgeometries_collection(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:237
Datum LWGEOM_getTYPE(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:117
Datum LWGEOM_set_srid(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:107
Datum LWGEOM_z_point(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:647
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwinline.h:203
int count
Definition: genraster.py:57
type
Definition: ovdump.py:42
unsigned int int32
Definition: shpopen.c:54
uint32_t ngeoms
Definition: liblwgeom.h:580
GBOX * bbox
Definition: liblwgeom.h:574
LWGEOM ** geoms
Definition: liblwgeom.h:575
int32_t srid
Definition: liblwgeom.h:576
LWGEOM ** rings
Definition: liblwgeom.h:603
uint32_t nrings
Definition: liblwgeom.h:608
uint8_t type
Definition: liblwgeom.h:462
int32_t srid
Definition: liblwgeom.h:460
POINTARRAY * points
Definition: liblwgeom.h:483
POINTARRAY ** rings
Definition: liblwgeom.h:519
uint32_t nrings
Definition: liblwgeom.h:524
GBOX * bbox
Definition: liblwgeom.h:518
int32_t srid
Definition: liblwgeom.h:520
int32_t srid
Definition: liblwgeom.h:496
GBOX * bbox
Definition: liblwgeom.h:494
POINTARRAY * points
Definition: liblwgeom.h:495
double m
Definition: liblwgeom.h:414
double x
Definition: liblwgeom.h:414
double z
Definition: liblwgeom.h:414
double y
Definition: liblwgeom.h:414
uint32_t npoints
Definition: liblwgeom.h:427
Parser result structure: returns the result of attempting to convert (E)WKT/(E)WKB to LWGEOM.
Definition: liblwgeom.h:2122