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 (C) 2001-2006 Refractions Research Inc.
22  *
23  **********************************************************************/
24 
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include "../postgis_config.h"
30 /*#define POSTGIS_DEBUG_LEVEL 4*/
31 #include "liblwgeom_internal.h"
32 #include "lwgeom_log.h"
33 
34 
35 /*
36  * Convenience functions to hide the POINTARRAY
37  * TODO: obsolete this
38  */
39 int
lwpoint_getPoint2d_p(const LWPOINT * point,POINT2D * out)40 lwpoint_getPoint2d_p(const LWPOINT *point, POINT2D *out)
41 {
42 	return lwpoint_is_empty(point) ? 0 : getPoint2d_p(point->point, 0, out);
43 }
44 
45 /* convenience functions to hide the POINTARRAY */
46 int
lwpoint_getPoint3dz_p(const LWPOINT * point,POINT3DZ * out)47 lwpoint_getPoint3dz_p(const LWPOINT *point, POINT3DZ *out)
48 {
49 	return lwpoint_is_empty(point) ? 0 : getPoint3dz_p(point->point,0,out);
50 }
51 int
lwpoint_getPoint3dm_p(const LWPOINT * point,POINT3DM * out)52 lwpoint_getPoint3dm_p(const LWPOINT *point, POINT3DM *out)
53 {
54 	return lwpoint_is_empty(point) ? 0 : getPoint3dm_p(point->point,0,out);
55 }
56 int
lwpoint_getPoint4d_p(const LWPOINT * point,POINT4D * out)57 lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out)
58 {
59 	return lwpoint_is_empty(point) ? 0 : getPoint4d_p(point->point,0,out);
60 }
61 
62 double
lwpoint_get_x(const LWPOINT * point)63 lwpoint_get_x(const LWPOINT *point)
64 {
65 	POINT4D pt;
66 	if ( lwpoint_is_empty(point) )
67 	{
68 		lwerror("lwpoint_get_x called with empty geometry");
69 		return 0;
70 	}
71 	getPoint4d_p(point->point, 0, &pt);
72 	return pt.x;
73 }
74 
75 double
lwpoint_get_y(const LWPOINT * point)76 lwpoint_get_y(const LWPOINT *point)
77 {
78 	POINT4D pt;
79 	if ( lwpoint_is_empty(point) )
80 	{
81 		lwerror("lwpoint_get_y called with empty geometry");
82 		return 0;
83 	}
84 	getPoint4d_p(point->point, 0, &pt);
85 	return pt.y;
86 }
87 
88 double
lwpoint_get_z(const LWPOINT * point)89 lwpoint_get_z(const LWPOINT *point)
90 {
91 	POINT4D pt;
92 	if ( lwpoint_is_empty(point) )
93 	{
94 		lwerror("lwpoint_get_z called with empty geometry");
95 		return 0;
96 	}
97 	if ( ! FLAGS_GET_Z(point->flags) )
98 	{
99 		lwerror("lwpoint_get_z called without z dimension");
100 		return 0;
101 	}
102 	getPoint4d_p(point->point, 0, &pt);
103 	return pt.z;
104 }
105 
106 double
lwpoint_get_m(const LWPOINT * point)107 lwpoint_get_m(const LWPOINT *point)
108 {
109 	POINT4D pt;
110 	if ( lwpoint_is_empty(point) )
111 	{
112 		lwerror("lwpoint_get_m called with empty geometry");
113 		return 0;
114 	}
115 	if ( ! FLAGS_GET_M(point->flags) )
116 	{
117 		lwerror("lwpoint_get_m called without m dimension");
118 		return 0;
119 	}
120 	getPoint4d_p(point->point, 0, &pt);
121 	return pt.m;
122 }
123 
124 /*
125  * Construct a new point.  point will not be copied
126  * use SRID=SRID_UNKNOWN for unknown SRID (will have 8bit type's S = 0)
127  */
128 LWPOINT *
lwpoint_construct(int32_t srid,GBOX * bbox,POINTARRAY * point)129 lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
130 {
131 	LWPOINT *result;
132 	lwflags_t flags = 0;
133 
134 	if (point == NULL)
135 		return NULL; /* error */
136 
137 	result = lwalloc(sizeof(LWPOINT));
138 	result->type = POINTTYPE;
139 	FLAGS_SET_Z(flags, FLAGS_GET_Z(point->flags));
140 	FLAGS_SET_M(flags, FLAGS_GET_M(point->flags));
141 	FLAGS_SET_BBOX(flags, bbox?1:0);
142 	result->flags = flags;
143 	result->srid = srid;
144 	result->point = point;
145 	result->bbox = bbox;
146 
147 	return result;
148 }
149 
150 LWPOINT *
lwpoint_construct_empty(int32_t srid,char hasz,char hasm)151 lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
152 {
153 	LWPOINT *result = lwalloc(sizeof(LWPOINT));
154 	result->type = POINTTYPE;
155 	result->flags = lwflags(hasz, hasm, 0);
156 	result->srid = srid;
157 	result->point = ptarray_construct(hasz, hasm, 0);
158 	result->bbox = NULL;
159 	return result;
160 }
161 
162 LWPOINT *
lwpoint_make2d(int32_t srid,double x,double y)163 lwpoint_make2d(int32_t srid, double x, double y)
164 {
165 	POINT4D p = {x, y, 0.0, 0.0};
166 	POINTARRAY *pa = ptarray_construct_empty(0, 0, 1);
167 
168 	ptarray_append_point(pa, &p, LW_TRUE);
169 	return lwpoint_construct(srid, NULL, pa);
170 }
171 
172 LWPOINT *
lwpoint_make3dz(int32_t srid,double x,double y,double z)173 lwpoint_make3dz(int32_t srid, double x, double y, double z)
174 {
175 	POINT4D p = {x, y, z, 0.0};
176 	POINTARRAY *pa = ptarray_construct_empty(1, 0, 1);
177 
178 	ptarray_append_point(pa, &p, LW_TRUE);
179 
180 	return lwpoint_construct(srid, NULL, pa);
181 }
182 
183 LWPOINT *
lwpoint_make3dm(int32_t srid,double x,double y,double m)184 lwpoint_make3dm(int32_t srid, double x, double y, double m)
185 {
186 	POINT4D p = {x, y, 0.0, m};
187 	POINTARRAY *pa = ptarray_construct_empty(0, 1, 1);
188 
189 	ptarray_append_point(pa, &p, LW_TRUE);
190 
191 	return lwpoint_construct(srid, NULL, pa);
192 }
193 
194 LWPOINT *
lwpoint_make4d(int32_t srid,double x,double y,double z,double m)195 lwpoint_make4d(int32_t srid, double x, double y, double z, double m)
196 {
197 	POINT4D p = {x, y, z, m};
198 	POINTARRAY *pa = ptarray_construct_empty(1, 1, 1);
199 
200 	ptarray_append_point(pa, &p, LW_TRUE);
201 
202 	return lwpoint_construct(srid, NULL, pa);
203 }
204 
205 LWPOINT *
lwpoint_make(int32_t srid,int hasz,int hasm,const POINT4D * p)206 lwpoint_make(int32_t srid, int hasz, int hasm, const POINT4D *p)
207 {
208 	POINTARRAY *pa = ptarray_construct_empty(hasz, hasm, 1);
209 	ptarray_append_point(pa, p, LW_TRUE);
210 	return lwpoint_construct(srid, NULL, pa);
211 }
212 
lwpoint_free(LWPOINT * pt)213 void lwpoint_free(LWPOINT *pt)
214 {
215 	if ( ! pt ) return;
216 
217 	if ( pt->bbox )
218 		lwfree(pt->bbox);
219 	if ( pt->point )
220 		ptarray_free(pt->point);
221 	lwfree(pt);
222 }
223 
printLWPOINT(LWPOINT * point)224 void printLWPOINT(LWPOINT *point)
225 {
226 	lwnotice("LWPOINT {");
227 	lwnotice("    ndims = %i", (int)FLAGS_NDIMS(point->flags));
228 	lwnotice("    BBOX = %i", FLAGS_GET_BBOX(point->flags) ? 1 : 0 );
229 	lwnotice("    SRID = %i", (int)point->srid);
230 	printPA(point->point);
231 	lwnotice("}");
232 }
233 
234 /* @brief Clone LWPOINT object. Serialized point lists are not copied.
235  *
236  * @see ptarray_clone
237  */
238 LWPOINT *
lwpoint_clone(const LWPOINT * g)239 lwpoint_clone(const LWPOINT *g)
240 {
241 	LWPOINT *ret = lwalloc(sizeof(LWPOINT));
242 
243 	LWDEBUG(2, "lwpoint_clone called");
244 
245 	memcpy(ret, g, sizeof(LWPOINT));
246 
247 	ret->point = ptarray_clone(g->point);
248 
249 	if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
250 	return ret;
251 }
252 
253 
254 
255 void
lwpoint_release(LWPOINT * lwpoint)256 lwpoint_release(LWPOINT *lwpoint)
257 {
258 	lwgeom_release(lwpoint_as_lwgeom(lwpoint));
259 }
260 
261 
262 /* check coordinate equality  */
263 char
lwpoint_same(const LWPOINT * p1,const LWPOINT * p2)264 lwpoint_same(const LWPOINT *p1, const LWPOINT *p2)
265 {
266 	return ptarray_same(p1->point, p2->point);
267 }
268 
269 
270 LWPOINT*
lwpoint_force_dims(const LWPOINT * point,int hasz,int hasm)271 lwpoint_force_dims(const LWPOINT *point, int hasz, int hasm)
272 {
273 	POINTARRAY *pdims = NULL;
274 	LWPOINT *pointout;
275 
276 	/* Return 2D empty */
277 	if( lwpoint_is_empty(point) )
278 	{
279 		pointout = lwpoint_construct_empty(point->srid, hasz, hasm);
280 	}
281 	else
282 	{
283 		/* Always we duplicate the ptarray and return */
284 		pdims = ptarray_force_dims(point->point, hasz, hasm);
285 		pointout = lwpoint_construct(point->srid, NULL, pdims);
286 	}
287 	pointout->type = point->type;
288 	return pointout;
289 }
290 
291 
292