PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
geometry_inout.c
Go to the documentation of this file.
1/**********************************************************************
2 *
3 * PostGIS - Spatial Types for PostgreSQL
4 * http://postgis.net
5 *
6 * PostGIS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * PostGIS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18 *
19 **********************************************************************
20 *
21 * ^copyright^
22 *
23 **********************************************************************/
24
25#include "postgres.h"
26#include "utils/geo_decls.h"
27
28#include "../postgis_config.h"
29
30#include "liblwgeom.h" /* For standard geometry types. */
31#include "lwgeom_pg.h" /* For debugging macros. */
32
33
34Datum geometry_to_point(PG_FUNCTION_ARGS);
35Datum point_to_geometry(PG_FUNCTION_ARGS);
36Datum geometry_to_path(PG_FUNCTION_ARGS);
37Datum path_to_geometry(PG_FUNCTION_ARGS);
38Datum geometry_to_polygon(PG_FUNCTION_ARGS);
39Datum polygon_to_geometry(PG_FUNCTION_ARGS);
40
45Datum point_to_geometry(PG_FUNCTION_ARGS)
46{
47 Point *point;
48 LWPOINT *lwpoint;
49 GSERIALIZED *geom;
50
51 POSTGIS_DEBUG(2, "point_to_geometry called");
52
53 if ( PG_ARGISNULL(0) )
54 PG_RETURN_NULL();
55
56 point = PG_GETARG_POINT_P(0);
57
58 if ( ! point )
59 PG_RETURN_NULL();
60
61 lwpoint = lwpoint_make2d(SRID_UNKNOWN, point->x, point->y);
62 geom = geometry_serialize(lwpoint_as_lwgeom(lwpoint));
63 lwpoint_free(lwpoint);
64
65 PG_RETURN_POINTER(geom);
66}
67
72Datum geometry_to_point(PG_FUNCTION_ARGS)
73{
74 Point *point;
75 POINT4D pt;
76 GSERIALIZED *geom;
77
78 if (PG_ARGISNULL(0))
79 PG_RETURN_NULL();
80 geom = PG_GETARG_GSERIALIZED_P(0);
81
83 elog(ERROR, "geometry_to_point only accepts Points");
84
86 PG_RETURN_NULL();
87
88 point = (Point *)palloc(sizeof(Point));
89 point->x = pt.x;
90 point->y = pt.y;
91
92 PG_RETURN_POINT_P(point);
93}
94
96Datum geometry_to_path(PG_FUNCTION_ARGS)
97{
98 PATH *path;
99 LWLINE *lwline;
100 LWGEOM *lwgeom;
101 GSERIALIZED *geom;
102 POINTARRAY *pa;
103 uint32_t i;
104 const POINT2D *pt;
105 size_t size;
106
107 POSTGIS_DEBUG(2, "geometry_to_path called");
108
109 if ( PG_ARGISNULL(0) )
110 PG_RETURN_NULL();
111
112 geom = PG_GETARG_GSERIALIZED_P(0);
113
114 if ( gserialized_get_type(geom) != LINETYPE )
115 elog(ERROR, "geometry_to_path only accepts LineStrings");
116
117 lwgeom = lwgeom_from_gserialized(geom);
118 if ( lwgeom_is_empty(lwgeom) )
119 PG_RETURN_NULL();
120 lwline = lwgeom_as_lwline(lwgeom);
121
122 pa = lwline->points;
123 size = offsetof(PATH, p[0]) + sizeof(path->p[0]) * pa->npoints;
124 path = (PATH*)palloc(size);
125 SET_VARSIZE(path, size);
126 path->npts = pa->npoints;
127 path->closed = 0;
128 path->dummy = 0;
129
130 for ( i = 0; i < pa->npoints; i++ )
131 {
132 pt = getPoint2d_cp(pa, i);
133 (path->p[i]).x = pt->x;
134 (path->p[i]).y = pt->y;
135 }
136
137 lwgeom_free(lwgeom);
138 PG_FREE_IF_COPY(geom,0);
139
140 PG_RETURN_PATH_P(path);
141}
142
143
145Datum path_to_geometry(PG_FUNCTION_ARGS)
146{
147 PATH *path;
148 LWLINE *lwline;
149 POINTARRAY *pa;
150 GSERIALIZED *geom;
151 POINT4D pt;
152 Point p;
153 int i;
154
155 POSTGIS_DEBUG(2, "path_to_geometry called");
156
157 if ( PG_ARGISNULL(0) )
158 PG_RETURN_NULL();
159
160 path = PG_GETARG_PATH_P(0);
161
162 if ( ! path )
163 PG_RETURN_NULL();
164
165 pa = ptarray_construct_empty(0, 0, path->npts);
166 for ( i = 0; i < path->npts; i++ )
167 {
168 p = path->p[i];
169 pt.x = p.x;
170 pt.y = p.y;
172 }
173 lwline = lwline_construct(SRID_UNKNOWN, NULL, pa);
174 geom = geometry_serialize(lwline_as_lwgeom(lwline));
175 lwline_free(lwline);
176
177 PG_RETURN_POINTER(geom);
178}
179
181Datum geometry_to_polygon(PG_FUNCTION_ARGS)
182{
183 POLYGON *polygon;
184 LWPOLY *lwpoly;
185 LWGEOM *lwgeom;
186 GSERIALIZED *geom;
187 POINTARRAY *pa;
188 GBOX gbox;
189 uint32_t i;
190 size_t size;
191
192 POSTGIS_DEBUG(2, "geometry_to_polygon called");
193
194 if ( PG_ARGISNULL(0) )
195 PG_RETURN_NULL();
196
197 geom = PG_GETARG_GSERIALIZED_P(0);
198
199 if ( gserialized_get_type(geom) != POLYGONTYPE )
200 elog(ERROR, "geometry_to_polygon only accepts Polygons");
201
202 lwgeom = lwgeom_from_gserialized(geom);
203 if ( lwgeom_is_empty(lwgeom) )
204 PG_RETURN_NULL();
205 lwpoly = lwgeom_as_lwpoly(lwgeom);
206
207 pa = lwpoly->rings[0];
208
209 size = offsetof(POLYGON, p[0]) + sizeof(polygon->p[0]) * pa->npoints;
210 polygon = (POLYGON*)palloc0(size); /* zero any holes */
211 SET_VARSIZE(polygon, size);
212
213 polygon->npts = pa->npoints;
214
215 lwgeom_calculate_gbox(lwgeom, &gbox);
216 polygon->boundbox.low.x = gbox.xmin;
217 polygon->boundbox.low.y = gbox.ymin;
218 polygon->boundbox.high.x = gbox.xmax;
219 polygon->boundbox.high.y = gbox.ymax;
220
221 for ( i = 0; i < pa->npoints; i++ )
222 {
223 const POINT2D *pt = getPoint2d_cp(pa, i);
224 (polygon->p[i]).x = pt->x;
225 (polygon->p[i]).y = pt->y;
226 }
227
228 lwgeom_free(lwgeom);
229 PG_FREE_IF_COPY(geom,0);
230
231 PG_RETURN_POLYGON_P(polygon);
232}
233
234
236Datum polygon_to_geometry(PG_FUNCTION_ARGS)
237{
238 POLYGON *polygon;
239 LWPOLY *lwpoly;
240 POINTARRAY *pa;
241 POINTARRAY **ppa;
242 GSERIALIZED *geom;
243 Point p;
244 int i = 0, unclosed = 0;
245
246 POSTGIS_DEBUG(2, "polygon_to_geometry called");
247
248 if ( PG_ARGISNULL(0) )
249 PG_RETURN_NULL();
250
251 polygon = PG_GETARG_POLYGON_P(0);
252
253 if ( ! polygon )
254 PG_RETURN_NULL();
255
256 /* Are first and last points different? If so we need to close this ring */
257 if ( memcmp( polygon->p, polygon->p + polygon->npts - 1, sizeof(Point) ) )
258 {
259 unclosed = 1;
260 }
261
262 pa = ptarray_construct_empty(0, 0, polygon->npts + unclosed);
263
264 for ( i = 0; i < (polygon->npts+unclosed); i++ )
265 {
266 POINT4D pt;
267 p = polygon->p[i % polygon->npts];
268 pt.x = p.x;
269 pt.y = p.y;
271 }
272
273 ppa = palloc(sizeof(POINTARRAY*));
274 ppa[0] = pa;
275 lwpoly = lwpoly_construct(SRID_UNKNOWN, NULL, 1, ppa);
276 geom = geometry_serialize(lwpoly_as_lwgeom(lwpoly));
277 lwpoly_free(lwpoly);
278
279 PG_RETURN_POINTER(geom);
280}
281
Datum point_to_geometry(PG_FUNCTION_ARGS)
Datum geometry_to_path(PG_FUNCTION_ARGS)
Datum geometry_to_polygon(PG_FUNCTION_ARGS)
Datum geometry_to_point(PG_FUNCTION_ARGS)
Datum path_to_geometry(PG_FUNCTION_ARGS)
Datum polygon_to_geometry(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(point_to_geometry)
Cast a PostgreSQL Point to a PostGIS geometry.
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int gserialized_peek_first_point(const GSERIALIZED *g, POINT4D *out_point)
Pull the first point values of a GSERIALIZED.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:372
#define LW_FALSE
Definition liblwgeom.h:94
void lwpoint_free(LWPOINT *pt)
Definition lwpoint.c:213
#define LW_FAILURE
Definition liblwgeom.h:96
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1246
#define LINETYPE
Definition liblwgeom.h:103
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition ptarray.c:59
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition lwgeom.c:243
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
LWPOINT * lwpoint_make2d(int32_t srid, double x, double y)
Definition lwpoint.c:163
#define POLYGONTYPE
Definition liblwgeom.h:104
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:367
LWPOLY * lwpoly_construct(int32_t srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
Definition lwpoly.c:43
int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox)
Calculate bounding box of a geometry, automatically taking into account whether it is cartesian or ge...
Definition lwgeom.c:783
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition lwgeom.c:207
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE,...
Definition ptarray.c:147
void lwpoly_free(LWPOLY *poly)
Definition lwpoly.c:175
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:215
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition lwgeom.c:357
void lwline_free(LWLINE *line)
Definition lwline.c:67
This library is the generic geometry handling section of PostGIS.
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:199
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition lwinline.h:97
double ymax
Definition liblwgeom.h:357
double xmax
Definition liblwgeom.h:355
double ymin
Definition liblwgeom.h:356
double xmin
Definition liblwgeom.h:354
POINTARRAY * points
Definition liblwgeom.h:483
POINTARRAY ** rings
Definition liblwgeom.h:519
double y
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:414
double y
Definition liblwgeom.h:414
uint32_t npoints
Definition liblwgeom.h:427