PostGIS  3.4.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 #if PARANOIA_LEVEL > 0
31 #include <assert.h>
32 #endif
33 
34 inline static double
35 distance2d_sqr_pt_pt(const POINT2D *p1, const POINT2D *p2)
36 {
37  double hside = p2->x - p1->x;
38  double vside = p2->y - p1->y;
39 
40  return hside * hside + vside * vside;
41 }
42 
43 inline static double
44 distance3d_sqr_pt_pt(const POINT3D *p1, const POINT3D *p2)
45 {
46  double hside = p2->x - p1->x;
47  double vside = p2->y - p1->y;
48  double zside = p2->z - p1->z;
49 
50  return hside * hside + vside * vside + zside * zside;
51 }
52 
53 /*
54  * Size of point represeneted in the POINTARRAY
55  * 16 for 2d, 24 for 3d, 32 for 4d
56  */
57 static inline size_t
59 {
60  return sizeof(double) * FLAGS_NDIMS(pa->flags);
61 }
62 
63 /*
64  * Get a pointer to Nth point of a POINTARRAY
65  * You'll need to cast it to appropriate dimensioned point.
66  * Note that if you cast to a higher dimensional point you'll
67  * possibly corrupt the POINTARRAY.
68  *
69  * Casting to returned pointer to POINT2D* should be safe,
70  * as gserialized format always keeps the POINTARRAY pointer
71  * aligned to double boundary.
72  *
73  * WARNING: Don't cast this to a POINT!
74  * it would not be reliable due to memory alignment constraints
75  */
76 static inline uint8_t *
77 getPoint_internal(const POINTARRAY *pa, uint32_t n)
78 {
79  size_t size;
80  uint8_t *ptr;
81 
82 #if PARANOIA_LEVEL > 0
83  assert(pa);
84  assert(n <= pa->npoints);
85  assert(n <= pa->maxpoints);
86 #endif
87 
88  size = ptarray_point_size(pa);
89  ptr = pa->serialized_pointlist + size * n;
90 
91  return ptr;
92 }
93 
100 static inline const POINT2D *
101 getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
102 {
103  return (const POINT2D *)getPoint_internal(pa, n);
104 }
105 
112 static inline const POINT3D *
113 getPoint3d_cp(const POINTARRAY *pa, uint32_t n)
114 {
115  return (const POINT3D *)getPoint_internal(pa, n);
116 }
117 
124 static inline const POINT4D *
125 getPoint4d_cp(const POINTARRAY *pa, uint32_t n)
126 {
127  return (const POINT4D *)getPoint_internal(pa, n);
128 }
129 
130 static inline LWPOINT *
131 lwgeom_as_lwpoint(const LWGEOM *lwgeom)
132 {
133  if (!lwgeom)
134  return NULL;
135  if (lwgeom->type == POINTTYPE)
136  return (LWPOINT *)lwgeom;
137  else
138  return NULL;
139 }
140 
144 static inline uint32_t
146 {
147  if (!geom)
148  return 0;
149  return geom->type;
150 }
151 
152 static inline int
154 {
155  return !point->point || point->point->npoints < 1;
156 }
157 
158 static inline int
160 {
161  return !line->points || line->points->npoints < 1;
162 }
163 
164 static inline int
166 {
167  return !circ->points || circ->points->npoints < 1;
168 }
169 
170 static inline int
172 {
173  return poly->nrings < 1 || !poly->rings || !poly->rings[0] || poly->rings[0]->npoints < 1;
174 }
175 
176 static inline int
178 {
179  return !triangle->points || triangle->points->npoints < 1;
180 }
181 
182 static inline int lwgeom_is_empty(const LWGEOM *geom);
183 
184 static inline int
186 {
187  uint32_t i;
188  if (col->ngeoms == 0 || !col->geoms)
189  return LW_TRUE;
190  for (i = 0; i < col->ngeoms; i++)
191  {
192  if (!lwgeom_is_empty(col->geoms[i]))
193  return LW_FALSE;
194  }
195  return LW_TRUE;
196 }
197 
202 static inline int
204 {
205  switch (geom->type)
206  {
207  case POINTTYPE:
208  return lwpoint_is_empty((LWPOINT *)geom);
209  break;
210  case LINETYPE:
211  return lwline_is_empty((LWLINE *)geom);
212  break;
213  case CIRCSTRINGTYPE:
214  return lwcircstring_is_empty((LWCIRCSTRING *)geom);
215  break;
216  case POLYGONTYPE:
217  return lwpoly_is_empty((LWPOLY *)geom);
218  break;
219  case TRIANGLETYPE:
220  return lwtriangle_is_empty((LWTRIANGLE *)geom);
221  break;
222  case MULTIPOINTTYPE:
223  case MULTILINETYPE:
224  case MULTIPOLYGONTYPE:
225  case COMPOUNDTYPE:
226  case CURVEPOLYTYPE:
227  case MULTICURVETYPE:
228  case MULTISURFACETYPE:
230  case TINTYPE:
231  case COLLECTIONTYPE:
232  return lwcollection_is_empty((LWCOLLECTION *)geom);
233  break;
234  default:
235  return LW_FALSE;
236  break;
237  }
238 }
239 
240 inline static uint64_t
241 uint64_interleave_2(uint64_t x, uint64_t y)
242 {
243  x = (x | (x << 16)) & 0x0000FFFF0000FFFFULL;
244  x = (x | (x << 8)) & 0x00FF00FF00FF00FFULL;
245  x = (x | (x << 4)) & 0x0F0F0F0F0F0F0F0FULL;
246  x = (x | (x << 2)) & 0x3333333333333333ULL;
247  x = (x | (x << 1)) & 0x5555555555555555ULL;
248 
249  y = (y | (y << 16)) & 0x0000FFFF0000FFFFULL;
250  y = (y | (y << 8)) & 0x00FF00FF00FF00FFULL;
251  y = (y | (y << 4)) & 0x0F0F0F0F0F0F0F0FULL;
252  y = (y | (y << 2)) & 0x3333333333333333ULL;
253  y = (y | (y << 1)) & 0x5555555555555555ULL;
254 
255  return x | (y << 1);
256 }
257 
258 /* Based on https://github.com/rawrunprotected/hilbert_curves Public Domain code */
259 inline static uint64_t
260 uint32_hilbert(uint32_t px, uint32_t py)
261 {
262  uint64_t x = px;
263  uint64_t y = py;
264 
265  uint64_t A, B, C, D;
266  uint64_t a, b, c, d;
267  uint64_t i0, i1;
268 
269  // Initial prefix scan round, prime with x and y
270  {
271  a = x ^ y;
272  b = 0xFFFFFFFFULL ^ a;
273  c = 0xFFFFFFFFULL ^ (x | y);
274  d = x & (y ^ 0xFFFFFFFFULL);
275 
276  A = a | (b >> 1);
277  B = (a >> 1) ^ a;
278  C = ((c >> 1) ^ (b & (d >> 1))) ^ c;
279  D = ((a & (c >> 1)) ^ (d >> 1)) ^ d;
280  }
281 
282  {
283  a = A;
284  b = B;
285  c = C;
286  d = D;
287 
288  A = ((a & (a >> 2)) ^ (b & (b >> 2)));
289  B = ((a & (b >> 2)) ^ (b & ((a ^ b) >> 2)));
290  C ^= ((a & (c >> 2)) ^ (b & (d >> 2)));
291  D ^= ((b & (c >> 2)) ^ ((a ^ b) & (d >> 2)));
292  }
293 
294  {
295  a = A;
296  b = B;
297  c = C;
298  d = D;
299 
300  A = ((a & (a >> 4)) ^ (b & (b >> 4)));
301  B = ((a & (b >> 4)) ^ (b & ((a ^ b) >> 4)));
302  C ^= ((a & (c >> 4)) ^ (b & (d >> 4)));
303  D ^= ((b & (c >> 4)) ^ ((a ^ b) & (d >> 4)));
304  }
305 
306  {
307  a = A;
308  b = B;
309  c = C;
310  d = D;
311 
312  A = ((a & (a >> 8)) ^ (b & (b >> 8)));
313  B = ((a & (b >> 8)) ^ (b & ((a ^ b) >> 8)));
314  C ^= ((a & (c >> 8)) ^ (b & (d >> 8)));
315  D ^= ((b & (c >> 8)) ^ ((a ^ b) & (d >> 8)));
316  }
317 
318  {
319  a = A;
320  b = B;
321  c = C;
322  d = D;
323 
324  C ^= ((a & (c >> 16)) ^ (b & (d >> 16)));
325  D ^= ((b & (c >> 16)) ^ ((a ^ b) & (d >> 16)));
326  }
327 
328  // Undo transformation prefix scan
329  a = C ^ (C >> 1);
330  b = D ^ (D >> 1);
331 
332  // Recover index bits
333  i0 = x ^ y;
334  i1 = b | (0xFFFFFFFFULL ^ (i0 | a));
335 
336  return uint64_interleave_2(i0, i1);
337 }
338 
339 /*
340  * This macro is based on PG_FREE_IF_COPY, except that it accepts two pointers.
341  * See PG_FREE_IF_COPY comment in src/include/fmgr.h in postgres source code
342  * for more details.
343  */
344 #define POSTGIS_FREE_IF_COPY_P(ptrsrc, ptrori) \
345  do \
346  { \
347  if ((Pointer)(ptrsrc) != (Pointer)(ptrori)) \
348  pfree(ptrsrc); \
349  } 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:101
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:113
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:125
static double distance2d_sqr_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition: lwinline.h:35
static uint64_t uint32_hilbert(uint32_t px, uint32_t py)
Definition: lwinline.h:260
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition: lwinline.h:145
static int lwcircstring_is_empty(const LWCIRCSTRING *circ)
Definition: lwinline.h:165
static int lwpoly_is_empty(const LWPOLY *poly)
Definition: lwinline.h:171
static size_t ptarray_point_size(const POINTARRAY *pa)
Definition: lwinline.h:58
static uint8_t * getPoint_internal(const POINTARRAY *pa, uint32_t n)
Definition: lwinline.h:77
static int lwcollection_is_empty(const LWCOLLECTION *col)
Definition: lwinline.h:185
static uint64_t uint64_interleave_2(uint64_t x, uint64_t y)
Definition: lwinline.h:241
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:203
static int lwline_is_empty(const LWLINE *line)
Definition: lwinline.h:159
static int lwtriangle_is_empty(const LWTRIANGLE *triangle)
Definition: lwinline.h:177
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition: lwinline.h:131
static double distance3d_sqr_pt_pt(const POINT3D *p1, const POINT3D *p2)
Definition: lwinline.h:44
static int lwpoint_is_empty(const LWPOINT *point)
Definition: lwinline.h:153
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