71 lines
2.1 KiB
C++
71 lines
2.1 KiB
C++
#pragma once
|
|
|
|
#include <array>
|
|
#include <spatial/spatial_index.h>
|
|
|
|
namespace extra2d {
|
|
|
|
class QuadTree : public ISpatialIndex {
|
|
public:
|
|
static constexpr int MAX_OBJECTS = 10;
|
|
static constexpr int MAX_LEVELS = 5;
|
|
|
|
struct QuadTreeNode {
|
|
Rect bounds;
|
|
int level;
|
|
std::vector<std::pair<Node *, Rect>> objects;
|
|
std::array<std::unique_ptr<QuadTreeNode>, 4> children;
|
|
|
|
QuadTreeNode(const Rect &bounds, int level);
|
|
bool contains(const Rect &rect) const;
|
|
bool intersects(const Rect &rect) const;
|
|
};
|
|
|
|
explicit QuadTree(const Rect &worldBounds);
|
|
~QuadTree() 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;
|
|
|
|
private:
|
|
void split(QuadTreeNode *node);
|
|
void insertIntoNode(QuadTreeNode *node, Node *object, const Rect &bounds);
|
|
void queryNode(const QuadTreeNode *node, const Rect &area,
|
|
std::vector<Node *> &results) const;
|
|
void queryNode(const QuadTreeNode *node, const Vec2 &point,
|
|
std::vector<Node *> &results) const;
|
|
void
|
|
collectCollisions(const QuadTreeNode *node,
|
|
std::vector<std::pair<Node *, Node *>> &collisions) const;
|
|
bool removeFromNode(QuadTreeNode *node, Node *object);
|
|
|
|
/**
|
|
* @brief 使用扫描线算法检测节点内对象的碰撞
|
|
* @param objects 对象列表
|
|
* @param collisions 输出碰撞对
|
|
*/
|
|
void detectCollisionsInNode(
|
|
const std::vector<std::pair<Node *, Rect>> &objects,
|
|
std::vector<std::pair<Node *, Node *>> &collisions) const;
|
|
|
|
std::unique_ptr<QuadTreeNode> root_;
|
|
Rect worldBounds_;
|
|
size_t objectCount_ = 0;
|
|
|
|
// 碰撞检测用的临时缓冲区,避免重复分配
|
|
mutable std::vector<std::pair<Node *, Rect>> collisionBuffer_;
|
|
};
|
|
|
|
} // namespace extra2d
|