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