PostGIS  3.7.0dev-r@@SVN_REVISION@@
lwinline.h
Go to the documentation of this file.
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 2018 Darafei Praliaskouski <me@komzpa.net>
22  * Copyright 2017-2018 Daniel Baston <dbaston@gmail.com>
23  * Copyright 2011 Sandro Santilli <strk@kbt.io>
24  * Copyright 2011 Paul Ramsey <pramsey@cleverelephant.ca>
25  * Copyright 2007-2008 Mark Cave-Ayland
26  * Copyright 2001-2006 Refractions Research Inc.
27  *
28  **********************************************************************/
29 
30 #include <assert.h>
31 
32 inline static double
33 distance2d_sqr_pt_pt(const POINT2D *p1, const POINT2D *p2)
34 {
35  double hside = p2->x - p1->x;
36  double vside = p2->y - p1->y;
37 
38  return hside * hside + vside * vside;
39 }
40 
41 inline static double
42 distance3d_sqr_pt_pt(const POINT3D *p1, const POINT3D *p2)
43 {
44  double hside = p2->x - p1->x;
45  double vside = p2->y - p1->y;
46  double zside = p2->z - p1->z;
47 
48  return hside * hside + vside * vside + zside * zside;
49 }
50 
51 /*
52  * Size of point represeneted in the POINTARRAY
53  * 16 for 2d, 24 for 3d, 32 for 4d
54  */
55 static inline size_t
57 {
58  return sizeof(double) * FLAGS_NDIMS(pa->flags);
59 }
60 
61 /*
62  * Get a pointer to Nth point of a POINTARRAY
63  * You'll need to cast it to appropriate dimensioned point.
64  * Note that if you cast to a higher dimensional point you'll
65  * possibly corrupt the POINTARRAY.
66  *
67  * Casting to returned pointer to POINT2D* should be safe,
68  * as gserialized format always keeps the POINTARRAY pointer
69  * aligned to double boundary.
70  *
71  * WARNING: Don't cast this to a POINT!
72  * it would not be reliable due to memory alignment constraints
73  */
74 static inline uint8_t *
75 getPoint_internal(const POINTARRAY *pa, uint32_t n)
76 {
77  size_t size;
78  uint8_t *ptr;
79 
80  assert(pa);
81  assert(n <= pa->npoints);
82  assert(n <= pa->maxpoints);
83 
84  size = ptarray_point_size(pa);
85  ptr = pa->serialized_pointlist + size * n;
86 
87  return ptr;
88 }
89 
96 static inline const POINT2D *
97 getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
98 {
99  return (const POINT2D *)getPoint_internal(pa, n);
100 }
101 
108 static inline const POINT3D *
109 getPoint3d_cp(const POINTARRAY *pa, uint32_t n)
110 {
111  return (const POINT3D *)getPoint_internal(pa, n);
112 }
113 
120 static inline const POINT4D *
121 getPoint4d_cp(const POINTARRAY *pa, uint32_t n)
122 {
123  return (const POINT4D *)getPoint_internal(pa, n);
124 }
125 
126 static inline LWPOINT *
127 lwgeom_as_lwpoint(const LWGEOM *lwgeom)
128 {
129  if (!lwgeom)
130  return NULL;
131  if (lwgeom->type == POINTTYPE)
132  return (LWPOINT *)lwgeom;
133  else
134  return NULL;
135 }
136 
140 static inline uint32_t
142 {
143  if (!geom)
144  return 0;
145  return geom->type;
146 }
147 
148 static inline int
150 {
151  return !point->point || point->point->npoints < 1;
152 }
153 
154 static inline int
156 {
157  return !line->points || line->points->npoints < 1;
158 }
159 
160 static inline int
162 {
163  return !circ->points || circ->points->npoints < 1;
164 }
165 
166 static inline int
168 {
169  return poly->nrings < 1 || !poly->rings || !poly->rings[0] || poly->rings[0]->npoints < 1;
170 }
171 
172 static inline int
174 {
175  return !triangle->points || triangle->points->npoints < 1;
176 }
177 
178 static inline int lwgeom_is_empty(const LWGEOM *geom);
179 
180 static inline int
182 {
183  uint32_t i;
184  if (col->ngeoms == 0 || !col->geoms)
185  return LW_TRUE;
186  for (i = 0; i < col->ngeoms; i++)
187  {
188  if (!lwgeom_is_empty(col->geoms[i]))
189  return LW_FALSE;
190  }
191  return LW_TRUE;
192 }
193 
198 static inline int
200 {
201  switch (geom->type)
202  {
203  case POINTTYPE:
204  return lwpoint_is_empty((LWPOINT *)geom);
205  break;
206  case LINETYPE:
207  return lwline_is_empty((LWLINE *)geom);
208  break;
209  case CIRCSTRINGTYPE:
210  return lwcircstring_is_empty((LWCIRCSTRING *)geom);
211  break;
212  case POLYGONTYPE:
213  return lwpoly_is_empty((LWPOLY *)geom);
214  break;
215  case TRIANGLETYPE:
216  return lwtriangle_is_empty((LWTRIANGLE *)geom);
217  break;
218  case MULTIPOINTTYPE:
219  case MULTILINETYPE:
220  case MULTIPOLYGONTYPE:
221  case COMPOUNDTYPE:
222  case CURVEPOLYTYPE:
223  case MULTICURVETYPE:
224  case MULTISURFACETYPE:
226  case TINTYPE:
227  case COLLECTIONTYPE:
228  return lwcollection_is_empty((LWCOLLECTION *)geom);
229  break;
230  default:
231  return LW_FALSE;
232  break;
233  }
234 }
235 
236 inline static uint64_t
237 uint64_interleave_2(uint64_t x, uint64_t y)
238 {
239  x = (x | (x << 16)) & 0x0000FFFF0000FFFFULL;
240  x = (x | (x << 8)) & 0x00FF00FF00FF00FFULL;
241  x = (x | (x << 4)) & 0x0F0F0F0F0F0F0F0FULL;
242  x = (x | (x << 2)) & 0x3333333333333333ULL;
243  x = (x | (x << 1)) & 0x5555555555555555ULL;
244 
245  y = (y | (y << 16)) & 0x0000FFFF0000FFFFULL;
246  y = (y | (y << 8)) & 0x00FF00FF00FF00FFULL;
247  y = (y | (y << 4)) & 0x0F0F0F0F0F0F0F0FULL;
248  y = (y | (y << 2)) & 0x3333333333333333ULL;
249  y = (y | (y << 1)) & 0x5555555555555555ULL;
250 
251  return x | (y << 1);
252 }
253 
254 /* Based on https://github.com/rawrunprotected/hilbert_curves Public Domain code */
255 inline static uint64_t
256 uint32_hilbert(uint32_t px, uint32_t py)
257 {
258  uint64_t x = px;
259  uint64_t y = py;
260 
261  uint64_t A, B, C, D;
262  uint64_t a, b, c, d;
263  uint64_t i0, i1;
264 
265  // Initial prefix scan round, prime with x and y
266  {
267  a = x ^ y;
268  b = 0xFFFFFFFFULL ^ a;
269  c = 0xFFFFFFFFULL ^ (x | y);
270  d = x & (y ^ 0xFFFFFFFFULL);
271 
272  A = a | (b >> 1);
273  B = (a >> 1) ^ a;
274  C = ((c >> 1) ^ (b & (d >> 1))) ^ c;
275  D = ((a & (c >> 1)) ^ (d >> 1)) ^ d;
276  }
277 
278  {
279  a = A;
280  b = B;
281  c = C;
282  d = D;
283 
284  A = ((a & (a >> 2)) ^ (b & (b >> 2)));
285  B = ((a & (b >> 2)) ^ (b & ((a ^ b) >> 2)));
286  C ^= ((a & (c >> 2)) ^ (b & (d >> 2)));
287  D ^= ((b & (c >> 2)) ^ ((a ^ b) & (d >> 2)));
288  }
289 
290  {
291  a = A;
292  b = B;
293  c = C;
294  d = D;
295 
296  A = ((a & (a >> 4)) ^ (b & (b >> 4)));
297  B = ((a & (b >> 4)) ^ (b & ((a ^ b) >> 4)));
298  C ^= ((a & (c >> 4)) ^ (b & (d >> 4)));
299  D ^= ((b & (c >> 4)) ^ ((a ^ b) & (d >> 4)));
300  }
301 
302  {
303  a = A;
304  b = B;
305  c = C;
306  d = D;
307 
308  A = ((a & (a >> 8)) ^ (b & (b >> 8)));
309  B = ((a & (b >> 8)) ^ (b & ((a ^ b) >> 8)));
310  C ^= ((a & (c >> 8)) ^ (b & (d >> 8)));
311  D ^= ((b & (c >> 8)) ^ ((a ^ b) & (d >> 8)));
312  }
313 
314  {
315  a = A;
316  b = B;
317  c = C;
318  d = D;
319 
320  C ^= ((a & (c >> 16)) ^ (b & (d >> 16)));
321  D ^= ((b & (c >> 16)) ^ ((a ^ b) & (d >> 16)));
322  }
323 
324  // Undo transformation prefix scan
325  a = C ^ (C >> 1);
326  b = D ^ (D >> 1);
327 
328  // Recover index bits
329  i0 = x ^ y;
330  i1 = b | (0xFFFFFFFFULL ^ (i0 | a));
331 
332  return uint64_interleave_2(i0, i1);
333 }
334 
335 /*
336  * This macro is based on PG_FREE_IF_COPY, except that it accepts two pointers.
337  * See PG_FREE_IF_COPY comment in src/include/fmgr.h in postgres source code
338  * for more details.
339  */
340 #define POSTGIS_FREE_IF_COPY_P(ptrsrc, ptrori) \
341  do \
342  { \
343  if ((Pointer)(ptrsrc) != (Pointer)(ptrori)) \
344  pfree(ptrsrc); \
345  } while (0)
#define LW_FALSE
Definition: liblwgeom.h:94
#define COLLECTIONTYPE
Definition: liblwgeom.h:108
#define COMPOUNDTYPE
Definition: liblwgeom.h:110
#define CURVEPOLYTYPE
Definition: liblwgeom.h:111
#define MULTILINETYPE
Definition: liblwgeom.h:106
#define MULTISURFACETYPE
Definition: liblwgeom.h:113
#define LINETYPE
Definition: liblwgeom.h:103
#define MULTIPOINTTYPE
Definition: liblwgeom.h:105
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:102
#define TINTYPE
Definition: liblwgeom.h:116
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:107
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:179
#define POLYGONTYPE
Definition: liblwgeom.h:104
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:114
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:109
#define MULTICURVETYPE
Definition: liblwgeom.h:112
#define TRIANGLETYPE
Definition: liblwgeom.h:115
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:93
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition: lwinline.h:97
static const POINT3D * getPoint3d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT3D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition: lwinline.h:109
static const POINT4D * getPoint4d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT4D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition: lwinline.h:121
static double distance2d_sqr_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition: lwinline.h:33
static uint64_t uint32_hilbert(uint32_t px, uint32_t py)
Definition: lwinline.h:256
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition: lwinline.h:141
static int lwcircstring_is_empty(const LWCIRCSTRING *circ)
Definition: lwinline.h:161
static int lwpoly_is_empty(const LWPOLY *poly)
Definition: lwinline.h:167
static size_t ptarray_point_size(const POINTARRAY *pa)
Definition: lwinline.h:56
static uint8_t * getPoint_internal(const POINTARRAY *pa, uint32_t n)
Definition: lwinline.h:75
static int lwcollection_is_empty(const LWCOLLECTION *col)
Definition: lwinline.h:181
static uint64_t uint64_interleave_2(uint64_t x, uint64_t y)
Definition: lwinline.h:237
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwinline.h:199
static int lwline_is_empty(const LWLINE *line)
Definition: lwinline.h:155
static int lwtriangle_is_empty(const LWTRIANGLE *triangle)
Definition: lwinline.h:173
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition: lwinline.h:127
static double distance3d_sqr_pt_pt(const POINT3D *p1, const POINT3D *p2)
Definition: lwinline.h:42
static int lwpoint_is_empty(const LWPOINT *point)
Definition: lwinline.h:149
POINTARRAY * points
Definition: liblwgeom.h:507
uint32_t ngeoms
Definition: liblwgeom.h:580
LWGEOM ** geoms
Definition: liblwgeom.h:575
uint8_t type
Definition: liblwgeom.h:462
POINTARRAY * points
Definition: liblwgeom.h:483
POINTARRAY * point
Definition: liblwgeom.h:471
POINTARRAY ** rings
Definition: liblwgeom.h:519
uint32_t nrings
Definition: liblwgeom.h:524
POINTARRAY * points
Definition: liblwgeom.h:495
double y
Definition: liblwgeom.h:390
double x
Definition: liblwgeom.h:390
double z
Definition: liblwgeom.h:402
double x
Definition: liblwgeom.h:402
double y
Definition: liblwgeom.h:402
lwflags_t flags
Definition: liblwgeom.h:431
uint32_t npoints
Definition: liblwgeom.h:427
uint8_t * serialized_pointlist
Definition: liblwgeom.h:434