Loading [MathJax]/extensions/tex2jax.js
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 27 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 93 of file OctTree.h.

94 {
95 NEL = 0,
96 NWL,
97 SWL,
98 SEL,
99 NEU,
100 NWU,
101 SWU,
102 SEU
103 };
@ NEU
south west upper
@ NEL
north east lower
@ SWU
south west upper
@ SEU
south east upper
@ NWL
north west lower
@ SWL
south west lower
@ NWU
south west upper
@ SEL
south east lower

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 68 of file OctTree-impl.h.

69{
70 for (auto c : _children)
71 {
72 delete c;
73 }
74}
std::array< OctTree< POINT, MAX_POINTS > *, 8 > _children
Definition OctTree.h:145

◆ 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 196 of file OctTree-impl.h.

198 : _ll(ll), _ur(ur), _is_leaf(true), _eps(eps)
199{
200 _children.fill(nullptr);
201}
Eigen::Vector3d const _ur
upper right back face point of the cube
Definition OctTree.h:149
bool _is_leaf
flag if this OctTree is a leaf
Definition OctTree.h:153
double const _eps
threshold for point uniqueness
Definition OctTree.h:155
Eigen::Vector3d const _ll
lower left front face point of the cube
Definition OctTree.h:147

References GeoLib::OctTree< POINT, MAX_POINTS >::_children.

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 77 of file OctTree-impl.h.

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

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 204 of file OctTree-impl.h.

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

◆ 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 242 of file OctTree-impl.h.

243{
244 if (isOutside(pnt))
245 {
246 return false;
247 }
248
249 if (_pnts.size() < MAX_POINTS)
250 {
251 _pnts.push_back(pnt);
252 }
253 else
254 { // i.e. _pnts.size () == MAX_POINTS
255 splitNode(pnt);
256 _pnts.clear();
257 }
258 return true;
259}

◆ 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 16 of file OctTree-impl.h.

18{
19 // compute an axis aligned cube around the points ll and ur
20 const double dx(ur[0] - ll[0]);
21 const double dy(ur[1] - ll[1]);
22 const double dz(ur[2] - ll[2]);
23 if (dx >= dy && dx >= dz)
24 {
25 ll[1] -= (dx - dy) / 2.0;
26 ur[1] += (dx - dy) / 2.0;
27 ll[2] -= (dx - dz) / 2.0;
28 ur[2] += (dx - dz) / 2.0;
29 }
30 else
31 {
32 if (dy >= dx && dy >= dz)
33 {
34 ll[0] -= (dy - dx) / 2.0;
35 ur[0] += (dy - dx) / 2.0;
36 ll[2] -= (dy - dz) / 2.0;
37 ur[2] += (dy - dz) / 2.0;
38 }
39 else
40 {
41 ll[0] -= (dz - dx) / 2.0;
42 ur[0] += (dz - dx) / 2.0;
43 ll[1] -= (dz - dy) / 2.0;
44 ur[1] += (dz - dy) / 2.0;
45 }
46 }
47 if (eps == 0.0)
48 {
49 eps = std::numeric_limits<double>::epsilon();
50 }
51 for (std::size_t k(0); k < 3; ++k)
52 {
53 if (ur[k] - ll[k] > 0.0)
54 {
55 ur[k] += (ur[k] - ll[k]) * 1e-6;
56 }
57 else
58 {
59 ur[k] += eps;
60 }
61 }
62 Eigen::Vector3d lower_left{ll[0], ll[1], ll[2]};
63 Eigen::Vector3d upper_right{ur[0], ur[1], ur[2]};
64 return new OctTree<POINT, MAX_POINTS>(lower_left, upper_right, eps);
65}
OctTree(Eigen::Vector3d const &ll, Eigen::Vector3d const &ur, double eps)

Referenced by main(), and MeshToolsLib::partitionNodesByCoordinateMatch().

◆ 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 79 of file OctTree.h.

80 {
81 return _children[i];
82 }

References GeoLib::OctTree< POINT, MAX_POINTS >::_children.

◆ getLowerLeftCornerPoint()

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

Definition at line 77 of file OctTree.h.

77{ return _ll; }

References GeoLib::OctTree< POINT, MAX_POINTS >::_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 148 of file OctTree-impl.h.

150{
151 if (max[0] == min[0] || max[1] == min[1] || max[2] == min[2])
152 {
153 ERR("The search range [{}, {}) x [{}, {}) x [{}, {}) is empty.", min[0],
154 max[0], min[1], max[1], min[2], max[2]);
155 return;
156 }
157
158 return getPointsInRange_(min, max, pnts);
159}
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:45
void getPointsInRange_(T const &min, T const &max, std::vector< POINT * > &pnts) const

References ERR().

Referenced by 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 163 of file OctTree-impl.h.

165{
166 if (_ur[0] < min[0] || _ur[1] < min[1] || _ur[2] < min[2])
167 {
168 return;
169 }
170
171 if (max[0] < _ll[0] || max[1] < _ll[1] || max[2] < _ll[2])
172 {
173 return;
174 }
175
176 if (_is_leaf)
177 {
178 std::copy_if(_pnts.begin(), _pnts.end(), std::back_inserter(pnts),
179 [&min, &max](auto const* p)
180 {
181 return (min[0] <= (*p)[0] && (*p)[0] < max[0] &&
182 min[1] <= (*p)[1] && (*p)[1] < max[1] &&
183 min[2] <= (*p)[2] && (*p)[2] < max[2]);
184 });
185 }
186 else
187 {
188 for (std::size_t k(0); k < 8; k++)
189 {
190 _children[k]->getPointsInRange_(min, max, pnts);
191 }
192 }
193}

◆ getPointVector()

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

Definition at line 83 of file OctTree.h.

83{ return _pnts; }

References GeoLib::OctTree< POINT, MAX_POINTS >::_pnts.

◆ getUpperRightCornerPoint()

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

Definition at line 78 of file OctTree.h.

78{ return _ur; }

References GeoLib::OctTree< POINT, MAX_POINTS >::_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 344 of file OctTree-impl.h.

345{
346 if ((*pnt)[0] < _ll[0] || (*pnt)[1] < _ll[1] || (*pnt)[2] < _ll[2])
347 {
348 return true;
349 }
350 if ((*pnt)[0] >= _ur[0] || (*pnt)[1] >= _ur[1] || (*pnt)[2] >= _ur[2])
351 {
352 return true;
353 }
354 return false;
355}

◆ 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 262 of file OctTree-impl.h.

263{
264 const double x_mid((_ur[0] + _ll[0]) / 2.0);
265 const double y_mid((_ur[1] + _ll[1]) / 2.0);
266 const double z_mid((_ur[2] + _ll[2]) / 2.0);
267 Eigen::Vector3d p0{x_mid, y_mid, _ll[2]};
268 Eigen::Vector3d p1{_ur[0], _ur[1], z_mid};
269
270 // create child NEL
271 _children[static_cast<std::int8_t>(Quadrant::NEL)] =
272 new OctTree<POINT, MAX_POINTS>(p0, p1, _eps);
273
274 // create child NWL
275 p0[0] = _ll[0];
276 p1[0] = x_mid;
277 _children[static_cast<std::int8_t>(Quadrant::NWL)] =
278 new OctTree<POINT, MAX_POINTS>(p0, p1, _eps);
279
280 // create child SWL
281 p0[1] = _ll[1];
282 p1[1] = y_mid;
283 _children[static_cast<std::int8_t>(Quadrant::SWL)] =
285
286 // create child NEU
287 _children[static_cast<std::int8_t>(Quadrant::NEU)] =
289
290 // create child SEL
291 p0[0] = x_mid;
292 p1[0] = _ur[0];
293 _children[static_cast<std::int8_t>(Quadrant::SEL)] =
294 new OctTree<POINT, MAX_POINTS>(p0, p1, _eps);
295
296 // create child NWU
297 p0[0] = _ll[0];
298 p0[1] = y_mid;
299 p0[2] = z_mid;
300 p1[0] = x_mid;
301 p1[1] = _ur[1];
302 p1[2] = _ur[2];
303 _children[static_cast<std::int8_t>(Quadrant::NWU)] =
304 new OctTree<POINT, MAX_POINTS>(p0, p1, _eps);
305
306 // create child SWU
307 p0[1] = _ll[1];
308 p1[1] = y_mid;
309 _children[static_cast<std::int8_t>(Quadrant::SWU)] =
310 new OctTree<POINT, MAX_POINTS>(p0, p1, _eps);
311
312 // create child SEU
313 p0[0] = x_mid;
314 p1[0] = _ur[0];
315 p1[1] = y_mid;
316 p1[2] = _ur[2];
317 _children[static_cast<std::int8_t>(Quadrant::SEU)] =
318 new OctTree<POINT, MAX_POINTS>(p0, p1, _eps);
319
320 // add the passed point pnt to the children at first
321 for (std::size_t k(0); k < 8; k++)
322 {
323 if (_children[k]->addPointToChild(pnt))
324 {
325 break;
326 }
327 }
328
329 // distribute points to sub quadtrees
330 const std::size_t n_pnts(_pnts.size());
331 for (std::size_t j(0); j < n_pnts; j++)
332 {
333 if (std::any_of(begin(_children), end(_children),
334 [&](auto* child)
335 { return child->addPointToChild(_pnts[j]); }))
336 {
337 continue;
338 }
339 }
340 _is_leaf = false;
341}
bool addPointToChild(POINT *pnt)

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 145 of file OctTree.h.

Referenced by GeoLib::OctTree< POINT, MAX_POINTS >::OctTree(), and GeoLib::OctTree< POINT, MAX_POINTS >::getChild().

◆ _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 155 of file OctTree.h.

◆ _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 153 of file OctTree.h.

◆ _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 147 of file OctTree.h.

Referenced by GeoLib::OctTree< POINT, MAX_POINTS >::getLowerLeftCornerPoint().

◆ _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 151 of file OctTree.h.

Referenced by GeoLib::OctTree< POINT, MAX_POINTS >::getPointVector().

◆ _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 149 of file OctTree.h.

Referenced by GeoLib::OctTree< POINT, MAX_POINTS >::getUpperRightCornerPoint().


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