18#include "SpatialIndex.h"
19#include "SpatialException.h"
25#include <sys/malloc.h>
39#define N(x) nodes_[(x)]
40#define V(x) vertices_[nodes_[index].v_[(x)]]
41#define IV(x) nodes_[index].v_[(x)]
42#define W(x) vertices_[nodes_[index].w_[(x)]]
43#define IW(x) nodes_[index].w_[(x)]
44#define ICHILD(x) nodes_[index].childID_[(x)]
46#define IV_(x) nodes_[index_].v_[(x)]
47#define IW_(x) nodes_[index_].w_[(x)]
48#define ICHILD_(x) nodes_[index_].childID_[(x)]
60 : maxlevel_(maxlevel), buildlevel_((buildlevel == 0 || buildlevel > maxlevel) ? maxlevel : buildlevel)
62 size_t nodes, vertices;
64 vMax(&nodes, &vertices);
65 layers_.resize(buildlevel_ + 1);
66 nodes_.resize(nodes + 1);
67 vertices_.resize(vertices + 1);
72 layers_[0].level_ = 0;
73 layers_[0].nVert_ = 6;
74 layers_[0].nNode_ = 8;
75 layers_[0].nEdge_ = 12;
76 layers_[0].firstIndex_ = 1;
77 layers_[0].firstVertex_ = 0;
84 { -1.0L, 0.0L, 0.0L },
85 { 0.0L, -1.0L, 0.0L },
89 for (
int i = 0; i < 6; i++)
90 vertices_[i].set(v[i][0], v[i][1], v[i][2]);
94 newNode(1, 5, 2, 8, 0);
95 newNode(2, 5, 3, 9, 0);
96 newNode(3, 5, 4, 10, 0);
97 newNode(4, 5, 1, 11, 0);
98 newNode(1, 0, 4, 12, 0);
99 newNode(4, 0, 3, 13, 0);
100 newNode(3, 0, 2, 14, 0);
101 newNode(2, 0, 1, 15, 0);
106 size_t level = buildlevel_;
109 SpatialEdge edge(*
this, pl);
110 edge.makeMidPoints();
123 if (buildlevel_ == maxlevel_)
125 uint32 idx = (uint32)
id - leaves_ + IOFFSET;
126 v0 = vertices_[nodes_[idx].v_[0]];
127 v1 = vertices_[nodes_[idx].v_[1]];
128 v2 = vertices_[nodes_[idx].v_[2]];
135 uint64 sid =
id >> ((maxlevel_ - buildlevel_) * 2);
136 uint32 idx = (uint32)(sid - storedleaves_ + IOFFSET);
138 v0 = vertices_[nodes_[idx].v_[0]];
139 v1 = vertices_[nodes_[idx].v_[1]];
140 v2 = vertices_[nodes_[idx].v_[2]];
145 for (uint32 i = buildlevel_ + 1; i <= maxlevel_; i++)
147 uint64 j = (
id >> ((maxlevel_ - i) * 2)) & 3;
183void SpatialIndex::makeNewLayer(
size_t oldlayer)
186 size_t newlayer = oldlayer + 1;
187 layers_[newlayer].level_ = layers_[oldlayer].level_ + 1;
188 layers_[newlayer].nVert_ = layers_[oldlayer].nVert_ + layers_[oldlayer].nEdge_;
189 layers_[newlayer].nNode_ = 4 * layers_[oldlayer].nNode_;
190 layers_[newlayer].nEdge_ = layers_[newlayer].nNode_ + layers_[newlayer].nVert_ - 2;
191 layers_[newlayer].firstIndex_ = index_;
192 layers_[newlayer].firstVertex_ = layers_[oldlayer].firstVertex_ + layers_[oldlayer].nVert_;
194 uint64 ioffset = layers_[oldlayer].firstIndex_;
196 for (index = ioffset; index < ioffset + layers_[oldlayer].nNode_; index++)
198 id = N(index).id_ << 2;
199 ICHILD(0) = newNode(IV(0), IW(2), IW(1),
id++, index);
200 ICHILD(1) = newNode(IV(1), IW(0), IW(2),
id++, index);
201 ICHILD(2) = newNode(IV(2), IW(1), IW(0),
id++, index);
202 ICHILD(3) = newNode(IW(0), IW(1), IW(2),
id, index);
209uint64 SpatialIndex::newNode(
size_t v1,
size_t v2,
size_t v3, uint64
id, uint64 parent)
225 N(index_).index_ = index_;
226 N(index_).parent_ = parent;
237void SpatialIndex::vMax(
size_t *nodes,
size_t *vertices)
242 int32 i = buildlevel_;
250 *nodes += (size_t)nf;
252 *vertices = (size_t)nv;
256 i = maxlevel_ - buildlevel_;
268void SpatialIndex::sortIndex()
270 std::vector<QuadNode> oldnodes(nodes_);
275#define ON(x) oldnodes[(x)]
278 for (index = IOFFSET, leaf = IOFFSET, nonleaf = nodes_.size() - 1; index < nodes_.size(); index++)
280 if (ON(index).childID_[0] == 0)
285 for (
size_t i = 0; i < 4; i++)
287 if (N(N(leaf).parent_).childID_[i] == index)
289 N(N(leaf).parent_).childID_[i] = leaf;
300 N(nonleaf) = ON(index);
301 ON(N(nonleaf).childID_[0]).parent_ = nonleaf;
302 ON(N(nonleaf).childID_[1]).parent_ = nonleaf;
303 ON(N(nonleaf).childID_[2]).parent_ = nonleaf;
304 ON(N(nonleaf).childID_[3]).parent_ = nonleaf;
306 for (
size_t i = 0; i < 4; i++)
308 if (N(N(nonleaf).parent_).childID_[i] == index)
310 N(N(nonleaf).parent_).childID_[i] = nonleaf;
348 if (name[0] !=
'N' && name[0] !=
'S')
354 throw SpatialFailure(
"SpatialIndex:idByName:invalid name - too short ", name);
355 if (size > HTMNAMEMAX)
356 throw SpatialFailure(
"SpatialIndex:idByName:invalid name - too long ", name);
358 for (i = size - 1; i > 0; i--)
360 if (name[i] >
'3' || name[i] <
'0')
361 throw SpatialFailure(
"SpatialIndex:idByName:invalid name digit ", name);
362 out += (uint64(name[i] -
'0') << 2 * (size - i - 1));
368 out += (i << (2 * size - 2));
402 uint64 IDHIGHBIT = 1;
403 uint64 IDHIGHBIT2 = 1;
404 IDHIGHBIT = IDHIGHBIT << 63;
405 IDHIGHBIT2 = IDHIGHBIT2 << 62;
422 for (i = 0; i < IDSIZE; i += 2)
424 if ((
id << i) & IDHIGHBIT)
426 if ((
id << i) & IDHIGHBIT2)
432 size = (IDSIZE - i) >> 1;
435 name =
new char[size + 1];
438 for (i = 0; i < size - 1; i++)
439 name[size - i - 1] =
'0' +
char((
id >> i * 2) & 3);
442 if ((
id >> (size * 2 - 2)) & 1)
460 float64 center_x, center_y, center_z, sum;
461 char name[HTMNAMEMAX];
489 center_x = v0.x_ + v1.x_ + v2.x_;
490 center_y = v0.y_ + v1.y_ + v2.y_;
491 center_z = v0.z_ + v1.z_ + v2.z_;
492 sum = center_x * center_x + center_y * center_y + center_z * center_z;
513 for (index = 1; index <= 8; index++)
515 if ((V(0) ^ V(1)) * v < -gEpsilon)
517 if ((V(1) ^ V(2)) * v < -gEpsilon)
519 if ((V(2) ^ V(0)) * v < -gEpsilon)
524 while (ICHILD(0) != 0)
526 uint64 oldindex = index;
527 for (
size_t i = 0; i < 4; i++)
529 index = nodes_[oldindex].childID_[i];
530 if ((V(0) ^ V(1)) * v < -gEpsilon)
532 if ((V(1) ^ V(2)) * v < -gEpsilon)
534 if ((V(2) ^ V(0)) * v < -gEpsilon)
540 if (maxlevel_ == buildlevel_)
546 char name[HTMNAMEMAX];
548 size_t len = strlen(name);
553 size_t level = maxlevel_ - buildlevel_;
563 if (isInside(v, v0, w2, w1))
570 else if (isInside(v, v1, w0, w2))
578 else if (isInside(v, v2, w1, w0))
586 else if (isInside(v, w0, w1, w2))
606 if ((v0 ^ v1) * v < -gEpsilon)
608 if ((v1 ^ v2) * v < -gEpsilon)
610 if ((v2 ^ v0) * v < -gEpsilon)
SpatialException thrown on operational failure.
uint64 idByPoint(const SpatialVector &vector) const
find a node by giving a vector.
static uint64 idByName(const char *)
NodeName conversion to integer ID.
void pointById(SpatialVector &vector, uint64 ID) const
find the vector to the centroid of a triangle represented by the ID
SpatialIndex(size_t maxlevel, size_t buildlevel=5)
Constructor.
void nodeVertex(const uint64 id, SpatialVector &v1, SpatialVector &v2, SpatialVector &v3) const
return the actual vertex vectors
static char * nameById(uint64 ID, char *name=nullptr)
int32 conversion to a string (name of database).
SpatialVector is a 3D vector usually living on the surface of the sphere.
void normalize()
Normalize vector length to 1.