PostGIS  2.2.8dev-r@@SVN_REVISION@@
geometry_inout.c
Go to the documentation of this file.
1 #include "postgres.h"
2 #include "utils/geo_decls.h"
3 
4 #include "../postgis_config.h"
5 
6 #include "liblwgeom.h" /* For standard geometry types. */
7 #include "lwgeom_pg.h" /* For debugging macros. */
8 
9 
10 Datum geometry_to_point(PG_FUNCTION_ARGS);
11 Datum point_to_geometry(PG_FUNCTION_ARGS);
12 Datum geometry_to_path(PG_FUNCTION_ARGS);
13 Datum path_to_geometry(PG_FUNCTION_ARGS);
14 Datum geometry_to_polygon(PG_FUNCTION_ARGS);
15 Datum polygon_to_geometry(PG_FUNCTION_ARGS);
16 
21 Datum point_to_geometry(PG_FUNCTION_ARGS)
22 {
23  Point *point;
24  LWPOINT *lwpoint;
25  GSERIALIZED *geom;
26 
27  POSTGIS_DEBUG(2, "point_to_geometry called");
28 
29  if ( PG_ARGISNULL(0) )
30  PG_RETURN_NULL();
31 
32  point = PG_GETARG_POINT_P(0);
33 
34  if ( ! point )
35  PG_RETURN_NULL();
36 
37  lwpoint = lwpoint_make2d(SRID_UNKNOWN, point->x, point->y);
38  geom = geometry_serialize(lwpoint_as_lwgeom(lwpoint));
39  lwpoint_free(lwpoint);
40 
41  PG_RETURN_POINTER(geom);
42 }
43 
48 Datum geometry_to_point(PG_FUNCTION_ARGS)
49 {
50  Point *point;
51  LWGEOM *lwgeom;
52  LWPOINT *lwpoint;
53  GSERIALIZED *geom;
54 
55  POSTGIS_DEBUG(2, "geometry_to_point called");
56 
57  if ( PG_ARGISNULL(0) )
58  PG_RETURN_NULL();
59 
60  geom = PG_GETARG_GSERIALIZED_P(0);
61 
62  if ( gserialized_get_type(geom) != POINTTYPE )
63  elog(ERROR, "geometry_to_point only accepts Points");
64 
65  lwgeom = lwgeom_from_gserialized(geom);
66 
67  if ( lwgeom_is_empty(lwgeom) )
68  PG_RETURN_NULL();
69 
70  lwpoint = lwgeom_as_lwpoint(lwgeom);
71 
72  point = (Point*)palloc(sizeof(Point));
73  point->x = lwpoint_get_x(lwpoint);
74  point->y = lwpoint_get_y(lwpoint);
75 
76  lwpoint_free(lwpoint);
77  PG_FREE_IF_COPY(geom,0);
78 
79  PG_RETURN_POINT_P(point);
80 }
81 
83 Datum geometry_to_path(PG_FUNCTION_ARGS)
84 {
85  PATH *path;
86  LWLINE *lwline;
87  LWGEOM *lwgeom;
88  GSERIALIZED *geom;
89  POINTARRAY *pa;
90  int i;
91  const POINT2D *pt;
92  size_t size;
93 
94  POSTGIS_DEBUG(2, "geometry_to_path called");
95 
96  if ( PG_ARGISNULL(0) )
97  PG_RETURN_NULL();
98 
99  geom = PG_GETARG_GSERIALIZED_P(0);
100 
101  if ( gserialized_get_type(geom) != LINETYPE )
102  elog(ERROR, "geometry_to_path only accepts LineStrings");
103 
104  lwgeom = lwgeom_from_gserialized(geom);
105  if ( lwgeom_is_empty(lwgeom) )
106  PG_RETURN_NULL();
107  lwline = lwgeom_as_lwline(lwgeom);
108 
109  pa = lwline->points;
110  size = offsetof(PATH, p[0]) + sizeof(path->p[0]) * pa->npoints;
111  path = (PATH*)palloc(size);
112  SET_VARSIZE(path, size);
113  path->npts = pa->npoints;
114  path->closed = 0;
115  path->dummy = 0;
116 
117  for ( i = 0; i < pa->npoints; i++ )
118  {
119  pt = getPoint2d_cp(pa, i);
120  (path->p[i]).x = pt->x;
121  (path->p[i]).y = pt->y;
122  }
123 
124  lwgeom_free(lwgeom);
125  PG_FREE_IF_COPY(geom,0);
126 
127  PG_RETURN_PATH_P(path);
128 }
129 
130 
132 Datum path_to_geometry(PG_FUNCTION_ARGS)
133 {
134  PATH *path;
135  LWLINE *lwline;
136  POINTARRAY *pa;
137  GSERIALIZED *geom;
138  POINT4D pt;
139  Point p;
140  int i;
141 
142  POSTGIS_DEBUG(2, "path_to_geometry called");
143 
144  if ( PG_ARGISNULL(0) )
145  PG_RETURN_NULL();
146 
147  path = PG_GETARG_PATH_P(0);
148 
149  if ( ! path )
150  PG_RETURN_NULL();
151 
152  pa = ptarray_construct_empty(0, 0, path->npts);
153  for ( i = 0; i < path->npts; i++ )
154  {
155  p = path->p[i];
156  pt.x = p.x;
157  pt.y = p.y;
158  ptarray_append_point(pa, &pt, LW_FALSE);
159  }
160  lwline = lwline_construct(SRID_UNKNOWN, NULL, pa);
161  geom = geometry_serialize(lwline_as_lwgeom(lwline));
162  lwline_free(lwline);
163 
164  PG_RETURN_POINTER(geom);
165 }
166 
168 Datum geometry_to_polygon(PG_FUNCTION_ARGS)
169 {
170  POLYGON *polygon;
171  LWPOLY *lwpoly;
172  LWGEOM *lwgeom;
173  GSERIALIZED *geom;
174  POINTARRAY *pa;
175  GBOX gbox;
176  int i;
177  size_t size;
178 
179  POSTGIS_DEBUG(2, "geometry_to_polygon called");
180 
181  if ( PG_ARGISNULL(0) )
182  PG_RETURN_NULL();
183 
184  geom = PG_GETARG_GSERIALIZED_P(0);
185 
186  if ( gserialized_get_type(geom) != POLYGONTYPE )
187  elog(ERROR, "geometry_to_polygon only accepts Polygons");
188 
189  lwgeom = lwgeom_from_gserialized(geom);
190  if ( lwgeom_is_empty(lwgeom) )
191  PG_RETURN_NULL();
192  lwpoly = lwgeom_as_lwpoly(lwgeom);
193 
194  pa = lwpoly->rings[0];
195 
196  size = offsetof(POLYGON, p[0]) + sizeof(polygon->p[0]) * pa->npoints;
197  polygon = (POLYGON*)palloc0(size); /* zero any holes */
198  SET_VARSIZE(polygon, size);
199 
200  polygon->npts = pa->npoints;
201 
202  lwgeom_calculate_gbox(lwgeom, &gbox);
203  polygon->boundbox.low.x = gbox.xmin;
204  polygon->boundbox.low.y = gbox.ymin;
205  polygon->boundbox.high.x = gbox.xmax;
206  polygon->boundbox.high.y = gbox.ymax;
207 
208  for ( i = 0; i < pa->npoints; i++ )
209  {
210  const POINT2D *pt = getPoint2d_cp(pa, i);
211  (polygon->p[i]).x = pt->x;
212  (polygon->p[i]).y = pt->y;
213  }
214 
215  lwgeom_free(lwgeom);
216  PG_FREE_IF_COPY(geom,0);
217 
218  PG_RETURN_POLYGON_P(polygon);
219 }
220 
221 
223 Datum polygon_to_geometry(PG_FUNCTION_ARGS)
224 {
225  POLYGON *polygon;
226  LWPOLY *lwpoly;
227  POINTARRAY *pa;
228  POINTARRAY **ppa;
229  GSERIALIZED *geom;
230  Point p;
231  int i = 0, unclosed = 0;
232 
233  POSTGIS_DEBUG(2, "polygon_to_geometry called");
234 
235  if ( PG_ARGISNULL(0) )
236  PG_RETURN_NULL();
237 
238  polygon = PG_GETARG_POLYGON_P(0);
239 
240  if ( ! polygon )
241  PG_RETURN_NULL();
242 
243  /* Are first and last points different? If so we need to close this ring */
244  if ( memcmp( polygon->p, polygon->p + polygon->npts - 1, sizeof(Point) ) )
245  {
246  unclosed = 1;
247  }
248 
249  pa = ptarray_construct_empty(0, 0, polygon->npts + unclosed);
250 
251  for ( i = 0; i < (polygon->npts+unclosed); i++ )
252  {
253  POINT4D pt;
254  p = polygon->p[i % polygon->npts];
255  pt.x = p.x;
256  pt.y = p.y;
257  ptarray_append_point(pa, &pt, LW_FALSE);
258  }
259 
260  ppa = palloc(sizeof(POINTARRAY*));
261  ppa[0] = pa;
262  lwpoly = lwpoly_construct(SRID_UNKNOWN, NULL, 1, ppa);
263  geom = geometry_serialize(lwpoly_as_lwgeom(lwpoly));
264  lwpoly_free(lwpoly);
265 
266  PG_RETURN_POINTER(geom);
267 }
268 
double x
Definition: liblwgeom.h:336
#define LINETYPE
Definition: liblwgeom.h:71
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:55
Datum path_to_geometry(PG_FUNCTION_ARGS)
Datum geometry_to_point(PG_FUNCTION_ARGS)
Datum point_to_geometry(PG_FUNCTION_ARGS)
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int npoints
Definition: liblwgeom.h:355
#define POLYGONTYPE
Definition: liblwgeom.h:72
LWPOINT * lwpoint_make2d(int srid, double x, double y)
Definition: lwpoint.c:132
double xmax
Definition: liblwgeom.h:277
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:70
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:182
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1050
void lwline_free(LWLINE *line)
Definition: lwline.c:63
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:125
Datum geometry_to_polygon(PG_FUNCTION_ARGS)
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition: lwgeom.c:80
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:239
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:652
double x
Definition: liblwgeom.h:312
double lwpoint_get_x(const LWPOINT *point)
Definition: lwpoint.c:50
double ymin
Definition: liblwgeom.h:278
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:249
double xmin
Definition: liblwgeom.h:276
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_TRUE, then a duplicate point will not be added.
Definition: ptarray.c:156
#define LW_FALSE
Definition: liblwgeom.h:62
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, int n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
Definition: lwgeom_api.c:472
LWPOLY * lwpoly_construct(int srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
Definition: lwpoly.c:29
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:79
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:29
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:172
POINTARRAY ** rings
Definition: liblwgeom.h:441
Datum polygon_to_geometry(PG_FUNCTION_ARGS)
double ymax
Definition: liblwgeom.h:279
double y
Definition: liblwgeom.h:312
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:89
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
PG_FUNCTION_INFO_V1(point_to_geometry)
Cast a PostgreSQL Point to a PostGIS geometry.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:70
double lwpoint_get_y(const LWPOINT *point)
Definition: lwpoint.c:60
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:254
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:1297
double y
Definition: liblwgeom.h:336
Datum geometry_to_path(PG_FUNCTION_ARGS)
This library is the generic geometry handling section of PostGIS.
POINTARRAY * points
Definition: liblwgeom.h:406