Coverage Report

Created: 2026-07-16 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgis/liblwgeom/lwpoint.c
Line
Count
Source
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
40
lwpoint_getPoint2d_p(const LWPOINT *point, POINT2D *out)
41
0
{
42
0
  return lwpoint_is_empty(point) ? 0 : getPoint2d_p(point->point, 0, out);
43
0
}
44
45
/* convenience functions to hide the POINTARRAY */
46
int
47
lwpoint_getPoint3dz_p(const LWPOINT *point, POINT3DZ *out)
48
0
{
49
0
  return lwpoint_is_empty(point) ? 0 : getPoint3dz_p(point->point,0,out);
50
0
}
51
int
52
lwpoint_getPoint3dm_p(const LWPOINT *point, POINT3DM *out)
53
0
{
54
0
  return lwpoint_is_empty(point) ? 0 : getPoint3dm_p(point->point,0,out);
55
0
}
56
int
57
lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out)
58
0
{
59
0
  return lwpoint_is_empty(point) ? 0 : getPoint4d_p(point->point,0,out);
60
0
}
61
62
double
63
lwpoint_get_x(const LWPOINT *point)
64
0
{
65
0
  POINT4D pt;
66
0
  if ( lwpoint_is_empty(point) )
67
0
  {
68
0
    lwerror("lwpoint_get_x called with empty geometry");
69
0
    return 0;
70
0
  }
71
0
  getPoint4d_p(point->point, 0, &pt);
72
0
  return pt.x;
73
0
}
74
75
double
76
lwpoint_get_y(const LWPOINT *point)
77
0
{
78
0
  POINT4D pt;
79
0
  if ( lwpoint_is_empty(point) )
80
0
  {
81
0
    lwerror("lwpoint_get_y called with empty geometry");
82
0
    return 0;
83
0
  }
84
0
  getPoint4d_p(point->point, 0, &pt);
85
0
  return pt.y;
86
0
}
87
88
double
89
lwpoint_get_z(const LWPOINT *point)
90
0
{
91
0
  POINT4D pt;
92
0
  if ( lwpoint_is_empty(point) )
93
0
  {
94
0
    lwerror("lwpoint_get_z called with empty geometry");
95
0
    return 0;
96
0
  }
97
0
  if ( ! FLAGS_GET_Z(point->flags) )
98
0
  {
99
0
    lwerror("lwpoint_get_z called without z dimension");
100
0
    return 0;
101
0
  }
102
0
  getPoint4d_p(point->point, 0, &pt);
103
0
  return pt.z;
104
0
}
105
106
double
107
lwpoint_get_m(const LWPOINT *point)
108
0
{
109
0
  POINT4D pt;
110
0
  if ( lwpoint_is_empty(point) )
111
0
  {
112
0
    lwerror("lwpoint_get_m called with empty geometry");
113
0
    return 0;
114
0
  }
115
0
  if ( ! FLAGS_GET_M(point->flags) )
116
0
  {
117
0
    lwerror("lwpoint_get_m called without m dimension");
118
0
    return 0;
119
0
  }
120
0
  getPoint4d_p(point->point, 0, &pt);
121
0
  return pt.m;
122
0
}
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 *
129
lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
130
228k
{
131
228k
  LWPOINT *result;
132
228k
  lwflags_t flags = 0;
133
134
228k
  if (point == NULL)
135
0
    return NULL; /* error */
136
137
228k
  result = lwalloc(sizeof(LWPOINT));
138
228k
  result->type = POINTTYPE;
139
228k
  FLAGS_SET_Z(flags, FLAGS_GET_Z(point->flags));
140
228k
  FLAGS_SET_M(flags, FLAGS_GET_M(point->flags));
141
228k
  FLAGS_SET_BBOX(flags, bbox?1:0);
142
228k
  result->flags = flags;
143
228k
  result->srid = srid;
144
228k
  result->point = point;
145
228k
  result->bbox = bbox;
146
147
228k
  return result;
148
228k
}
149
150
LWPOINT *
151
lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
152
1.37k
{
153
1.37k
  LWPOINT *result = lwalloc(sizeof(LWPOINT));
154
1.37k
  result->type = POINTTYPE;
155
1.37k
  result->flags = lwflags(hasz, hasm, 0);
156
1.37k
  result->srid = srid;
157
1.37k
  result->point = ptarray_construct(hasz, hasm, 0);
158
1.37k
  result->bbox = NULL;
159
1.37k
  return result;
160
1.37k
}
161
162
LWPOINT *
163
lwpoint_make2d(int32_t srid, double x, double y)
164
0
{
165
0
  POINT4D p = {x, y, 0.0, 0.0};
166
0
  POINTARRAY *pa = ptarray_construct_empty(0, 0, 1);
167
168
0
  ptarray_append_point(pa, &p, LW_TRUE);
169
0
  return lwpoint_construct(srid, NULL, pa);
170
0
}
171
172
LWPOINT *
173
lwpoint_make3dz(int32_t srid, double x, double y, double z)
174
0
{
175
0
  POINT4D p = {x, y, z, 0.0};
176
0
  POINTARRAY *pa = ptarray_construct_empty(1, 0, 1);
177
178
0
  ptarray_append_point(pa, &p, LW_TRUE);
179
180
0
  return lwpoint_construct(srid, NULL, pa);
181
0
}
182
183
LWPOINT *
184
lwpoint_make3dm(int32_t srid, double x, double y, double m)
185
0
{
186
0
  POINT4D p = {x, y, 0.0, m};
187
0
  POINTARRAY *pa = ptarray_construct_empty(0, 1, 1);
188
189
0
  ptarray_append_point(pa, &p, LW_TRUE);
190
191
0
  return lwpoint_construct(srid, NULL, pa);
192
0
}
193
194
LWPOINT *
195
lwpoint_make4d(int32_t srid, double x, double y, double z, double m)
196
0
{
197
0
  POINT4D p = {x, y, z, m};
198
0
  POINTARRAY *pa = ptarray_construct_empty(1, 1, 1);
199
200
0
  ptarray_append_point(pa, &p, LW_TRUE);
201
202
0
  return lwpoint_construct(srid, NULL, pa);
203
0
}
204
205
LWPOINT *
206
lwpoint_make(int32_t srid, int hasz, int hasm, const POINT4D *p)
207
0
{
208
0
  POINTARRAY *pa = ptarray_construct_empty(hasz, hasm, 1);
209
0
  ptarray_append_point(pa, p, LW_TRUE);
210
0
  return lwpoint_construct(srid, NULL, pa);
211
0
}
212
213
void lwpoint_free(LWPOINT *pt)
214
131k
{
215
131k
  if ( ! pt ) return;
216
217
131k
  if ( pt->bbox )
218
429
    lwfree(pt->bbox);
219
131k
  if ( pt->point )
220
131k
    ptarray_free(pt->point);
221
131k
  lwfree(pt);
222
131k
}
223
224
void printLWPOINT(LWPOINT *point)
225
0
{
226
0
  lwnotice("LWPOINT {");
227
0
  lwnotice("    ndims = %i", (int)FLAGS_NDIMS(point->flags));
228
0
  lwnotice("    BBOX = %i", FLAGS_GET_BBOX(point->flags) ? 1 : 0 );
229
0
  lwnotice("    SRID = %i", (int)point->srid);
230
0
  printPA(point->point);
231
0
  lwnotice("}");
232
0
}
233
234
/* @brief Clone LWPOINT object. Serialized point lists are not copied.
235
 *
236
 * @see ptarray_clone
237
 */
238
LWPOINT *
239
lwpoint_clone(const LWPOINT *g)
240
0
{
241
0
  LWPOINT *ret = lwalloc(sizeof(LWPOINT));
242
243
0
  LWDEBUG(2, "lwpoint_clone called");
244
245
0
  memcpy(ret, g, sizeof(LWPOINT));
246
247
0
  ret->point = ptarray_clone(g->point);
248
249
0
  if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
250
0
  return ret;
251
0
}
252
253
254
255
void
256
lwpoint_release(LWPOINT *lwpoint)
257
0
{
258
0
  lwgeom_release(lwpoint_as_lwgeom(lwpoint));
259
0
}
260
261
262
/* check coordinate equality  */
263
char
264
lwpoint_same(const LWPOINT *p1, const LWPOINT *p2)
265
0
{
266
0
  return ptarray_same(p1->point, p2->point);
267
0
}
268
269
/* check 2d coordinate equality  */
270
char
271
lwpoint_same2d(const LWPOINT *p1, const LWPOINT *p2)
272
0
{
273
0
  return ptarray_same2d(p1->point, p2->point);
274
0
}
275
276
LWPOINT *
277
lwpoint_project_lwpoint(const LWPOINT* lwpoint1, const LWPOINT* lwpoint2, double distance)
278
0
{
279
0
  POINT4D p1, p2, p3;
280
0
  int srid = lwgeom_get_srid((const LWGEOM*)lwpoint1);
281
0
  int hasz = lwgeom_has_z((const LWGEOM*)lwpoint1);
282
0
  int hasm = lwgeom_has_m((const LWGEOM*)lwpoint1);
283
0
  lwpoint_getPoint4d_p(lwpoint1, &p1);
284
0
  lwpoint_getPoint4d_p(lwpoint2, &p2);
285
0
  project_pt_pt(&p1, &p2, distance, &p3);
286
0
  return lwpoint_make(srid, hasz, hasm, &p3);
287
0
}
288
289
LWPOINT *
290
lwpoint_project(const LWPOINT* lwpoint1, double distance, double azimuth)
291
0
{
292
0
  POINT4D p1, p2;
293
0
  int srid = lwgeom_get_srid((const LWGEOM*)lwpoint1);
294
0
  int hasz = lwgeom_has_z((const LWGEOM*)lwpoint1);
295
0
  int hasm = lwgeom_has_m((const LWGEOM*)lwpoint1);
296
0
  lwpoint_getPoint4d_p(lwpoint1, &p1);
297
0
  lwpoint_getPoint4d_p(lwpoint1, &p2);
298
0
  project_pt((POINT2D*)&p1, distance, azimuth, (POINT2D*)&p2);
299
0
  return lwpoint_make(srid, hasz, hasm, &p2);
300
0
}
301
302
303
LWPOINT*
304
lwpoint_force_dims(const LWPOINT *point, int hasz, int hasm, double zval, double mval)
305
0
{
306
0
  POINTARRAY *pdims = NULL;
307
0
  LWPOINT *pointout;
308
309
  /* Return 2D empty */
310
0
  if( lwpoint_is_empty(point) )
311
0
  {
312
0
    pointout = lwpoint_construct_empty(point->srid, hasz, hasm);
313
0
  }
314
0
  else
315
0
  {
316
    /* Always we duplicate the ptarray and return */
317
0
    pdims = ptarray_force_dims(point->point, hasz, hasm, zval, mval);
318
    pointout = lwpoint_construct(point->srid, NULL, pdims);
319
0
  }
320
0
  pointout->type = point->type;
321
0
  return pointout;
322
0
}
323
324