Extra2D/Extra2D/include/extra2d/spatial/quadtree.h

71 lines
2.1 KiB
C++

#pragma once
#include <array>
#include <extra2d/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