VoxelHash.h
Go to the documentation of this file.00001 #ifndef VOXEL_HASH_HPP_
00002 #define VOXEL_HASH_HPP_
00003
00004 #include "SimTKsimbody.h"
00005 #include "molmodel/internal/common.h"
00006 #include <vector>
00007 #include <map>
00008
00009
00010 #ifdef __GNUC__
00011 #include <ext/hash_map>
00012 #define HASH_MAP_NAMESPACE __gnu_cxx
00013 #else
00014 #include <hash_map>
00015 #define HASH_MAP_NAMESPACE stdext
00016 #endif
00017
00018
00019
00020
00021 namespace SimTK {
00022
00023
00024 namespace units { namespace md
00025 {
00026 typedef Real dimensionless_t;
00027 typedef Real length_t;
00028 typedef Real mass_t;
00029 typedef Real area_t;
00030 typedef Real inverse_volume_t;
00031 typedef Vec3 location_t;
00032
00033 static const Real nanometers = 1.0;
00034 static const Real daltons = 1.0;
00035 static const Real cubic_nanometer = 1.0;
00036 static const Real square_nanometers = 1.0;
00037 }}
00038
00039 template< class T >
00040 class SimTK_MOLMODEL_EXPORT VoxelHash
00041 {
00042 public:
00043 typedef std::pair<SimTK::Vec3, T> VoxelItem;
00044 typedef std::vector< VoxelItem > Voxel;
00045
00046 class VoxelIndex {
00047 public:
00048 VoxelIndex(int x, int y, int z, size_t numBuckets)
00049 : x(x), y(y), z(z), numBuckets(numBuckets)
00050 {}
00051
00052
00053 bool operator<(const VoxelIndex& other) const {
00054 if (x < other.x) return true;
00055 else if (x > other.x) return false;
00056 else if (y < other.y) return true;
00057 else if (y > other.y) return false;
00058 else if (z < other.z) return true;
00059 else return false;
00060 }
00061 bool operator==(const VoxelIndex& other) const {
00062 if (x != other.x) return false;
00063 else if (y != other.y) return false;
00064 else if (z != other.z) return false;
00065 else return true;
00066 }
00067
00068
00069 operator size_t() const {
00070 return hash_value();
00071 }
00072
00073 size_t hash_value() const {
00074
00075 size_t n = (size_t)(x * 0x8da6b343 + y * 0xd8163841 + z * 0xcb1ab31f);
00076 n = n % numBuckets;
00077 if (n < 0) n += numBuckets;
00078 return n;
00079 }
00080
00081 int x;
00082 int y;
00083 int z;
00084 size_t numBuckets;
00085 };
00086
00087 private:
00088 VoxelIndex getVoxelIndex(const Vec3& location) const
00089 {
00090 SimTK::Real voxSize = voxelSize;
00091 int x = int(floor(location[0] / voxSize));
00092 int y = int(floor(location[1] / voxSize));
00093 int z = int(floor(location[2] / voxSize));
00094 return VoxelIndex(x, y, z, numBuckets);
00095 }
00096
00097 SimTK::units::md::length_t voxelSize;
00098
00099
00100
00101 std::map<VoxelIndex, Voxel> voxelMap;
00102
00103 size_t numBuckets;
00104
00105 public:
00106 VoxelHash(SimTK::units::md::length_t voxelSize, int numBuckets)
00107 : voxelSize(voxelSize), numBuckets(numBuckets)
00108 {}
00109
00110 void insert(const T& item, const SimTK::Vec3& location)
00111 {
00112 VoxelIndex voxelIndex = getVoxelIndex(location);
00113 if ( voxelMap.find(voxelIndex) == voxelMap.end() ) voxelMap[voxelIndex] = Voxel();
00114 Voxel& voxel = voxelMap.find(voxelIndex)->second;
00115 voxel.push_back( VoxelItem(location, item) );
00116 }
00117
00118 void findNeighbors(std::vector<T>& neighbors, const SimTK::Vec3& locationI, SimTK::units::md::length_t maxDistance) const
00119 {
00120 SimTK::units::md::area_t maxDistanceSquared(maxDistance * maxDistance);
00121
00122 int dIndex = int(maxDistance / voxelSize) + 1;
00123 VoxelIndex centerVoxelIndex(getVoxelIndex(locationI));
00124
00125 for (int x = centerVoxelIndex.x - dIndex; x <= centerVoxelIndex.x + dIndex; ++x)
00126 for (int y = centerVoxelIndex.y - dIndex; y <= centerVoxelIndex.y + dIndex; ++y)
00127 for (int z = centerVoxelIndex.z - dIndex; z <= centerVoxelIndex.z + dIndex; ++z)
00128 {
00129 const VoxelIndex voxelIndex(x, y, z, numBuckets);
00130
00131
00132 if ( voxelMap.find(voxelIndex) == voxelMap.end() ) continue;
00133
00134 const Voxel& voxel = voxelMap.find(voxelIndex)->second;
00135 typename std::vector<VoxelItem>::const_iterator itemIter;
00136 for (itemIter = voxel.begin(); itemIter != voxel.end(); ++itemIter)
00137 {
00138 const SimTK::Vec3 r = locationI - itemIter->first;
00139 SimTK::units::md::area_t dSquared(dot(r, r) * units::md::square_nanometers);
00140 if (dSquared > maxDistanceSquared) continue;
00141
00142 neighbors.push_back(itemIter->second);
00143 }
00144 }
00145 }
00146
00147 };
00148
00149 }
00150
00151
00152 #endif