PostGIS  3.0.6dev-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 "lwgeom_pg.h"
44 
45 
46 /* ---- SRID(geometry) */
47 Datum LWGEOM_get_srid(PG_FUNCTION_ARGS);
48 /* ---- SetSRID(geometry, integer) */
49 Datum LWGEOM_set_srid(PG_FUNCTION_ARGS);
50 /* ---- GeometryType(geometry) */
51 Datum LWGEOM_getTYPE(PG_FUNCTION_ARGS);
52 Datum geometry_geometrytype(PG_FUNCTION_ARGS);
53 /* ---- NumPoints(geometry) */
54 Datum LWGEOM_numpoints_linestring(PG_FUNCTION_ARGS);
55 /* ---- NumGeometries(geometry) */
56 Datum LWGEOM_numgeometries_collection(PG_FUNCTION_ARGS);
57 /* ---- GeometryN(geometry, integer) */
58 Datum LWGEOM_geometryn_collection(PG_FUNCTION_ARGS);
59 /* ---- Dimension(geometry) */
60 Datum LWGEOM_dimension(PG_FUNCTION_ARGS);
61 /* ---- ExteriorRing(geometry) */
62 Datum LWGEOM_exteriorring_polygon(PG_FUNCTION_ARGS);
63 /* ---- InteriorRingN(geometry, integer) */
64 Datum LWGEOM_interiorringn_polygon(PG_FUNCTION_ARGS);
65 /* ---- NumInteriorRings(geometry) */
66 Datum LWGEOM_numinteriorrings_polygon(PG_FUNCTION_ARGS);
67 /* ---- PointN(geometry, integer) */
68 Datum LWGEOM_pointn_linestring(PG_FUNCTION_ARGS);
69 /* ---- X(geometry) */
70 Datum LWGEOM_x_point(PG_FUNCTION_ARGS);
71 /* ---- Y(geometry) */
72 Datum LWGEOM_y_point(PG_FUNCTION_ARGS);
73 /* ---- Z(geometry) */
74 Datum LWGEOM_z_point(PG_FUNCTION_ARGS);
75 /* ---- M(geometry) */
76 Datum LWGEOM_m_point(PG_FUNCTION_ARGS);
77 /* ---- StartPoint(geometry) */
78 Datum LWGEOM_startpoint_linestring(PG_FUNCTION_ARGS);
79 /* ---- EndPoint(geometry) */
80 Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS);
81 /* ---- AsText(geometry) */
82 Datum LWGEOM_asText(PG_FUNCTION_ARGS);
83 /* ---- AsBinary(geometry, [XDR|NDR]) */
84 Datum LWGEOM_asBinary(PG_FUNCTION_ARGS);
85 /* ---- GeometryFromText(text, integer) */
86 Datum LWGEOM_from_text(PG_FUNCTION_ARGS);
87 /* ---- GeomFromWKB(bytea, integer) */
88 Datum LWGEOM_from_WKB(PG_FUNCTION_ARGS);
89 /* ---- IsClosed(geometry) */
90 Datum LWGEOM_isclosed(PG_FUNCTION_ARGS);
91 
92 /*------------------------------------------------------------------*/
93 
94 /* getSRID(lwgeom) :: int4 */
96 Datum LWGEOM_get_srid(PG_FUNCTION_ARGS)
97 {
98  GSERIALIZED *geom=PG_GETARG_GSERIALIZED_P(0);
99  int32_t srid = gserialized_get_srid(geom);
100  PG_FREE_IF_COPY(geom,0);
101  PG_RETURN_INT32(srid);
102 }
103 
104 /* setSRID(lwgeom, int4) :: lwgeom */
106 Datum LWGEOM_set_srid(PG_FUNCTION_ARGS)
107 {
108  GSERIALIZED *g = (GSERIALIZED *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
109  int32_t srid = PG_GETARG_INT32(1);
110  gserialized_set_srid(g, srid);
111  PG_RETURN_POINTER(g);
112 }
113 
114 /* returns a string representation of this geometry's type */
116 Datum LWGEOM_getTYPE(PG_FUNCTION_ARGS)
117 {
118  GSERIALIZED *gser;
119  text *text_ob;
120  char *result;
121  uint8_t type;
122  static int maxtyplen = 20;
123 
124  gser = PG_GETARG_GSERIALIZED_P_SLICE(0, 0, gserialized_max_header_size());
125  text_ob = palloc0(VARHDRSZ + maxtyplen);
126  result = VARDATA(text_ob);
127 
128  type = gserialized_get_type(gser);
129 
130  if (type == POINTTYPE)
131  strcpy(result,"POINT");
132  else if (type == MULTIPOINTTYPE)
133  strcpy(result,"MULTIPOINT");
134  else if (type == LINETYPE)
135  strcpy(result,"LINESTRING");
136  else if (type == CIRCSTRINGTYPE)
137  strcpy(result,"CIRCULARSTRING");
138  else if (type == COMPOUNDTYPE)
139  strcpy(result, "COMPOUNDCURVE");
140  else if (type == MULTILINETYPE)
141  strcpy(result,"MULTILINESTRING");
142  else if (type == MULTICURVETYPE)
143  strcpy(result, "MULTICURVE");
144  else if (type == POLYGONTYPE)
145  strcpy(result,"POLYGON");
146  else if (type == TRIANGLETYPE)
147  strcpy(result,"TRIANGLE");
148  else if (type == CURVEPOLYTYPE)
149  strcpy(result,"CURVEPOLYGON");
150  else if (type == MULTIPOLYGONTYPE)
151  strcpy(result,"MULTIPOLYGON");
152  else if (type == MULTISURFACETYPE)
153  strcpy(result, "MULTISURFACE");
154  else if (type == COLLECTIONTYPE)
155  strcpy(result,"GEOMETRYCOLLECTION");
156  else if (type == POLYHEDRALSURFACETYPE)
157  strcpy(result,"POLYHEDRALSURFACE");
158  else if (type == TINTYPE)
159  strcpy(result,"TIN");
160  else
161  strcpy(result,"UNKNOWN");
162 
163  if ( gserialized_has_m(gser) && ! gserialized_has_z(gser) )
164  strcat(result, "M");
165 
166  SET_VARSIZE(text_ob, strlen(result) + VARHDRSZ); /* size of string */
167 
168  PG_FREE_IF_COPY(gser, 0);
169 
170  PG_RETURN_TEXT_P(text_ob);
171 }
172 
173 /* Matches lwutil.c::lwgeomTypeName */
174 static char *stTypeName[] = {"Unknown",
175  "ST_Point",
176  "ST_LineString",
177  "ST_Polygon",
178  "ST_MultiPoint",
179  "ST_MultiLineString",
180  "ST_MultiPolygon",
181  "ST_GeometryCollection",
182  "ST_CircularString",
183  "ST_CompoundCurve",
184  "ST_CurvePolygon",
185  "ST_MultiCurve",
186  "ST_MultiSurface",
187  "ST_PolyhedralSurface",
188  "ST_Triangle",
189  "ST_Tin"};
190 
191 /* returns a string representation of this geometry's type */
193 Datum geometry_geometrytype(PG_FUNCTION_ARGS)
194 {
195  GSERIALIZED *gser;
196  text *type_text;
197 
198  /* Read just the header from the toasted tuple */
199  gser = PG_GETARG_GSERIALIZED_P_SLICE(0, 0, gserialized_max_header_size());
200 
201  /* Build a text type to store things in */
202  type_text = cstring_to_text(stTypeName[gserialized_get_type(gser)]);
203 
204  PG_FREE_IF_COPY(gser, 0);
205  PG_RETURN_TEXT_P(type_text);
206 }
207 
208 
209 
215 Datum LWGEOM_numpoints_linestring(PG_FUNCTION_ARGS)
216 {
217  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
218  LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
219  int count = -1;
220  int type = lwgeom->type;
221 
222  if ( type == LINETYPE || type == CIRCSTRINGTYPE || type == COMPOUNDTYPE )
223  count = lwgeom_count_vertices(lwgeom);
224 
225  lwgeom_free(lwgeom);
226  PG_FREE_IF_COPY(geom, 0);
227 
228  /* OGC says this functions is only valid on LINESTRING */
229  if ( count < 0 )
230  PG_RETURN_NULL();
231 
232  PG_RETURN_INT32(count);
233 }
234 
236 Datum LWGEOM_numgeometries_collection(PG_FUNCTION_ARGS)
237 {
238  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
239  LWGEOM *lwgeom;
240  int32 ret = 1;
241 
242  lwgeom = lwgeom_from_gserialized(geom);
243  if ( lwgeom_is_empty(lwgeom) )
244  {
245  ret = 0;
246  }
247  else if ( lwgeom_is_collection(lwgeom) )
248  {
249  LWCOLLECTION *col = lwgeom_as_lwcollection(lwgeom);
250  ret = col->ngeoms;
251  }
252  lwgeom_free(lwgeom);
253  PG_FREE_IF_COPY(geom, 0);
254  PG_RETURN_INT32(ret);
255 }
256 
259 Datum LWGEOM_geometryn_collection(PG_FUNCTION_ARGS)
260 {
261  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
262  GSERIALIZED *result;
263  int type = gserialized_get_type(geom);
264  int32 idx;
265  LWCOLLECTION *coll;
266  LWGEOM *subgeom;
267 
268  POSTGIS_DEBUG(2, "LWGEOM_geometryn_collection called.");
269 
270  /* elog(NOTICE, "GeometryN called"); */
271 
272  idx = PG_GETARG_INT32(1);
273  idx -= 1; /* index is 1-based */
274 
275  /* call is valid on multi* geoms only */
279  {
280  if ( idx == 0 ) PG_RETURN_POINTER(geom);
281  PG_RETURN_NULL();
282  }
283 
285 
286  if ( idx < 0 ) PG_RETURN_NULL();
287  if ( idx >= (int32) coll->ngeoms ) PG_RETURN_NULL();
288 
289  subgeom = coll->geoms[idx];
290  subgeom->srid = coll->srid;
291 
292  /* COMPUTE_BBOX==TAINTING */
293  if ( coll->bbox ) lwgeom_add_bbox(subgeom);
294 
295  result = geometry_serialize(subgeom);
296 
297  lwcollection_free(coll);
298  PG_FREE_IF_COPY(geom, 0);
299 
300  PG_RETURN_POINTER(result);
301 
302 }
303 
304 
310 Datum LWGEOM_dimension(PG_FUNCTION_ARGS)
311 {
312  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
313  LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
314  int dimension = -1;
315 
316  dimension = lwgeom_dimension(lwgeom);
317  lwgeom_free(lwgeom);
318  PG_FREE_IF_COPY(geom, 0);
319 
320  if ( dimension < 0 )
321  {
322  elog(NOTICE, "Could not compute geometry dimensions");
323  PG_RETURN_NULL();
324  }
325 
326  PG_RETURN_INT32(dimension);
327 }
328 
329 
336 Datum LWGEOM_exteriorring_polygon(PG_FUNCTION_ARGS)
337 {
338  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
339  GSERIALIZED *result;
340  POINTARRAY *extring;
341  LWGEOM *lwgeom;
342  LWLINE *line;
343  GBOX *bbox=NULL;
344  int type = gserialized_get_type(geom);
345 
346  POSTGIS_DEBUG(2, "LWGEOM_exteriorring_polygon called.");
347 
348  if ( (type != POLYGONTYPE) &&
349  (type != CURVEPOLYTYPE) &&
350  (type != TRIANGLETYPE))
351  {
352  PG_RETURN_NULL();
353  }
354 
355  lwgeom = lwgeom_from_gserialized(geom);
356 
357  if( lwgeom_is_empty(lwgeom) )
358  {
359  line = lwline_construct_empty(lwgeom->srid,
360  lwgeom_has_z(lwgeom),
361  lwgeom_has_m(lwgeom));
362  result = geometry_serialize(lwline_as_lwgeom(line));
363  }
364  else if ( type == POLYGONTYPE )
365  {
366  LWPOLY *poly = lwgeom_as_lwpoly(lwgeom);
367 
368  /* Ok, now we have a polygon. Here is its exterior ring. */
369  extring = poly->rings[0];
370 
371  /*
372  * This is a LWLINE constructed by exterior ring POINTARRAY
373  * If the input geom has a bbox, use it for
374  * the output geom, as exterior ring makes it up !
375  */
376  if ( poly->bbox )
377  bbox = gbox_copy(poly->bbox);
378 
379  line = lwline_construct(poly->srid, bbox, extring);
380  result = geometry_serialize((LWGEOM *)line);
381 
382  lwgeom_release((LWGEOM *)line);
383  }
384  else if ( type == TRIANGLETYPE )
385  {
386  LWTRIANGLE *triangle = lwgeom_as_lwtriangle(lwgeom);
387 
388  /*
389  * This is a LWLINE constructed by exterior ring POINTARRAY
390  * If the input geom has a bbox, use it for
391  * the output geom, as exterior ring makes it up !
392  */
393  if ( triangle->bbox )
394  bbox = gbox_copy(triangle->bbox);
395  line = lwline_construct(triangle->srid, bbox, triangle->points);
396 
397  result = geometry_serialize((LWGEOM *)line);
398 
399  lwgeom_release((LWGEOM *)line);
400  }
401  else
402  {
403  LWCURVEPOLY *curvepoly = lwgeom_as_lwcurvepoly(lwgeom);
404  result = geometry_serialize(curvepoly->rings[0]);
405  }
406 
407  lwgeom_free(lwgeom);
408  PG_FREE_IF_COPY(geom, 0);
409  PG_RETURN_POINTER(result);
410 }
411 
419 Datum LWGEOM_numinteriorrings_polygon(PG_FUNCTION_ARGS)
420 {
421  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
422  int type = gserialized_get_type(geom);
423  LWGEOM *lwgeom;
424  int result = -1;
425 
426  if ( (type != POLYGONTYPE) &&
427  (type != CURVEPOLYTYPE) &&
428  (type != TRIANGLETYPE))
429  {
430  PG_RETURN_NULL();
431  }
432 
433  lwgeom = lwgeom_from_gserialized(geom);
434  if ( lwgeom_is_empty(lwgeom) )
435  {
436  result = 0;
437  }
438  else
439  {
440  const LWPOLY *poly = (LWPOLY*)lwgeom;
441  result = poly->nrings - 1;
442  }
443 
444  lwgeom_free(lwgeom);
445  PG_FREE_IF_COPY(geom, 0);
446 
447  if ( result < 0 )
448  PG_RETURN_NULL();
449 
450  PG_RETURN_INT32(result);
451 }
452 
460 Datum LWGEOM_interiorringn_polygon(PG_FUNCTION_ARGS)
461 {
462  GSERIALIZED *geom;
463  int32 wanted_index;
464  LWCURVEPOLY *curvepoly = NULL;
465  LWPOLY *poly = NULL;
466  POINTARRAY *ring;
467  LWLINE *line;
468  LWGEOM *lwgeom;
469  GSERIALIZED *result;
470  GBOX *bbox = NULL;
471  int type;
472 
473  POSTGIS_DEBUG(2, "LWGEOM_interiorringn_polygon called.");
474 
475  wanted_index = PG_GETARG_INT32(1);
476  if ( wanted_index < 1 )
477  {
478  PG_RETURN_NULL(); /* index out of range */
479  }
480 
481  geom = PG_GETARG_GSERIALIZED_P(0);
482  type = gserialized_get_type(geom);
483 
484  if ( (type != POLYGONTYPE) && (type != CURVEPOLYTYPE) )
485  {
486  PG_FREE_IF_COPY(geom, 0);
487  PG_RETURN_NULL();
488  }
489 
490  lwgeom = lwgeom_from_gserialized(geom);
491  if( lwgeom_is_empty(lwgeom) )
492  {
493  lwpoly_free(poly);
494  PG_FREE_IF_COPY(geom, 0);
495  PG_RETURN_NULL();
496  }
497 
498  if ( type == POLYGONTYPE)
499  {
501 
502  /* Ok, now we have a polygon. Let's see if it has enough holes */
503  if ( wanted_index >= (int32)poly->nrings )
504  {
505  lwpoly_free(poly);
506  PG_FREE_IF_COPY(geom, 0);
507  PG_RETURN_NULL();
508  }
509 
510  ring = poly->rings[wanted_index];
511 
512  /* COMPUTE_BBOX==TAINTING */
513  if ( poly->bbox )
514  {
515  bbox = lwalloc(sizeof(GBOX));
517  }
518 
519  /* This is a LWLINE constructed by interior ring POINTARRAY */
520  line = lwline_construct(poly->srid, bbox, ring);
521 
522 
523  result = geometry_serialize((LWGEOM *)line);
524  lwline_release(line);
525  lwpoly_free(poly);
526  }
527  else
528  {
530 
531  if (wanted_index >= (int32)curvepoly->nrings)
532  {
533  PG_FREE_IF_COPY(geom, 0);
534  lwgeom_release((LWGEOM *)curvepoly);
535  PG_RETURN_NULL();
536  }
537 
538  result = geometry_serialize(curvepoly->rings[wanted_index]);
539  lwgeom_free((LWGEOM*)curvepoly);
540  }
541 
542  PG_FREE_IF_COPY(geom, 0);
543  PG_RETURN_POINTER(result);
544 }
545 
552 Datum LWGEOM_pointn_linestring(PG_FUNCTION_ARGS)
553 {
554  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
555  int where = PG_GETARG_INT32(1);
556  LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
557  LWPOINT *lwpoint = NULL;
558  int type = lwgeom->type;
559 
560  /* If index is negative, count backward */
561  if( where < 1 )
562  {
563  int count = -1;
564  if ( type == LINETYPE || type == CIRCSTRINGTYPE || type == COMPOUNDTYPE )
565  count = lwgeom_count_vertices(lwgeom);
566  if(count >0)
567  {
568  /* only work if we found the total point number */
569  /* converting where to positive backward indexing, +1 because 1 indexing */
570  where = where + count + 1;
571  }
572  if (where < 1)
573  PG_RETURN_NULL();
574  }
575 
576  if ( type == LINETYPE || type == CIRCSTRINGTYPE )
577  {
578  /* OGC index starts at one, so we substract first. */
579  lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, where - 1);
580  }
581  else if ( type == COMPOUNDTYPE )
582  {
583  lwpoint = lwcompound_get_lwpoint((LWCOMPOUND*)lwgeom, where - 1);
584  }
585 
586  lwgeom_free(lwgeom);
587  PG_FREE_IF_COPY(geom, 0);
588 
589  if ( ! lwpoint )
590  PG_RETURN_NULL();
591 
592  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(lwpoint)));
593 }
594 
600 Datum LWGEOM_x_point(PG_FUNCTION_ARGS)
601 {
602  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
603  POINT4D pt;
604 
605  if (gserialized_get_type(geom) != POINTTYPE)
606  lwpgerror("Argument to ST_X() must have type POINT");
607 
608  if (gserialized_peek_first_point(geom, &pt) == LW_FAILURE)
609  {
610  PG_RETURN_NULL();
611  }
612  PG_RETURN_FLOAT8(pt.x);
613 }
614 
620 Datum LWGEOM_y_point(PG_FUNCTION_ARGS)
621 {
622  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
623  POINT4D pt;
624 
625  if (gserialized_get_type(geom) != POINTTYPE)
626  lwpgerror("Argument to ST_Y() must have type POINT");
627 
628  if (gserialized_peek_first_point(geom, &pt) == LW_FAILURE)
629  {
630  PG_RETURN_NULL();
631  }
632  PG_RETURN_FLOAT8(pt.y);
633 }
634 
641 Datum LWGEOM_z_point(PG_FUNCTION_ARGS)
642 {
643  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
644  POINT4D pt;
645 
646  if (gserialized_get_type(geom) != POINTTYPE)
647  lwpgerror("Argument to ST_Z() must have type POINT");
648 
649  if (!gserialized_has_z(geom) || (gserialized_peek_first_point(geom, &pt) == LW_FAILURE))
650  {
651  PG_RETURN_NULL();
652  }
653  PG_RETURN_FLOAT8(pt.z);
654 }
655 
661 Datum LWGEOM_m_point(PG_FUNCTION_ARGS)
662 {
663  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
664  POINT4D pt;
665 
666  if (gserialized_get_type(geom) != POINTTYPE)
667  lwpgerror("Argument to ST_M() must have type POINT");
668 
669  if (!gserialized_has_m(geom) || (gserialized_peek_first_point(geom, &pt) == LW_FAILURE))
670  {
671  PG_RETURN_NULL();
672  }
673  PG_RETURN_FLOAT8(pt.m);
674 }
675 
682 Datum LWGEOM_startpoint_linestring(PG_FUNCTION_ARGS)
683 {
684  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
685  LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
686  LWPOINT *lwpoint = NULL;
687  int type = lwgeom->type;
688 
689  if ( type == LINETYPE || type == CIRCSTRINGTYPE )
690  {
691  lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, 0);
692  }
693  else if ( type == COMPOUNDTYPE )
694  {
695  lwpoint = lwcompound_get_startpoint((LWCOMPOUND*)lwgeom);
696  }
697 
698  lwgeom_free(lwgeom);
699  PG_FREE_IF_COPY(geom, 0);
700 
701  if ( ! lwpoint )
702  PG_RETURN_NULL();
703 
704  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(lwpoint)));
705 }
706 
712 Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS)
713 {
714  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
715  LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
716  LWPOINT *lwpoint = NULL;
717  int type = lwgeom->type;
718 
719  if ( type == LINETYPE || type == CIRCSTRINGTYPE )
720  {
721  LWLINE *line = (LWLINE*)lwgeom;
722  if ( line->points )
723  lwpoint = lwline_get_lwpoint((LWLINE*)lwgeom, line->points->npoints - 1);
724  }
725  else if ( type == COMPOUNDTYPE )
726  {
727  lwpoint = lwcompound_get_endpoint((LWCOMPOUND*)lwgeom);
728  }
729 
730  lwgeom_free(lwgeom);
731  PG_FREE_IF_COPY(geom, 0);
732 
733  if ( ! lwpoint )
734  PG_RETURN_NULL();
735 
736  PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(lwpoint)));
737 }
738 
747 Datum LWGEOM_from_text(PG_FUNCTION_ARGS)
748 {
749  text *wkttext = PG_GETARG_TEXT_P(0);
750  char *wkt = text_to_cstring(wkttext);
751  LWGEOM_PARSER_RESULT lwg_parser_result;
752  GSERIALIZED *geom_result = NULL;
753  LWGEOM *lwgeom;
754 
755  POSTGIS_DEBUG(2, "LWGEOM_from_text");
756  POSTGIS_DEBUGF(3, "wkt: [%s]", wkt);
757 
758  if (lwgeom_parse_wkt(&lwg_parser_result, wkt, LW_PARSER_CHECK_ALL) == LW_FAILURE )
759  PG_PARSER_ERROR(lwg_parser_result);
760 
761  lwgeom = lwg_parser_result.geom;
762 
763  if ( lwgeom->srid != SRID_UNKNOWN )
764  {
765  elog(WARNING, "OGC WKT expected, EWKT provided - use GeomFromEWKT() for this");
766  }
767 
768  /* read user-requested SRID if any */
769  if ( PG_NARGS() > 1 )
770  lwgeom_set_srid(lwgeom, PG_GETARG_INT32(1));
771 
772  geom_result = geometry_serialize(lwgeom);
773  lwgeom_parser_result_free(&lwg_parser_result);
774 
775  PG_RETURN_POINTER(geom_result);
776 }
777 
788 Datum LWGEOM_from_WKB(PG_FUNCTION_ARGS)
789 {
790  bytea *bytea_wkb = PG_GETARG_BYTEA_P(0);
791  int32 srid = 0;
792  GSERIALIZED *geom;
793  LWGEOM *lwgeom;
794  uint8_t *wkb = (uint8_t*)VARDATA(bytea_wkb);
795 
796  lwgeom = lwgeom_from_wkb(wkb, VARSIZE_ANY_EXHDR(bytea_wkb), LW_PARSER_CHECK_ALL);
797  if (!lwgeom)
798  lwpgerror("Unable to parse WKB");
799 
800  geom = geometry_serialize(lwgeom);
801  lwgeom_free(lwgeom);
802  PG_FREE_IF_COPY(bytea_wkb, 0);
803 
804  if ( gserialized_get_srid(geom) != SRID_UNKNOWN )
805  {
806  elog(WARNING, "OGC WKB expected, EWKB provided - use GeometryFromEWKB() for this");
807  }
808 
809  if ( PG_NARGS() > 1 )
810  {
811  srid = PG_GETARG_INT32(1);
812  if ( srid != gserialized_get_srid(geom) )
813  gserialized_set_srid(geom, srid);
814  }
815 
816  PG_RETURN_POINTER(geom);
817 }
818 
821 Datum LWGEOM_asText(PG_FUNCTION_ARGS)
822 {
823  GSERIALIZED *geom;
824  LWGEOM *lwgeom;
825  char *wkt;
826  size_t wkt_size;
827  text *result;
828  int dbl_dig_for_wkt = DBL_DIG;
829 
830  POSTGIS_DEBUG(2, "Called.");
831 
832  geom = PG_GETARG_GSERIALIZED_P(0);
833  lwgeom = lwgeom_from_gserialized(geom);
834 
835  if (PG_NARGS() > 1) dbl_dig_for_wkt = PG_GETARG_INT32(1);
836 
837  /* Write to WKT and free the geometry */
838  wkt = lwgeom_to_wkt(lwgeom, WKT_ISO, dbl_dig_for_wkt, &wkt_size);
839  lwgeom_free(lwgeom);
840  POSTGIS_DEBUGF(3, "WKT size = %u, WKT length = %u", (unsigned int)wkt_size, (unsigned int)strlen(wkt));
841 
842  /* Write to text and free the WKT */
843  result = cstring_to_text(wkt);
844  lwfree(wkt);
845 
846  /* Return the text */
847  PG_FREE_IF_COPY(geom, 0);
848  PG_RETURN_TEXT_P(result);
849 }
850 
851 
854 Datum LWGEOM_asBinary(PG_FUNCTION_ARGS)
855 {
856  GSERIALIZED *geom;
857  LWGEOM *lwgeom;
858  uint8_t *wkb;
859  size_t wkb_size;
860  bytea *result;
861  uint8_t variant = WKB_ISO;
862 
863  if (PG_ARGISNULL(0))
864  PG_RETURN_NULL();
865 
866  /* Get a 2D version of the geometry */
867  geom = PG_GETARG_GSERIALIZED_P(0);
868  lwgeom = lwgeom_from_gserialized(geom);
869 
870 
871  /* If user specified endianness, respect it */
872  if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) )
873  {
874  text *wkb_endian = PG_GETARG_TEXT_P(1);
875 
876  if ( ! strncmp(VARDATA(wkb_endian), "xdr", 3) ||
877  ! strncmp(VARDATA(wkb_endian), "XDR", 3) )
878  {
879  variant = variant | WKB_XDR;
880  }
881  else
882  {
883  variant = variant | WKB_NDR;
884  }
885  }
886 
887  /* Write to WKB and free the geometry */
888  wkb = lwgeom_to_wkb(lwgeom, variant, &wkb_size);
889  lwgeom_free(lwgeom);
890 
891  /* Write to text and free the WKT */
892  result = palloc(wkb_size + VARHDRSZ);
893  memcpy(VARDATA(result), wkb, wkb_size);
894  SET_VARSIZE(result, wkb_size + VARHDRSZ);
895  lwfree(wkb);
896 
897  /* Return the text */
898  PG_FREE_IF_COPY(geom, 0);
899  PG_RETURN_BYTEA_P(result);
900 }
901 
902 
903 
911 Datum LWGEOM_isclosed(PG_FUNCTION_ARGS)
912 {
913  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
914  LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
915  int closed = lwgeom_is_closed(lwgeom);
916 
917  lwgeom_free(lwgeom);
918  PG_FREE_IF_COPY(geom, 0);
919  PG_RETURN_BOOL(closed);
920 }
static uint8_t variant
Definition: cu_in_twkb.c:26
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
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
uint32_t gserialized_max_header_size(void)
Returns the size in bytes to read from toast to get the basic information from a geometry: GSERIALIZE...
Definition: gserialized.c:101
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:1035
#define LW_PARSER_CHECK_ALL
Definition: liblwgeom.h:2061
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:321
#define COLLECTIONTYPE
Definition: liblwgeom.h:122
#define COMPOUNDTYPE
Definition: liblwgeom.h:124
#define WKB_ISO
Definition: liblwgeom.h:2121
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:1530
#define LW_FAILURE
Definition: liblwgeom.h:110
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1138
#define CURVEPOLYTYPE
Definition: liblwgeom.h:125
#define MULTILINETYPE
Definition: liblwgeom.h:120
LWPOINT * lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, uint32_t where)
Definition: lwcompound.c:213
#define MULTISURFACETYPE
Definition: liblwgeom.h:127
#define LINETYPE
Definition: liblwgeom.h:117
void lwline_release(LWLINE *lwline)
Definition: lwline.c:125
#define MULTIPOINTTYPE
Definition: liblwgeom.h:119
int lwgeom_parse_wkt(LWGEOM_PARSER_RESULT *parser_result, char *wktstr, int parse_flags)
Parse a WKT geometry string into an LWGEOM structure.
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:790
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:916
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:116
LWPOINT * lwcompound_get_startpoint(const LWCOMPOUND *lwcmp)
Definition: lwcompound.c:248
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
LWTRIANGLE * lwgeom_as_lwtriangle(const LWGEOM *lwgeom)
Definition: lwgeom.c:206
#define TINTYPE
Definition: liblwgeom.h:130
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:121
uint32_t lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition: lwgeom.c:1229
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:1281
void lwfree(void *mem)
Definition: lwutil.c:242
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:326
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1079
#define POLYGONTYPE
Definition: liblwgeom.h:118
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:128
LWCURVEPOLY * lwgeom_as_lwcurvepoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:188
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:123
#define WKT_ISO
Definition: liblwgeom.h:2130
#define WKB_NDR
Definition: liblwgeom.h:2124
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:357
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:676
#define MULTICURVETYPE
Definition: liblwgeom.h:126
#define TRIANGLETYPE
Definition: liblwgeom.h:129
void * lwalloc(size_t size)
Definition: lwutil.c:227
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition: lwgeom.c:215
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:175
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:197
void lwgeom_release(LWGEOM *lwgeom)
Free the containing LWGEOM and the associated BOX.
Definition: lwgeom.c:450
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:229
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:825
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:923
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
Definition: lwgeom.c:677
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:2125
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.
Datum LWGEOM_asBinary(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:854
Datum LWGEOM_exteriorring_polygon(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:336
Datum LWGEOM_from_WKB(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:788
Datum LWGEOM_dimension(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:310
PG_FUNCTION_INFO_V1(LWGEOM_get_srid)
Datum LWGEOM_get_srid(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:96
Datum LWGEOM_isclosed(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:911
Datum LWGEOM_asText(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:821
static char * stTypeName[]
Definition: lwgeom_ogc.c:174
Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:712
Datum LWGEOM_startpoint_linestring(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:682
Datum LWGEOM_from_text(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:747
Datum LWGEOM_pointn_linestring(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:552
Datum LWGEOM_numpoints_linestring(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:215
Datum LWGEOM_geometryn_collection(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:259
Datum geometry_geometrytype(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:193
Datum LWGEOM_x_point(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:600
Datum LWGEOM_interiorringn_polygon(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:460
Datum LWGEOM_y_point(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:620
Datum LWGEOM_m_point(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:661
Datum LWGEOM_numinteriorrings_polygon(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:419
Datum LWGEOM_numgeometries_collection(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:236
Datum LWGEOM_getTYPE(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:116
Datum LWGEOM_set_srid(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:106
Datum LWGEOM_z_point(PG_FUNCTION_ARGS)
Definition: lwgeom_ogc.c:641
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:193
int count
Definition: genraster.py:57
type
Definition: ovdump.py:42
char * text_to_cstring(const text *textptr)
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
unsigned int int32
Definition: shpopen.c:273
uint32_t ngeoms
Definition: liblwgeom.h:566
GBOX * bbox
Definition: liblwgeom.h:560
LWGEOM ** geoms
Definition: liblwgeom.h:561
int32_t srid
Definition: liblwgeom.h:562
LWGEOM ** rings
Definition: liblwgeom.h:589
uint32_t nrings
Definition: liblwgeom.h:594
uint8_t type
Definition: liblwgeom.h:448
int32_t srid
Definition: liblwgeom.h:446
POINTARRAY * points
Definition: liblwgeom.h:469
POINTARRAY ** rings
Definition: liblwgeom.h:505
uint32_t nrings
Definition: liblwgeom.h:510
GBOX * bbox
Definition: liblwgeom.h:504
int32_t srid
Definition: liblwgeom.h:506
int32_t srid
Definition: liblwgeom.h:482
GBOX * bbox
Definition: liblwgeom.h:480
POINTARRAY * points
Definition: liblwgeom.h:481
double m
Definition: liblwgeom.h:400
double x
Definition: liblwgeom.h:400
double z
Definition: liblwgeom.h:400
double y
Definition: liblwgeom.h:400
uint32_t npoints
Definition: liblwgeom.h:413
Parser result structure: returns the result of attempting to convert (E)WKT/(E)WKB to LWGEOM.
Definition: liblwgeom.h:2068