KdTree.hpp
Go to the documentation of this file.
1 // ========================================================================================
2 // ApproxMVBB
3 // Copyright (C) 2014 by Gabriel Nützi <nuetzig (at) imes (d0t) mavt (d0t) ethz (døt) ch>
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 // ========================================================================================
9 
10 #ifndef ApproxMVBB_KdTree_hpp
11 #define ApproxMVBB_KdTree_hpp
12 
13 #include <type_traits>
14 #include <initializer_list>
15 #include <memory>
16 #include <algorithm>
17 #include <array>
18 #include <queue>
19 #include <deque>
20 #include <list>
21 #include <tuple>
22 #include <unordered_set>
23 #include <unordered_map>
24 #include <utility>
25 
26 #include <fstream>
27 
28 #include <meta/meta.hpp>
29 
31 
32 #include ApproxMVBB_TypeDefs_INCLUDE_FILE
33 #include ApproxMVBB_AssertionDebug_INCLUDE_FILE
34 
38 
39 #include "ApproxMVBB/AABB.hpp"
40 
41 
42 
43 namespace ApproxMVBB{
44 
45  namespace KdTree {
46 
47 
50 
51 
52  namespace details{
53  struct TakeDefault;
54 
55  template<typename T>
56  using isDefault = meta::or_<
57  meta::_t<std::is_same<T,TakeDefault> >,
58  meta::_t<std::is_same<T,void> >
59  >;
60  }
61 
62  #define DEFINE_KDTREE_BASETYPES( __Traits__ ) \
63  /* NodeDataType, Dimension and NodeType */ \
64  using NodeDataType = typename __Traits__::NodeDataType; \
65  static const unsigned int Dimension = __Traits__::NodeDataType::Dimension; \
66  using NodeType = typename __Traits__::NodeType; \
67  /*Containers*/ \
68  using NodeContainerType = std::vector<NodeType *>; \
69  using LeafContainerType = NodeContainerType; \
70  using LeafNeighbourMapType = std::unordered_map<std::size_t, std::unordered_set<std::size_t> >;
71 
72 
73  struct EuclideanDistSq {
74  template <typename Derived>
75  static
76  typename Derived::Scalar apply( const MatrixBase<Derived> & p) {
77  return p.squaredNorm();
78  }
79  };
80 
81  template<typename TPoint, typename TPointGetter, typename DistSq = EuclideanDistSq>
82  struct DistanceComp {
84  m_ref.setZero();
85  }
86  template<typename T>
87  DistanceComp( const T & ref ): m_ref(ref) {}
88 
89  template<typename T>
90  inline bool operator()(const T & p1, const T & p2) {
91  return DistSq::apply(m_ref - TPointGetter::get(p1)) <
92  DistSq::apply(m_ref - TPointGetter::get(p2));
93  }
94 
95  template<typename T>
96  inline PREC operator()(const T & p1) {
97  return DistSq::apply(m_ref - TPointGetter::get(p1));
98  }
99 
100  TPoint m_ref;
101  };
102 
104  template<typename TPoint, typename TPointGetter>
106  template<typename TDistSq>
108  };
109 
111  template<unsigned int Dim = 3,
112  typename TPoint = Vector3,
113  typename TValue = Vector3 *,
114  typename TPointGetter = details::TakeDefault, /* decides on TValue type */
115  typename TDistanceCompTraits = details::TakeDefault /* decides on TPoint,TPointGetter */
116  >
118  public:
119  static const unsigned int Dimension = Dim;
120  using PointType = TPoint;
121  using PointListType = StdVecAligned<TValue>;
122 
123  using iterator = typename PointListType::iterator;
124  using const_iterator= typename PointListType::const_iterator;
125 
126 
127  private:
128  /* Standart Point Getter (T = value_type no ptr) */
129  template<typename T>
131  inline static PointType & get(T & t) {
132  return t;
133  }
134  inline static const PointType & get(const T & t) {
135  return t;
136  }
137  };
138 
139  template<typename TT>
140  struct PointGetterImpl<TT*> {
141  inline static PointType & get(TT * t) {
142  return *t;
143  }
144  inline static const PointType & get(const TT * t) {
145  return *t;
146  }
147  };
148 
149 
150 
151  public:
153  using PointGetter = meta::if_< details::isDefault<TPointGetter> ,
155  TPointGetter
156  >;
157 
159  using DistCompTraits = meta::if_< details::isDefault<TDistanceCompTraits> ,
161  TDistanceCompTraits
162  >;
163 
164  };
165 
167  template<typename TTraits = DefaultPointDataTraits<> >
168  class PointData {
169  public:
170 
171  using Traits = TTraits;
172  static const unsigned int Dimension = Traits::Dimension;
173  using PointType = typename Traits::PointType;
174  using PointListType = typename Traits::PointListType;
175  using iterator = typename Traits::iterator;
176  using const_iterator= typename Traits::const_iterator;
177  using PointGetter = typename Traits::PointGetter;
178 
179  template<typename TDistSq>
180  using DistanceComp = typename Traits::DistCompTraits::template DistanceComp<TDistSq>;
181 
182 
183 
184 
189  PointData(iterator begin, iterator end, std::unique_ptr<PointListType> points = nullptr)
190  : m_begin(begin), m_end(end), m_points(points.release()) {}
191 
193  if(m_points) {
194  delete m_points;
195  }
196  }
198  std::pair<PointData *, PointData * >
199  split(iterator splitRightIt) const {
200  // make left
201  PointData * left = new PointData(m_begin, splitRightIt );
202  // make right
203  PointData * right = new PointData(splitRightIt, m_end);
204  return std::make_pair(left,right);
205 
206  }
207 
208  PREC getGeometricMean(unsigned int axis) {
209  PREC ret = 0.0;
210 
211  for(auto & pPoint : *this) {
212  ret += PointGetter::get(pPoint)(axis);
213  }
214  ret /= size();
215  return ret;
216  }
217 
219  return m_begin;
220  }
221 
223  return m_end;
224  }
225 
226 
228  return m_begin;
229  }
230 
231  const_iterator end() const {
232  return m_end;
233  }
234 
235 
236  std::size_t size() const {
237  return std::distance(m_begin,m_end);
238  }
239 
240  std::string getPointString() {
241  std::stringstream ss;
242  for(auto & pPoint : *this) {
243  ss << PointGetter::get(pPoint).transpose().format(MyMatrixIOFormat::SpaceSep) << std::endl;
244  }
245  return ss.str();
246  }
247 
248 
249  friend class XML;
250  private:
251  iterator m_begin,m_end;
252 
254  PointListType* m_points = nullptr;
255  };
256 
257 
267  public:
272  LinearQualityEvaluator(PREC ws = 0.0, PREC wp = 0.0, PREC we = 1.0):
273  m_weightSplitRatio(ws), m_weightPointRatio(wp), m_weightMinMaxExtentRatio(we) {}
274 
275  inline void setLevel(unsigned int level) {
276  /* set parameters for tree level dependent (here not used)*/
277  }
278 
279  inline PREC compute(const PREC & splitRatio, const PREC & pointRatio, const PREC & minMaxExtentRatio) {
280  return m_weightSplitRatio * 2.0 * splitRatio
281  + m_weightPointRatio * 2.0 * pointRatio
282  + m_weightMinMaxExtentRatio * minMaxExtentRatio;
283  }
284 
285  private:
287  PREC m_weightSplitRatio = 0.0;
288  PREC m_weightPointRatio = 0.0;
289  PREC m_weightMinMaxExtentRatio = 1.0;
290  };
291 
292 
293  template< typename Traits >
295 
296  template< typename TQualityEvaluator, typename Traits >
298  public:
299 
300  DEFINE_KDTREE_BASETYPES( Traits )
301 
302  using PointDataType = NodeDataType;
303  using PointListType = typename NodeDataType::PointListType;
304  using PointType = typename PointDataType::PointType ;
305  using iterator = typename PointDataType::iterator;
307 
308  enum class Method : char { MIDPOINT, MEDIAN, GEOMETRIC_MEAN };
309 
314  enum class SearchCriteria : char { FIND_FIRST, FIND_BEST };
315 
316  using QualityEvaluator = TQualityEvaluator;
317 
318  using SplitAxisType = typename NodeType::SplitAxisType;
319 
320 
321  SplitHeuristicPointData() : m_methods({Method::MIDPOINT}), m_searchCriteria(SearchCriteria::FIND_BEST) {
322  for(SplitAxisType i = 0; i < static_cast<SplitAxisType>(Dimension); i++) {
323  m_splitAxes.push_back(i);
324  }
325  resetStatistics();
326  }
327 
328  void init(const std::initializer_list<Method> & m,
329  unsigned int allowSplitAboveNPoints = 100,
330  PREC minExtent = 0.0,
331  SearchCriteria searchCriteria = SearchCriteria::FIND_BEST,
332  const QualityEvaluator & qualityEval = QualityEvaluator(),
333  PREC minSplitRatio = 0.0, PREC minPointRatio = 0.0, PREC minExtentRatio = 0.0) {
334 
335  m_methods = m;
336 
337  if(m_methods.size()==0) {
338  ApproxMVBB_ERRORMSG("No methods for splitting given!")
339  }
340  m_allowSplitAboveNPoints = allowSplitAboveNPoints;
341  m_minExtent = minExtent;
342  if( m_minExtent < 0) {
343  ApproxMVBB_ERRORMSG("Minimal extent has wrong value!")
344  }
345  m_searchCriteria = searchCriteria;
346 
347  m_qualityEval = qualityEval;
348 
349  m_minSplitRatio = minSplitRatio;
350  m_minPointRatio = minPointRatio;
351  m_minExtentRatio = minExtentRatio;
352 
353  if( m_minSplitRatio < 0 || m_minPointRatio < 0 || m_minExtentRatio <0) {
354  ApproxMVBB_ERRORMSG("Minimal split ratio, point ratio or extent ratio have <0 values!");
355  }
356 
357  resetStatistics();
358 
359  }
360 
362  m_splitCalls = 0;
363  m_tries = 0;
364  m_splits = 0;
365 
366  m_avgSplitRatio = 0.0;
367  m_avgPointRatio = 0.0;
368  m_avgExtentRatio = 0.0;
369  }
370 
371  std::string getStatisticsString() {
372  std::stringstream s;
373  s<< "\t splits : " << m_splits
374  << "\n\t avg. split ratio (0,0.5] : " << m_avgSplitRatio / m_splits
375  << "\n\t avg. point ratio [0,0.5] : " << m_avgPointRatio/ m_splits
376  << "\n\t avg. extent ratio (0,1] : " << m_avgExtentRatio / m_splits
377  << "\n\t tries / calls : " << m_tries << "/" << m_splitCalls << " = " <<(PREC)m_tries/m_splitCalls;
378  return s.str();
379  }
380 
384  std::pair<NodeDataType *, NodeDataType * >
385  doSplit(NodeType * node, SplitAxisType & splitAxis, PREC & splitPosition) {
386 
387  ++m_splitCalls;
388 
389  auto * data = node->data();
390 
391  // No split for to little points or extent to small!
392  if(data->size() <= m_allowSplitAboveNPoints) {
393  return std::make_pair(nullptr,nullptr);
394  }
395 
396 
397  // Sort split axes according to biggest extent
398  m_extent = node->aabb().extent();
399 
400  auto biggest = [&](const SplitAxisType & a, const SplitAxisType & b) {
401  return m_extent(a) > m_extent(b);
402  };
403  std::sort(m_splitAxes.begin(),m_splitAxes.end(),biggest);
404 
405  // Cycle through each method and check each axis
406  unsigned int tries = 0;
407 
408  std::size_t nMethods = m_methods.size();
409  std::size_t methodIdx = 0;
410  std::size_t axisIdx = 0;
411  m_found = false;
412  m_bestQuality = std::numeric_limits<PREC>::lowest();
413  //std::cout << "start: " << std::endl;
414  while(((m_searchCriteria == SearchCriteria::FIND_FIRST && !m_found) ||
415  m_searchCriteria == SearchCriteria::FIND_BEST )
416  && methodIdx < nMethods) {
417 
418  //std::cout << "method " << methodIdx<<std::endl;
419  m_wasLastTry = false;
420  m_method = m_methods[methodIdx];
421  m_splitAxis = m_splitAxes[axisIdx];
422 
423  // skip all axes which are smaller or equal than 2* min Extent
424  // -> if we would split, left or right would be smaller or equal to min_extent!
425  if( m_extent(m_splitAxis) > 2.0* m_minExtent ) {
426 
427  // Check split
428  if( computeSplitPosition(node)) {
429 
430  // check all min ratio values (hard cutoff)
431  if( m_splitRatio >= m_minSplitRatio &&
432  m_pointRatio >= m_minPointRatio &&
433  m_extentRatio >= m_minExtentRatio) {
434  // if quality is better, update
435  updateSolution();
436  //std::cout << "Axis: " << axisIdx << "," << int(m_splitAxis)<< " q: " << m_quality << std::endl;
437  m_found = true;
438 
439  }
440 
441  }
442 
443  ++tries;
444  } else {
445  //std::cout << "cannot split -> extent " << std::endl;
446  }
447 
448 
449  // next axis
450  if( ++axisIdx == Dimension) {
451  axisIdx = 0;
452  ++methodIdx;
453  }
454 
455  }
456  m_tries += tries;
457 
458  if(m_found) {
459 
460  // take best values
461  // finalize sorting (for all except (lastTry true and method was median) )
462  if( !(m_wasLastTry && m_bestMethod==Method::MEDIAN) ) {
463 
464  switch(m_bestMethod) {
465  case Method::GEOMETRIC_MEAN:
466  case Method::MIDPOINT: {
467  auto leftPredicate = [&](const typename PointListType::value_type & a) {
468  return PointGetter::get(a)(m_bestSplitAxis) < m_bestSplitPosition;
469  };
470  m_bestSplitRightIt = std::partition(data->begin(), data->end(), leftPredicate );
471  break;
472  }
473  case Method::MEDIAN: {
474  auto less = [&](const typename PointListType::value_type & a, const typename PointListType::value_type & b) {
475  return PointGetter::get(a)(m_bestSplitAxis) < PointGetter::get(b)(m_bestSplitAxis);
476  };
477  std::nth_element(data->begin(), m_bestSplitRightIt, data->end(), less );
478  m_bestSplitPosition = PointGetter::get(*(m_bestSplitRightIt))(m_bestSplitAxis);
479  auto leftPredicate = [&](const typename PointListType::value_type & a) {
480  return PointGetter::get(a)(m_bestSplitAxis) < m_bestSplitPosition;
481  };
482  m_bestSplitRightIt = std::partition(data->begin(),m_bestSplitRightIt, leftPredicate);
483  break;
484  }
485  }
486  }
487 
488  computeStatistics();
489 
490  // Finally set the position and axis and return
491  splitAxis = m_bestSplitAxis;
492  splitPosition = m_bestSplitPosition;
493  return data->split(m_bestSplitRightIt);
494  }
495 
496 
497 
498  return std::make_pair(nullptr,nullptr);
499  };
500 
501  private:
502 
504  bool computeSplitPosition(NodeType * node,
505  unsigned int tries = 1) {
506 
507  auto * data = node->data();
508  ApproxMVBB_ASSERTMSG( data, "Node @ " << node << " has no data!")
509 
510  auto & aabb = node->aabb();
511  switch(m_method) {
512  case Method::MIDPOINT: {
513  m_splitPosition = 0.5*(aabb.m_minPoint(m_splitAxis) + aabb.m_maxPoint(m_splitAxis));
514 
515  if(!checkPosition(aabb)) {
516  return false;
517  }
518  // Compute bodyRatio/splitRatio and quality
519  m_splitRatio = 0.5;
520  m_extentRatio = computeExtentRatio(aabb);
521  m_pointRatio = computePointRatio(data);
522  m_quality = m_qualityEval.compute(m_splitRatio,m_pointRatio,m_extentRatio);
523 
524  break;
525  }
526  case Method::MEDIAN: {
527  auto beg = data->begin();
528  m_splitRightIt = beg + data->size()/2; // split position is the median!
529 
530  auto less = [&](const typename PointListType::value_type & a,
531  const typename PointListType::value_type & b) {
532  return PointGetter::get(a)(m_splitAxis) < PointGetter::get(b)(m_splitAxis);
533  };
534  // [5, 5, 1, 5, 6, 7, 9, 5] example for [beg ... end]
535  // partition such that: left points(m_splitAxis) <= nth element (splitRightIt) <= right points(m_splitAxis)
536  std::nth_element(beg, m_splitRightIt, data->end(), less );
537  m_splitPosition = PointGetter::get(*(m_splitRightIt))(m_splitAxis); // TODO make transform iterator to avoid PointGetter::geterence here!
538 
539  if(!checkPosition(aabb)) {
540  return false;
541  }
542 
543 
544  // e.g [ 5 5 5 1 5 5 6 9 7 ]
545  // ^median, splitPosition = 5;
546 
547  // move left points which are equal to nth element to the right!
548 
549  auto leftPredicate = [&](const typename PointListType::value_type & a) {
550  return PointGetter::get(a)(m_splitAxis) < m_splitPosition;
551  };
552  m_splitRightIt = std::partition(beg,m_splitRightIt, leftPredicate);
553  // it could happen that the list now looks [1 5 5 5 5 5 6 9 7]
554  // ^splitRightIt
555 
556  // Compute bodyRatio/splitRatio and quality
557  m_splitRatio = computeSplitRatio(aabb);
558  m_extentRatio = computeExtentRatio(aabb);
559  m_pointRatio = (PREC)std::distance(beg,m_splitRightIt) / std::distance(beg,data->end());
560  // normally 0.5 but we shift all equal points to the right (so this changes!)
561  m_quality = m_qualityEval.compute(m_splitRatio,m_pointRatio,m_extentRatio);
562 
563  // to avoid this check if in tolerance (additional points < 5%) if not choose other axis and try again!
564  // bool notInTolerance = (data->size()/2 - std::distance(beg,splitRightIt)) >= 0.05 * data->size();
565 
566  // if( notInTolerance ) {
567  // if(tries < NodeDataType::Dimension) {
568  // ++tries;
569  // m_splitAxis = (m_splitAxis + 1) % NodeDataType::Dimension;
570  // return computeSplitPosition(splitRightIt,node,tries);
571  // }
572  // }
573 
574  break;
575  }
576  case Method::GEOMETRIC_MEAN: {
577  m_splitPosition = data->getGeometricMean(m_splitAxis);
578  if(!checkPosition(aabb)) {
579  return false;
580  }
581  // Compute bodyRatio/splitRatio and quality
582  m_splitRatio = computeSplitRatio(aabb);
583  m_extentRatio = computeExtentRatio(aabb);
584  m_pointRatio = computePointRatio(data);
585  m_quality = m_qualityEval.compute(m_splitRatio,m_pointRatio,m_extentRatio);
586  break;
587  }
588  }
589  return true;
590  }
591 
592  inline bool checkPosition(AABB<Dimension> & aabb) {
593  ApproxMVBB_ASSERTMSG( m_splitPosition >= aabb.m_minPoint(m_splitAxis)
594  && m_splitPosition <= aabb.m_maxPoint(m_splitAxis),
595  "split position wrong: " << m_splitPosition << " min: " << aabb.m_minPoint.transpose()
596  << " max: " << aabb.m_maxPoint.transpose() )
597 
598  if( (m_splitPosition - aabb.m_minPoint(m_splitAxis)) <= m_minExtent ||
599  (aabb.m_maxPoint(m_splitAxis) - m_splitPosition) <= m_minExtent ) {
600  return false;
601  }
602  return true;
603  }
604 
605  inline void updateSolution() {
606  if( m_quality > m_bestQuality ) {
607  m_wasLastTry = true;
608 
609  m_bestMethod = m_method;
610  m_bestQuality = m_quality;
611  m_bestSplitRightIt = m_splitRightIt;
612  m_bestSplitAxis = m_splitAxis;
613  m_bestSplitPosition = m_splitPosition;
614 
615  m_bestSplitRatio = m_splitRatio;
616  m_bestPointRatio = m_pointRatio;
617  m_bestExtentRatio = m_extentRatio;
618  }
619  }
620 
621 
622  inline PREC computePointRatio(NodeDataType * data) {
623  PREC n = 0.0;
624  for(auto & p: *data) {
625  if(PointGetter::get(p)(m_splitAxis) < m_splitPosition) {
626  n+=1.0;
627  }
628  }
629  n /= data->size();
630  return (n>0.5)? 1.0-n : n ;
631  }
632 
633  inline PREC computeSplitRatio(AABB<Dimension> & aabb) {
634  PREC n = (m_splitPosition - aabb.m_minPoint(m_splitAxis))
635  / (aabb.m_maxPoint(m_splitAxis) - aabb.m_minPoint(m_splitAxis)) ;
636  ApproxMVBB_ASSERTMSG(n>0.0 && n <=1.0," split ratio negative!, somthing wrong with splitPosition: " << n );
637  return (n>0.5)? 1.0-n : n ;
638  }
639 
640  inline PREC computeExtentRatio(AABB<Dimension> & aabb) {
641  // take the lowest min/max extent ratio
642  static ArrayStat<Dimension> t;
643  t = m_extent;
644  PREC tt = t(m_splitAxis);
645 
646  t(m_splitAxis) = m_splitPosition - aabb.m_minPoint(m_splitAxis);
647  PREC r = t.minCoeff() / t.maxCoeff(); // gives NaN if max == 0, cannot happen since initial aabb is feasible!
648 
649  t(m_splitAxis) = tt; //restore
650  t(m_splitAxis) = aabb.m_maxPoint(m_splitAxis) - m_splitPosition;
651  r = std::min(r,t.minCoeff() / t.maxCoeff());
652 
653  ApproxMVBB_ASSERTMSG(r > 0, "extent ratio <= 0!" );
654  return r;
655 
656  }
657 
658 
659 
660  inline void computeStatistics() {
661  ++m_splits;
662  m_avgSplitRatio += m_bestSplitRatio;
663  m_avgPointRatio += m_bestPointRatio;
664  m_avgExtentRatio += m_bestExtentRatio;
665  }
666 
668  unsigned int m_splitCalls = 0;
669  unsigned int m_tries = 0;
670  unsigned int m_splits = 0;
671  PREC m_avgSplitRatio = 0;
672  PREC m_avgPointRatio = 0;
673  PREC m_avgExtentRatio = 0;
674 
675 
677 
679  ArrayStat<Dimension> m_extent; // current extent of the aabb
681  PREC m_quality = 0.0;
682 
683  PREC m_splitRatio = 0;
684  PREC m_pointRatio = 0;
685  PREC m_extentRatio = 0;
686 
688  PREC m_minSplitRatio = 0.0;
689  PREC m_minPointRatio = 0.0;
690  PREC m_minExtentRatio = 0.0;
691 
693  PREC m_splitPosition = 0.0;
695 
696 
698  bool m_wasLastTry = false;
699  bool m_found = false;
701  PREC m_bestQuality = std::numeric_limits<PREC>::lowest();
702  PREC m_bestSplitRatio = 0, m_bestPointRatio = 0, m_bestExtentRatio = 0;
704  PREC m_bestSplitPosition = 0.0;
706 
708  std::vector<SplitAxisType> m_splitAxes;
709  std::vector<Method> m_methods;
711 
712  std::size_t m_allowSplitAboveNPoints = 100;
713  PREC m_minExtent = 0.0;
714 
715  };
716 
717 
719  template<typename T> class TreeBase;
720  template<typename T> class TreeSimple;
721  template<typename T> class Tree;
722 
723 
724  #define DEFINE_KDTREE_BASENODETYPES( _Base_ ) \
725  using SplitAxisType = typename _Base_::SplitAxisType; \
726  using BoundaryInfoType = typename _Base_::BoundaryInfoType;
727 
730  template<typename TDerivedNode, unsigned int Dimension>
731  class NodeBase {
732  private:
733 
734  ApproxMVBB_STATIC_ASSERT( Dimension <= std::numeric_limits<char>::max())
735 
736  template<typename D, unsigned int Dim>
737  friend class NodeBase;
738 
739  public:
740 
741  using DerivedNode = TDerivedNode;
742  using SplitAxisType = char;
743 
744  private:
746  public:
747  static const unsigned int size = Dimension * 2;
748 
749 
750  inline DerivedNode* & at(unsigned int idx){
751  ApproxMVBB_ASSERTMSG(idx < size, "Index " << idx << "out of bound!");
752  return m_nodes[idx];
753  }
754  inline DerivedNode* const & at(unsigned int idx) const{
755  ApproxMVBB_ASSERTMSG(idx < size, "Index " << idx << "out of bound!");
756  return m_nodes[idx];
757  }
758 
759  inline DerivedNode* & at(unsigned int axis, char minMax){
760  ApproxMVBB_ASSERTMSG(minMax*Dimension + axis < size, "Index " << minMax*Dimension + axis << "out of bound!");
761  return m_nodes[minMax*Dimension + axis];
762  }
763  inline DerivedNode* const & at(unsigned int axis, char minMax) const{
764  ApproxMVBB_ASSERTMSG(minMax*Dimension + axis < size, "Index " << minMax*Dimension + axis << "out of bound!");
765  return m_nodes[minMax*Dimension + axis];
766  }
767 
768  DerivedNode* * begin(){ return m_nodes;}
769  DerivedNode* * end(){ return m_nodes + size;}
770 
771  DerivedNode* const * begin() const { return m_nodes;}
772  DerivedNode* const * end() const { return m_nodes + size;}
773 
774  private:
775  DerivedNode* m_nodes[size] = {nullptr};
776  };
777 
778  public:
779  using BoundaryInfoType = BoundaryInformation;
780 
782 
783  NodeBase(std::size_t idx, const AABB<Dimension> & aabb, unsigned int treeLevel = 0)
784  : m_idx(idx), m_treeLevel(treeLevel), m_aabb(aabb) {
785  }
786 
788 
794  template<typename Derived>
796  m_idx(n.m_idx),m_treeLevel(n.m_treeLevel), m_aabb(n.m_aabb),
797  m_splitAxis(n.m_splitAxis),m_splitPosition(n.m_splitPosition),
798  m_child{{nullptr,nullptr}}, m_parent{nullptr}
799  {}
801  template<typename Derived>
803  m_idx(n.m_idx), m_treeLevel(n.m_treeLevel),
804  m_aabb(std::move(n.m_aabb)),m_splitAxis(n.m_splitAxis),
805  m_splitPosition(n.m_splitPosition) , m_child(n.child), m_parent(n.parent)
806  {
807  n.m_parent = nullptr;
808  n.m_child = {{nullptr,nullptr}};
809  }
810 
811  inline void setChilds(DerivedNode * r, DerivedNode * l){
812  m_child[0]=r;
813  m_child[1]=l;
814  }
815 
816  inline DerivedNode * parent(){ return m_parent;}
817  inline const DerivedNode * parent() const { return m_parent;}
818 
819  inline DerivedNode * leftNode() {
820  return m_child[0];
821  }
822  inline const DerivedNode * leftNode() const {
823  return m_child[0];
824  }
825 
826  inline DerivedNode * rightNode() {
827  return m_child[1];
828  }
829  inline const DerivedNode * rightNode()const {
830  return m_child[1];
831  }
832 
833  inline AABB<Dimension> & aabb() {
834  return m_aabb;
835  }
836  inline const AABB<Dimension> & aabb() const {
837  return m_aabb;
838  }
839 
840  inline bool hasLeftChildren() const {
841  return m_child[0];
842  }
843  inline bool hasChildren() const {
844  return m_child[0] && m_child[1];
845  }
846 
847  inline bool isLeaf() const {
848  return (m_splitAxis == -1);
849  }
850 
851  inline void setIdx(std::size_t i){
852  m_idx = i;
853  }
854 
855  inline std::size_t getIdx() const {
856  return m_idx;
857  }
858 
859  inline void setSplitAxis(SplitAxisType splitAxis) {
860  m_splitAxis= splitAxis ;
861  }
862  inline void setSplitPosition(PREC splitPos) {
863  m_splitPosition= splitPos ;
864  }
865 
866  inline SplitAxisType getSplitAxis() const {
867  return m_splitAxis ;
868  }
869  inline PREC getSplitPosition() const {
870  return m_splitPosition;
871  }
872  inline PREC getSplitRatio() const {
873  return (m_splitPosition - m_aabb.m_minPoint(m_splitAxis) )
874  / (m_aabb.m_maxPoint(m_splitAxis)-m_aabb.m_minPoint(m_splitAxis));
875  }
876 
877  inline unsigned int getLevel() const {
878  return m_treeLevel;
879  }
880 
881  inline void setLevel(unsigned int l) const {
882  m_treeLevel = l;
883  }
884 
885  protected:
886 
887  NodeBase(std::size_t idx, const AABB<Dimension> & aabb, SplitAxisType axis, PREC splitPos)
888  : m_idx(idx), m_aabb(aabb), m_splitAxis(axis), m_splitPosition(splitPos) {
889  }
890 
891  std::size_t m_idx = std::numeric_limits<std::size_t>::max();
892  unsigned int m_treeLevel = 0;
894  SplitAxisType m_splitAxis = -1;
895  PREC m_splitPosition = 0.0;
896 
901  std::array<DerivedNode *,2> m_child{{nullptr,nullptr}};
902  DerivedNode * m_parent = nullptr;
903  };
904 
906  template<typename Traits> class Node;
907 
908  namespace details{
909  // Helper to select the correct Derived type
910  template<typename PD,typename T>
911  struct select{ using type = PD;};
912 
913  template<typename T>
914  struct select<void,T>{ using type = T; };
915  }
916 
917  template<typename TTraits, typename PD = void> /*PD = PossibleDerived */
918  class NodeSimple : public NodeBase< typename details::select<PD, NodeSimple<TTraits,PD> >::type ,
919  TTraits::Dimension>
920  {
921  public:
922  using Traits = TTraits;
923 
926 
927  protected:
928  using Base::m_idx;
929  using Base::m_aabb;
930  using Base::m_splitAxis;
931  using Base::m_splitPosition;
932  using Base::m_child;
933 
934  template<typename T>
935  friend class TreeBase;
936 
937 
942 
943  public:
944 
947 
949  NodeSimple(std::size_t idx, const AABB<Dimension> & aabb): Base(idx,aabb) {}
950  NodeSimple(NodeSimple&& t): Base(std::move(t)) {}
951  NodeSimple(const NodeSimple& t): Base(t) {}
952 
954  template<typename T>
955  explicit NodeSimple(const Node<T> & t): Base(t) {
956 
957  }
958 
962  template<typename T, typename NodeVector>
963  void setup( const Node<T> * t, const NodeVector & nodes){
964 
966 
967 
968  // link left child
969  Node<T> * c = t->m_child[0];
970  if(c){
971  m_child[0] = nodes[c->getIdx()];
972  m_child[0]->m_parent = static_cast<DerivedType*>(this);
973  }
974 
975  // link right child
976  c = t->m_child[1];
977  if(c){
978  m_child[1] = nodes[c->getIdx()];
979  m_child[1]->m_parent = static_cast<DerivedType*>(this);
980  }
981 
982 
983  // link boundary information if this (and of course t) is a leaf
984  if(t->isLeaf()){
985  auto it = m_bound.begin();
986  for(const auto * bNode : t->m_bound){
987 
988  if( bNode ){ // if boundary node is valid
989  // find node idx in node list (access by index)
990  auto * p = nodes[bNode->getIdx()];
991  if(p == nullptr){
992  ApproxMVBB_ERRORMSG("Setup in node: " << this->getIdx() << " failed!");
993  }
994  *it = p; // set boundary pointer to the found node pointer.
995  }else{
996  *it = nullptr;
997  }
998 
999  ++it;
1000  }
1001  }
1002 
1003  }
1004 
1005  const BoundaryInfoType & getBoundaries() const {return m_bound;}
1006  BoundaryInfoType & getBoundaries() {return m_bound;}
1007  };
1008 
1010  template<unsigned int Dim = 3>
1011  struct NoData {
1012  static const unsigned int Dimension = Dim;
1013  };
1014 
1015 
1016  template<typename TTraits>
1017  class Node : public NodeBase<Node<TTraits>,TTraits::Dimension> {
1018  public:
1019  using Traits = TTraits;
1020  using Base = NodeBase<Node<TTraits>,TTraits::Dimension>;
1021  private:
1022 
1023  using Base::m_idx;
1024  using Base::m_aabb;
1025  using Base::m_splitAxis;
1026  using Base::m_splitPosition;
1027  using Base::m_child;
1028 
1029 
1030 
1032  template<typename T>
1033  friend class Tree;
1034  template<typename T>
1035  friend class TreeBase;
1036 
1038  template<typename T>
1039  friend class Node;
1040  template<typename T,typename PD>
1041  friend class NodeSimple;
1042 
1043  public:
1044 
1047 
1048 
1049 
1050  Node(std::size_t idx, const AABB<Dimension> & aabb, NodeDataType * data, unsigned int treeLevel = 0)
1051  : Base(idx,aabb,treeLevel), m_data(data) {
1052  }
1053 
1054  ~Node() {
1055  cleanUp();
1056  }
1057 
1063  template<typename Traits>
1064  Node(const Node<Traits> & n): Base(n) {
1065  if(n.m_data) {
1066  m_data = new NodeDataType(*n.m_data);
1067  }
1068  }
1069 
1071  Node(Node && n): Base(std::move(n)),
1072  m_bound(n.m_bound),
1073  m_data(n.m_data) {
1074  n.m_data = nullptr;
1075  }
1076 
1077  const BoundaryInfoType & getBoundaries() const {return m_bound;}
1078  BoundaryInfoType & getBoundaries() {return m_bound;}
1079 
1081  m_bound = b;
1082  }
1083 
1084  inline NodeDataType * data() {
1085  return m_data;
1086  }
1087  inline const NodeDataType * data() const {
1088  return m_data;
1089  }
1090 
1096  template<typename TSplitHeuristic>
1097  bool split(TSplitHeuristic & s, std::size_t startIdx = 0) {
1098 
1099  auto pLR = s.doSplit(this, m_splitAxis, m_splitPosition);
1100 
1101  if(pLR.first == nullptr) { // split has failed!
1102  return false;
1103  }
1104 
1105  // if startIdx for numbering is zero then number according to complete binary tree
1106  startIdx = (startIdx == 0) ? 2*m_idx + 1 : startIdx;
1107 
1108  // Split aabb and make left and right
1109  // left (idx for next child if tree is complete binary tree, then idx = 2*idx+1 for left child)
1110  AABB<Dimension> t(m_aabb);
1111  PREC v = t.m_maxPoint(m_splitAxis);
1112  t.m_maxPoint(m_splitAxis) = m_splitPosition;
1113  m_child[0] = new Node(startIdx,t,pLR.first, this->m_treeLevel+1);
1114  m_child[0]->m_parent = this;
1115 
1116  // right
1117  t.m_maxPoint(m_splitAxis) = v; //restore
1118  t.m_minPoint(m_splitAxis) = m_splitPosition;
1119  m_child[1] = new Node(startIdx+1,t,pLR.second, this->m_treeLevel+1);
1120  m_child[1]->m_parent = this;
1121 
1122  // Set Boundary Information
1123  BoundaryInfoType b = m_bound; //copy
1124  Node * tn = b.at(m_splitAxis,1);
1125  b.at(m_splitAxis,1) = m_child[1]; // left changes pointer at max value
1126  m_child[0]->setBoundaryInfo(b);
1127 
1128  b.at(m_splitAxis,1) = tn; // restore
1129  b.at(m_splitAxis,0) = m_child[0]; // right changes pointer at min value
1130  m_child[1]->setBoundaryInfo(b);
1131 
1132  // clean up own node if it is not the root node on level 0
1133  if(this->m_treeLevel != 0) {
1134  cleanUp();
1135  }
1136 
1137  return true;
1138  }
1139 
1140  template<typename NeighbourIdxMap>
1141  void getNeighbourLeafsIdx( NeighbourIdxMap & neigbourIdx, PREC minExtent) {
1142  // we determine in each direction of the kd-Tree in R^n (if 3D, 3 directions)
1143  // for "min" and "max" the corresponding leafs in the subtrees given by
1144  // the boundary information in the leaf node:
1145  // e.g. for the "max" direction in x for one leaf, we traverse the subtree of the boundary
1146  // information in "max" x direction
1147  // for "max" we always take the left node (is the one which is closer to our max x boundary)
1148  // for "min" we always take the right node (is the one which is closer to our min x boundary)
1149  // in this way we get all candidate leaf nodes (which share the same split axis with split position s)
1150  // which need still to be checked if they are neighbours
1151  // this is done by checking if the boundary subspace with the corresponding axis set to the split position s
1152  // (space without the axis which is checked, e.g y-z space, with x = s)
1153  // against the current leaf nodes boundary subspace
1154  // (which is thickened up by the amount of the minimal leaf node extent size,
1155  // important because its not clear what should count as a neighbour or what not)
1156  // if this neighbour n subspace overlaps the thickened leaf node subspace then this node is
1157  // considered as a neighbour for leaf l, (and also neighbour n has l as neighbour obviously)
1158  // the tree should be build with a slightly bigger min_extent size than the thickening in the step here!
1159  // to avoid to many nodes to be classified as neighbours (trivial example, min_extent grid)
1160  // if we have no boundary information
1161 
1162 
1163  std::deque<Node*> nodes; // Breath First Search
1164  auto & neighbours = neigbourIdx[m_idx]; // Get this neighbour map
1165  Node * f;
1166 
1167  AABB<Dimension> aabb(m_aabb);
1168  aabb.expand(minExtent); // expand this nodes aabb such that we find all the neighbours which overlap this aabb;
1169 
1170  // For each axis traverse subtree
1171  for(SplitAxisType d = 0; d< static_cast<SplitAxisType>(Dimension); ++d) {
1172 
1173  // for min and max
1174  for(unsigned int m = 0; m<2; ++m) {
1175 
1176  // push first -> Breath First Search (of boundary subtree)
1177  Node * subTreeRoot = m_bound.at(d,m);
1178  if(!subTreeRoot) {
1179  continue;
1180  } else {
1181  nodes.emplace_back(subTreeRoot);
1182  }
1183 
1184  while(!nodes.empty()) {
1185  //std::cout << nodes.size() << std::endl;
1186  f = nodes.front();
1187  ApproxMVBB_ASSERTMSG(f, "Node f is nullptr")
1188 
1189  auto axis = f->m_splitAxis;
1190  if(f->isLeaf()) {
1191  //std::cerr << "is leaf" << std::endl;
1192  // determine if f is a neighbour to this node
1193  // if leaf is not already in neighbour map for this node (skip)
1194  if( neighbours.find(f->m_idx) == neighbours.end() ) {
1195 
1196  // check if the subspace (fixedAxis = m) overlaps
1197  if(aabb.overlapsSubSpace(f->m_aabb,d)) {
1198  //std::cerr << m_idx << " overlaps" << f->getIdx() << std::endl;
1199  neighbours.emplace(f->m_idx);
1200  neigbourIdx[f->m_idx].emplace(m_idx);
1201  }
1202 
1203  }
1204 
1205  } else {
1206  // if the node f currently processed has the same split axis as the boundary direction
1207  // add only the nodes closer to the cell of this node
1208  if(axis == d) {
1209  if(m==0) {
1210  // for minmal boundary only visit right nodes (closer to this)
1211  nodes.emplace_back(f->rightNode());
1212  } else {
1213  // for maximal boundary only visit left nodes (closer to this)
1214  nodes.emplace_back(f->leftNode());
1215  }
1216  } else {
1217  // otherwise add all
1218  nodes.emplace_back(f->leftNode());
1219  nodes.emplace_back(f->rightNode());
1220  }
1221  }
1222  nodes.pop_front();
1223  }
1224 
1225 
1226  }
1227 
1228  }
1229 
1230  }
1231 
1232  void cleanUp(bool data = true /*,bool bounds = true*/) {
1233  if(data && m_data) {
1234  delete m_data;
1235  m_data = nullptr;
1236  }
1237  }
1238 
1239  std::size_t size() {
1240  return (m_data)? m_data->size() : 0;
1241  }
1242 
1243  private:
1244 
1245  NodeDataType* m_data = nullptr;
1246 
1251 
1252  };
1258  template<typename Traits>
1259  class TreeBase {
1260  private:
1261  template<typename T>
1262  friend class TreeBase;
1263  public:
1264 
1265  DEFINE_KDTREE_BASETYPES( Traits )
1266 
1268 
1270  : m_nodes(std::move(t.m_nodes)), m_leafs( std::move(t.m_leafs) ), m_root(t.m_root) {
1271  // Make other tree empty
1272  t.m_root = nullptr;
1273  t.m_nodes.clear();
1274  t.m_leafs.clear();
1275  }
1276 
1277  TreeBase(const TreeBase & t) {
1278  copyFrom(t);
1279  }
1280 
1281  template<typename T>
1282  explicit TreeBase(const TreeBase<T> & t) {
1283  copyFrom(t);
1284  }
1285 
1286 
1287  protected:
1288 
1289 
1290 
1297  template<typename T>
1298  void copyFrom(const TreeBase<T> & tree) {
1299 
1300  //using CNodeType = typename TreeBase<T>::NodeType;
1301 
1302  if(!tree.m_root) {
1303  return;
1304  }
1305 
1306  this->m_nodes.reserve(tree.m_nodes.size());
1307  this->m_leafs.reserve(tree.m_leafs.size());
1308 
1309  // copy all nodes
1310  for( auto * n : tree.m_nodes){
1311  ApproxMVBB_ASSERTMSG(n, "Node of tree to copy from is nullptr!")
1312  this->m_nodes.emplace_back( new NodeType(*n) );
1313  }
1314 
1315  // setup all nodes
1316  auto s = tree.m_nodes.size();
1317  for( std::size_t i=0;i<s;++i){
1318  this->m_nodes[i]->setup(tree.m_nodes[i],this->m_nodes);
1319  }
1320 
1321  // setup leaf list
1322  for( auto * n : tree.m_leafs){
1323  //std::cerr << "Approx:: n->getIdx() " << n->getIdx() << std::endl;
1324  ApproxMVBB_ASSERTMSG( (n->getIdx() < this->m_nodes.size()) , "Leaf node from source is out of range: " << n->getIdx() <<"," << this->m_nodes.size() )
1325  this->m_leafs.emplace_back( this->m_nodes[n->getIdx()] );
1326  }
1327 
1328  // setup root
1329  ApproxMVBB_ASSERTMSG( tree.m_root->getIdx() < this->m_nodes.size(), "Root idx out of range: " << tree.m_root->getIdx() << "," << this->m_nodes.size() )
1330  m_root = m_nodes[ tree.m_root->getIdx() ];
1331 
1332  }
1333 
1335  resetTree();
1336  }
1337 
1338  public:
1339 
1340 
1348  template<typename NodeMap, typename NodeToChildMap>
1349  void build( NodeType * root, NodeMap & c, NodeToChildMap & links) {
1350 
1351  resetTree();
1352  m_leafs.clear();
1353  m_nodes.clear();
1354  m_nodes.reserve(c.size());
1355  m_nodes.assign(c.begin(),c.end());
1356 
1357  for(auto * n: m_nodes) {
1358  if(n->isLeaf()) {
1359  m_leafs.push_back(n);
1360  }
1361  }
1362 
1363  if( c.find(root->getIdx()) == c.end()) {
1364  ApproxMVBB_ERRORMSG("Root node not in NodeMap!")
1365  }
1366 
1367 
1368  std::unordered_set<std::size_t> hasParent;
1369  // first link all nodes together
1370  auto itE = c.end();
1371  for(auto & l : links) { // first idx, second pair<idxL,idxR>
1372  auto it = c.find(l.first);
1373  auto itL = c.find(l.second.first);
1374  auto itR = c.find(l.second.second);
1375 
1376  if(it==itE || itL==itE || itR==itE) {
1377  ApproxMVBB_ERRORMSG("Link at node idx: " << l.first << " wrong!")
1378  }
1379 
1380  if(!hasParent.emplace(l.second.first).second) {
1381  ApproxMVBB_ERRORMSG("Node idx: " << l.second.first << "has already a parent!")
1382  };
1383  if(!hasParent.emplace(l.second.second).second) {
1384  ApproxMVBB_ERRORMSG("Node idx: " << l.second.first << "has already a parent!")
1385  };
1386  if( !it->second || !itL->second || !itR->second) {
1387  ApproxMVBB_ERRORMSG("Ptr for link zero")
1388  }
1389  it->second->m_child[0] = itL->second; // link left
1390  it->second->m_child[1] = itR->second; // link right
1391  }
1392 
1393  if(hasParent.size() != c.size()-1) {
1394  ApproxMVBB_ERRORMSG("Tree needs to have N nodes, with one root, which gives N-1 parents!")
1395  }
1396 
1397  // Save root as it is a valid binary tree
1398  m_root = root;
1399 
1400 
1401  // Move over all nodes again an do some setup
1402  }
1403 
1404  void resetTree() {
1405  for(auto * n: this->m_nodes) {
1406  delete n;
1407  }
1408  // root node is also in node list!
1409  this->m_root= nullptr;
1410 
1411  m_leafs.clear();
1412  m_nodes.clear();
1413  }
1414 
1419  template<typename Derived>
1420  const NodeType * getLeaf(const MatrixBase<Derived> & point) const {
1421  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,Dimension);
1422  // Recursively traverse tree to find the leaf which contains the point
1423  ApproxMVBB_ASSERTMSG(m_root, "Tree is not built!")
1424  const NodeType * currentNode = m_root;
1425 
1426  while(!currentNode->isLeaf()) {
1427  // all points greater or equal to the splitPosition belong to the right node
1428  if(point(currentNode->getSplitAxis()) >= currentNode->getSplitPosition()) {
1429  currentNode = currentNode->rightNode();
1430  } else {
1431  currentNode = currentNode->leftNode();
1432  }
1433  }
1434  return currentNode;
1435  }
1436 
1440  const NodeType * getLowestCommonAncestor(const NodeType * a, const NodeType * b){
1441  // build list of parents to root
1442 
1443  ApproxMVBB_ASSERTMSG(a && b, "Input nodes are nullptr!")
1444 
1445  static std::vector<NodeType *> aL; // reserve treelevel nodes
1446  static std::vector<NodeType *> bL; // reserve treelevel nodes
1447  aL.clear();
1448  bL.clear();
1449 
1450  //std::cerr << " List A: ";
1451  NodeType * r = a->m_parent;
1452  while(r != nullptr){ // root has nullptr which stops
1453  aL.emplace_back(r);
1454  //std::cerr << r->getIdx() << ",";
1455  r = r->m_parent;
1456  }
1457  //std::cerr << std::endl;
1458 
1459  //std::cerr << " List B: ";
1460  r = b->m_parent;
1461  while(r != nullptr){
1462  bL.emplace_back(r);
1463  //std::cerr << r->getIdx() << ",";
1464  r = r->m_parent;
1465  }
1466  //std::cerr << std::endl;
1467 
1468  // list a = [5,4,3,1]
1469  // list b = [9,13,11,2,3,1]
1470  // lowest common ancestor = 3
1471  // get the node from root (from back of both lists)
1472  // where it differs
1473 
1474 
1475 
1476 
1477  std::size_t sizeA = aL.size();
1478  std::size_t sizeB = bL.size();
1479  NodeType * ret = nullptr;
1480  std::size_t s = std::min(sizeA,sizeB);
1481 
1482  for(std::size_t i = 1; i<=s;++i){
1483  if (aL[sizeA-i] == bL[sizeB-i]){
1484  ret = aL[sizeA-i];
1485  }else{
1486  break;
1487  }
1488  }
1489  return ret;
1490  }
1491 
1492  inline const NodeType * getLeaf(const std::size_t & leafIndex) const {
1493  if(leafIndex < m_leafs.size() ) {
1494  return m_leafs[leafIndex];
1495  }
1496  return nullptr;
1497  }
1498 
1499  inline const LeafContainerType & getLeafs() {
1500  return m_leafs;
1501  }
1502 
1503  inline const NodeType * getNode(const std::size_t & globalIndex) const {
1504  if(globalIndex < m_nodes.size()) {
1505  return m_nodes[globalIndex];
1506  }
1507  return nullptr;
1508  }
1509 
1510  inline const NodeContainerType & getNodes() {
1511  return m_nodes;
1512  }
1513 
1514  inline const NodeType * getRootNode(){
1515  return m_root;
1516  }
1517 
1518 
1522  template<typename... T>
1523  void cleanUp(T && ... t) {
1524  for(auto * p : m_nodes) {
1525  p->cleanUp(std::forward<T>(t)...);
1526  }
1527  }
1528 
1529  std::tuple<std::size_t, std::size_t >
1531  return std::make_tuple(m_nodes.size(),m_leafs.size());
1532  }
1533 
1534 
1539 
1540  std::size_t leafIdx = 0;
1541 
1542  this->m_leafs.clear(); // rebuild leafs list
1543 
1544  // reenumerate leaf nodes and isnert in leaf list
1545  for(auto * n : this->m_nodes) {
1546  if(n->isLeaf()) {
1547  n->m_idx=leafIdx++;
1548  this->m_leafs.emplace_back(n);
1549  }
1550  }
1551  std::size_t nonleafIdx = this->m_leafs.size();
1552 
1553  // reenumerate other nodes
1554  for(auto * n : this->m_nodes) {
1555  if(!n->isLeaf()) {
1556  n->m_idx = nonleafIdx++;
1557  }
1558  }
1559 
1560  // Sort m_nodes (IMPORTANT such that m_nodes[getIdx()] gives the correct node
1561  std::sort(m_nodes.begin(),m_nodes.end(), [](NodeType * a, NodeType * b) {return a->getIdx()< b->getIdx() ;} );
1562 
1563  }
1564 
1565  friend class XML;
1566  protected:
1567 
1568  NodeContainerType m_leafs;
1569  NodeContainerType m_nodes;
1570 
1571  NodeType * m_root = nullptr;
1572  };
1577  public:
1579  reset();
1580  }
1581  TreeStatistics(const TreeStatistics & s) = default;
1582 
1584  unsigned int m_treeDepth;
1591  std::size_t m_minLeafDataSize;
1592  std::size_t m_maxLeafDataSize;
1593 
1596  std::size_t m_minNeighbours;
1597  std::size_t m_maxNeighbours;
1599 
1600  void reset() {
1601  m_computedTreeStats = false;
1602  m_treeDepth = 0;
1603  m_avgSplitPercentage = 0.0;
1604  m_minLeafExtent = std::numeric_limits<PREC>::max();
1605  m_maxLeafExtent = 0.0;
1606  m_avgLeafSize = 0;
1607  m_minLeafDataSize = std::numeric_limits<std::size_t>::max();
1608  m_maxLeafDataSize = 0;
1609 
1610  m_computedNeighbourStats = false;
1611  m_minNeighbours = std::numeric_limits<std::size_t>::max();
1612  m_maxNeighbours = 0;
1613  m_avgNeighbours = 0;
1614  }
1615 
1616  void average(std::size_t nodes, std::size_t leafs) {
1617  if( nodes ){
1618  m_avgLeafSize /= nodes;
1619  }
1620  if(leafs){
1621  m_avgSplitPercentage /= nodes - leafs;
1622  }
1623  }
1624 
1625  template<typename TNode>
1626  void addNode(TNode * n) {
1627  if(n->isLeaf()) {
1628  auto s = n->data()->size();
1629  m_avgLeafSize += s;
1630  m_minLeafDataSize = std::min(m_minLeafDataSize,s);
1631  m_maxLeafDataSize = std::max(m_maxLeafDataSize,s);
1632  m_minLeafExtent = std::min(m_minLeafExtent,n->aabb().extent().minCoeff());
1633  m_maxLeafExtent = std::max(m_maxLeafExtent,n->aabb().extent().maxCoeff());
1634  }
1635  }
1636 
1637  friend class XML;
1638  };
1639 
1640 
1643  template<
1644  typename TNodeData = NoData<>,
1645  template<typename...> class TNode = NodeSimple
1646  >
1648 
1649  struct BaseTraits {
1650  using NodeDataType = TNodeData;
1651  static const unsigned int Dimension = NodeDataType::Dimension;
1652  using NodeType = TNode<BaseTraits>;
1653  };
1654 
1655  };
1656 
1657 
1659  template<typename TTraits = TreeSimpleTraits<> >
1660  class TreeSimple : public TreeBase<typename TTraits::BaseTraits> {
1661  public:
1662 
1663  using Traits = TTraits;
1664  using BaseTraits = typename TTraits::BaseTraits;
1666 
1668 
1669 
1671 
1673  template<typename Traits>
1675  : Base(std::move(tree)), m_statistics(std::move(tree.m_statistics)) {}
1677  template<typename Traits>
1679  : Base(tree), m_statistics(tree.m_statistics){}
1680 
1684  template< typename Traits >
1685  explicit TreeSimple( const Tree<Traits> & tree)
1686  : Base( tree ) , m_statistics(tree.m_statistics)
1687  {}
1688 
1689 
1690 
1692 
1696  std::tuple<std::size_t, std::size_t, std::size_t, PREC, std::size_t, std::size_t, PREC, PREC,std::size_t,std::size_t,PREC>
1698  return std::tuple_cat(
1699  Base::getStatistics(),
1700  std::make_tuple(
1701  m_statistics.m_treeDepth,
1702  m_statistics.m_avgLeafSize,
1703  m_statistics.m_minLeafDataSize,
1704  m_statistics.m_maxLeafDataSize,
1705  m_statistics.m_minLeafExtent,
1706  m_statistics.m_maxLeafExtent,
1707  m_statistics.m_minNeighbours,
1708  m_statistics.m_maxNeighbours,
1709  m_statistics.m_avgNeighbours)
1710  );
1711  }
1712 
1713 
1714  std::string getStatisticsString() {
1715  std::stringstream s;
1716  auto t = getStatistics();
1717  s << "Tree Stats: "
1718  << "\n\t nodes : " << std::get<0>(t)
1719  << "\n\t leafs : " << std::get<1>(t)
1720  << "\n\t tree level : " << std::get<2>(t)
1721  << "\n\t avg. leaf data size : " << std::get<3>(t)
1722  << "\n\t min. leaf data size : " << std::get<4>(t)
1723  << "\n\t max. leaf data size : " << std::get<5>(t)
1724  << "\n\t min. leaf extent : " << std::get<6>(t)
1725  << "\n\t max. leaf extent : " << std::get<7>(t)
1726  << "\nNeighbour Stats (if computed): \n"
1727  << "\n\t min. leaf neighbours : " << std::get<8>(t)
1728  << "\n\t max. leaf neighbours : " << std::get<9>(t)
1729  << "\n\t avg. leaf neighbours : " << std::get<10>(t) << std::endl;
1730 
1731  return s.str();
1732  }
1733 
1734 
1735  friend class XML;
1736  protected:
1737 
1738  using Base::m_nodes;
1739  using Base::m_leafs;
1740  using Base::m_root;
1741 
1743  };
1744 
1749  template<typename Traits>
1750  using SplitHeuristicPointDataDefault = meta::invoke<meta::bind_front<
1751  meta::quote<SplitHeuristicPointData>,
1753  >, Traits>;
1754 
1755 
1756  template<
1757  typename TNodeData = PointData<>,
1758  template<typename...> class TSplitHeuristic = SplitHeuristicPointDataDefault,
1759  template<typename...> class TNode = Node
1760  >
1761  struct TreeTraits {
1762 
1763  struct BaseTraits {
1764  using NodeDataType = TNodeData;
1765  static const unsigned int Dimension = NodeDataType::Dimension;
1766  using NodeType = TNode<BaseTraits>;
1767  };
1768 
1769  using SplitHeuristicType = TSplitHeuristic<BaseTraits>;
1770 
1771 
1772  };
1773 
1774 
1775 
1778  template<typename TTraits = TreeTraits<> >
1779  class Tree : public TreeBase<typename TTraits::BaseTraits> {
1780  private:
1781 
1782  template<typename T>
1783  friend class Tree;
1784 
1785  template<typename T>
1786  friend class TreeSimple;
1787 
1788  public:
1789 
1790  using Traits = TTraits;
1791  using BaseTraits = typename TTraits::BaseTraits;
1794 
1796 
1797  Tree() {}
1798  ~Tree() {}
1799 
1801  Tree( Tree && tree)
1802  : Base(std::move(tree)),
1803  m_heuristic(std::move(tree.m_heuristic)),
1804  m_statistics(std::move(tree.m_statistics)),
1805  m_maxLeafs(tree.m_maxLeafs), m_maxTreeDepth(tree.m_maxTreeDepth) {
1806  tree.resetStatistics();
1807  }
1808 
1810  Tree( const Tree & tree): Base(tree),
1811  m_heuristic(tree.m_heuristic),
1812  m_statistics(tree.m_statistics),
1813  m_maxLeafs(tree.m_maxLeafs), m_maxTreeDepth(tree.m_maxTreeDepth) {
1814  }
1816  template<typename T>
1817  explicit Tree( const Tree<T> & tree): Base(tree),
1818  m_statistics(tree.m_statistics),
1819  m_maxLeafs(tree.m_maxLeafs), m_maxTreeDepth(tree.m_maxTreeDepth) {
1820  }
1821 
1825  template<typename TTree>
1826  Tree( const TTree & tree): Base(tree) {}
1827 
1828 
1829 
1830  Tree & operator=(const Tree & t) = delete;
1831 
1832  void resetTree() {
1833  resetStatistics();
1834  Base::resetTree();
1835  }
1836 
1842  template<bool computeStatistics = true>
1843  void build(const AABB<Dimension> & aabb, std::unique_ptr<NodeDataType> data,
1844  unsigned int maxTreeDepth = 50,
1845  unsigned int maxLeafs = std::numeric_limits<unsigned int>::max()) {
1846 
1847  resetTree();
1848 
1849 
1850  m_statistics.m_computedTreeStats = computeStatistics;
1851  m_maxTreeDepth = maxTreeDepth;
1852  m_maxLeafs = maxLeafs;
1853 
1854 
1855  if((aabb.extent() <= 0.0).any()) {
1856  ApproxMVBB_ERRORMSG("AABB given has wrong extent!");
1857  }
1858  this->m_root = new NodeType(0,aabb,data.release());
1859 
1860  std::deque<NodeType*> splitList; // Breath first splitting
1861  splitList.push_back(this->m_root);
1862  this->m_nodes.push_back(this->m_root);
1863 
1864  bool nodeSplitted;
1865 
1866  m_statistics.m_treeDepth = 0;
1867  unsigned int nNodesLevelCurr = 1; // number of nodes in list of current level
1868  unsigned int nNodesLevelNext = 0; // number of nodes in list (after the current nodes with next level)
1869 
1870  unsigned int nLeafs = 1;
1871  // unsigned int nodeIdx = 0; // root node has idx = 0;
1872 
1873 // auto greaterData = [](const NodeType * a, const NodeType * b) {
1874 // return a->data()->size() > b->data()->size() ;
1875 // };
1876 
1877  while( !splitList.empty()) {
1878 
1879 
1880  auto * f = splitList.front();
1881 
1882  // first check if number of nodes at curr level is zero
1883  if(nNodesLevelCurr==0) {
1884  //std::cout << "Tree Level: " << m_statistics.m_treeDepth << " done, added childs: " << nNodesLevelNext << std::endl;
1885  ++m_statistics.m_treeDepth;
1886 
1887  std::swap(nNodesLevelCurr, nNodesLevelNext);
1888 
1889  // may be sort the child nodes in splitList according to their data size
1890  // (slow for big trees) std::sort(splitList.begin(),splitList.end(),greaterData);
1891 
1892  f = splitList.front();
1893  //std::cout << "biggest leaf size: " << splitList.front()->data()->size() << std::endl;
1894  }
1895 
1896  if(m_statistics.m_treeDepth+1 <= m_maxTreeDepth && nLeafs < m_maxLeafs) {
1897 
1898  // try to split the nodes in the list (number continuously!)
1899  nodeSplitted = f->split(m_heuristic,this->m_nodes.size());
1900  if(nodeSplitted) {
1901  auto * l = f->leftNode();
1902  auto * r = f->rightNode();
1903  splitList.emplace_back(l); // add to front
1904  splitList.emplace_back(r);// add to front
1905 
1906  // Push to total list
1907  this->m_nodes.emplace_back(l);
1908  this->m_nodes.emplace_back(r);
1909 
1910  nNodesLevelNext+=2;
1911  ++nLeafs; // each split adds one leaf
1912 
1913  } else {
1914  // this is a leaf
1915  this->m_leafs.emplace_back(f);
1916  }
1917 
1918  // add to node statistic:
1919  if(computeStatistics) {
1920  m_statistics.addNode(f);
1921  }
1922 
1923  } else {
1924  // depth level reached, add to leafs
1925 
1926  this->m_leafs.emplace_back(f);
1927 
1928  // add to node statistics
1929  if(computeStatistics) {
1930  m_statistics.addNode(f);
1931  }
1932 
1933  }
1934  --nNodesLevelCurr;
1935  // pop node at the front
1936  splitList.pop_front();
1937  }
1938 
1939  // enumerate nodes new (firsts leafs then all other nodes)
1940  this->enumerateNodes();
1941 
1942 
1943  if(computeStatistics) {
1944  averageStatistics();
1945  }
1946  }
1947 
1948  template<typename... T>
1949  void initSplitHeuristic(T &&... t) {
1950  m_heuristic.init(std::forward<T>(t)...);
1951  }
1952 
1953  template<bool computeStatistics = true, bool safetyCheck = true>
1954  LeafNeighbourMapType
1956  if(!m_statistics.m_computedTreeStats) {
1957  ApproxMVBB_ERRORMSG("You did not compute statistics for this tree while constructing it!")
1958  }
1959  /* Here the minLeafExtent ratio is made slightly smaller to make the neighbour classification sensfull */
1960  /* Multiple cells can have m_minLeafExtent */
1961  return buildLeafNeighbours<computeStatistics,safetyCheck>(0.99*m_statistics.m_minLeafExtent);
1962  }
1963 
1964  template<bool computeStatistics = true, bool safetyCheck = true>
1965  LeafNeighbourMapType
1966  buildLeafNeighbours(PREC minExtent) {
1967  if(!this->m_root) {
1968  ApproxMVBB_ERRORMSG("There is not root node! KdTree not built!")
1969  }
1970 
1971  m_statistics.m_computedNeighbourStats = computeStatistics;
1972 
1973  // Get all leaf neighbour indices for each leaf node!
1974  // To do this, we traverse the leaf list and for each leaf l
1975  // we determine in each direction of the kd-Tree in R^n (if 3D, 3 directions)
1976  // for "min" and "max" the corresponding leafs in the subtrees given by
1977  // the boundary information in the leaf node:
1978  // e.g. for the "max" direction in x for one leaf, we traverse the subtree of the boundary
1979  // information in "max" x direction
1980  // for "max" we always take the left node (is the one which is closer to our max x boundary)
1981  // for "min" we always take the right node (is the one which is closer to our min x boundary)
1982  // in this way we get all candidate leaf nodes (which share the same split axis with split position s)
1983  // which need still to be checked if they are neighbours
1984  // this is done by checking if the boundary subspace with the corresponding axis set to the split position s
1985  // (space without the axis which is checked, e.g y-z space, with x = s)
1986  // against the current leaf nodes boundary subspace
1987  // (which is thickened up by the amount of the minimal leaf node extent size,
1988  // important because its not clear what should count as a neighbout or what not)
1989  // if this neighbour n subspace overlaps the thickened leaf node subspace then this node is
1990  // considered as a neighbour for leaf l, (and also neighbour n has l as neighbour obviously)
1991  // If the tree is build with the same min_extent size as the thickening in this step here, then it should work
1992  // since the tree has all extents striclty greater then min_extent, and here
1993  // to avoid to many nodes to be classified as neighbours (trivial example, min_extent grid)
1994 
1995  // each leaf gets a
1996  std::unordered_map<std::size_t, std::unordered_set<std::size_t> > leafToNeighbourIdx;
1997 
1998  // iterate over all leafs
1999  for(auto * node: this->m_leafs) {
2000  node->getNeighbourLeafsIdx(leafToNeighbourIdx, minExtent);
2001  }
2002 
2003  // Do safety check in debug mode
2004  if(safetyCheck) {
2005  safetyCheckNeighbours(leafToNeighbourIdx,minExtent);
2006  }
2007 
2008  // Compute statistics
2009  if(computeStatistics) {
2010  m_statistics.m_minNeighbours = std::numeric_limits<std::size_t>::max();
2011  m_statistics.m_maxNeighbours = 0;
2012  m_statistics.m_avgNeighbours = 0;
2013 
2014  for(auto & n: leafToNeighbourIdx) {
2015  m_statistics.m_avgNeighbours += n.second.size();
2016  m_statistics.m_minNeighbours = std::min(m_statistics.m_minNeighbours,n.second.size());
2017  m_statistics.m_maxNeighbours = std::max(m_statistics.m_maxNeighbours,n.second.size());
2018 
2019  }
2020  m_statistics.m_avgNeighbours /= this->m_leafs.size();
2021  }
2022 
2023  return leafToNeighbourIdx;
2024  }
2025 
2027  struct ParentInfo {
2028  ParentInfo( NodeType* p, bool l=false,bool r = false): m_parent(p), childVisited{l,r} {}
2029  NodeType* m_parent;
2030  bool childVisited[2];
2031  };
2032 
2033  private:
2034 
2039  template <typename Container, typename Compare>
2040  class KNearestPrioQueue : public std::priority_queue<typename NodeDataType::PointListType::value_type,
2041  Container,
2042  Compare> {
2043  public:
2044 
2045  using value_type = typename Container::value_type;
2046 
2047  ApproxMVBB_STATIC_ASSERT((std::is_same< value_type,
2048  typename NodeDataType::PointListType::value_type>::value))
2049 
2050  using Base = std::priority_queue<typename NodeDataType::PointListType::value_type,Container,Compare>;
2051 
2052  using iterator = typename Container::iterator;
2053  using reverse_iterator = typename Container::reverse_iterator;
2054 
2055  Container &getContainer() {
2056  return this->c;
2057  }
2058  Compare &getComperator() {
2059  return this->comp;
2060  }
2061 
2063  return this->c.begin();
2064  }
2066  return this->c.end();
2067  }
2068 
2070  return this->c.rbegin();
2071  }
2073  return this->c.rend();
2074  }
2075 
2076  KNearestPrioQueue(std::size_t maxSize): m_maxSize(maxSize) {
2077  this->c.reserve(m_maxSize);
2078  }
2079 
2080  inline void clear() {
2081  this->c.clear();
2082  }
2083 
2084  inline bool full() {
2085  return this->size() == m_maxSize;
2086  }
2087 
2088  inline void push( const typename Base::value_type & v) {
2089  if (this->size() < m_maxSize) {
2090  Base::push(v);
2091  } else if( this->comp(v,this->top()) ) {
2092  Base::pop();
2093  Base::push(v);
2094  }
2095  }
2096 
2097  template<typename It>
2098  inline void push(It beg, It end) {
2099  It it = beg;
2100  auto s = this->size();
2101  while(s < m_maxSize && it!=end) {
2102  Base::push(*it);
2103  ++it;
2104  ++s;
2105  }
2106  while(it!=end) {
2107  // if *it < top -> insert
2108  if( this->comp(*it,this->top()) ) {
2109  Base::pop();
2110  Base::push(*it);
2111  }
2112  ++it;
2113  }
2114  }
2115 
2117  template<typename Iterator>
2118  void replace(Iterator begin, Iterator end) {
2119  this->c.clear();
2120  this->c.insert(this->c.begin(),begin, end);
2121  std::make_heap(this->c.begin(), this->c.end(), this->comp );
2122  }
2123 
2124  std::size_t maxSize() {
2125  return m_maxSize;
2126  }
2127 
2128  private:
2129  std::size_t m_maxSize;
2130  };
2131 
2132  public:
2133 
2134  template<typename TDistSq = EuclideanDistSq,
2135  typename TContainer = StdVecAligned<typename NodeDataType::PointListType::value_type>
2136  >
2137  struct KNNTraits {
2139  using ContainerType = TContainer;
2140  using DistCompType = typename NodeDataType::template DistanceComp<DistSqType>;
2141  using PrioQueue = KNearestPrioQueue<
2142  ContainerType,
2143  DistCompType
2144  >;
2145  };
2146 
2147  private:
2148 
2149  template<typename T> struct isKNNTraits;
2150  template<typename N, typename C>
2151  struct isKNNTraits< KNNTraits<N,C> > {
2152  static const bool value = true;
2153  };
2154 
2155  public:
2156 
2157  template<typename TKNNTraits>
2158  void getKNearestNeighbours( typename TKNNTraits::PrioQueue & kNearest) const {
2159 
2161 
2162  kNearest.clear();
2163 
2164  if(!this->m_root || kNearest.maxSize() == 0) {
2165  return;
2166  }
2167 
2168  // distance comperator
2169  //using DistSqType = typename TKNNTraits::DistSqType;
2170  typename TKNNTraits::DistCompType & distComp = kNearest.getComperator();
2171  // reference point is distComp.m_ref
2172 
2173  // Debug set, will be optimized away in release
2174  // std::set<NodeType*> visitedLeafs;
2175 
2176  // Get leaf node and parent stack by traversing down the tree
2177  std::vector< ParentInfo > parents;
2178  parents.reserve(m_statistics.m_treeDepth);
2179 
2180  parents.emplace_back( nullptr, false, false); // emplace
2181  NodeType * currNode = this->m_root;
2182 
2183 
2184  while(!currNode->isLeaf()) {
2185  // all points greater or equal to the splitPosition belong to the right node
2186  if(distComp.m_ref(currNode->m_splitAxis) >= currNode->m_splitPosition) {
2187  parents.emplace_back( currNode, false,true );
2188  currNode = currNode->rightNode();
2189  } else {
2190  parents.emplace_back( currNode, true,false );
2191  currNode = currNode->leftNode();
2192  }
2193  }
2194  ApproxMVBB_ASSERTMSG(currNode && currNode->isLeaf(), "currNode is nullptr!")
2195  // currNode is a leaf !
2196 
2197  PREC d = 0.0;
2198  PREC maxDistSq = 0.0;
2199  ParentInfo * currParentInfo = nullptr;
2200 
2201  // Move up the tree, always visiting the all childs which overlap the norm ball
2202  while(currNode!=nullptr) {
2203 
2204  currParentInfo = &parents.back();
2205  ApproxMVBB_ASSERTMSG(currNode, "currNode is nullptr!")
2206 
2207  if( !currNode->isLeaf()) {
2208 
2209  // this is no leaf
2210  if (!currParentInfo->childVisited[0]) {
2211  // left not visited
2212  // we processed this child
2213  currParentInfo->childVisited[0] = true; // set parents flag
2214 
2215  if( kNearest.full()) {
2216  // compute distance to split Axis
2217  d = currParentInfo->m_parent->m_splitPosition - distComp.m_ref(currParentInfo->m_parent->m_splitAxis);
2218  if(d<=0.0) {
2219  // ref point is right of split axis
2220  if( d*d >= maxDistSq) {
2221  continue; // no overlap
2222  }
2223  }
2224  // ref point is left of split axis
2225  }
2226  // maxNorm ball overlaps left side or to little points
2227  // visit left side!
2228  currNode = currNode->leftNode(); // cannot be nullptr, since currNode is not leaf
2229  ApproxMVBB_ASSERTMSG(currNode,"cannot be nullptr, since a leaf")
2230  if (!currNode->isLeaf()) {
2231  // add the parent if no leaf
2232  parents.emplace_back(currNode);
2233  }
2234 
2235  continue;
2236 
2237  } else if (!currParentInfo->childVisited[1]) {
2238  // right not visited
2239  // we processed this child
2240  currParentInfo->childVisited[1] = true; // set parents flag
2241  if( kNearest.full()) {
2242  d = currParentInfo->m_parent->m_splitPosition - distComp.m_ref(currParentInfo->m_parent->m_splitAxis);
2243  if( d > 0) {
2244  // ref point is left of split axis
2245  if( d*d > maxDistSq) {
2246  continue; // no overlap
2247  }
2248  }
2249  }
2250 
2251  // maxNorm ball overlaps right side or to little points!
2252  // visit right side!
2253  currNode = currNode->rightNode();
2254  ApproxMVBB_ASSERTMSG(currNode,"cannot be nullptr, since a leaf")
2255  if (!currNode->isLeaf()) {
2256  // add to parent
2257  parents.emplace_back( currNode );
2258  }
2259  continue;
2260  }
2261 
2262  // we have have visited both,
2263  // we pop parent and move a level up!
2264  parents.pop_back(); // last one is this nonleaf, pop it
2265  // the first parent contains a nullptr, such that we break when we move up from the root
2266  currNode = parents.back().m_parent;
2267 
2268  } else {
2269  // this is a leaf
2270  // if(visitedLeafs.insert(currNode).second==false){
2271  // ApproxMVBB_ERRORMSG("leaf has already been visited!")
2272  // }
2273 
2274  // get at least k nearst points in this leaf and merge with kNearest list
2275  if(currNode->size()>0) {
2276  kNearest.push(currNode->data()->begin(),currNode->data()->end());
2277  // update max norm
2278  maxDistSq = distComp(kNearest.top());
2279  }
2280  // finished with this leaf, got to parent!
2281  currNode = currParentInfo->m_parent;
2282  continue;
2283  }
2284 
2285 
2286  }
2287  }
2288 
2294  std::tuple<std::size_t, std::size_t, std::size_t, PREC, std::size_t, std::size_t, PREC, PREC,std::size_t,std::size_t,PREC>
2296  return std::tuple_cat(
2297  Base::getStatistics(),
2298  std::make_tuple(
2299  m_statistics.m_treeDepth,
2300  m_statistics.m_avgLeafSize,
2301  m_statistics.m_minLeafDataSize,
2302  m_statistics.m_maxLeafDataSize,
2303  m_statistics.m_minLeafExtent,
2304  m_statistics.m_maxLeafExtent,
2305  m_statistics.m_minNeighbours,
2306  m_statistics.m_maxNeighbours,
2307  m_statistics.m_avgNeighbours)
2308  );
2309  }
2310 
2311  std::string getStatisticsString() {
2312  std::stringstream s;
2313  auto t = getStatistics();
2314  std::string h = m_heuristic.getStatisticsString();
2315  s << "Tree Stats: "
2316  << "\n\t nodes : " << std::get<0>(t)
2317  << "\n\t leafs : " << std::get<1>(t)
2318  << "\n\t tree level : " << std::get<2>(t)
2319  << "\n\t avg. leaf data size : " << std::get<3>(t)
2320  << "\n\t min. leaf data size : " << std::get<4>(t)
2321  << "\n\t max. leaf data size : " << std::get<5>(t)
2322  << "\n\t min. leaf extent : " << std::get<6>(t)
2323  << "\n\t max. leaf extent : " << std::get<7>(t)
2324  << "\nSplitHeuristics Stats: \n"
2325  << h
2326  << "\nNeighbour Stats (if computed): \n"
2327  << "\n\t min. leaf neighbours : " << std::get<8>(t)
2328  << "\n\t max. leaf neighbours : " << std::get<9>(t)
2329  << "\n\t avg. leaf neighbours : " << std::get<10>(t) << std::endl;
2330 
2331  return s.str();
2332  }
2333 
2334  friend class XML;
2335  private:
2336 
2337 
2339 
2340  unsigned int m_maxTreeDepth = 50;
2341  unsigned int m_maxLeafs = std::numeric_limits<unsigned int>::max();
2342 
2345 
2346 
2348  m_statistics.reset();
2349  m_heuristic.resetStatistics();
2350  }
2352  m_statistics.average(this->m_nodes.size(),this->m_leafs.size());
2353  }
2354 
2355 
2357  template<typename NeighbourMap>
2358  void safetyCheckNeighbours(const NeighbourMap & n, PREC minExtent) {
2359 
2360  if(n.size() != this->m_leafs.size()) {
2361  ApproxMVBB_ERRORMSG("Safety check for neighbours failed!: size:" << n.size() <<","<<this->m_leafs.size())
2362  }
2363 
2364 
2365  for(auto * l: this->m_leafs) {
2366  // Check leaf l
2367  AABB<Dimension> t = l->aabb();
2368  t.expand(minExtent);
2369 
2370  // check against neighbours ( if all neighbours really overlap )
2371  auto it = n.find(l->getIdx()); // get neighbours for this leaf
2372  if(it == n.end()) {
2373  ApproxMVBB_ERRORMSG("Safety check: Leaf idx" << l->getIdx() << " not in neighbour map!")
2374  }
2375 
2376  for(const auto & idx : it->second ) {
2377  if(this->getLeaf(idx) == nullptr) {
2378  ApproxMVBB_ERRORMSG("Safety check: Neighbour idx" << idx << " not found!")
2379  }
2380  // check if this neighbour overlaps
2381  if( ! t.overlaps( this->m_leafs[idx]->aabb() ) ) {
2382  ApproxMVBB_ERRORMSG("Safety check: Leaf idx: " << idx << " does not overlap " << l->getIdx())
2383  }
2384  // check if this neighbours also has this leaf as neighbour
2385  auto nIt = n.find(idx);
2386  if(nIt == n.end()) {
2387  ApproxMVBB_ERRORMSG("Safety check: Neighbour idx" << idx << " not in neighbour map!")
2388  }
2389  if(nIt->second.find(l->getIdx()) == nIt->second.end() ) {
2390  ApproxMVBB_ERRORMSG("Safety check: Neighbour idx" << idx << " does not have leaf idx: " << l->getIdx() << " as neighbour")
2391  }
2392  }
2393 
2394  // built brute force list with AABB t
2395  std::unordered_set<std::size_t> ns;
2396  for(auto * ll : this->m_leafs){
2397  if( ll->getIdx() != l->getIdx() && t.overlaps( ll->aabb() ) ) {
2398  ns.emplace(ll->getIdx());
2399  }
2400  }
2401  // check brute force list with computed list
2402  for(auto & i : ns){
2403  if( it->second.find(i) == it->second.end() ){
2404  ApproxMVBB_ERRORMSG("Safety check: Bruteforce list has neighbour idx: " << i << " for leaf idx: " << l->getIdx() << " but not computed list!")
2405  }
2406  }
2407  if(ns.size() != it->second.size()){
2408  ApproxMVBB_ERRORMSG("Safety check: Bruteforce list and computed list are not the same size!" << ns.size() << "," << it->second.size() )
2409  }
2410 
2411  }
2412 
2413  }
2414  };
2415 
2418  template<typename TTraits = KdTree::DefaultPointDataTraits<> >
2420  public:
2421 
2422  using PointDataTraits = TTraits;
2423  static const unsigned int Dim = PointDataTraits::Dimension;
2424  using PointListType = typename PointDataTraits::PointListType;
2425  using PointType = typename PointDataTraits::PointType;
2426  using PointGetter = typename PointDataTraits::PointGetter;
2427 
2430  >
2431  >;
2433  using NodeDataType = typename Tree::NodeDataType;
2434 
2436  NearestNeighbourFilter( std::size_t kNeighboursMean = 20,
2437  PREC stdDevMult=1.0,
2438  std::size_t allowSplitAboveNPoints = 10 ):
2439  m_kNeighboursMean(kNeighboursMean), m_stdDevMult(stdDevMult), m_allowSplitAboveNPoints(allowSplitAboveNPoints) {
2440  if(m_kNeighboursMean==0) {
2441  ApproxMVBB_ERRORMSG("kNeighboursMean is zero! (needs to be >=1)")
2442  }
2443  }
2444 
2445  inline std::tuple<std::size_t,PREC,std::size_t>
2447  {
2448  return std::make_tuple(m_kNeighboursMean,m_stdDevMult,m_allowSplitAboveNPoints);
2449  }
2450 
2451  inline void setSettings(std::size_t kNeighboursMean,
2452  PREC stdDevMult,
2453  std::size_t allowSplitAboveNPoints)
2454  {
2455  m_kNeighboursMean = kNeighboursMean;
2456  m_stdDevMult = stdDevMult;
2457  m_allowSplitAboveNPoints = allowSplitAboveNPoints;
2458  }
2459 
2468  template<typename Container,
2469  typename DistSq = EuclideanDistSq,
2470  typename = typename std::enable_if<ContainerTags::has_randomAccessIterator<Container>::value>::type
2471  >
2472  void filter(Container & points, const AABB<Dim> & aabb, Container & output, bool invert=false) {
2473 
2474  ApproxMVBB_STATIC_ASSERTM( (std::is_same< typename Container::value_type,
2475  typename PointListType::value_type>::value),
2476  "Container value_type needs to be the same as value_type of PointDataTraits!")
2477 
2478  // Make kdTree;
2479  Tree tree;
2480 
2481  typename SplitHeuristicType::QualityEvaluator qual(0.0, /* splitratio (maximized by MidPoint) */
2482  2.0, /* pointratio (maximized by MEDIAN)*/
2483  1.0);/* extentratio (maximized by MidPoint)*/
2484 
2485  PREC minExtent = 0.0; // box extents are bigger than this!
2486  tree.initSplitHeuristic( std::initializer_list<typename SplitHeuristicType::Method> {
2487  /*SplitHeuristicType::Method::MEDIAN,*/
2488  /*SplitHeuristicType::Method::GEOMETRIC_MEAN,*/
2489  SplitHeuristicType::Method::MIDPOINT
2490  },
2491  m_allowSplitAboveNPoints, minExtent,
2492  SplitHeuristicType::SearchCriteria::FIND_FIRST, qual,
2493  0.0, 0.0, 0.1);
2494 
2495  auto rootData = std::unique_ptr<NodeDataType>(new NodeDataType(points.begin(),points.end()));
2496  unsigned int inf = std::numeric_limits<unsigned int>::max();
2497  tree.build(aabb,std::move(rootData), inf /*max tree depth*/, inf /*max leafs*/);
2498 
2499 
2500  // Start filtering =======================================
2501  using KNNTraits = typename Tree::template KNNTraits<DistSq>;
2502  typename KNNTraits::PrioQueue kNearest(m_kNeighboursMean+1);
2503  typename KNNTraits::DistCompType & compDist = kNearest.getComperator();
2504 
2505  // reserve space for all nearest distances (we basically analyse the histogram of the nearst distances)
2506 
2507  m_nearestDists.assign(points.size(),0.0);
2508 
2509 
2510  std::size_t validPoints = 0;
2511  typename KNNTraits::PrioQueue::iterator it;
2512  typename KNNTraits::PrioQueue::iterator e;
2513  PREC sum = 0.0;
2514  auto nPoints = points.size();
2515  for(std::size_t i = 0; i < nPoints; ++i) {
2516  //std::cout << "i: " << i << std::endl;
2517  // Get the kNearest neighbours
2518  kNearest.getComperator().m_ref = PointGetter::get(points[i]);
2519  tree.template getKNearestNeighbours<KNNTraits>(kNearest);
2520 
2521  // compute sample mean and standart deviation of the sample
2522 
2523  // we dont include our own point (which is also a result)
2524  // we should always have some kNearst neighbours, if we have a non-empty point cloud
2525  // otherwise something is fishy!, anyway check for this
2526 
2527  if( kNearest.size() > 1) {
2528  e = kNearest.end();
2529  sum = 0.0;
2530  for(it=++kNearest.begin(); it!=e; ++it) {
2531  sum += std::sqrt(compDist(*it));
2532  }
2533  // save mean nearest distance
2534  m_nearestDists[i] = sum / (kNearest.size()-1);
2535  ++validPoints;
2536  }
2537 
2538  }
2539 
2540  // compute mean and standart deviation
2541  sum = 0.0;
2542  PREC sumSq = 0.0;
2543  for (std::size_t i = 0; i < nPoints; ++i) {
2544  sum += m_nearestDists[i];
2545  sumSq += m_nearestDists[i] * m_nearestDists[i];
2546  }
2547  m_mean = sum / validPoints;
2548  m_stdDev = std::sqrt( (sumSq - sum*sum/validPoints) / validPoints );
2549 
2550 
2551  PREC distanceThreshold = m_mean + m_stdDevMult * m_stdDev; // a distance that is bigger than this signals an outlier
2552 
2553  // move over all points and build new list (without outliers)
2554  // all points which where invalid are left untouched since m_nearestDists[i] == 0
2555  output.resize(points.size());
2556  std::size_t nPointsOut = 0;
2557  if(!invert) {
2558  for(std::size_t i = 0; i < nPoints; ++i) {
2559  if (m_nearestDists[i] < distanceThreshold) {
2560  // no outlier add to list
2561  output[nPointsOut] = points[i];
2562  ++nPointsOut;
2563  }
2564  }
2565  } else {
2566  for(std::size_t i = 0; i < nPoints; ++i) {
2567  if (m_nearestDists[i] >= distanceThreshold) {
2568  // outlier add to list
2569  output[nPointsOut] = points[i];
2570  ++nPointsOut;
2571  }
2572  }
2573  }
2574  output.resize(nPointsOut);
2575 
2576  // =======================================================
2577 
2578  }
2579 
2586  using NearestDistancesType = std::vector<PREC>;
2587  std::vector<PREC> & getNearestDists() {
2588  return m_nearestDists;
2589  }
2590 
2594  std::pair<PREC,PREC> getMoments(){
2595  return std::make_pair(m_mean,m_stdDev);
2596  }
2597 
2598 
2599  private:
2600 
2602  PREC m_mean = 0;
2603  PREC m_stdDev = 0;
2604 
2606  std::size_t m_kNeighboursMean;
2612 
2614 
2615 
2616  };
2617 
2618  }
2619 
2620 }
2621 
2622 #endif
std::pair< PointData *, PointData * > split(iterator splitRightIt) const
Definition: KdTree.hpp:199
#define ApproxMVBB_ASSERTMSG(condition, message)
An Assert Macro to use within C++ code.
std::vector< PREC > & getNearestDists()
Definition: KdTree.hpp:2587
NodeDataType * data()
Definition: KdTree.hpp:1084
NodeDataType * m_data
Definition: KdTree.hpp:1245
const_iterator end() const
Definition: KdTree.hpp:231
std::string getStatisticsString()
Definition: KdTree.hpp:2311
typename Traits::const_iterator const_iterator
Definition: KdTree.hpp:176
std::vector< SplitAxisType > m_splitAxes
Definition: KdTree.hpp:708
typename NodeType::SplitAxisType SplitAxisType
Definition: KdTree.hpp:318
BoundaryInfoType m_bound
Definition: KdTree.hpp:1250
typename Traits::PointType PointType
Definition: KdTree.hpp:173
std::tuple< std::size_t, std::size_t > getStatistics()
Definition: KdTree.hpp:1530
Tree(const Tree &tree)
Definition: KdTree.hpp:1810
void setSplitAxis(SplitAxisType splitAxis)
Definition: KdTree.hpp:859
NodeContainerType m_leafs
Only leaf nodes , continously index ordered: leafs[idx]->getIdx() < leafs[idx+1]->getIdx();.
Definition: KdTree.hpp:1568
const BoundaryInfoType & getBoundaries() const
Definition: KdTree.hpp:1077
void setLevel(unsigned int level)
Definition: KdTree.hpp:275
VectorStat< Dim > m_minPoint
Definition: AABB.hpp:254
BoundaryInfoType & getBoundaries()
Definition: KdTree.hpp:1078
bool operator()(const T &p1, const T &p2)
Definition: KdTree.hpp:90
bool split(TSplitHeuristic &s, std::size_t startIdx=0)
Definition: KdTree.hpp:1097
void safetyCheckNeighbours(const NeighbourMap &n, PREC minExtent)
Definition: KdTree.hpp:2358
These are some container definitions.
NodeSimple(const NodeSimple &t)
Definition: KdTree.hpp:951
typename PointDataType::iterator iterator
Definition: KdTree.hpp:305
std::size_t getIdx() const
Definition: KdTree.hpp:855
DistanceComp< TPoint, TPointGetter > DistanceComp
Definition: KdTree.hpp:107
const NodeType * getRootNode()
Definition: KdTree.hpp:1514
LinearQualityEvaluator(PREC ws=0.0, PREC wp=0.0, PREC we=1.0)
Definition: KdTree.hpp:272
std::size_t size()
Definition: KdTree.hpp:1239
const DerivedNode * parent() const
Definition: KdTree.hpp:817
LeafNeighbourMapType buildLeafNeighboursAutomatic()
Definition: KdTree.hpp:1955
typename Traits::iterator iterator
Definition: KdTree.hpp:175
typename Container::iterator iterator
Definition: KdTree.hpp:2052
PREC getGeometricMean(unsigned int axis)
Definition: KdTree.hpp:208
std::size_t size() const
Definition: KdTree.hpp:236
LeafNeighbourMapType buildLeafNeighbours(PREC minExtent)
Definition: KdTree.hpp:1966
#define ApproxMVBB_ERRORMSG(message)
DerivedNode *const * begin() const
Definition: KdTree.hpp:771
void setBoundaryInfo(const BoundaryInfoType &b)
Definition: KdTree.hpp:1080
NodeSimple(std::size_t idx, const AABB< Dimension > &aabb)
Definition: KdTree.hpp:949
const_iterator begin() const
Definition: KdTree.hpp:227
void push(const typename Base::value_type &v)
Definition: KdTree.hpp:2088
Node(const Node< Traits > &n)
Definition: KdTree.hpp:1064
typename NodeDataType::template DistanceComp< DistSqType > DistCompType
Definition: KdTree.hpp:2140
void setSplitPosition(PREC splitPos)
Definition: KdTree.hpp:862
PREC computeExtentRatio(AABB< Dimension > &aabb)
Definition: KdTree.hpp:640
bool overlaps(const AABB &box) const
Definition: AABB.hpp:140
NodeBase(NodeBase< Derived, Dimension > &&n)
Definition: KdTree.hpp:802
void build(const AABB< Dimension > &aabb, std::unique_ptr< NodeDataType > data, unsigned int maxTreeDepth=50, unsigned int maxLeafs=std::numeric_limits< unsigned int >::max())
Definition: KdTree.hpp:1843
typename Traits::PointGetter PointGetter
Definition: KdTree.hpp:177
Tree(const Tree< T > &tree)
Definition: KdTree.hpp:1817
NearestNeighbourFilter(std::size_t kNeighboursMean=20, PREC stdDevMult=1.0, std::size_t allowSplitAboveNPoints=10)
Definition: KdTree.hpp:2436
DerivedNode * rightNode()
Definition: KdTree.hpp:826
VectorStat< Dim > m_maxPoint
Definition: AABB.hpp:255
DerivedNode * leftNode()
Definition: KdTree.hpp:819
std::tuple< std::size_t, std::size_t, std::size_t, PREC, std::size_t, std::size_t, PREC, PREC, std::size_t, std::size_t, PREC > getStatistics()
Definition: KdTree.hpp:2295
iterator m_end
The actual range of m_points which this node contains.
Definition: KdTree.hpp:251
~TreeBase()
Prohibit the use of this base polymophically.
Definition: KdTree.hpp:1334
TSplitHeuristic< BaseTraits > SplitHeuristicType
Definition: KdTree.hpp:1769
void getKNearestNeighbours(typename TKNNTraits::PrioQueue &kNearest) const
Definition: KdTree.hpp:2158
typename Traits::SplitHeuristicType SplitHeuristicType
Definition: KdTree.hpp:1795
void setLevel(unsigned int l) const
Definition: KdTree.hpp:881
bool computeSplitPosition(NodeType *node, unsigned int tries=1)
Definition: KdTree.hpp:504
NodeSimple(const Node< T > &t)
Definition: KdTree.hpp:955
void setup(const Node< T > *t, const NodeVector &nodes)
Definition: KdTree.hpp:963
const NodeType * getLeaf(const std::size_t &leafIndex) const
Definition: KdTree.hpp:1492
void average(std::size_t nodes, std::size_t leafs)
Definition: KdTree.hpp:1616
void replace(Iterator begin, Iterator end)
Definition: KdTree.hpp:2118
bool hasChildren() const
Definition: KdTree.hpp:843
typename PointDataTraits::PointListType PointListType
Definition: KdTree.hpp:2424
std::string getPointString()
Definition: KdTree.hpp:240
typename TTraits::BaseTraits BaseTraits
Definition: KdTree.hpp:1791
TreeBase(const TreeBase< T > &t)
Definition: KdTree.hpp:1282
DerivedNode *& at(unsigned int idx)
Definition: KdTree.hpp:750
unsigned int getLevel() const
Definition: KdTree.hpp:877
PREC getSplitPosition() const
Definition: KdTree.hpp:869
PREC operator()(const T &p1)
Definition: KdTree.hpp:96
void filter(Container &points, const AABB< Dim > &aabb, Container &output, bool invert=false)
Definition: KdTree.hpp:2472
const NodeType * getLeaf(const MatrixBase< Derived > &point) const
Definition: KdTree.hpp:1420
Base::BoundaryInfoType m_bound
Definition: KdTree.hpp:941
meta::if_< details::isDefault< TPointGetter >, PointGetterImpl< typename PointListType::value_type >, TPointGetter > PointGetter
Definition: KdTree.hpp:156
#define DEFINE_KDTREE_BASETYPES(__Traits__)
Definition: KdTree.hpp:62
typename Tree::NodeDataType NodeDataType
Definition: KdTree.hpp:2433
const BoundaryInfoType & getBoundaries() const
Definition: KdTree.hpp:1005
TreeBase(const TreeBase &t)
Definition: KdTree.hpp:1277
void setChilds(DerivedNode *r, DerivedNode *l)
Definition: KdTree.hpp:811
SplitAxisType m_splitAxis
-1 indicates leaf node
Definition: KdTree.hpp:894
std::string getStatisticsString()
Definition: KdTree.hpp:1714
typename details::select< PD, NodeSimple< TTraits, PD > >::type DerivedType
Definition: KdTree.hpp:925
bool hasLeftChildren() const
Definition: KdTree.hpp:840
static const Eigen::IOFormat SpaceSep
#define ApproxMVBB_STATIC_ASSERT(B)
typename Traits::PointListType PointListType
Definition: KdTree.hpp:174
const DerivedNode * leftNode() const
Definition: KdTree.hpp:822
NodeBase(const NodeBase< Derived, Dimension > &n)
Definition: KdTree.hpp:795
void getNeighbourLeafsIdx(NeighbourIdxMap &neigbourIdx, PREC minExtent)
Definition: KdTree.hpp:1141
typename PointDataType::PointType PointType
Definition: KdTree.hpp:304
meta::invoke< meta::bind_front< meta::quote< SplitHeuristicPointData >, LinearQualityEvaluator >, Traits > SplitHeuristicPointDataDefault
Definition: KdTree.hpp:1753
const NodeContainerType & getNodes()
Definition: KdTree.hpp:1510
std::pair< PREC, PREC > getMoments()
Definition: KdTree.hpp:2594
std::size_t m_idx
node index
Definition: KdTree.hpp:891
void setSettings(std::size_t kNeighboursMean, PREC stdDevMult, std::size_t allowSplitAboveNPoints)
Definition: KdTree.hpp:2451
meta::if_< details::isDefault< TDistanceCompTraits >, DefaultDistanceCompTraits< PointType, PointGetter >, TDistanceCompTraits > DistCompTraits
Definition: KdTree.hpp:162
void initSplitHeuristic(T &&...t)
Definition: KdTree.hpp:1949
ParentInfo(NodeType *p, bool l=false, bool r=false)
Definition: KdTree.hpp:2028
typename Tree::SplitHeuristicType SplitHeuristicType
Definition: KdTree.hpp:2432
typename PointDataTraits::PointType PointType
Definition: KdTree.hpp:2425
typename TTraits::BaseTraits BaseTraits
Definition: KdTree.hpp:1664
#define ApproxMVBB_DEFINE_POINTS_CONFIG_TYPES
void build(NodeType *root, NodeMap &c, NodeToChildMap &links)
Definition: KdTree.hpp:1349
TreeSimple(const Tree< Traits > &tree)
Definition: KdTree.hpp:1685
DerivedNode *const & at(unsigned int idx) const
Definition: KdTree.hpp:754
NodeBase(std::size_t idx, const AABB< Dimension > &aabb, SplitAxisType axis, PREC splitPos)
Definition: KdTree.hpp:887
TreeSimple(const TreeSimple< Traits > &tree)
Definition: KdTree.hpp:1678
const NodeType * getLowestCommonAncestor(const NodeType *a, const NodeType *b)
Definition: KdTree.hpp:1440
DerivedNode *const & at(unsigned int axis, char minMax) const
Definition: KdTree.hpp:763
bool checkPosition(AABB< Dimension > &aabb)
Definition: KdTree.hpp:592
std::tuple< std::size_t, std::size_t, std::size_t, PREC, std::size_t, std::size_t, PREC, PREC, std::size_t, std::size_t, PREC > getStatistics()
Definition: KdTree.hpp:1697
TreeStatistics m_statistics
Definition: KdTree.hpp:2344
PREC computePointRatio(NodeDataType *data)
Definition: KdTree.hpp:622
BoundaryInfoType & getBoundaries()
Definition: KdTree.hpp:1006
typename PointListType::iterator iterator
Definition: KdTree.hpp:123
PointData(iterator begin, iterator end, std::unique_ptr< PointListType > points=nullptr)
Definition: KdTree.hpp:189
void copyFrom(const TreeBase< T > &tree)
Definition: KdTree.hpp:1298
SplitAxisType getSplitAxis() const
Definition: KdTree.hpp:866
std::pair< NodeDataType *, NodeDataType * > doSplit(NodeType *node, SplitAxisType &splitAxis, PREC &splitPosition)
Definition: KdTree.hpp:385
typename PointDataTraits::PointGetter PointGetter
Definition: KdTree.hpp:2426
TreeSimple(TreeSimple< Traits > &&tree)
Definition: KdTree.hpp:1674
const LeafContainerType & getLeafs()
Definition: KdTree.hpp:1499
void init(const std::initializer_list< Method > &m, unsigned int allowSplitAboveNPoints=100, PREC minExtent=0.0, SearchCriteria searchCriteria=SearchCriteria::FIND_BEST, const QualityEvaluator &qualityEval=QualityEvaluator(), PREC minSplitRatio=0.0, PREC minPointRatio=0.0, PREC minExtentRatio=0.0)
Definition: KdTree.hpp:328
const DerivedNode * rightNode() const
Definition: KdTree.hpp:829
PREC compute(const PREC &splitRatio, const PREC &pointRatio, const PREC &minMaxExtentRatio)
Definition: KdTree.hpp:279
DerivedNode * parent()
Definition: KdTree.hpp:816
typename Traits::DistCompTraits::template DistanceComp< TDistSq > DistanceComp
Definition: KdTree.hpp:180
const NodeDataType * data() const
Definition: KdTree.hpp:1087
std::tuple< std::size_t, PREC, std::size_t > getSettings()
Definition: KdTree.hpp:2446
typename NodeDataType::PointListType PointListType
Definition: KdTree.hpp:303
typename PointDataType::PointGetter PointGetter
Definition: KdTree.hpp:306
meta::or_< meta::_t< std::is_same< T, TakeDefault > >, meta::_t< std::is_same< T, void > > > isDefault
Definition: KdTree.hpp:59
void cleanUp(bool data=true)
Definition: KdTree.hpp:1232
NodeContainerType m_nodes
All nodes, continously index ordered, with first element = m_root.
Definition: KdTree.hpp:1569
Tree(const TTree &tree)
Definition: KdTree.hpp:1826
typename Container::reverse_iterator reverse_iterator
Definition: KdTree.hpp:2053
Eigen::Matrix< Scalar, 3, 1 > Vector3
NodeBase(std::size_t idx, const AABB< Dimension > &aabb, unsigned int treeLevel=0)
Definition: KdTree.hpp:783
DerivedNode *& at(unsigned int axis, char minMax)
Definition: KdTree.hpp:759
bool overlapsSubSpace(const AABB &box, unsigned int fixedAxis) const
Definition: AABB.hpp:149
AABB< Dimension > & aabb()
Definition: KdTree.hpp:833
StdVecAligned< TValue > PointListType
Definition: KdTree.hpp:121
static Derived::Scalar apply(const MatrixBase< Derived > &p)
Definition: KdTree.hpp:76
void expand(PREC d)
Definition: AABB.hpp:169
#define ApproxMVBB_STATIC_ASSERTM(B, COMMENT)
#define DEFINE_KDTREE_BASENODETYPES(_Base_)
Definition: KdTree.hpp:724
#define ApproxMVBB_DEFINE_MATRIX_TYPES
Definition: TypeDefs.hpp:26
PREC getSplitRatio() const
Definition: KdTree.hpp:872
NodeType * m_root
Root node, has index 0!
Definition: KdTree.hpp:1571
const NodeType * getNode(const std::size_t &globalIndex) const
Definition: KdTree.hpp:1503
ArrayStat< Dim > extent() const
Definition: AABB.hpp:155
NodeSimple(NodeSimple &&t)
Definition: KdTree.hpp:950
void setIdx(std::size_t i)
Definition: KdTree.hpp:851
typename Container::value_type value_type
Definition: KdTree.hpp:2045
PREC computeSplitRatio(AABB< Dimension > &aabb)
Definition: KdTree.hpp:633
const AABB< Dimension > & aabb() const
Definition: KdTree.hpp:836
AABB< Dimension > m_aabb
Definition: KdTree.hpp:893
SplitHeuristicType m_heuristic
Definition: KdTree.hpp:2338
typename PointListType::const_iterator const_iterator
Definition: KdTree.hpp:124


asr_approx_mvbb
Author(s): Gassner Nikolai
autogenerated on Mon Jun 10 2019 12:38:08