OGS
GeoLib::OctTree< POINT, MAX_POINTS > Class Template Reference

Detailed Description

template<typename POINT, std::size_t MAX_POINTS>
class GeoLib::OctTree< POINT, MAX_POINTS >
Template Parameters
POINTpoint data type the OctTree will use
MAX_POINTSmaximum number of pointers of POINT in a leaf

Definition at line 16 of file OctTree.h.

#include <OctTree.h>

Public Member Functions

virtual ~OctTree ()
bool addPoint (POINT *pnt, POINT *&ret_pnt)
template<typename T>
void getPointsInRange (T const &min, T const &max, std::vector< POINT * > &pnts) const
Eigen::Vector3d const & getLowerLeftCornerPoint () const
Eigen::Vector3d const & getUpperRightCornerPoint () const
OctTree< POINT, MAX_POINTS > const * getChild (std::size_t i) const
std::vector< POINT * > const & getPointVector () const

Static Public Member Functions

static OctTree< POINT, MAX_POINTS > * createOctTree (Eigen::Vector3d ll, Eigen::Vector3d ur, double eps=std::numeric_limits< double >::epsilon())

Private Types

enum class  Quadrant : std::int8_t {
  NEL = 0 , NWL , SWL , SEL ,
  NEU , NWU , SWU , SEU
}

Private Member Functions

 OctTree (Eigen::Vector3d const &ll, Eigen::Vector3d const &ur, double eps)
bool addPoint_ (POINT *pnt, POINT *&ret_pnt)
bool addPointToChild (POINT *pnt)
void splitNode (POINT *pnt)
bool isOutside (POINT *pnt) const
template<typename T>
void getPointsInRange_ (T const &min, T const &max, std::vector< POINT * > &pnts) const

Private Attributes

std::array< OctTree< POINT, MAX_POINTS > *, 8 > _children
Eigen::Vector3d const _ll
 lower left front face point of the cube
Eigen::Vector3d const _ur
 upper right back face point of the cube
std::vector< POINT * > _pnts
 vector of pointers to POINT objects
bool _is_leaf
 flag if this OctTree is a leaf
double const _eps
 threshold for point uniqueness

Member Enumeration Documentation

◆ Quadrant

template<typename POINT, std::size_t MAX_POINTS>
enum class GeoLib::OctTree::Quadrant : std::int8_t
strongprivate
Enumerator
NEL 

north east lower

NWL 

north west lower

SWL 

south west lower

SEL 

south east lower

NEU 

south west upper

NWU 

south west upper

SWU 

south west upper

SEU 

south east upper

Definition at line 82 of file OctTree.h.

83 {
84 NEL = 0,
85 NWL,
86 SWL,
87 SEL,
88 NEU,
89 NWU,
90 SWU,
91 SEU
92 };

Constructor & Destructor Documentation

◆ ~OctTree()

template<typename POINT, std::size_t MAX_POINTS>
GeoLib::OctTree< POINT, MAX_POINTS >::~OctTree ( )
virtual

Destroys the children of this node.

Attention
Does not destroy the pointers to the managed objects.

Definition at line 59 of file OctTree-impl.h.

60{
61 for (auto c : _children)
62 {
63 delete c;
64 }
65}
std::array< OctTree< POINT, MAX_POINTS > *, 8 > _children
Definition OctTree.h:134

References _children.

◆ OctTree()

template<typename POINT, std::size_t MAX_POINTS>
GeoLib::OctTree< POINT, MAX_POINTS >::OctTree ( Eigen::Vector3d const & ll,
Eigen::Vector3d const & ur,
double eps )
private

private constructor

Parameters
lllower left point
urupper right point
epsthe euclidean distance as a threshold to make objects unique

Definition at line 187 of file OctTree-impl.h.

189 : _ll(ll), _ur(ur), _is_leaf(true), _eps(eps)
190{
191 _children.fill(nullptr);
192}
Eigen::Vector3d const _ur
upper right back face point of the cube
Definition OctTree.h:138
bool _is_leaf
flag if this OctTree is a leaf
Definition OctTree.h:142
double const _eps
threshold for point uniqueness
Definition OctTree.h:144
Eigen::Vector3d const _ll
lower left front face point of the cube
Definition OctTree.h:136

References _children, _eps, _is_leaf, _ll, and _ur.

Referenced by createOctTree(), getChild(), and splitNode().

Member Function Documentation

◆ addPoint()

template<typename POINT, std::size_t MAX_POINTS>
bool GeoLib::OctTree< POINT, MAX_POINTS >::addPoint ( POINT * pnt,
POINT *& ret_pnt )

This method adds the given point to the OctTree. If necessary, new OctTree nodes will be inserted deploying a split of the corresponding OctTree node.

Parameters
pntthe pointer to a point that should be inserted
ret_pntthe pointer to a point in the OctTree. Three cases can occur: (1) ret_pnt is nullptr: the given point (pnt) is outside of the OctTree domain (2) ret_pnt is equal to pnt: the point is added to the OctTree (3) In case ret_pnt is neither equal to pnt nor equal to nullptr, another item within the eps distance is already in the OctTree and the pointer to this object is returned.
Returns
If the point can be inserted the method returns true, else false.

Definition at line 68 of file OctTree-impl.h.

69{
70 // first do a range query using a small box around the point pnt
72 Eigen::Vector3d const min = pnt->asEigenVector3d().array() - _eps;
73 Eigen::Vector3d const max = {
74 std::abs(((*pnt)[0] + _eps) - (*pnt)[0]) > 0.0
75 ? (*pnt)[0] + _eps
76 : std::nextafter((*pnt)[0],
78 std::abs(((*pnt)[1] + _eps) - (*pnt)[1]) > 0.0
79 ? (*pnt)[1] + _eps
80 : std::nextafter((*pnt)[1],
82 std::abs(((*pnt)[2] + _eps) - (*pnt)[2]) > 0.0
83 ? (*pnt)[2] + _eps
84 : std::nextafter((*pnt)[2],
87 auto const it =
88 std::find_if(query_pnts.begin(), query_pnts.end(),
89 [pnt, this](auto const* p)
90 {
91 return (p->asEigenVector3d() - pnt->asEigenVector3d())
92 .squaredNorm() < _eps * _eps;
93 });
94 if (it != query_pnts.end())
95 {
96 ret_pnt = *it;
97 return false;
98 }
99
100 // the point pnt is not yet in the OctTree
101 if (isOutside(pnt))
102 {
103 ret_pnt = nullptr;
104 return false;
105 }
106
107 // at this place it holds true that the point is within [_ll, _ur]
108 if (!_is_leaf)
109 {
110 for (auto c : _children)
111 {
112 if (c->addPoint_(pnt, ret_pnt))
113 {
114 return true;
115 }
116 if (ret_pnt != nullptr)
117 {
118 return false;
119 }
120 }
121 }
122
123 ret_pnt = pnt;
124
125 if (_pnts.size() < MAX_POINTS)
126 {
127 _pnts.push_back(pnt);
128 }
129 else
130 { // i.e. _pnts.size () == MAX_POINTS
131 splitNode(pnt);
132 _pnts.clear();
133 }
134 return true;
135}
bool addPoint_(POINT *pnt, POINT *&ret_pnt)
void splitNode(POINT *pnt)
void getPointsInRange(T const &min, T const &max, std::vector< POINT * > &pnts) const
std::vector< POINT * > _pnts
vector of pointers to POINT objects
Definition OctTree.h:140
bool isOutside(POINT *pnt) const

References _children, _eps, _is_leaf, _pnts, getPointsInRange(), isOutside(), GeoLib::POINT, and splitNode().

Referenced by makeNodesUnique(), and resetNodesInRegularElements().

◆ addPoint_()

template<typename POINT, std::size_t MAX_POINTS>
bool GeoLib::OctTree< POINT, MAX_POINTS >::addPoint_ ( POINT * pnt,
POINT *& ret_pnt )
private

This method tries to add the given point to the OctTree. If necessary for adding the point, new nodes will be inserted into the OctTree.

Parameters
pnt,ret_pntsee documentation of addPoint()
Returns
If the point can be inserted the method returns true, else false.

Definition at line 195 of file OctTree-impl.h.

196{
197 if (isOutside(pnt))
198 {
199 ret_pnt = nullptr;
200 return false;
201 }
202
203 // at this place it holds true that the point is within [_ll, _ur]
204 if (!_is_leaf)
205 {
206 for (auto c : _children)
207 {
208 if (c->addPoint_(pnt, ret_pnt))
209 {
210 return true;
211 }
212 if (ret_pnt != nullptr)
213 {
214 return false;
215 }
216 }
217 }
218
219 ret_pnt = pnt;
220 if (_pnts.size() < MAX_POINTS)
221 {
222 _pnts.push_back(pnt);
223 }
224 else
225 { // i.e. _pnts.size () == MAX_POINTS
226 splitNode(pnt);
227 _pnts.clear();
228 }
229 return true;
230}

References _children, _is_leaf, _pnts, isOutside(), GeoLib::POINT, and splitNode().

◆ addPointToChild()

template<typename POINT, std::size_t MAX_POINTS>
bool GeoLib::OctTree< POINT, MAX_POINTS >::addPointToChild ( POINT * pnt)
private

This method adds the given point to the OctTree. If necessary, the OctTree will be extended.

Parameters
pntthe point
Returns
If the point can be inserted the method returns true, else false.

Definition at line 233 of file OctTree-impl.h.

234{
235 if (isOutside(pnt))
236 {
237 return false;
238 }
239
240 if (_pnts.size() < MAX_POINTS)
241 {
242 _pnts.push_back(pnt);
243 }
244 else
245 { // i.e. _pnts.size () == MAX_POINTS
246 splitNode(pnt);
247 _pnts.clear();
248 }
249 return true;
250}

References _pnts, isOutside(), GeoLib::POINT, and splitNode().

Referenced by splitNode().

◆ createOctTree()

template<typename POINT, std::size_t MAX_POINTS>
OctTree< POINT, MAX_POINTS > * GeoLib::OctTree< POINT, MAX_POINTS >::createOctTree ( Eigen::Vector3d ll,
Eigen::Vector3d ur,
double eps = std::numeric_limits<double>::epsilon() )
static

Create an OctTree object. The arguments ll and ur are used to compute a cube domain the OctTree will living in.

Attention
This cubic domain can not be resized during the life time of the OctTree.
Parameters
lllower left front point, used for computation of cubic domain
urupper right back point, used for computation of cubic domain
epsthe euclidean distance as a threshold to make objects unique [default std::numeric_limits<double>::epsilon()] Adding a new item to an already "filled" OctTree node results in a split of the OctTree node. The smaller this number is the more leaves the OctTree will have, i.e. it needs more memory and more time to walk through the OctTree, but the search inside a leaf is fast. In contrast a big value results into a smaller number of OctTree leaves, the memory requirements for the OctTree may be lower but the search inside a OctTree leaf may be more expensive. The value should be chosen application dependent. [default 8]

Definition at line 7 of file OctTree-impl.h.

9{
10 // compute an axis aligned cube around the points ll and ur
11 const double dx(ur[0] - ll[0]);
12 const double dy(ur[1] - ll[1]);
13 const double dz(ur[2] - ll[2]);
14 if (dx >= dy && dx >= dz)
15 {
16 ll[1] -= (dx - dy) / 2.0;
17 ur[1] += (dx - dy) / 2.0;
18 ll[2] -= (dx - dz) / 2.0;
19 ur[2] += (dx - dz) / 2.0;
20 }
21 else
22 {
23 if (dy >= dx && dy >= dz)
24 {
25 ll[0] -= (dy - dx) / 2.0;
26 ur[0] += (dy - dx) / 2.0;
27 ll[2] -= (dy - dz) / 2.0;
28 ur[2] += (dy - dz) / 2.0;
29 }
30 else
31 {
32 ll[0] -= (dz - dx) / 2.0;
33 ur[0] += (dz - dx) / 2.0;
34 ll[1] -= (dz - dy) / 2.0;
35 ur[1] += (dz - dy) / 2.0;
36 }
37 }
38 if (eps == 0.0)
39 {
41 }
42 for (std::size_t k(0); k < 3; ++k)
43 {
44 if (ur[k] - ll[k] > 0.0)
45 {
46 ur[k] += (ur[k] - ll[k]) * 1e-6;
47 }
48 else
49 {
50 ur[k] += eps;
51 }
52 }
53 Eigen::Vector3d lower_left{ll[0], ll[1], ll[2]};
56}
OctTree(Eigen::Vector3d const &ll, Eigen::Vector3d const &ur, double eps)

References OctTree().

Referenced by mergeSubdomainMeshes(), MeshToolsLib::partitionNodesByCoordinateMatch(), GeoLib::PointVec::resetInternalDataStructures(), and GeoLib::PointVec::uniqueInsert().

◆ getChild()

template<typename POINT, std::size_t MAX_POINTS>
OctTree< POINT, MAX_POINTS > const * GeoLib::OctTree< POINT, MAX_POINTS >::getChild ( std::size_t i) const
inline

Definition at line 68 of file OctTree.h.

69 {
70 return _children[i];
71 }

References OctTree(), and _children.

◆ getLowerLeftCornerPoint()

template<typename POINT, std::size_t MAX_POINTS>
Eigen::Vector3d const & GeoLib::OctTree< POINT, MAX_POINTS >::getLowerLeftCornerPoint ( ) const
inline

Definition at line 66 of file OctTree.h.

66{ return _ll; }

References _ll.

◆ getPointsInRange()

template<typename POINT, std::size_t MAX_POINTS>
template<typename T>
void GeoLib::OctTree< POINT, MAX_POINTS >::getPointsInRange ( T const & min,
T const & max,
std::vector< POINT * > & pnts ) const

range query - returns all points inside the range [min[0], max[0]) x [min[1], max[1]) x [min[2], max[2])

Definition at line 139 of file OctTree-impl.h.

141{
142 if (max[0] == min[0] || max[1] == min[1] || max[2] == min[2])
143 {
144 ERR("The search range [{}, {}) x [{}, {}) x [{}, {}) is empty.", min[0],
145 max[0], min[1], max[1], min[2], max[2]);
146 return;
147 }
148
149 return getPointsInRange_(min, max, pnts);
150}
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
void getPointsInRange_(T const &min, T const &max, std::vector< POINT * > &pnts) const

References ERR(), and getPointsInRange_().

Referenced by addPoint(), and getExistingNodeFromOctTree().

◆ getPointsInRange_()

template<typename POINT, std::size_t MAX_POINTS>
template<typename T>
void GeoLib::OctTree< POINT, MAX_POINTS >::getPointsInRange_ ( T const & min,
T const & max,
std::vector< POINT * > & pnts ) const
private

range query - returns all points inside the range [min[0], max[0]) x [min[1], max[1]) x [min[2], max[2])

Definition at line 154 of file OctTree-impl.h.

156{
157 if (_ur[0] < min[0] || _ur[1] < min[1] || _ur[2] < min[2])
158 {
159 return;
160 }
161
162 if (max[0] < _ll[0] || max[1] < _ll[1] || max[2] < _ll[2])
163 {
164 return;
165 }
166
167 if (_is_leaf)
168 {
170 [&min, &max](auto const* p)
171 {
172 return (min[0] <= (*p)[0] && (*p)[0] < max[0] &&
173 min[1] <= (*p)[1] && (*p)[1] < max[1] &&
174 min[2] <= (*p)[2] && (*p)[2] < max[2]);
175 });
176 }
177 else
178 {
179 for (std::size_t k(0); k < 8; k++)
180 {
181 _children[k]->getPointsInRange_(min, max, pnts);
182 }
183 }
184}

References _children, _is_leaf, _ll, _pnts, and _ur.

Referenced by getPointsInRange().

◆ getPointVector()

template<typename POINT, std::size_t MAX_POINTS>
std::vector< POINT * > const & GeoLib::OctTree< POINT, MAX_POINTS >::getPointVector ( ) const
inline

Definition at line 72 of file OctTree.h.

72{ return _pnts; }

References _pnts.

◆ getUpperRightCornerPoint()

template<typename POINT, std::size_t MAX_POINTS>
Eigen::Vector3d const & GeoLib::OctTree< POINT, MAX_POINTS >::getUpperRightCornerPoint ( ) const
inline

Definition at line 67 of file OctTree.h.

67{ return _ur; }

References _ur.

◆ isOutside()

template<typename POINT, std::size_t MAX_POINTS>
bool GeoLib::OctTree< POINT, MAX_POINTS >::isOutside ( POINT * pnt) const
private

checks if the given point pnt is outside of the OctTree node.

Parameters
pntthe point that check is performed on
Returns
true if the point is outside of the OctTree node.

Definition at line 335 of file OctTree-impl.h.

336{
337 if ((*pnt)[0] < _ll[0] || (*pnt)[1] < _ll[1] || (*pnt)[2] < _ll[2])
338 {
339 return true;
340 }
341 if ((*pnt)[0] >= _ur[0] || (*pnt)[1] >= _ur[1] || (*pnt)[2] >= _ur[2])
342 {
343 return true;
344 }
345 return false;
346}

References _ll, _ur, and GeoLib::POINT.

Referenced by addPoint(), addPoint_(), and addPointToChild().

◆ splitNode()

template<typename POINT, std::size_t MAX_POINTS>
void GeoLib::OctTree< POINT, MAX_POINTS >::splitNode ( POINT * pnt)
private

Creates the child nodes of this leaf and distribute the points stored in _pnts to the children.

Parameters
pntthe pointer to the points that is responsible for the split

Definition at line 253 of file OctTree-impl.h.

254{
255 const double x_mid((_ur[0] + _ll[0]) / 2.0);
256 const double y_mid((_ur[1] + _ll[1]) / 2.0);
257 const double z_mid((_ur[2] + _ll[2]) / 2.0);
259 Eigen::Vector3d p1{_ur[0], _ur[1], z_mid};
260
261 // create child NEL
262 _children[static_cast<std::int8_t>(Quadrant::NEL)] =
264
265 // create child NWL
266 p0[0] = _ll[0];
267 p1[0] = x_mid;
268 _children[static_cast<std::int8_t>(Quadrant::NWL)] =
270
271 // create child SWL
272 p0[1] = _ll[1];
273 p1[1] = y_mid;
274 _children[static_cast<std::int8_t>(Quadrant::SWL)] =
276
277 // create child NEU
278 _children[static_cast<std::int8_t>(Quadrant::NEU)] =
280
281 // create child SEL
282 p0[0] = x_mid;
283 p1[0] = _ur[0];
284 _children[static_cast<std::int8_t>(Quadrant::SEL)] =
286
287 // create child NWU
288 p0[0] = _ll[0];
289 p0[1] = y_mid;
290 p0[2] = z_mid;
291 p1[0] = x_mid;
292 p1[1] = _ur[1];
293 p1[2] = _ur[2];
294 _children[static_cast<std::int8_t>(Quadrant::NWU)] =
296
297 // create child SWU
298 p0[1] = _ll[1];
299 p1[1] = y_mid;
300 _children[static_cast<std::int8_t>(Quadrant::SWU)] =
302
303 // create child SEU
304 p0[0] = x_mid;
305 p1[0] = _ur[0];
306 p1[1] = y_mid;
307 p1[2] = _ur[2];
308 _children[static_cast<std::int8_t>(Quadrant::SEU)] =
310
311 // add the passed point pnt to the children at first
312 for (std::size_t k(0); k < 8; k++)
313 {
315 {
316 break;
317 }
318 }
319
320 // distribute points to sub quadtrees
321 const std::size_t n_pnts(_pnts.size());
322 for (std::size_t j(0); j < n_pnts; j++)
323 {
325 [&](auto* child)
326 { return child->addPointToChild(_pnts[j]); }))
327 {
328 continue;
329 }
330 }
331 _is_leaf = false;
332}
bool addPointToChild(POINT *pnt)
@ NEU
south west upper
Definition OctTree.h:88
@ NEL
north east lower
Definition OctTree.h:84
@ SWU
south west upper
Definition OctTree.h:90
@ SEU
south east upper
Definition OctTree.h:91
@ NWL
north west lower
Definition OctTree.h:85
@ SWL
south west lower
Definition OctTree.h:86
@ NWU
south west upper
Definition OctTree.h:89
@ SEL
south east lower
Definition OctTree.h:87

References OctTree(), _children, _eps, _is_leaf, _ll, _pnts, _ur, addPointToChild(), NEL, NEU, NWL, NWU, GeoLib::POINT, SEL, SEU, SWL, and SWU.

Referenced by addPoint(), addPoint_(), and addPointToChild().

Member Data Documentation

◆ _children

template<typename POINT, std::size_t MAX_POINTS>
std::array<OctTree<POINT, MAX_POINTS>*, 8> GeoLib::OctTree< POINT, MAX_POINTS >::_children
private

children are sorted: _children[0] is north east lower child _children[1] is north west lower child _children[2] is south west lower child _children[3] is south east lower child _children[4] is north east upper child _children[5] is north west upper child _children[6] is south west upper child _children[7] is south east upper child

Definition at line 134 of file OctTree.h.

Referenced by OctTree(), ~OctTree(), addPoint(), addPoint_(), getChild(), getPointsInRange_(), and splitNode().

◆ _eps

template<typename POINT, std::size_t MAX_POINTS>
double const GeoLib::OctTree< POINT, MAX_POINTS >::_eps
private

threshold for point uniqueness

Definition at line 144 of file OctTree.h.

Referenced by OctTree(), addPoint(), and splitNode().

◆ _is_leaf

template<typename POINT, std::size_t MAX_POINTS>
bool GeoLib::OctTree< POINT, MAX_POINTS >::_is_leaf
private

flag if this OctTree is a leaf

Definition at line 142 of file OctTree.h.

Referenced by OctTree(), addPoint(), addPoint_(), getPointsInRange_(), and splitNode().

◆ _ll

template<typename POINT, std::size_t MAX_POINTS>
Eigen::Vector3d const GeoLib::OctTree< POINT, MAX_POINTS >::_ll
private

lower left front face point of the cube

Definition at line 136 of file OctTree.h.

Referenced by OctTree(), getLowerLeftCornerPoint(), getPointsInRange_(), isOutside(), and splitNode().

◆ _pnts

template<typename POINT, std::size_t MAX_POINTS>
std::vector<POINT*> GeoLib::OctTree< POINT, MAX_POINTS >::_pnts
private

vector of pointers to POINT objects

Definition at line 140 of file OctTree.h.

Referenced by addPoint(), addPoint_(), addPointToChild(), getPointsInRange_(), getPointVector(), and splitNode().

◆ _ur

template<typename POINT, std::size_t MAX_POINTS>
Eigen::Vector3d const GeoLib::OctTree< POINT, MAX_POINTS >::_ur
private

upper right back face point of the cube

Definition at line 138 of file OctTree.h.

Referenced by OctTree(), getPointsInRange_(), getUpperRightCornerPoint(), isOutside(), and splitNode().


The documentation for this class was generated from the following files: