对于由IEEE 32位浮点组成的散列2d和3d向量,有什么好的散列函数(快速,良好的分布,很少的碰撞)。我假设一般的3d向量,但假设法线(始终在[-1,1])的算法也是受欢迎的。我也不担心比特操纵,因为IEEE浮动也是IEEE浮动。
另一个更普遍的问题是散列Nd浮点向量,其中N非常小(3-12)并且是常量但在编译时不知道。目前我只是将这些花车作为uint并将它们混合在一起,这可能不是最好的解决方案。
答案 0 :(得分:41)
Optimized Spatial Hashing for Collision Detection of Deformable Objects中描述了空间哈希函数。他们使用哈希函数
hash(x,y,z)=(x p1 xor y p2 xor z p3)mod n
其中p1,p2,p3很大 素数,在我们的案例中为73856093, 分别为19349663,83492791。该 value n是哈希表的大小。
在论文中,x,y和z是离散化的坐标;你也可以使用你的花车的二进制值。
答案 1 :(得分:8)
我有两个建议。
如果你不进行量化,它就不会对亲密度(局部性)敏感。
答案 2 :(得分:0)
我是根据此处看到的注释用Python编写的,
l = 5
n = 5
p1,p2,p3 = 73856093, 19349663, 83492791
x1 = [33,4,11]
x2 = [31,1,14]
x3 = [10,44,19]
def spatial_hash(x):
ix,iy,iz = np.floor(x[0]/l), np.floor(x[1]/l), np.floor(x[2]/l)
return (int(ix*p1) ^ int(iy*p2) ^ int(iz*p3)) % n
print (spatial_hash(x1))
print (spatial_hash(x2))
print (spatial_hash(x3))
它给
1
1
3
似乎可行。
在C ++中
#include <cstdlib>
#include <iostream>
#include <unordered_map>
#include <vector>
#include <random>
#include <eigen3/Eigen/Dense>
using namespace Eigen;
using namespace std;
const int HASH_SIZE = 200;
//const float MAX = 500.0;
const float L = 0.2f;
const float mmin = -1.f;
const float mmax = 1.f;
unordered_map<int, vector<Vector3d>> map ;
inline size_t hasha(Vector3d &p) {
int ix = (unsigned int)((p[0]+2.f) / L);
int iy = (unsigned int)((p[1]+2.f) / L);
int iz = (unsigned int)((p[2]+2.f) / L);
return (unsigned int)((ix * 73856093) ^ (iy * 19349663) ^ (iz * 83492791)) % HASH_SIZE;
}
int main(int argc, char** argv) {
std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(-1.0,1.0);
for(size_t i=0;i<300;i++){
float x = distribution(generator);
float y = distribution(generator);
float z = distribution(generator);
Vector3d v(x,y,z);
std::cout << hasha(v) << " " << v[0] << " " << v[1] << " " << v[2] << std::endl;
map[hasha(v)].push_back(v);
vector<Vector3d> entry = map[hasha(v)];
std::cout << "size " << entry.size() << std::endl;
}
for (const auto & [ key, value ] : map) {
cout << key << std::endl;
vector<Vector3d> v = map[key];
float average = 0.0f;
for (int i=0; i<v.size(); i++){
for (int j=0; j<v.size(); j++){
if (i!=j){
Vector3d v1 = v[i];
Vector3d v2 = v[j];
std::cout << " dist " << (v1-v2).norm() << std::endl;
}
}
}
}
}