1 #ifndef INCLUDE_AL_HASHSPACE_HPP
2 #define INCLUDE_AL_HASHSPACE_HPP
7 #include "al/math/al_Vec.hpp"
124 double distanceSquared;
127 return x.distanceSquared > y.distanceSquared;
130 Result() : object(0), distanceSquared(0) {}
132 : object(cpy.object), distanceSquared(cpy.distanceSquared) {}
135 typedef std::vector<Result> Results;
136 typedef Results::iterator Iterator;
160 double minRadius = 0.);
162 double minRadius = 0.);
181 unsigned size()
const {
return mObjects.size(); }
184 double distanceSquared(
unsigned i)
const {
185 return mObjects[i].distanceSquared;
187 double distance(
unsigned i)
const {
return sqrt(distanceSquared(i)); }
208 Iterator
begin() {
return mObjects.begin(); }
209 Iterator end() {
return mObjects.end(); }
210 Results &results() {
return mObjects; }
213 uint32_t mMaxResults;
229 HashSpace(uint32_t resolution = 5, uint32_t numObjects = 0);
234 uint32_t
dim()
const {
return mDim; }
239 void numObjects(
int numObjects);
240 uint32_t numObjects()
const {
return mObjects.size(); }
274 uint32_t distanceSquared(
double a1,
double a2,
double a3)
const;
278 inline uint32_t hash(
unsigned x,
unsigned y,
unsigned z)
const {
279 return hashx(x) + hashy(y) + hashz(z);
281 template <
typename T>
inline uint32_t hash(Vec<3, T> v)
const {
282 return hash(v[0], v[1], v[2]);
285 inline uint32_t hash(uint32_t x, uint32_t y, uint32_t z,
286 uint32_t offset)
const {
287 return hashx(unhashx(offset) + x) + hashy(unhashy(offset) + y) +
288 hashz(unhashz(offset) + z);
290 template <
typename T>
291 inline uint32_t hash(Vec<3, T> v, uint32_t offset)
const {
292 return hash(v[0], v[1], v[2], offset);
295 inline uint32_t hashx(uint32_t v)
const {
return v & mWrap; }
296 inline uint32_t hashy(uint32_t v)
const {
return (v & mWrap) << mShift; }
297 inline uint32_t hashz(uint32_t v)
const {
return (v & mWrap) << mShift2; }
300 inline Vec3i unhash(uint32_t h)
const {
301 return Vec3i(unhashx(h), unhashy(h), unhashz(h));
304 inline uint32_t unhashx(uint32_t h)
const {
return (h)&mWrap; }
305 inline uint32_t unhashy(uint32_t h)
const {
return (h >> mShift) & mWrap; }
306 inline uint32_t unhashz(uint32_t h)
const {
return (h >> mShift2) & mWrap; }
309 static double wrap(
double x,
double mod);
310 static double wrap(
double x,
double lo,
double hi);
312 uint32_t mShift, mShift2, mDim, mDim2, mDim3, mWrap, mWrap3;
314 uint32_t mMaxD2, mMaxHalfD2;
326 std::vector<uint32_t> mVoxelIndicesToDistance;
359 o->
prev = o->next = NULL;
363 return (*
this)(space, center, space.
maxRadius());
368 return (*
this)(space, obj, space.
maxRadius());
377 double minr2 = minRadius * minRadius;
379 uint32_t iminr2 =
std::max(uint32_t(0), uint32_t(minRadius * minRadius));
380 uint32_t imaxr2 =
std::min(space.mMaxHalfD2,
382 if (iminr2 < imaxr2) {
385 for (uint32_t i = cellstart; i < cellend; i++) {
396 if (d2 >= minr2 && d2 <= maxr2) {
399 r.distanceSquared = d2;
404 }
while (o != head && nres < mMaxResults);
406 if (nres == mMaxResults) {
422 const Vec3d ¢er = obj->pos;
423 double minr2 = minRadius * minRadius;
425 uint32_t iminr2 =
std::max(uint32_t(0), uint32_t(minRadius * minRadius));
426 uint32_t imaxr2 =
std::min(space.mMaxHalfD2,
428 if (iminr2 < imaxr2) {
431 for (uint32_t i = cellstart; i < cellend; i++) {
443 if (d2 >= minr2 && d2 <= maxr2) {
447 r.distanceSquared = d2;
453 }
while (o != head && nres < mMaxResults);
455 if (nres == mMaxResults)
467 const Vec3d ¢er = src->pos;
468 uint32_t results = (*this)(space, src, space.mMaxHalfD2);
471 double rd2 = space.mMaxHalfD2;
472 for (uint32_t i = 0; i < results; i++) {
484 inline void HashSpace ::numObjects(
int numObjects) {
488 for (
unsigned i = 0; i <
mVoxels.size(); i++) {
493 template <
typename T>
496 o.pos.set(
wrap(pos));
497 uint32_t newhash = hash(o.pos);
498 if (newhash != o.hash) {
516 inline uint32_t HashSpace ::distanceSquared(
double x,
double y,
518 return x * x + y * y + z * z;
528 if (x > (mod * 2.)) {
530 double div = x / mod;
532 double divl = (long)div;
533 double fract = div - (double)divl;
543 double div = x / mod;
545 double divl = (long)div;
546 double fract = div - (double)divl;
547 double x1 = fract * mod;
548 return (x1 < 0.) ? x1 + mod : x1;
562 return lo +
wrap(x - lo, hi - lo);
std::vector< Voxel > mVoxels
the array of voxels (indexed by hashed location)
std::vector< uint32_t > mDistanceToVoxelIndices
a baked array mapping distance to mVoxelIndices offsets
uint32_t maxRadius() const
the maximum valid radius to query (half the dimension):
HashSpace & remove(uint32_t objectId)
std::vector< Object > mObjects
the array of objects
Object & object(uint32_t i)
get the object at a given index:
std::vector< uint32_t > mVoxelIndices
a baked array of voxel indices sorted by distance
uint32_t dim() const
the dimension of the space per axis:
double wrapRelative(double x) const
double wrap(double x) const
wrap an absolute position within the space:
static uint32_t invalidHash()
an invalid voxel index used to indicate non-membership
HashSpace(uint32_t resolution=5, uint32_t numObjects=0)
HashSpace & move(uint32_t objectId, double x, double y, double z)
set the position of an object:
T magSqr() const
Returns magnitude squared.
T min(const T &v1, const T &v2, const T &v3)
T max(const T &v1, const T &v2, const T &v3)
Vec< 3, double > Vec3d
double 3-vector
Vec< 3, int > Vec3i
integer 3-vector
container for registered spatial elements
uint32_t hash
which voxel ID it belongs to (or invalidHash())
uint32_t id
< a way to attach user-defined payloads:
Object * prev
neighbors in the same voxel
Object * operator[](unsigned i) const
get each result:
uint32_t maxResults() const
get the maximum number of desired results
Query(uint32_t maxResults=128)
Iterator begin()
std::vector interface:
Object * nearest(const HashSpace &space, const Object *obj)
unsigned size() const
get number of results:
int operator()(const HashSpace &space, const Vec3d center, double maxRadius, double minRadius=0.)
Query & maxResults(uint32_t i)
set the maximum number of desired results
each Voxel contains a linked list of Objects
void add(Object *o)
definitely not thread-safe.
void remove(Object *o)
definitely not thread-safe.
Object * mObjects
the linked list of objects in this voxel