Extra2D/include/spatial/spatial_hash.h

76 lines
2.2 KiB
C
Raw Normal View History

2026-02-11 19:40:26 +08:00
#pragma once
#include <spatial/spatial_index.h>
2026-02-11 19:40:26 +08:00
#include <unordered_map>
#include <vector>
namespace extra2d {
/**
* @brief -
* 使
*/
class SpatialHash : public ISpatialIndex {
public:
using CellKey = std::pair<int64_t, int64_t>;
struct CellKeyHash {
size_t operator()(const CellKey &key) const {
return std::hash<int64_t>()(key.first) ^
(std::hash<int64_t>()(key.second) << 1);
}
};
explicit SpatialHash(float cellSize = 64.0f);
~SpatialHash() override = default;
void insert(Node *node, const Rect &bounds) override;
void remove(Node *node) override;
void update(Node *node, const Rect &newBounds) override;
std::vector<Node *> query(const Rect &area) const override;
std::vector<Node *> query(const Vec2 &point) const override;
std::vector<std::pair<Node *, Node *>> queryCollisions() const override;
void clear() override;
size_t size() const override;
bool empty() const override;
void rebuild() override;
void setCellSize(float cellSize);
float getCellSize() const { return cellSize_; }
private:
/**
* @brief - 使vector代替unordered_set减少内存开销
*/
struct Cell {
std::vector<Node *> objects;
void insert(Node *node);
void remove(Node *node);
bool contains(Node *node) const;
void clear() { objects.clear(); }
size_t size() const { return objects.size(); }
bool empty() const { return objects.empty(); }
};
CellKey getCellKey(float x, float y) const;
void getCellsForRect(const Rect &rect, std::vector<CellKey> &cells) const;
void insertIntoCells(Node *node, const Rect &bounds);
void removeFromCells(Node *node, const Rect &bounds);
float cellSize_;
// 使用vector存储对象列表代替unordered_set内存更紧凑
std::unordered_map<CellKey, Cell, CellKeyHash> grid_;
std::unordered_map<Node *, Rect> objectBounds_;
size_t objectCount_ = 0;
// 查询用的临时缓冲区,避免重复分配
mutable std::vector<Node *> queryBuffer_;
mutable std::vector<std::pair<Node *, Node *>> collisionBuffer_;
};
} // namespace extra2d