1 /**********************************************************************
2 *
3 * rttopo - topology library
4 * http://git.osgeo.org/gitea/rttopo/librttopo
5 *
6 * rttopo 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 * rttopo 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 rttopo. If not, see <http://www.gnu.org/licenses/>.
18 *
19 **********************************************************************
20 *
21 * Copyright (C) 2001-2006 Refractions Research Inc.
22 *
23 **********************************************************************/
24
25
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include "rttopo_config.h"
31 /*#define RTGEOM_DEBUG_LEVEL 4*/
32 #include "librttopo_geom_internal.h"
33 #include "rtgeom_log.h"
34
35
36 /*
37 * Convenience functions to hide the RTPOINTARRAY
38 * TODO: obsolete this
39 */
40 int
rtpoint_getPoint2d_p(const RTCTX * ctx,const RTPOINT * point,RTPOINT2D * out)41 rtpoint_getPoint2d_p(const RTCTX *ctx, const RTPOINT *point, RTPOINT2D *out)
42 {
43 return rt_getPoint2d_p(ctx, point->point, 0, out);
44 }
45
46 /* convenience functions to hide the RTPOINTARRAY */
47 int
rtpoint_getPoint3dz_p(const RTCTX * ctx,const RTPOINT * point,RTPOINT3DZ * out)48 rtpoint_getPoint3dz_p(const RTCTX *ctx, const RTPOINT *point, RTPOINT3DZ *out)
49 {
50 return rt_getPoint3dz_p(ctx, point->point,0,out);
51 }
52 int
rtpoint_getPoint3dm_p(const RTCTX * ctx,const RTPOINT * point,RTPOINT3DM * out)53 rtpoint_getPoint3dm_p(const RTCTX *ctx, const RTPOINT *point, RTPOINT3DM *out)
54 {
55 return rt_getPoint3dm_p(ctx, point->point,0,out);
56 }
57 int
rtpoint_getPoint4d_p(const RTCTX * ctx,const RTPOINT * point,RTPOINT4D * out)58 rtpoint_getPoint4d_p(const RTCTX *ctx, const RTPOINT *point, RTPOINT4D *out)
59 {
60 return rt_getPoint4d_p(ctx, point->point,0,out);
61 }
62
63 double
rtpoint_get_x(const RTCTX * ctx,const RTPOINT * point)64 rtpoint_get_x(const RTCTX *ctx, const RTPOINT *point)
65 {
66 RTPOINT4D pt;
67 if ( rtpoint_is_empty(ctx, point) )
68 rterror(ctx, "rtpoint_get_x called with empty geometry");
69 rt_getPoint4d_p(ctx, point->point, 0, &pt);
70 return pt.x;
71 }
72
73 double
rtpoint_get_y(const RTCTX * ctx,const RTPOINT * point)74 rtpoint_get_y(const RTCTX *ctx, const RTPOINT *point)
75 {
76 RTPOINT4D pt;
77 if ( rtpoint_is_empty(ctx, point) )
78 rterror(ctx, "rtpoint_get_y called with empty geometry");
79 rt_getPoint4d_p(ctx, point->point, 0, &pt);
80 return pt.y;
81 }
82
83 double
rtpoint_get_z(const RTCTX * ctx,const RTPOINT * point)84 rtpoint_get_z(const RTCTX *ctx, const RTPOINT *point)
85 {
86 RTPOINT4D pt;
87 if ( rtpoint_is_empty(ctx, point) )
88 rterror(ctx, "rtpoint_get_z called with empty geometry");
89 if ( ! RTFLAGS_GET_Z(point->flags) )
90 rterror(ctx, "rtpoint_get_z called without z dimension");
91 rt_getPoint4d_p(ctx, point->point, 0, &pt);
92 return pt.z;
93 }
94
95 double
rtpoint_get_m(const RTCTX * ctx,const RTPOINT * point)96 rtpoint_get_m(const RTCTX *ctx, const RTPOINT *point)
97 {
98 RTPOINT4D pt;
99 if ( rtpoint_is_empty(ctx, point) )
100 rterror(ctx, "rtpoint_get_m called with empty geometry");
101 if ( ! RTFLAGS_GET_M(point->flags) )
102 rterror(ctx, "rtpoint_get_m called without m dimension");
103 rt_getPoint4d_p(ctx, point->point, 0, &pt);
104 return pt.m;
105 }
106
107 /*
108 * Construct a new point. point will not be copied
109 * use SRID=SRID_UNKNOWN for unknown SRID (will have 8bit type's S = 0)
110 */
111 RTPOINT *
rtpoint_construct(const RTCTX * ctx,int srid,RTGBOX * bbox,RTPOINTARRAY * point)112 rtpoint_construct(const RTCTX *ctx, int srid, RTGBOX *bbox, RTPOINTARRAY *point)
113 {
114 RTPOINT *result;
115 uint8_t flags = 0;
116
117 if (point == NULL)
118 return NULL; /* error */
119
120 result = rtalloc(ctx, sizeof(RTPOINT));
121 result->type = RTPOINTTYPE;
122 RTFLAGS_SET_Z(flags, RTFLAGS_GET_Z(point->flags));
123 RTFLAGS_SET_M(flags, RTFLAGS_GET_M(point->flags));
124 RTFLAGS_SET_BBOX(flags, bbox?1:0);
125 result->flags = flags;
126 result->srid = srid;
127 result->point = point;
128 result->bbox = bbox;
129
130 return result;
131 }
132
133 RTPOINT *
rtpoint_construct_empty(const RTCTX * ctx,int srid,char hasz,char hasm)134 rtpoint_construct_empty(const RTCTX *ctx, int srid, char hasz, char hasm)
135 {
136 RTPOINT *result = rtalloc(ctx, sizeof(RTPOINT));
137 result->type = RTPOINTTYPE;
138 result->flags = gflags(ctx, hasz, hasm, 0);
139 result->srid = srid;
140 result->point = ptarray_construct(ctx, hasz, hasm, 0);
141 result->bbox = NULL;
142 return result;
143 }
144
145 RTPOINT *
rtpoint_make2d(const RTCTX * ctx,int srid,double x,double y)146 rtpoint_make2d(const RTCTX *ctx, int srid, double x, double y)
147 {
148 RTPOINT4D p = {x, y, 0.0, 0.0};
149 RTPOINTARRAY *pa = ptarray_construct_empty(ctx, 0, 0, 1);
150
151 ptarray_append_point(ctx, pa, &p, RT_TRUE);
152 return rtpoint_construct(ctx, srid, NULL, pa);
153 }
154
155 RTPOINT *
rtpoint_make3dz(const RTCTX * ctx,int srid,double x,double y,double z)156 rtpoint_make3dz(const RTCTX *ctx, int srid, double x, double y, double z)
157 {
158 RTPOINT4D p = {x, y, z, 0.0};
159 RTPOINTARRAY *pa = ptarray_construct_empty(ctx, 1, 0, 1);
160
161 ptarray_append_point(ctx, pa, &p, RT_TRUE);
162
163 return rtpoint_construct(ctx, srid, NULL, pa);
164 }
165
166 RTPOINT *
rtpoint_make3dm(const RTCTX * ctx,int srid,double x,double y,double m)167 rtpoint_make3dm(const RTCTX *ctx, int srid, double x, double y, double m)
168 {
169 RTPOINT4D p = {x, y, 0.0, m};
170 RTPOINTARRAY *pa = ptarray_construct_empty(ctx, 0, 1, 1);
171
172 ptarray_append_point(ctx, pa, &p, RT_TRUE);
173
174 return rtpoint_construct(ctx, srid, NULL, pa);
175 }
176
177 RTPOINT *
rtpoint_make4d(const RTCTX * ctx,int srid,double x,double y,double z,double m)178 rtpoint_make4d(const RTCTX *ctx, int srid, double x, double y, double z, double m)
179 {
180 RTPOINT4D p = {x, y, z, m};
181 RTPOINTARRAY *pa = ptarray_construct_empty(ctx, 1, 1, 1);
182
183 ptarray_append_point(ctx, pa, &p, RT_TRUE);
184
185 return rtpoint_construct(ctx, srid, NULL, pa);
186 }
187
188 RTPOINT *
rtpoint_make(const RTCTX * ctx,int srid,int hasz,int hasm,const RTPOINT4D * p)189 rtpoint_make(const RTCTX *ctx, int srid, int hasz, int hasm, const RTPOINT4D *p)
190 {
191 RTPOINTARRAY *pa = ptarray_construct_empty(ctx, hasz, hasm, 1);
192 ptarray_append_point(ctx, pa, p, RT_TRUE);
193 return rtpoint_construct(ctx, srid, NULL, pa);
194 }
195
rtpoint_free(const RTCTX * ctx,RTPOINT * pt)196 void rtpoint_free(const RTCTX *ctx, RTPOINT *pt)
197 {
198 if ( ! pt ) return;
199
200 if ( pt->bbox )
201 rtfree(ctx, pt->bbox);
202 if ( pt->point )
203 ptarray_free(ctx, pt->point);
204 rtfree(ctx, pt);
205 }
206
printRTPOINT(const RTCTX * ctx,RTPOINT * point)207 void printRTPOINT(const RTCTX *ctx, RTPOINT *point)
208 {
209 rtnotice(ctx, "RTPOINT {");
210 rtnotice(ctx, " ndims = %i", (int)RTFLAGS_NDIMS(point->flags));
211 rtnotice(ctx, " BBOX = %i", RTFLAGS_GET_BBOX(point->flags) ? 1 : 0 );
212 rtnotice(ctx, " SRID = %i", (int)point->srid);
213 printPA(ctx, point->point);
214 rtnotice(ctx, "}");
215 }
216
217 /* @brief Clone RTPOINT object. Serialized point lists are not copied.
218 *
219 * @see ptarray_clone
220 */
221 RTPOINT *
rtpoint_clone(const RTCTX * ctx,const RTPOINT * g)222 rtpoint_clone(const RTCTX *ctx, const RTPOINT *g)
223 {
224 RTPOINT *ret = rtalloc(ctx, sizeof(RTPOINT));
225
226 RTDEBUG(ctx, 2, "rtpoint_clone called");
227
228 memcpy(ret, g, sizeof(RTPOINT));
229
230 ret->point = ptarray_clone(ctx, g->point);
231
232 if ( g->bbox ) ret->bbox = gbox_copy(ctx, g->bbox);
233 return ret;
234 }
235
236
237
238 void
rtpoint_release(const RTCTX * ctx,RTPOINT * rtpoint)239 rtpoint_release(const RTCTX *ctx, RTPOINT *rtpoint)
240 {
241 rtgeom_release(ctx, rtpoint_as_rtgeom(ctx, rtpoint));
242 }
243
244
245 /* check coordinate equality */
246 char
rtpoint_same(const RTCTX * ctx,const RTPOINT * p1,const RTPOINT * p2)247 rtpoint_same(const RTCTX *ctx, const RTPOINT *p1, const RTPOINT *p2)
248 {
249 return ptarray_same(ctx, p1->point, p2->point);
250 }
251
252
253 RTPOINT*
rtpoint_force_dims(const RTCTX * ctx,const RTPOINT * point,int hasz,int hasm)254 rtpoint_force_dims(const RTCTX *ctx, const RTPOINT *point, int hasz, int hasm)
255 {
256 RTPOINTARRAY *pdims = NULL;
257 RTPOINT *pointout;
258
259 /* Return 2D empty */
260 if( rtpoint_is_empty(ctx, point) )
261 {
262 pointout = rtpoint_construct_empty(ctx, point->srid, hasz, hasm);
263 }
264 else
265 {
266 /* Artays we duplicate the ptarray and return */
267 pdims = ptarray_force_dims(ctx, point->point, hasz, hasm);
268 pointout = rtpoint_construct(ctx, point->srid, NULL, pdims);
269 }
270 pointout->type = point->type;
271 return pointout;
272 }
273
rtpoint_is_empty(const RTCTX * ctx,const RTPOINT * point)274 int rtpoint_is_empty(const RTCTX *ctx, const RTPOINT *point)
275 {
276 if ( ! point->point || point->point->npoints < 1 )
277 return RT_TRUE;
278 return RT_FALSE;
279 }
280
281
282 RTPOINT *
rtpoint_grid(const RTCTX * ctx,const RTPOINT * point,const gridspec * grid)283 rtpoint_grid(const RTCTX *ctx, const RTPOINT *point, const gridspec *grid)
284 {
285 RTPOINTARRAY *opa = ptarray_grid(ctx, point->point, grid);
286 return rtpoint_construct(ctx, point->srid, NULL, opa);
287 }
288
289