1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
| #include <vector> #include <memory> #include <cmath>
struct Point { float x, y; };
class Quadtree { private: struct Node { float x, y, width; std::vector<Point> points; std::unique_ptr<Node> ne, nw, se, sw; Node(float x, float y, float width) : x(x), y(y), width(width), ne(nullptr), nw(nullptr), se(nullptr), sw(nullptr) {} ~Node() { ne.reset(); nw.reset(); se.reset(); sw.reset(); } bool insert(Node*& node, const Point& p, int depth) { if (!contains(node, p)) return false; if (node->points.size() < 4 && !node->ne) { node->points.push_back(p); return true; } if (!node->ne) { split(node); } if (insert(node->ne.get(), p, depth+1)) return true; if (insert(node->nw.get(), p, depth+1)) return true; if (insert(node->se.get(), p, depth+1)) return true; if (insert(node->sw.get(), p, depth+1)) return true; return false; } bool contains(Node* node, const Point& p) { return p.x >= node->x - node->width/2 && p.x <= node->x + node->width/2 && p.y >= node->y - node->width/2 && p.y <= node->y + node->width/2; } void split(Node* node) { float half = node->width / 2; node->ne = std::make_unique<Node>(node->x + half/2, node->y + half/2, half); node->nw = std::make_unique<Node>(node->x - half/2, node->y + half/2, half); node->se = std::make_unique<Node>(node->x + half/2, node->y - half/2, half); node->sw = std::make_unique<Node>(node->x - half/2, node->y - half/2, half); for (auto& p : node->points) { insert(node->ne.get(), p, 0); insert(node->nw.get(), p, 0); insert(node->se.get(), p, 0); insert(node->sw.get(), p, 0); } node->points.clear(); } std::vector<Point> query(Node* node, float minX, float maxX, float minY, float maxY) { std::vector<Point> result; if (!intersects(node, minX, maxX, minY, maxY)) return result; if (!node->ne) { for (auto& p : node->points) { if (p.x >= minX && p.x <= maxX && p.y >= minY && p.y <= maxY) { result.push_back(p); } } return result; } auto neRes = query(node->ne.get(), minX, maxX, minY, maxY); auto nwRes = query(node->nw.get(), minX, maxX, minY, maxY); auto seRes = query(node->se.get(), minX, maxX, minY, maxY); auto swRes = query(node->sw.get(), minX, maxX, minY, maxY); result.insert(result.end(), neRes.begin(), neRes.end()); result.insert(result.end(), nwRes.begin(), nwRes.end()); result.insert(result.end(), seRes.begin(), seRes.end()); result.insert(result.end(), swRes.begin(), swRes.end()); return result; } bool intersects(Node* node, float minX, float maxX, float minY, float maxY) { return !(maxX < node->x - node->width/2 || minX > node->x + node->width/2 || maxY < node->y - node->width/2 || minY > node->y + node->width/2); } }; std::unique_ptr<Node> root; int maxDepth; public: Quadtree(float rootX, float rootY, float rootWidth, int maxDepth = 16) : root(std::make_unique<Node>(rootX, rootY, rootWidth)), maxDepth(maxDepth) {} void insert(const Point& p) { root->insert(root.get(), p, 0); } std::vector<Point> query(float minX, float maxX, float minY, float maxY) { return root->query(root.get(), minX, maxX, minY, maxY); } };
|