Garfield++ 5.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
QuadTree.cc
Go to the documentation of this file.
2#include <iostream>
3
4namespace Garfield {
5
6std::vector<int> QuadTree::emptyBlock = {};
7
8QuadTree::QuadTree(const double x0, const double y0,
9 const double hx, const double hy)
10 : m_x0(x0), m_y0(y0), m_hx(hx), m_hy(hy) {
11 m_xmin = x0 - hx;
12 m_ymin = y0 - hy;
13 m_xmax = x0 + hx;
14 m_ymax = y0 + hy;
15
16 // Initially, there are no children.
17 for (size_t i = 0; i < 4; ++i) children[i] = nullptr;
18}
19
21 for (size_t i = 0; i < 4; ++i) delete children[i];
22}
23
24bool QuadTree::DoesBoxOverlap(const double bb[4]) const {
25 if (m_xmax < bb[0] || m_ymax < bb[1]) return false;
26 if (m_xmin > bb[2] || m_ymin > bb[3]) return false;
27 return true;
28}
29
30int QuadTree::GetQuadrant(const double x, const double y) const {
31 int quad = 0;
32 if (x >= m_x0) quad |= 2;
33 if (y >= m_y0) quad |= 1;
34 return quad;
35}
36
37bool QuadTree::IsLeafNode() const {
38 // We are a leaf if we have no children. Since we either have none or
39 // all, it is sufficient to just check the first.
40 return children[0] == nullptr;
41}
42
43void QuadTree::InsertMeshNode(const double x, const double y, const int index) {
44 // Check if it is a leaf node.
45 if (!IsLeafNode()) {
46 // We are at an interior node.
47 // Insert recursively into appropriate child quadrant.
48 int quad = GetQuadrant(x, y);
49 children[quad]->InsertMeshNode(x, y, index);
50 return;
51 }
52
53 // Add the new point if the block is not full.
54 if (nodes.size() < BlockCapacity) {
55 nodes.push_back(std::make_tuple(x, y, index));
56 return;
57 }
58 // Block is full, so we need to partition it.
59 // Split the current node and create new empty trees for each child.
60 for (int i = 0; i < 4; ++i) {
61 // Compute new bounding box for this child.
62 const double xi = m_x0 + m_hx * (i & 2 ? 0.5 : -0.5);
63 const double yi = m_y0 + m_hy * (i & 1 ? 0.5 : -0.5);
64 children[i] = new QuadTree(xi, yi, 0.5 * m_hx, 0.5 * m_hy);
65 }
66
67 // Move the mesh nodes from the partitioned node (now marked as interior) to
68 // its children.
69 while (!nodes.empty()) {
70 auto node = nodes.back();
71 nodes.pop_back();
72 const double xn = std::get<0>(node);
73 const double yn = std::get<1>(node);
74 const int quad = GetQuadrant(xn, yn);
75 children[quad]->InsertMeshNode(xn, yn, std::get<2>(node));
76 }
77 // Insert the new point in the appropriate octant.
78 children[GetQuadrant(x, y)]->InsertMeshNode(x, y, index);
79}
80
81void QuadTree::InsertMeshElement(const double bb[4], const int index) {
82 if (IsLeafNode()) {
83 // Add the element to the list of this quadrant.
84 elements.push_back(index);
85 return;
86 }
87 // Check which children overlap with the element's bounding box.
88 for (int i = 0; i < 4; ++i) {
89 if (!children[i]->DoesBoxOverlap(bb)) continue;
90 children[i]->InsertMeshElement(bb, index);
91 }
92}
93
94const std::vector<int>& QuadTree::GetElementsInBlock(const double x,
95 const double y) const {
96 const auto node = GetBlockFromPoint(x, y);
97 return node ? node->elements : emptyBlock;
98}
99
100const QuadTree* QuadTree::GetBlockFromPoint(
101 const double x, const double y) const {
102 if (x < m_xmin || x > m_xmax || y < m_ymin || y > m_ymax) {
103 return nullptr;
104 }
105 return GetBlockFromPointHelper(x, y);
106}
107
108const QuadTree* QuadTree::GetBlockFromPointHelper(
109 const double x, const double y) const {
110 // If we're at a leaf node, it means, the point is inside this block.
111 if (IsLeafNode()) return this;
112 // We are at the interior node, so check which child contains the point.
113 int quad = GetQuadrant(x, y);
114 return children[quad]->GetBlockFromPointHelper(x, y);
115}
116}
Quadtree search.
Definition QuadTree.hh:12
QuadTree(const double x0, const double y0, const double hx, const double hy)
Constructor.
Definition QuadTree.cc:8
void InsertMeshElement(const double bb[4], const int index)
Insert a mesh element with given bounding box and index to the tree.
Definition QuadTree.cc:81
void InsertMeshNode(const double x, const double y, const int index)
Insert a mesh node (a vertex/point) to the tree.
Definition QuadTree.cc:43
~QuadTree()
Destructor.
Definition QuadTree.cc:20
const std::vector< int > & GetElementsInBlock(const double x, const double y) const
Get all elements linked to a block corresponding to the given point.
Definition QuadTree.cc:94