载入中...
搜索中...
未找到
SpatialHash3D.cpp
浏览该文件的文档.
2
3#include "common/Exception.h"
4
5#include <algorithm>
6#include <cmath>
7
8namespace eve::spatial {
9
10SpatialHash3D::SpatialHash3D(float cellSize) { setCellSize(cellSize); }
11
12void SpatialHash3D::setCellSize(float cellSize) {
13 if (cellSize <= 0.f) {
14 throw Exception("SpatialHash3D: cellSize must be > 0");
15 }
16 if (!items_.empty() && cellSize != cellSize_) {
17 auto snapshot = items_;
18 clear();
19 cellSize_ = cellSize;
20 for (const auto &kv : snapshot) {
21 insert(kv.first, kv.second.minX, kv.second.minY, kv.second.minZ, kv.second.maxX,
22 kv.second.maxY, kv.second.maxZ);
23 }
24 return;
25 }
26 cellSize_ = cellSize;
27}
28
30 items_.clear();
31 cells_.clear();
32 results_.clear();
33}
34
35bool SpatialHash3D::contains(int id) const { return items_.find(id) != items_.end(); }
36
37void SpatialHash3D::cellRange(const AABB3 &b, int &minCX, int &minCY, int &minCZ, int &maxCX,
38 int &maxCY, int &maxCZ) const {
39 minCX = static_cast<int>(std::floor(b.minX / cellSize_));
40 minCY = static_cast<int>(std::floor(b.minY / cellSize_));
41 minCZ = static_cast<int>(std::floor(b.minZ / cellSize_));
42 maxCX = static_cast<int>(std::floor(b.maxX / cellSize_));
43 maxCY = static_cast<int>(std::floor(b.maxY / cellSize_));
44 maxCZ = static_cast<int>(std::floor(b.maxZ / cellSize_));
45}
46
47void SpatialHash3D::insertCells(int id, const AABB3 &b) {
48 int minCX, minCY, minCZ, maxCX, maxCY, maxCZ;
49 cellRange(b, minCX, minCY, minCZ, maxCX, maxCY, maxCZ);
50 for (int cz = minCZ; cz <= maxCZ; ++cz) {
51 for (int cy = minCY; cy <= maxCY; ++cy) {
52 for (int cx = minCX; cx <= maxCX; ++cx) {
53 cells_[cellKey3(cx, cy, cz)].push_back(id);
54 }
55 }
56 }
57}
58
59void SpatialHash3D::eraseCells(int id, const AABB3 &b) {
60 int minCX, minCY, minCZ, maxCX, maxCY, maxCZ;
61 cellRange(b, minCX, minCY, minCZ, maxCX, maxCY, maxCZ);
62 for (int cz = minCZ; cz <= maxCZ; ++cz) {
63 for (int cy = minCY; cy <= maxCY; ++cy) {
64 for (int cx = minCX; cx <= maxCX; ++cx) {
65 auto it = cells_.find(cellKey3(cx, cy, cz));
66 if (it == cells_.end()) continue;
67 auto &vec = it->second;
68 vec.erase(std::remove(vec.begin(), vec.end(), id), vec.end());
69 if (vec.empty()) cells_.erase(it);
70 }
71 }
72 }
73}
74
75bool SpatialHash3D::insert(int id, float minX, float minY, float minZ, float maxX, float maxY,
76 float maxZ) {
77 AABB3 b = makeAABB3(minX, minY, minZ, maxX, maxY, maxZ);
78 if (!b.valid()) return false;
79 if (contains(id)) remove(id);
80 items_[id] = b;
81 insertCells(id, b);
82 return true;
83}
84
86 auto it = items_.find(id);
87 if (it == items_.end()) return false;
88 eraseCells(id, it->second);
89 items_.erase(it);
90 return true;
91}
92
93bool SpatialHash3D::update(int id, float minX, float minY, float minZ, float maxX, float maxY,
94 float maxZ) {
95 if (!contains(id)) return false;
96 return insert(id, minX, minY, minZ, maxX, maxY, maxZ);
97}
98
99void SpatialHash3D::queryCells(int minCX, int minCY, int minCZ, int maxCX, int maxCY, int maxCZ,
100 const AABB3 *box, float cx, float cy, float cz, float radius,
101 bool useSphere, bool usePoint) {
102 results_.clear();
103 std::unordered_set<int> seen;
104 for (int z = minCZ; z <= maxCZ; ++z) {
105 for (int y = minCY; y <= maxCY; ++y) {
106 for (int x = minCX; x <= maxCX; ++x) {
107 auto it = cells_.find(cellKey3(x, y, z));
108 if (it == cells_.end()) continue;
109 for (int id : it->second) {
110 if (!seen.insert(id).second) continue;
111 auto item = items_.find(id);
112 if (item == items_.end()) continue;
113 const AABB3 &b = item->second;
114 bool hit = false;
115 if (box) {
116 hit = b.intersectsAABB(*box);
117 } else if (useSphere) {
118 hit = b.intersectsSphere(cx, cy, cz, radius);
119 } else if (usePoint) {
120 hit = b.containsPoint(cx, cy, cz);
121 }
122 if (hit) results_.addUnchecked(id);
123 }
124 }
125 }
126 }
127}
128
129int SpatialHash3D::queryPoint(float x, float y, float z) {
130 const int cx = static_cast<int>(std::floor(x / cellSize_));
131 const int cy = static_cast<int>(std::floor(y / cellSize_));
132 const int cz = static_cast<int>(std::floor(z / cellSize_));
133 queryCells(cx, cy, cz, cx, cy, cz, nullptr, x, y, z, 0.f, false, true);
134 return results_.getCount();
135}
136
137int SpatialHash3D::queryAABB(float minX, float minY, float minZ, float maxX, float maxY,
138 float maxZ) {
139 AABB3 box = makeAABB3(minX, minY, minZ, maxX, maxY, maxZ);
140 int minCX, minCY, minCZ, maxCX, maxCY, maxCZ;
141 cellRange(box, minCX, minCY, minCZ, maxCX, maxCY, maxCZ);
142 queryCells(minCX, minCY, minCZ, maxCX, maxCY, maxCZ, &box, 0.f, 0.f, 0.f, 0.f, false, false);
143 return results_.getCount();
144}
145
146int SpatialHash3D::querySphere(float cx, float cy, float cz, float radius) {
147 if (radius < 0.f) radius = 0.f;
148 AABB3 box = makeAABB3(cx - radius, cy - radius, cz - radius, cx + radius, cy + radius,
149 cz + radius);
150 int minCX, minCY, minCZ, maxCX, maxCY, maxCZ;
151 cellRange(box, minCX, minCY, minCZ, maxCX, maxCY, maxCZ);
152 queryCells(minCX, minCY, minCZ, maxCX, maxCY, maxCZ, nullptr, cx, cy, cz, radius, true, false);
153 return results_.getCount();
154}
155
156} // namespace eve::spatial
float cx
Definition CardTypes.cpp:31
float cy
Definition CardTypes.cpp:32
std::string id
int y
Definition Grass.cpp:135
int z
Definition Grass.cpp:135
int x
Definition Grass.cpp:135
uint32_t b
void addUnchecked(int id)
Definition QueryIds.h:22
int getCount() const
Definition QueryIds.h:24
SpatialHash3D(float cellSize=64.f)
bool insert(int id, float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
int querySphere(float cx, float cy, float cz, float radius)
void setCellSize(float cellSize)
bool update(int id, float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
bool contains(int id) const
int queryAABB(float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
int queryPoint(float x, float y, float z)
AABB3 makeAABB3(float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
Definition Bounds.h:91
uint64_t cellKey3(int cx, int cy, int cz)
Definition Bounds.h:103
bool intersectsAABB(const AABB3 &o) const
Definition Bounds.h:69