Molmodel

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 // #include "md_units.hpp"
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 // Subystem for managing atom locations.
00019 // Depends on matter subsystem
00020 
00021 namespace SimTK {
00022 
00023 // Elide use of boost::units for now
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         // operator<() needed for map
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         // size_t conversion for use by hash_map
00069         operator size_t() const {
00070             return hash_value();
00071         }
00072         
00073         size_t hash_value() const {
00074             // multiply each index by a different large prime number
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     // TODO - replace std::map with hash_map or unordered map
00100     // std::map<VoxelIndex, Voxel> voxelMap;
00101     std::map<VoxelIndex, Voxel> voxelMap;
00102     // HASH_MAP_NAMESPACE::hash_map<VoxelIndex, Voxel> voxelMap;
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; // How may voxels away do we have to look?
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                     // TODO - store a list of neighbors for each voxel
00132                     if ( voxelMap.find(voxelIndex) == voxelMap.end() ) continue; // no such voxel; skip
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; // beyond cutoff
00141 
00142                         neighbors.push_back(itemIter->second); // store neighbor
00143                     }
00144                 }
00145     }
00146 
00147 };
00148 
00149 } // namespace SimTK
00150 
00151 
00152 #endif /* VOXEL_HASH_HPP_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines