Cogs.Core
Quadtree.cpp
1#include "Quadtree.h"
2
3#include "assert.h"
4
5int Cogs::Core::SeaCurrentQuadtree::getSubQuad(const QuadBounds& bounds, const glm::vec2& arrow) const
6{
7 glm::vec2 center = (bounds.min + bounds.max) * 0.5f;
8
9 if (arrow.x < center.x) // Left
10 {
11 if (arrow.y < center.y) // Bottom
12 return 0;
13 else
14 return 2; // Top
15 }
16 else // Right
17 {
18 if (arrow.y < center.y) // Bottom
19 return 1;
20 else
21 return 3; // Top
22 }
23}
24
25void Cogs::Core::SeaCurrentQuadtree::split(QuadNode* node)
26{
27 assert(node != nullptr);
28 assert(isLeaf(node) && "Error. Trying to split a non leaf node");
29
30 int i = 0;
31 // Create children
32 for (auto& child : node->mChildren)
33 {
34 child = std::make_unique<QuadNode>();
35 QuadBounds b = computeSubQuad(node->mBounds, i++);
36
37 child->mBounds = b;
38 }
39}
40
41void Cogs::Core::SeaCurrentQuadtree::clear(QuadNode * node)
42{
43 for (auto& child : node->mChildren)
44 {
45
46 if (child.get() != nullptr)
47 {
48 clear(child.get());
49 child.release();
50 }
51 }
52}
53
54Cogs::Core::QuadBounds Cogs::Core::SeaCurrentQuadtree::computeSubQuad(const QuadBounds& bounds, int i) const
55{
56 glm::vec2 center = (bounds.min + bounds.max) * 0.5f;
57 switch (i)
58 {
59 // Bot Left
60 case 0:
61 return QuadBounds{ bounds.min, center };
62 // Bot Right
63 case 1:
64 return QuadBounds{ glm::vec2(center.x, bounds.min.y), glm::vec2(bounds.max.x, center.y) };
65 // Top Left
66 case 2:
67 return QuadBounds{ glm::vec2(bounds.min.x, center.y), glm::vec2(center.x, bounds.max.y) };
68 // Top Right
69 case 3:
70 return QuadBounds{ center, bounds.max };
71 default:
72 return bounds;
73 }
74}
75
76void Cogs::Core::SeaCurrentQuadtree::insert(QuadNode* node, size_t depth, const glm::vec2& arrow)
77{
78 // What is a better policy, assert or log and return?
79 assert(node != nullptr);
80 if (node->mNearestArrow.x)
81 {
82 glm::vec2 center = (node->mBounds.min + node->mBounds.max) * 0.5f;
83 if (glm::distance(arrow, center) < glm::distance(node->mNearestArrow, center))
84 {
85 if (isLeaf(node))
86 split(node);
87
88 int id = getSubQuad(node->mBounds, node->mNearestArrow);
89 if (id != -1)
90 insert(node->mChildren[id].get(), depth + 1, node->mNearestArrow);
91
92 node->mNearestArrow = arrow;
93 }
94 else
95 {
96 if (isLeaf(node))
97 split(node);
98
99 int id = getSubQuad(node->mBounds, arrow);
100 if (id != -1)
101 insert(node->mChildren[id].get(), depth + 1, arrow);
102 }
103 }
104 else
105 {
106 node->mNearestArrow = arrow;
107 }
108}
109
110int Cogs::Core::SeaCurrentQuadtree::search(QuadNode* node, const glm::vec2& arrow, int priority) const
111{
112 assert(node != nullptr);
113
114 // Narrow down the search by checking bounds against the child nodes
115 int i = getSubQuad(node->mBounds, arrow);
116
117 if (i != -1 && node->mChildren[i].get())
118 return search(node->mChildren[i].get(), arrow, ++priority);
119 else // It is not contained within the children so it has to be in the current parent
120 {
121 return priority;
122 }
123}