Garfield++ 3.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
TetrahedralTree.cc
Go to the documentation of this file.
2#include <iostream>
3
4namespace Garfield {
5
6/**
7TetrahedralTree.cc
8This class stores the mesh nodes and elements in an Octree data
9structure to optimize the element search operations
10
11Author: Ali Sheharyar
12Organization: Texas A&M University at Qatar
13*/
14TetrahedralTree::TetrahedralTree(const Vec3& origin, const Vec3& halfDimension)
15 : m_origin(origin), m_halfDimension(halfDimension) {
16 min.x = origin.x - halfDimension.x;
17 min.y = origin.y - halfDimension.y;
18 min.z = origin.z - halfDimension.z;
19 max.x = origin.x + halfDimension.x;
20 max.y = origin.y + halfDimension.y;
21 max.z = origin.z + halfDimension.z;
22
23 // Initially, there are no children
24 for (int i = 0; i < 8; ++i) children[i] = nullptr;
25}
26
28 // Recursively destroy octants
29 for (int i = 0; i < 8; ++i) delete children[i];
30}
31
32// Check if a box specified as two min/max points overlap
33bool TetrahedralTree::DoesBoxOverlap(const Vec3& b_min,
34 const Vec3& b_max) const {
35 if (max.x < b_min.x) return false; // this box is left of the input box
36 if (max.y < b_min.y) return false; // this box is below the input box
37 if (max.z < b_min.z) return false; // this box is behind the input box
38 if (min.x > b_max.x) return false; // this box is right of the input
39 if (min.y > b_max.y) return false; // this box is above the input
40 if (min.z > b_max.z) return false; // this in front of the input
41
42 return true;
43}
44
45// Determine which octant of the tree would contain 'point'
46int TetrahedralTree::GetOctantContainingPoint(const Vec3& point) const {
47 int oct = 0;
48 if (point.x >= m_origin.x) oct |= 4;
49 if (point.y >= m_origin.y) oct |= 2;
50 if (point.z >= m_origin.z) oct |= 1;
51 return oct;
52}
53
54bool TetrahedralTree::IsFull() const {
55 // the block size cannot be more the the block capacity
56 return iBlockElems.size() == BLOCK_CAPACITY;
57}
58
59bool TetrahedralTree::IsEmpty() const { return iBlockElems.size() == 0; }
60
61bool TetrahedralTree::IsLeafNode() const {
62 // We are a leaf if we have no children. Since we either have none, or
63 // all eight, it is sufficient to just check the first.
64 return children[0] == nullptr; // || (!block && block->isFull());
65}
66
67void TetrahedralTree::InsertMeshNode(Vec3 point, int nodeIndex) {
68 // check if it is a leaf node
69 if (IsLeafNode()) {
70 // add the new point if the block is not full
71 if (!this->IsFull()) {
72 iBlockElems.push_back(OctreeBlockElem(point, nodeIndex));
73 } else {
74 // block is full, so we need to partition it.
75 // Split the current node and create new empty trees for each
76 // child octant.
77 for (int i = 0; i < 8; ++i) {
78 // Compute new bounding box for this child
79 Vec3 newOrigin = m_origin;
80 newOrigin.x += m_halfDimension.x * (i & 4 ? .5f : -.5f);
81 newOrigin.y += m_halfDimension.y * (i & 2 ? .5f : -.5f);
82 newOrigin.z += m_halfDimension.z * (i & 1 ? .5f : -.5f);
83 children[i] = new TetrahedralTree(newOrigin, m_halfDimension * .5f);
84 }
85
86 // move the nodes from the partitioned node (now marked as interior) to
87 // its children
88 while (!this->IsEmpty()) {
89 OctreeBlockElem bElem = iBlockElems.back();
90 iBlockElems.pop_back();
91 int octant = GetOctantContainingPoint(bElem.point);
92 children[octant]->InsertMeshNode(bElem.point, bElem.nodeIndex);
93 }
94
95 // insert the new node in the appropriate octant
96 children[GetOctantContainingPoint(point)]->InsertMeshNode(point,
97 nodeIndex);
98 }
99 } else {
100 // We are at an interior node. Insert recursively into the
101 // appropriate child octant
102 int octant = GetOctantContainingPoint(point);
103 children[octant]->InsertMeshNode(point, nodeIndex);
104 }
105}
106
107void TetrahedralTree::InsertTetrahedron(const double elemBoundingBox[6],
108 const int elemIndex) {
109 if (IsLeafNode()) {
110 // add the element to the list of this octant
111 tetList.push_back(elemIndex);
112 } else {
113 // check which child overlaps with the element's bounding box
114 for (int i = 0; i < 8; i++) {
115 Vec3 elem_min(elemBoundingBox[0], elemBoundingBox[1], elemBoundingBox[2]);
116 Vec3 elem_max(elemBoundingBox[3], elemBoundingBox[4], elemBoundingBox[5]);
117
118 if (children[i]->DoesBoxOverlap(elem_min, elem_max))
119 children[i]->InsertTetrahedron(elemBoundingBox, elemIndex);
120 }
121 }
122}
123
124// It returns the list of tetrahedrons that intersects in a bounding box (Octree
125// block) that contains the
126// point passed as input.
127std::vector<int> TetrahedralTree::GetTetListInBlock(const Vec3& point) {
128 const TetrahedralTree* octreeNode = GetBlockFromPoint(point);
129
130 if (octreeNode) {
131 return octreeNode->tetList;
132 }
133
134 return std::vector<int>();
135}
136
137// check if the point is inside the domain.
138// This function is only executed at root to ensure that input point is inside
139// the mesh's bounding box
140// If we don't check this, the case when root is leaf node itself will return
141// wrong block
142const TetrahedralTree* TetrahedralTree::GetBlockFromPoint(const Vec3& point) {
143 if (!(m_origin.x - m_halfDimension.x <= point.x &&
144 point.x <= m_origin.x + m_halfDimension.x &&
145 m_origin.y - m_halfDimension.y <= point.y &&
146 point.y <= m_origin.y + m_halfDimension.y &&
147 m_origin.z - m_halfDimension.z <= point.z &&
148 point.z <= m_origin.z + m_halfDimension.z))
149 return nullptr;
150
151 return GetBlockFromPointHelper(point);
152}
153
154const TetrahedralTree* TetrahedralTree::GetBlockFromPointHelper(
155 const Vec3& point) {
156 // If we're at a leaf node, it means, the point is inside this block
157 if (IsLeafNode()) return this;
158 // We are at the interior node, so check which child octant contains the
159 // point
160 int octant = GetOctantContainingPoint(point);
161 return children[octant]->GetBlockFromPointHelper(point);
162}
163}
#define BLOCK_CAPACITY
Helper class for searches in field maps.
std::vector< int > GetTetListInBlock(const Vec3 &point)
void InsertTetrahedron(const double elemBoundingBox[6], const int elemIndex)
TetrahedralTree(const Vec3 &origin, const Vec3 &halfDimension)
void InsertMeshNode(Vec3 point, const int nodeIndex)