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