Skip to content

Commit ea3b138

Browse files
authored
Merge pull request #7 from src-lua/patch-3
Implement Quadtree structure with geometric shapes
2 parents 566f7b9 + 688f48e commit ea3b138

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed

Library/Geometry/quadtree.cpp

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#include <bits/stdc++.h> //LATEX_IGNORED_LINE
2+
using namespace std;
3+
4+
const int MXN = 1e5+100;
5+
6+
struct Point {
7+
int x, y;
8+
9+
bool const operator<(const Point& o) const {
10+
return make_tuple(x, y) < make_tuple(o.x, o.y);
11+
}
12+
};
13+
14+
struct AABB {
15+
int x1, y1, x2, y2;
16+
17+
AABB() : x1(0), y1(0), x2(MXN), y2(MXN) {}
18+
AABB(int x1, int y1, int x2, int y2) : x1(x1), y1(y1), x2(x2), y2(y2) {}
19+
20+
bool intersects(const AABB& other) const {
21+
bool overlap_x = (x1 <= other.x2) && (x2 >= other.x1);
22+
bool overlap_y = (y1 <= other.y2) && (y2 >= other.y1);
23+
return overlap_x && overlap_y;
24+
}
25+
26+
bool contains(int x, int y) const {
27+
return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
28+
}
29+
30+
array<AABB, 4> subdivide() const {
31+
int x_center = x1 + (x2 - x1) / 2;
32+
int y_center = y1 + (y2 - y1) / 2;
33+
return {
34+
AABB{x1, y1, x_center, y_center}, // NW
35+
AABB{x_center, y1, x2, y_center}, // NE
36+
AABB{x1, y_center, x_center, y2}, // SW
37+
AABB{x_center, y_center, x2, y2} // SE
38+
};
39+
}
40+
};
41+
42+
43+
struct Circle {
44+
Point c;
45+
int r, w;
46+
AABB box;
47+
48+
Circle(Point c, int r, int w)
49+
: c(c), r(r), w(w), box(c.x - r, c.y - r, c.x + r, c.y + r) {}
50+
51+
bool const operator<(const Circle& o) const {
52+
return make_tuple(c.x, c.y, r) < make_tuple(o.c.x, o.c.y, o.r);
53+
}
54+
};
55+
56+
struct Square {
57+
Point p1, p2;
58+
int w;
59+
AABB box;
60+
61+
Square(Point p1, Point p2)
62+
: p1(p1), p2(p2), box(min(p1.x, p2.x), min(p1.y, p2.y),
63+
max(p1.x, p2.x), max(p1.y, p2.y)) {}
64+
65+
bool const operator<(const Square& o) const {
66+
return make_tuple(p1, p2) < make_tuple(o.p1, o.p2);
67+
}
68+
};
69+
70+
struct Triangle {
71+
Point p1, p2, p3;
72+
int w;
73+
AABB box;
74+
75+
Triangle(Point p1, Point p2, Point p3)
76+
: p1(p1), p2(p2), p3(p3),
77+
box(min({p1.x, p2.x, p3.x}), min({p1.y, p2.y, p3.y}), max({p1.x, p2.x, p3.x}), max({p1.y, p2.y, p3.y})) {}
78+
79+
bool const operator<(const Triangle& o) const {
80+
return make_tuple(p1, p2, p3) < make_tuple(o.p1, o.p2, o.p3);
81+
}
82+
};
83+
84+
template <typename T>
85+
class Quadtree {
86+
public:
87+
static const int MIN_OBJECTS = 8;
88+
static const int MAX_DEPTH = 16;
89+
90+
Quadtree(const AABB& root_bounds, const vector<T>& all_objects)
91+
: bounds(root_bounds), depth(0) {
92+
93+
vector<const T*> object_ptrs;
94+
object_ptrs.reserve(all_objects.size());
95+
for (const auto& obj : all_objects) {
96+
object_ptrs.push_back(&obj);
97+
}
98+
99+
build(object_ptrs);
100+
}
101+
102+
const vector<const T*>& query(int x, int y) const {
103+
const Quadtree* node = this;
104+
105+
while (node->is_branch) {
106+
int child_index = node->get_child_index(x, y);
107+
if (child_index == -1) break;
108+
node = node->children[child_index].get();
109+
}
110+
111+
return node->objects;
112+
}
113+
114+
private:
115+
AABB bounds;
116+
int depth;
117+
bool is_branch = false;
118+
int x_center, y_center;
119+
120+
array<unique_ptr<Quadtree<T>>, 4> children;
121+
122+
vector<const T*> objects;
123+
124+
Quadtree(const AABB& box, int d) : bounds(box), depth(d) {}
125+
126+
void build(const vector<const T*>& parent_objects) {
127+
x_center = bounds.x1 + (bounds.x2 - bounds.x1) / 2;
128+
y_center = bounds.y1 + (bounds.y2 - bounds.y1) / 2;
129+
130+
for (const T* obj : parent_objects) {
131+
if (bounds.intersects(obj->box)) {
132+
objects.push_back(obj);
133+
}
134+
}
135+
136+
if (objects.size() > MIN_OBJECTS && depth < MAX_DEPTH) {
137+
is_branch = true;
138+
auto child_bounds = bounds.subdivide();
139+
140+
for (int i = 0; i < 4; ++i) {
141+
children[i] = unique_ptr<Quadtree<T>>(new Quadtree<T>(child_bounds[i], depth + 1));
142+
children[i]->build(objects);
143+
}
144+
145+
objects.clear();
146+
}
147+
}
148+
149+
int get_child_index(int x, int y) const {
150+
if (y <= y_center) return (x <= x_center) ? 0 : 1; // 0 (NW) ou 1 (NE)
151+
else return (x <= x_center) ? 2 : 3; // 2 (SW) ou 3 (SE)
152+
}
153+
};

0 commit comments

Comments
 (0)