载入中...
搜索中...
未找到
SpatialHash2D.cpp
浏览该文件的文档.
2
3#include "common/Exception.h"
4
5#include <algorithm>
6#include <cmath>
7
8namespace eve::spatial {
9
10SpatialHash2D::SpatialHash2D(float cellSize) { setCellSize(cellSize); }
11
12void SpatialHash2D::setCellSize(float cellSize) {
13 if (cellSize <= 0.f) {
14 throw Exception("SpatialHash2D: cellSize must be > 0");
15 }
16 if (!items_.empty() && cellSize != cellSize_) {
17 // Rebuild with new size.
18 auto snapshot = items_;
19 clear();
20 cellSize_ = cellSize;
21 for (const auto &kv : snapshot) {
22 insert(kv.first, kv.second.minX, kv.second.minY, kv.second.maxX, kv.second.maxY);
23 }
24 return;
25 }
26 cellSize_ = cellSize;
27}
28
30 items_.clear();
31 cells_.clear();
32 results_.clear();
33}
34
35bool SpatialHash2D::contains(int id) const { return items_.find(id) != items_.end(); }
36
37void SpatialHash2D::cellRange(const AABB2 &b, int &minCX, int &minCY, int &maxCX,
38 int &maxCY) const {
39 minCX = static_cast<int>(std::floor(b.minX / cellSize_));
40 minCY = static_cast<int>(std::floor(b.minY / cellSize_));
41 maxCX = static_cast<int>(std::floor(b.maxX / cellSize_));
42 maxCY = static_cast<int>(std::floor(b.maxY / cellSize_));
43}
44
45void SpatialHash2D::insertCells(int id, const AABB2 &b) {
46 int minCX, minCY, maxCX, maxCY;
47 cellRange(b, minCX, minCY, maxCX, maxCY);
48 for (int cy = minCY; cy <= maxCY; ++cy) {
49 for (int cx = minCX; cx <= maxCX; ++cx) {
50 cells_[cellKey2(cx, cy)].push_back(id);
51 }
52 }
53}
54
55void SpatialHash2D::eraseCells(int id, const AABB2 &b) {
56 int minCX, minCY, maxCX, maxCY;
57 cellRange(b, minCX, minCY, maxCX, maxCY);
58 for (int cy = minCY; cy <= maxCY; ++cy) {
59 for (int cx = minCX; cx <= maxCX; ++cx) {
60 auto it = cells_.find(cellKey2(cx, cy));
61 if (it == cells_.end()) continue;
62 auto &vec = it->second;
63 vec.erase(std::remove(vec.begin(), vec.end(), id), vec.end());
64 if (vec.empty()) cells_.erase(it);
65 }
66 }
67}
68
69bool SpatialHash2D::insert(int id, float minX, float minY, float maxX, float maxY) {
70 AABB2 b = makeAABB2(minX, minY, maxX, maxY);
71 if (!b.valid()) return false;
72 if (contains(id)) remove(id);
73 items_[id] = b;
74 insertCells(id, b);
75 return true;
76}
77
79 auto it = items_.find(id);
80 if (it == items_.end()) return false;
81 eraseCells(id, it->second);
82 items_.erase(it);
83 return true;
84}
85
86bool SpatialHash2D::update(int id, float minX, float minY, float maxX, float maxY) {
87 if (!contains(id)) return false;
88 return insert(id, minX, minY, maxX, maxY);
89}
90
91void SpatialHash2D::queryCells(int minCX, int minCY, int maxCX, int maxCY, const AABB2 *rect,
92 float cx, float cy, float radius, bool useCircle, bool usePoint) {
93 results_.clear();
94 std::unordered_set<int> seen;
95 for (int y = minCY; y <= maxCY; ++y) {
96 for (int x = minCX; x <= maxCX; ++x) {
97 auto it = cells_.find(cellKey2(x, y));
98 if (it == cells_.end()) continue;
99 for (int id : it->second) {
100 if (!seen.insert(id).second) continue;
101 auto item = items_.find(id);
102 if (item == items_.end()) continue;
103 const AABB2 &b = item->second;
104 bool hit = false;
105 if (rect) {
106 hit = b.intersectsAABB(*rect);
107 } else if (useCircle) {
108 hit = b.intersectsCircle(cx, cy, radius);
109 } else if (usePoint) {
110 hit = b.containsPoint(cx, cy);
111 }
112 if (hit) results_.addUnchecked(id);
113 }
114 }
115 }
116}
117
118int SpatialHash2D::queryPoint(float x, float y) {
119 const int cx = static_cast<int>(std::floor(x / cellSize_));
120 const int cy = static_cast<int>(std::floor(y / cellSize_));
121 queryCells(cx, cy, cx, cy, nullptr, x, y, 0.f, false, true);
122 return results_.getCount();
123}
124
125int SpatialHash2D::queryRect(float minX, float minY, float maxX, float maxY) {
126 AABB2 rect = makeAABB2(minX, minY, maxX, maxY);
127 int minCX, minCY, maxCX, maxCY;
128 cellRange(rect, minCX, minCY, maxCX, maxCY);
129 queryCells(minCX, minCY, maxCX, maxCY, &rect, 0.f, 0.f, 0.f, false, false);
130 return results_.getCount();
131}
132
133int SpatialHash2D::queryCircle(float cx, float cy, float radius) {
134 if (radius < 0.f) radius = 0.f;
135 AABB2 rect = makeAABB2(cx - radius, cy - radius, cx + radius, cy + radius);
136 int minCX, minCY, maxCX, maxCY;
137 cellRange(rect, minCX, minCY, maxCX, maxCY);
138 queryCells(minCX, minCY, maxCX, maxCY, nullptr, cx, cy, radius, true, false);
139 return results_.getCount();
140}
141
142} // namespace eve::spatial
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float cx
Definition CardTypes.cpp:33
float cy
Definition CardTypes.cpp:34
std::int32_t second
MeleePoint3 b
Definition MeleeHit.cpp:41
float radius
std::string id
Definition PlayHost.cpp:108
bool hit
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
void clear()
Removes all stored entries.
Definition QueryIds.h:14
void addUnchecked(int id)
Appends id without uniqueness checks.
Definition QueryIds.h:25
int getCount() const
Number of stored ids.
Definition QueryIds.h:28
void clear()
Removes all stored entries.
bool remove(int id)
Removes an item by id; false if unknown.
bool contains(int id) const
True if the id is currently stored.
bool update(int id, float minX, float minY, float maxX, float maxY)
Moves an existing item to a new AABB; false if unknown or out of bounds.
void setCellSize(float cellSize)
Sets cell size and clears existing entries.
SpatialHash2D(float cellSize=64.f)
Creates a 2D spatial hash with the given cell size.
int queryPoint(float x, float y)
Finds items overlapping a point; fills the result buffer.
int queryRect(float minX, float minY, float maxX, float maxY)
Finds items overlapping an AABB; fills the result buffer.
int queryCircle(float cx, float cy, float radius)
Finds items overlapping a circle; fills the result buffer.
bool insert(int id, float minX, float minY, float maxX, float maxY)
Inserts an item AABB; false if out of bounds or id already present.
AABB2 makeAABB2(float minX, float minY, float maxX, float maxY)
Builds a normalized 2D AABB (swaps inverted mins/maxes).
Definition Bounds.h:108
uint64_t cellKey2(int cx, int cy)
Integer cell key for spatial hashing (stable across platforms for reasonable ranges).
Definition Bounds.h:123
Axis-aligned 2D bounding box (min/max inclusive).
Definition Bounds.h:10
bool intersectsAABB(const AABB2 &o) const
True if the boxes overlap (inclusive edges).
Definition Bounds.h:39