PostGIS  2.5.7dev-r@@SVN_REVISION@@
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 
34 Datum geometry_to_point(PG_FUNCTION_ARGS);
35 Datum point_to_geometry(PG_FUNCTION_ARGS);
36 Datum geometry_to_path(PG_FUNCTION_ARGS);
37 Datum path_to_geometry(PG_FUNCTION_ARGS);
38 Datum geometry_to_polygon(PG_FUNCTION_ARGS);
39 Datum polygon_to_geometry(PG_FUNCTION_ARGS);
40 
45 Datum 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 
72 Datum geometry_to_point(PG_FUNCTION_ARGS)
73 {
74  Point *point;
75  LWGEOM *lwgeom;
76  LWPOINT *lwpoint;
77  GSERIALIZED *geom;
78 
79  POSTGIS_DEBUG(2, "geometry_to_point called");
80 
81  if ( PG_ARGISNULL(0) )
82  PG_RETURN_NULL();
83 
84  geom = PG_GETARG_GSERIALIZED_P(0);
85 
86  if ( gserialized_get_type(geom) != POINTTYPE )
87  elog(ERROR, "geometry_to_point only accepts Points");
88 
89  lwgeom = lwgeom_from_gserialized(geom);
90 
91  if ( lwgeom_is_empty(lwgeom) )
92  PG_RETURN_NULL();
93 
94  lwpoint = lwgeom_as_lwpoint(lwgeom);
95 
96  point = (Point*)palloc(sizeof(Point));
97  point->x = lwpoint_get_x(lwpoint);
98  point->y = lwpoint_get_y(lwpoint);
99 
100  lwpoint_free(lwpoint);
101  PG_FREE_IF_COPY(geom,0);
102 
103  PG_RETURN_POINT_P(point);
104 }
105 
107 Datum geometry_to_path(PG_FUNCTION_ARGS)
108 {
109  PATH *path;
110  LWLINE *lwline;
111  LWGEOM *lwgeom;
112  GSERIALIZED *geom;
113  POINTARRAY *pa;
114  uint32_t i;
115  const POINT2D *pt;
116  size_t size;
117 
118  POSTGIS_DEBUG(2, "geometry_to_path called");
119 
120  if ( PG_ARGISNULL(0) )
121  PG_RETURN_NULL();
122 
123  geom = PG_GETARG_GSERIALIZED_P(0);
124 
125  if ( gserialized_get_type(geom) != LINETYPE )
126  elog(ERROR, "geometry_to_path only accepts LineStrings");
127 
128  lwgeom = lwgeom_from_gserialized(geom);
129  if ( lwgeom_is_empty(lwgeom) )
130  PG_RETURN_NULL();
131  lwline = lwgeom_as_lwline(lwgeom);
132 
133  pa = lwline->points;
134  size = offsetof(PATH, p[0]) + sizeof(path->p[0]) * pa->npoints;
135  path = (PATH*)palloc(size);
136  SET_VARSIZE(path, size);
137  path->npts = pa->npoints;
138  path->closed = 0;
139  path->dummy = 0;
140 
141  for ( i = 0; i < pa->npoints; i++ )
142  {
143  pt = getPoint2d_cp(pa, i);
144  (path->p[i]).x = pt->x;
145  (path->p[i]).y = pt->y;
146  }
147 
148  lwgeom_free(lwgeom);
149  PG_FREE_IF_COPY(geom,0);
150 
151  PG_RETURN_PATH_P(path);
152 }
153 
154 
156 Datum path_to_geometry(PG_FUNCTION_ARGS)
157 {
158  PATH *path;
159  LWLINE *lwline;
160  POINTARRAY *pa;
161  GSERIALIZED *geom;
162  POINT4D pt;
163  Point p;
164  int i;
165 
166  POSTGIS_DEBUG(2, "path_to_geometry called");
167 
168  if ( PG_ARGISNULL(0) )
169  PG_RETURN_NULL();
170 
171  path = PG_GETARG_PATH_P(0);
172 
173  if ( ! path )
174  PG_RETURN_NULL();
175 
176  pa = ptarray_construct_empty(0, 0, path->npts);
177  for ( i = 0; i < path->npts; i++ )
178  {
179  p = path->p[i];
180  pt.x = p.x;
181  pt.y = p.y;
182  ptarray_append_point(pa, &pt, LW_FALSE);
183  }
184  lwline = lwline_construct(SRID_UNKNOWN, NULL, pa);
185  geom = geometry_serialize(lwline_as_lwgeom(lwline));
186  lwline_free(lwline);
187 
188  PG_RETURN_POINTER(geom);
189 }
190 
192 Datum geometry_to_polygon(PG_FUNCTION_ARGS)
193 {
194  POLYGON *polygon;
195  LWPOLY *lwpoly;
196  LWGEOM *lwgeom;
197  GSERIALIZED *geom;
198  POINTARRAY *pa;
199  GBOX gbox;
200  uint32_t i;
201  size_t size;
202 
203  POSTGIS_DEBUG(2, "geometry_to_polygon called");
204 
205  if ( PG_ARGISNULL(0) )
206  PG_RETURN_NULL();
207 
208  geom = PG_GETARG_GSERIALIZED_P(0);
209 
210  if ( gserialized_get_type(geom) != POLYGONTYPE )
211  elog(ERROR, "geometry_to_polygon only accepts Polygons");
212 
213  lwgeom = lwgeom_from_gserialized(geom);
214  if ( lwgeom_is_empty(lwgeom) )
215  PG_RETURN_NULL();
216  lwpoly = lwgeom_as_lwpoly(lwgeom);
217 
218  pa = lwpoly->rings[0];
219 
220  size = offsetof(POLYGON, p[0]) + sizeof(polygon->p[0]) * pa->npoints;
221  polygon = (POLYGON*)palloc0(size); /* zero any holes */
222  SET_VARSIZE(polygon, size);
223 
224  polygon->npts = pa->npoints;
225 
226  lwgeom_calculate_gbox(lwgeom, &gbox);
227  polygon->boundbox.low.x = gbox.xmin;
228  polygon->boundbox.low.y = gbox.ymin;
229  polygon->boundbox.high.x = gbox.xmax;
230  polygon->boundbox.high.y = gbox.ymax;
231 
232  for ( i = 0; i < pa->npoints; i++ )
233  {
234  const POINT2D *pt = getPoint2d_cp(pa, i);
235  (polygon->p[i]).x = pt->x;
236  (polygon->p[i]).y = pt->y;
237  }
238 
239  lwgeom_free(lwgeom);
240  PG_FREE_IF_COPY(geom,0);
241 
242  PG_RETURN_POLYGON_P(polygon);
243 }
244 
245 
247 Datum polygon_to_geometry(PG_FUNCTION_ARGS)
248 {
249  POLYGON *polygon;
250  LWPOLY *lwpoly;
251  POINTARRAY *pa;
252  POINTARRAY **ppa;
253  GSERIALIZED *geom;
254  Point p;
255  int i = 0, unclosed = 0;
256 
257  POSTGIS_DEBUG(2, "polygon_to_geometry called");
258 
259  if ( PG_ARGISNULL(0) )
260  PG_RETURN_NULL();
261 
262  polygon = PG_GETARG_POLYGON_P(0);
263 
264  if ( ! polygon )
265  PG_RETURN_NULL();
266 
267  /* Are first and last points different? If so we need to close this ring */
268  if ( memcmp( polygon->p, polygon->p + polygon->npts - 1, sizeof(Point) ) )
269  {
270  unclosed = 1;
271  }
272 
273  pa = ptarray_construct_empty(0, 0, polygon->npts + unclosed);
274 
275  for ( i = 0; i < (polygon->npts+unclosed); i++ )
276  {
277  POINT4D pt;
278  p = polygon->p[i % polygon->npts];
279  pt.x = p.x;
280  pt.y = p.y;
281  ptarray_append_point(pa, &pt, LW_FALSE);
282  }
283 
284  ppa = palloc(sizeof(POINTARRAY*));
285  ppa[0] = pa;
286  lwpoly = lwpoly_construct(SRID_UNKNOWN, NULL, 1, ppa);
287  geom = geometry_serialize(lwpoly_as_lwgeom(lwpoly));
288  lwpoly_free(lwpoly);
289 
290  PG_RETURN_POINTER(geom);
291 }
292 
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
uint32_t gserialized_get_type(const GSERIALIZED *s)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
Definition: g_serialized.c:86
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.
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:170
LWPOINT * lwpoint_make2d(int srid, double x, double y)
Definition: lwpoint.c:163
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:330
#define LW_FALSE
Definition: liblwgeom.h:77
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:213
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1144
#define LINETYPE
Definition: liblwgeom.h:86
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:320
double lwpoint_get_x(const LWPOINT *point)
Definition: lwpoint.c:63
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition: lwgeom.c:161
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:335
#define POLYGONTYPE
Definition: liblwgeom.h:87
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:70
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwgeom.c:1393
LWPOLY * lwpoly_construct(int 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:746
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:156
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:175
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:206
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:188
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
void lwline_free(LWLINE *line)
Definition: lwline.c:76
double lwpoint_get_y(const LWPOINT *point)
Definition: lwpoint.c:76
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition: lwgeom_api.c:374
This library is the generic geometry handling section of PostGIS.
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
double ymax
Definition: liblwgeom.h:298
double xmax
Definition: liblwgeom.h:296
double ymin
Definition: liblwgeom.h:297
double xmin
Definition: liblwgeom.h:295
POINTARRAY * points
Definition: liblwgeom.h:425
POINTARRAY ** rings
Definition: liblwgeom.h:460
double y
Definition: liblwgeom.h:331
double x
Definition: liblwgeom.h:331
double x
Definition: liblwgeom.h:355
double y
Definition: liblwgeom.h:355
uint32_t npoints
Definition: liblwgeom.h:374
unsigned int uint32_t
Definition: uthash.h:78