PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
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) */
47Datum LWGEOM_get_srid(PG_FUNCTION_ARGS);
48/* ---- SetSRID(geometry, integer) */
49Datum LWGEOM_set_srid(PG_FUNCTION_ARGS);
50/* ---- GeometryType(geometry) */
51Datum LWGEOM_getTYPE(PG_FUNCTION_ARGS);
52Datum geometry_geometrytype(PG_FUNCTION_ARGS);
53/* ---- NumPoints(geometry) */
54Datum LWGEOM_numpoints_linestring(PG_FUNCTION_ARGS);
55/* ---- NumGeometries(geometry) */
56Datum LWGEOM_numgeometries_collection(PG_FUNCTION_ARGS);
57/* ---- GeometryN(geometry, integer) */
58Datum LWGEOM_geometryn_collection(PG_FUNCTION_ARGS);
59/* ---- Dimension(geometry) */
60Datum LWGEOM_dimension(PG_FUNCTION_ARGS);
61/* ---- ExteriorRing(geometry) */
62Datum LWGEOM_exteriorring_polygon(PG_FUNCTION_ARGS);
63/* ---- InteriorRingN(geometry, integer) */
64Datum LWGEOM_interiorringn_polygon(PG_FUNCTION_ARGS);
65/* ---- NumInteriorRings(geometry) */
66Datum LWGEOM_numinteriorrings_polygon(PG_FUNCTION_ARGS);
67/* ---- PointN(geometry, integer) */
68Datum LWGEOM_pointn_linestring(PG_FUNCTION_ARGS);
69/* ---- X(geometry) */
70Datum LWGEOM_x_point(PG_FUNCTION_ARGS);
71/* ---- Y(geometry) */
72Datum LWGEOM_y_point(PG_FUNCTION_ARGS);
73/* ---- Z(geometry) */
74Datum LWGEOM_z_point(PG_FUNCTION_ARGS);
75/* ---- M(geometry) */
76Datum LWGEOM_m_point(PG_FUNCTION_ARGS);
77/* ---- StartPoint(geometry) */
78Datum LWGEOM_startpoint_linestring(PG_FUNCTION_ARGS);
79/* ---- EndPoint(geometry) */
80Datum LWGEOM_endpoint_linestring(PG_FUNCTION_ARGS);
81/* ---- AsText(geometry) */
82Datum LWGEOM_asText(PG_FUNCTION_ARGS);
83/* ---- AsBinary(geometry, [XDR|NDR]) */
84Datum LWGEOM_asBinary(PG_FUNCTION_ARGS);
85/* ---- GeometryFromText(text, integer) */
86Datum LWGEOM_from_text(PG_FUNCTION_ARGS);
87/* ---- GeomFromWKB(bytea, integer) */
88Datum LWGEOM_from_WKB(PG_FUNCTION_ARGS);
89/* ---- IsClosed(geometry) */
90Datum LWGEOM_isclosed(PG_FUNCTION_ARGS);
91
92/*------------------------------------------------------------------*/
93
94/* getSRID(lwgeom) :: int4 */
96Datum 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 */
106Datum 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 */
116Datum 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 */
174static 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 */
193Datum 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
215Datum 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
236Datum 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 {
250 ret = col->ngeoms;
251 }
252 lwgeom_free(lwgeom);
253 PG_FREE_IF_COPY(geom, 0);
254 PG_RETURN_INT32(ret);
255}
256
259Datum 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 */
276 if (type==POINTTYPE || type==LINETYPE || type==CIRCSTRINGTYPE ||
277 type==COMPOUNDTYPE || type==POLYGONTYPE ||
278 type==CURVEPOLYTYPE || type==TRIANGLETYPE)
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
310Datum 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
336Datum 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
419Datum 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
460Datum 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
552Datum 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
600Datum 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
609 {
610 PG_RETURN_NULL();
611 }
612 PG_RETURN_FLOAT8(pt.x);
613}
614
620Datum 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
629 {
630 PG_RETURN_NULL();
631 }
632 PG_RETURN_FLOAT8(pt.y);
633}
634
641Datum 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
661Datum 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
682Datum 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
712Datum 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
747Datum 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
788Datum 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
821Datum 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
854Datum 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 {
880 }
881 else
882 {
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
911Datum 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
int ptarray_calculate_gbox_cartesian(const POINTARRAY *pa, GBOX *gbox)
Calculate box (x/y) and add values to gbox.
Definition gbox.c:601
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
Definition gbox.c:426
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)...
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int gserialized_has_m(const GSERIALIZED *g)
Check if a GSERIALIZED has an M ordinate.
int gserialized_peek_first_point(const GSERIALIZED *g, POINT4D *out_point)
Pull the first point values of a GSERIALIZED.
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).
int gserialized_has_z(const GSERIALIZED *g)
Check if a GSERIALIZED has a Z ordinate.
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...
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 * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:326
#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
LWPOINT * lwline_get_lwpoint(const LWLINE *line, uint32_t where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition lwline.c:309
#define MULTILINETYPE
Definition liblwgeom.h:120
#define MULTISURFACETYPE
Definition liblwgeom.h:127
#define LINETYPE
Definition liblwgeom.h:117
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition lwgeom.c:215
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition lwout_wkt.c:676
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.
LWPOINT * lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, uint32_t where)
Definition lwcompound.c:213
LWCURVEPOLY * lwgeom_as_lwcurvepoly(const LWGEOM *lwgeom)
Definition lwgeom.c:188
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
void * lwalloc(size_t size)
Definition lwutil.c:227
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition lwgeom.c:197
LWPOINT * lwcompound_get_endpoint(const LWCOMPOUND *lwcmp)
Definition lwcompound.c:254
#define TINTYPE
Definition liblwgeom.h:130
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
#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
LWTRIANGLE * lwgeom_as_lwtriangle(const LWGEOM *lwgeom)
Definition lwgeom.c:206
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
LWPOINT * lwcompound_get_startpoint(const LWCOMPOUND *lwcmp)
Definition lwcompound.c:248
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:321
#define POLYHEDRALSURFACETYPE
Definition liblwgeom.h:128
#define CIRCSTRINGTYPE
Definition liblwgeom.h:123
#define WKT_ISO
Definition liblwgeom.h:2130
#define WKB_NDR
Definition liblwgeom.h:2124
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
void lwcollection_free(LWCOLLECTION *col)
#define MULTICURVETYPE
Definition liblwgeom.h:126
#define TRIANGLETYPE
Definition liblwgeom.h:129
void lwpoly_free(LWPOLY *poly)
Definition lwpoly.c:175
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
LWLINE * lwline_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwline.c:55
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition lwgeom.c:923
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:833
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
Definition lwgeom.c:677
void lwgeom_parser_result_free(LWGEOM_PARSER_RESULT *parser_result)
Definition lwin_wkt.c:886
#define WKB_XDR
Definition liblwgeom.h:2125
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
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