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