10 #ifndef ApproxMVBB_KdTree_hpp 11 #define ApproxMVBB_KdTree_hpp 13 #include <type_traits> 14 #include <initializer_list> 22 #include <unordered_set> 23 #include <unordered_map> 28 #include <meta/meta.hpp> 32 #include ApproxMVBB_TypeDefs_INCLUDE_FILE 33 #include ApproxMVBB_AssertionDebug_INCLUDE_FILE 57 meta::_t<std::is_same<T,TakeDefault> >,
58 meta::_t<std::is_same<T,void> >
62 #define DEFINE_KDTREE_BASETYPES( __Traits__ ) \ 64 using NodeDataType = typename __Traits__::NodeDataType; \ 65 static const unsigned int Dimension = __Traits__::NodeDataType::Dimension; \ 66 using NodeType = typename __Traits__::NodeType; \ 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> >; 74 template <
typename Derived>
76 typename Derived::Scalar
apply(
const MatrixBase<Derived> & p) {
77 return p.squaredNorm();
81 template<
typename TPo
int,
typename TPo
intGetter,
typename DistSq = Eucl
ideanDistSq>
91 return DistSq::apply(m_ref - TPointGetter::get(p1)) <
92 DistSq::apply(m_ref - TPointGetter::get(p2));
97 return DistSq::apply(m_ref - TPointGetter::get(p1));
104 template<
typename TPo
int,
typename TPo
intGetter>
106 template<
typename TDistSq>
111 template<
unsigned int Dim = 3,
114 typename TPointGetter = details::TakeDefault,
115 typename TDistanceCompTraits = details::TakeDefault
119 static const unsigned int Dimension = Dim;
139 template<
typename TT>
153 using PointGetter = meta::if_< details::isDefault<TPointGetter> ,
159 using DistCompTraits = meta::if_< details::isDefault<TDistanceCompTraits> ,
167 template<
typename TTraits = DefaultPo
intDataTraits<> >
172 static const unsigned int Dimension = Traits::Dimension;
179 template<
typename TDistSq>
190 : m_begin(begin), m_end(end), m_points(points.release()) {}
198 std::pair<PointData *, PointData * >
204 return std::make_pair(left,right);
211 for(
auto & pPoint : *
this) {
212 ret += PointGetter::get(pPoint)(axis);
237 return std::distance(m_begin,m_end);
241 std::stringstream ss;
242 for(
auto & pPoint : *
this) {
273 m_weightSplitRatio(ws), m_weightPointRatio(wp), m_weightMinMaxExtentRatio(we) {}
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;
287 PREC m_weightSplitRatio = 0.0;
288 PREC m_weightPointRatio = 0.0;
289 PREC m_weightMinMaxExtentRatio = 1.0;
293 template<
typename Traits >
296 template<
typename TQualityEvaluator,
typename Traits >
308 enum class
Method :
char { MIDPOINT, MEDIAN, GEOMETRIC_MEAN };
322 for(
SplitAxisType i = 0; i < static_cast<SplitAxisType>(Dimension); i++) {
323 m_splitAxes.push_back(i);
328 void init(
const std::initializer_list<Method> & m,
329 unsigned int allowSplitAboveNPoints = 100,
330 PREC minExtent = 0.0,
333 PREC minSplitRatio = 0.0, PREC minPointRatio = 0.0, PREC minExtentRatio = 0.0) {
337 if(m_methods.size()==0) {
340 m_allowSplitAboveNPoints = allowSplitAboveNPoints;
341 m_minExtent = minExtent;
342 if( m_minExtent < 0) {
345 m_searchCriteria = searchCriteria;
347 m_qualityEval = qualityEval;
349 m_minSplitRatio = minSplitRatio;
350 m_minPointRatio = minPointRatio;
351 m_minExtentRatio = minExtentRatio;
353 if( m_minSplitRatio < 0 || m_minPointRatio < 0 || m_minExtentRatio <0) {
366 m_avgSplitRatio = 0.0;
367 m_avgPointRatio = 0.0;
368 m_avgExtentRatio = 0.0;
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;
384 std::pair<NodeDataType *, NodeDataType * >
389 auto * data = node->data();
392 if(data->size() <= m_allowSplitAboveNPoints) {
393 return std::make_pair(
nullptr,
nullptr);
398 m_extent = node->aabb().extent();
401 return m_extent(a) > m_extent(b);
403 std::sort(m_splitAxes.begin(),m_splitAxes.end(),biggest);
406 unsigned int tries = 0;
408 std::size_t nMethods = m_methods.size();
409 std::size_t methodIdx = 0;
410 std::size_t axisIdx = 0;
412 m_bestQuality = std::numeric_limits<PREC>::lowest();
414 while(((m_searchCriteria == SearchCriteria::FIND_FIRST && !m_found) ||
415 m_searchCriteria == SearchCriteria::FIND_BEST )
416 && methodIdx < nMethods) {
419 m_wasLastTry =
false;
420 m_method = m_methods[methodIdx];
421 m_splitAxis = m_splitAxes[axisIdx];
425 if( m_extent(m_splitAxis) > 2.0* m_minExtent ) {
428 if( computeSplitPosition(node)) {
431 if( m_splitRatio >= m_minSplitRatio &&
432 m_pointRatio >= m_minPointRatio &&
433 m_extentRatio >= m_minExtentRatio) {
450 if( ++axisIdx == Dimension) {
462 if( !(m_wasLastTry && m_bestMethod==Method::MEDIAN) ) {
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;
470 m_bestSplitRightIt = std::partition(data->begin(), data->end(), leftPredicate );
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);
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;
482 m_bestSplitRightIt = std::partition(data->begin(),m_bestSplitRightIt, leftPredicate);
491 splitAxis = m_bestSplitAxis;
492 splitPosition = m_bestSplitPosition;
493 return data->split(m_bestSplitRightIt);
498 return std::make_pair(
nullptr,
nullptr);
505 unsigned int tries = 1) {
507 auto * data = node->data();
510 auto & aabb = node->aabb();
512 case Method::MIDPOINT: {
513 m_splitPosition = 0.5*(aabb.m_minPoint(m_splitAxis) + aabb.m_maxPoint(m_splitAxis));
515 if(!checkPosition(aabb)) {
520 m_extentRatio = computeExtentRatio(aabb);
521 m_pointRatio = computePointRatio(data);
522 m_quality = m_qualityEval.compute(m_splitRatio,m_pointRatio,m_extentRatio);
526 case Method::MEDIAN: {
527 auto beg = data->begin();
528 m_splitRightIt = beg + data->size()/2;
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);
536 std::nth_element(beg, m_splitRightIt, data->end(), less );
537 m_splitPosition = PointGetter::get(*(m_splitRightIt))(m_splitAxis);
539 if(!checkPosition(aabb)) {
549 auto leftPredicate = [&](
const typename PointListType::value_type & a) {
550 return PointGetter::get(a)(m_splitAxis) < m_splitPosition;
552 m_splitRightIt = std::partition(beg,m_splitRightIt, leftPredicate);
557 m_splitRatio = computeSplitRatio(aabb);
558 m_extentRatio = computeExtentRatio(aabb);
559 m_pointRatio = (PREC)std::distance(beg,m_splitRightIt) / std::distance(beg,data->end());
561 m_quality = m_qualityEval.compute(m_splitRatio,m_pointRatio,m_extentRatio);
576 case Method::GEOMETRIC_MEAN: {
577 m_splitPosition = data->getGeometricMean(m_splitAxis);
578 if(!checkPosition(aabb)) {
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);
594 && m_splitPosition <= aabb.
m_maxPoint(m_splitAxis),
595 "split position wrong: " << m_splitPosition <<
" min: " << aabb.
m_minPoint.transpose()
598 if( (m_splitPosition - aabb.
m_minPoint(m_splitAxis)) <= m_minExtent ||
599 (aabb.
m_maxPoint(m_splitAxis) - m_splitPosition) <= m_minExtent ) {
606 if( m_quality > m_bestQuality ) {
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;
615 m_bestSplitRatio = m_splitRatio;
616 m_bestPointRatio = m_pointRatio;
617 m_bestExtentRatio = m_extentRatio;
624 for(
auto & p: *data) {
625 if(PointGetter::get(p)(m_splitAxis) < m_splitPosition) {
630 return (n>0.5)? 1.0-n : n ;
634 PREC n = (m_splitPosition - 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 ;
642 static ArrayStat<Dimension> t;
644 PREC tt = t(m_splitAxis);
646 t(m_splitAxis) = m_splitPosition - aabb.
m_minPoint(m_splitAxis);
647 PREC r = t.minCoeff() / t.maxCoeff();
650 t(m_splitAxis) = aabb.
m_maxPoint(m_splitAxis) - m_splitPosition;
651 r = std::min(r,t.minCoeff() / t.maxCoeff());
662 m_avgSplitRatio += m_bestSplitRatio;
663 m_avgPointRatio += m_bestPointRatio;
664 m_avgExtentRatio += m_bestExtentRatio;
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;
681 PREC m_quality = 0.0;
683 PREC m_splitRatio = 0;
684 PREC m_pointRatio = 0;
685 PREC m_extentRatio = 0;
688 PREC m_minSplitRatio = 0.0;
689 PREC m_minPointRatio = 0.0;
690 PREC m_minExtentRatio = 0.0;
693 PREC m_splitPosition = 0.0;
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;
712 std::size_t m_allowSplitAboveNPoints = 100;
713 PREC m_minExtent = 0.0;
721 template<
typename T>
class Tree;
724 #define DEFINE_KDTREE_BASENODETYPES( _Base_ ) \ 725 using SplitAxisType = typename _Base_::SplitAxisType; \ 726 using BoundaryInfoType = typename _Base_::BoundaryInfoType; 730 template<
typename TDerivedNode,
unsigned int Dimension>
736 template<
typename D,
unsigned int Dim>
741 using DerivedNode = TDerivedNode;
747 static const unsigned int size = Dimension * 2;
760 ApproxMVBB_ASSERTMSG(minMax*Dimension + axis < size,
"Index " << minMax*Dimension + axis <<
"out of bound!");
761 return m_nodes[minMax*Dimension + axis];
764 ApproxMVBB_ASSERTMSG(minMax*Dimension + axis < size,
"Index " << minMax*Dimension + axis <<
"out of bound!");
765 return m_nodes[minMax*Dimension + axis];
784 : m_idx(idx), m_treeLevel(treeLevel), m_aabb(aabb) {
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}
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)
807 n.m_parent =
nullptr;
808 n.m_child = {{
nullptr,
nullptr}};
811 inline void setChilds(DerivedNode * r, DerivedNode * l){
816 inline DerivedNode *
parent(){
return m_parent;}
817 inline const DerivedNode *
parent()
const {
return m_parent;}
844 return m_child[0] && m_child[1];
848 return (m_splitAxis == -1);
860 m_splitAxis= splitAxis ;
863 m_splitPosition= splitPos ;
870 return m_splitPosition;
873 return (m_splitPosition - m_aabb.m_minPoint(m_splitAxis) )
874 / (m_aabb.m_maxPoint(m_splitAxis)-m_aabb.m_minPoint(m_splitAxis));
888 : m_idx(idx), m_aabb(aabb), m_splitAxis(axis), m_splitPosition(splitPos) {
891 std::size_t m_idx = std::numeric_limits<std::size_t>::max();
892 unsigned int m_treeLevel = 0;
895 PREC m_splitPosition = 0.0;
901 std::array<DerivedNode *,2> m_child{{
nullptr,
nullptr}};
902 DerivedNode * m_parent =
nullptr;
906 template<
typename Traits>
class Node;
910 template<
typename PD,
typename T>
917 template<
typename TTraits,
typename PD =
void>
930 using Base::m_splitAxis;
931 using Base::m_splitPosition;
962 template<
typename T,
typename NodeVector>
971 m_child[0] = nodes[c->
getIdx()];
972 m_child[0]->m_parent =
static_cast<DerivedType*
>(
this);
978 m_child[1] = nodes[c->
getIdx()];
979 m_child[1]->m_parent =
static_cast<DerivedType*
>(
this);
985 auto it = m_bound.
begin();
986 for(
const auto * bNode : t->
m_bound){
990 auto * p = nodes[bNode->getIdx()];
1010 template<
unsigned int Dim = 3>
1012 static const unsigned int Dimension = Dim;
1016 template<
typename TTraits>
1017 class Node :
public NodeBase<Node<TTraits>,TTraits::Dimension> {
1025 using Base::m_splitAxis;
1026 using Base::m_splitPosition;
1027 using Base::m_child;
1032 template<
typename T>
1034 template<
typename T>
1038 template<
typename T>
1040 template<
typename T,
typename PD>
1050 Node(
std::
size_t idx, const
AABB<Dimension> & aabb, NodeDataType * data,
unsigned int treeLevel = 0)
1051 :
Base(idx,aabb,treeLevel), m_data(data) {
1063 template<
typename Traits>
1066 m_data =
new NodeDataType(*n.
m_data);
1087 inline const NodeDataType *
data()
const {
1096 template<
typename TSplitHeuristic>
1097 bool split(TSplitHeuristic & s, std::size_t startIdx = 0) {
1099 auto pLR = s.doSplit(
this, m_splitAxis, m_splitPosition);
1101 if(pLR.first ==
nullptr) {
1106 startIdx = (startIdx == 0) ? 2*m_idx + 1 : startIdx;
1113 m_child[0] =
new Node(startIdx,t,pLR.first, this->m_treeLevel+1);
1114 m_child[0]->m_parent =
this;
1119 m_child[1] =
new Node(startIdx+1,t,pLR.second, this->m_treeLevel+1);
1120 m_child[1]->m_parent =
this;
1124 Node * tn = b.at(m_splitAxis,1);
1125 b.at(m_splitAxis,1) = m_child[1];
1128 b.at(m_splitAxis,1) = tn;
1129 b.at(m_splitAxis,0) = m_child[0];
1133 if(this->m_treeLevel != 0) {
1140 template<
typename NeighbourIdxMap>
1163 std::deque<Node*> nodes;
1164 auto & neighbours = neigbourIdx[m_idx];
1171 for(
SplitAxisType d = 0; d< static_cast<SplitAxisType>(Dimension); ++d) {
1174 for(
unsigned int m = 0; m<2; ++m) {
1177 Node * subTreeRoot = m_bound.at(d,m);
1181 nodes.emplace_back(subTreeRoot);
1184 while(!nodes.empty()) {
1194 if( neighbours.find(f->
m_idx) == neighbours.end() ) {
1199 neighbours.emplace(f->
m_idx);
1200 neigbourIdx[f->
m_idx].emplace(m_idx);
1233 if(data && m_data) {
1240 return (m_data)? m_data->size() : 0;
1245 NodeDataType* m_data =
nullptr;
1258 template<
typename Traits>
1261 template<
typename T>
1270 : m_nodes(
std::move(t.m_nodes)), m_leafs(
std::move(t.m_leafs) ), m_root(t.m_root) {
1281 template<
typename T>
1297 template<
typename T>
1306 this->m_nodes.reserve(tree.
m_nodes.size());
1307 this->m_leafs.reserve(tree.
m_leafs.size());
1310 for(
auto * n : tree.
m_nodes){
1312 this->m_nodes.emplace_back(
new NodeType(*n) );
1317 for( std::size_t i=0;i<s;++i){
1318 this->m_nodes[i]->setup(tree.
m_nodes[i],this->m_nodes);
1322 for(
auto * n : tree.
m_leafs){
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()] );
1330 m_root = m_nodes[ tree.
m_root->getIdx() ];
1348 template<
typename NodeMap,
typename NodeToChildMap>
1349 void build( NodeType * root, NodeMap & c, NodeToChildMap & links) {
1354 m_nodes.reserve(c.size());
1355 m_nodes.assign(c.begin(),c.end());
1357 for(
auto * n: m_nodes) {
1359 m_leafs.push_back(n);
1363 if( c.find(root->getIdx()) == c.end()) {
1368 std::unordered_set<std::size_t> hasParent;
1371 for(
auto & l : links) {
1372 auto it = c.find(l.first);
1373 auto itL = c.find(l.second.first);
1374 auto itR = c.find(l.second.second);
1376 if(it==itE || itL==itE || itR==itE) {
1380 if(!hasParent.emplace(l.second.first).second) {
1383 if(!hasParent.emplace(l.second.second).second) {
1386 if( !it->second || !itL->second || !itR->second) {
1389 it->second->m_child[0] = itL->second;
1390 it->second->m_child[1] = itR->second;
1393 if(hasParent.size() != c.size()-1) {
1394 ApproxMVBB_ERRORMSG(
"Tree needs to have N nodes, with one root, which gives N-1 parents!")
1405 for(
auto * n: this->m_nodes) {
1409 this->m_root=
nullptr;
1419 template<
typename Derived>
1420 const NodeType *
getLeaf(
const MatrixBase<Derived> & point)
const {
1421 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,Dimension);
1424 const NodeType * currentNode = m_root;
1426 while(!currentNode->isLeaf()) {
1428 if(point(currentNode->getSplitAxis()) >= currentNode->getSplitPosition()) {
1429 currentNode = currentNode->rightNode();
1431 currentNode = currentNode->leftNode();
1445 static std::vector<NodeType *> aL;
1446 static std::vector<NodeType *> bL;
1451 NodeType * r = a->m_parent;
1452 while(r !=
nullptr){
1461 while(r !=
nullptr){
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);
1482 for(std::size_t i = 1; i<=s;++i){
1483 if (aL[sizeA-i] == bL[sizeB-i]){
1492 inline const NodeType *
getLeaf(
const std::size_t & leafIndex)
const {
1493 if(leafIndex < m_leafs.size() ) {
1494 return m_leafs[leafIndex];
1503 inline const NodeType *
getNode(
const std::size_t & globalIndex)
const {
1504 if(globalIndex < m_nodes.size()) {
1505 return m_nodes[globalIndex];
1522 template<
typename... T>
1524 for(
auto * p : m_nodes) {
1525 p->cleanUp(std::forward<T>(t)...);
1529 std::tuple<std::size_t, std::size_t >
1531 return std::make_tuple(m_nodes.size(),m_leafs.size());
1540 std::size_t leafIdx = 0;
1542 this->m_leafs.clear();
1545 for(
auto * n : this->m_nodes) {
1548 this->m_leafs.emplace_back(n);
1551 std::size_t nonleafIdx = this->m_leafs.size();
1554 for(
auto * n : this->m_nodes) {
1556 n->m_idx = nonleafIdx++;
1561 std::sort(m_nodes.begin(),m_nodes.end(), [](NodeType * a, NodeType * b) {
return a->getIdx()< b->getIdx() ;} );
1571 NodeType * m_root =
nullptr;
1601 m_computedTreeStats =
false;
1603 m_avgSplitPercentage = 0.0;
1604 m_minLeafExtent = std::numeric_limits<PREC>::max();
1605 m_maxLeafExtent = 0.0;
1607 m_minLeafDataSize = std::numeric_limits<std::size_t>::max();
1608 m_maxLeafDataSize = 0;
1610 m_computedNeighbourStats =
false;
1611 m_minNeighbours = std::numeric_limits<std::size_t>::max();
1612 m_maxNeighbours = 0;
1613 m_avgNeighbours = 0;
1616 void average(std::size_t nodes, std::size_t leafs) {
1618 m_avgLeafSize /= nodes;
1621 m_avgSplitPercentage /= nodes - leafs;
1625 template<
typename TNode>
1628 auto s = n->data()->size();
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());
1645 template<
typename...>
class TNode =
NodeSimple 1651 static const unsigned int Dimension = NodeDataType::Dimension;
1659 template<
typename TTraits = TreeSimpleTraits<> >
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){}
1684 template<
typename Traits >
1686 :
Base( tree ) , m_statistics(tree.m_statistics)
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(),
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)
1715 std::stringstream s;
1716 auto t = getStatistics();
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;
1738 using Base::m_nodes;
1739 using Base::m_leafs;
1749 template<
typename Traits>
1751 meta::quote<SplitHeuristicPointData>,
1759 template<
typename...>
class TNode =
Node 1765 static const unsigned int Dimension = NodeDataType::Dimension;
1778 template<
typename TTraits = TreeTraits<> >
1779 class Tree :
public TreeBase<typename TTraits::BaseTraits> {
1782 template<
typename T>
1785 template<
typename T>
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();
1811 m_heuristic(tree.m_heuristic),
1812 m_statistics(tree.m_statistics),
1813 m_maxLeafs(tree.m_maxLeafs), m_maxTreeDepth(tree.m_maxTreeDepth) {
1816 template<
typename T>
1818 m_statistics(tree.m_statistics),
1819 m_maxLeafs(tree.m_maxLeafs), m_maxTreeDepth(tree.m_maxTreeDepth) {
1825 template<
typename TTree>
1830 Tree & operator=(
const Tree & t) =
delete;
1842 template<
bool computeStatistics = true>
1844 unsigned int maxTreeDepth = 50,
1845 unsigned int maxLeafs = std::numeric_limits<unsigned int>::max()) {
1850 m_statistics.m_computedTreeStats = computeStatistics;
1851 m_maxTreeDepth = maxTreeDepth;
1852 m_maxLeafs = maxLeafs;
1855 if((aabb.
extent() <= 0.0).any()) {
1858 this->m_root =
new NodeType(0,aabb,data.release());
1860 std::deque<NodeType*> splitList;
1861 splitList.push_back(this->m_root);
1862 this->m_nodes.push_back(this->m_root);
1866 m_statistics.m_treeDepth = 0;
1867 unsigned int nNodesLevelCurr = 1;
1868 unsigned int nNodesLevelNext = 0;
1870 unsigned int nLeafs = 1;
1877 while( !splitList.empty()) {
1880 auto * f = splitList.front();
1883 if(nNodesLevelCurr==0) {
1885 ++m_statistics.m_treeDepth;
1887 std::swap(nNodesLevelCurr, nNodesLevelNext);
1892 f = splitList.front();
1896 if(m_statistics.m_treeDepth+1 <= m_maxTreeDepth && nLeafs < m_maxLeafs) {
1899 nodeSplitted = f->split(m_heuristic,this->m_nodes.size());
1901 auto * l = f->leftNode();
1902 auto * r = f->rightNode();
1903 splitList.emplace_back(l);
1904 splitList.emplace_back(r);
1907 this->m_nodes.emplace_back(l);
1908 this->m_nodes.emplace_back(r);
1915 this->m_leafs.emplace_back(f);
1919 if(computeStatistics) {
1920 m_statistics.addNode(f);
1926 this->m_leafs.emplace_back(f);
1929 if(computeStatistics) {
1930 m_statistics.addNode(f);
1936 splitList.pop_front();
1940 this->enumerateNodes();
1943 if(computeStatistics) {
1944 averageStatistics();
1948 template<
typename... T>
1950 m_heuristic.init(std::forward<T>(t)...);
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!")
1961 return buildLeafNeighbours<computeStatistics,safetyCheck>(0.99*m_statistics.m_minLeafExtent);
1964 template<
bool computeStatistics = true,
bool safetyCheck = true>
1965 LeafNeighbourMapType
1971 m_statistics.m_computedNeighbourStats = computeStatistics;
1996 std::unordered_map<std::size_t, std::unordered_set<std::size_t> > leafToNeighbourIdx;
1999 for(
auto * node: this->m_leafs) {
2000 node->getNeighbourLeafsIdx(leafToNeighbourIdx, minExtent);
2005 safetyCheckNeighbours(leafToNeighbourIdx,minExtent);
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;
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());
2020 m_statistics.m_avgNeighbours /= this->m_leafs.size();
2023 return leafToNeighbourIdx;
2028 ParentInfo( NodeType* p,
bool l=
false,
bool r =
false): m_parent(p), childVisited{l,r} {}
2030 bool childVisited[2];
2039 template <
typename Container,
typename Compare>
2040 class KNearestPrioQueue :
public std::priority_queue<typename NodeDataType::PointListType::value_type,
2048 typename NodeDataType::PointListType::value_type>::value))
2050 using
Base =
std::priority_queue<typename NodeDataType::PointListType::
value_type,Container,Compare>;
2055 Container &getContainer() {
2063 return this->c.begin();
2066 return this->c.end();
2070 return this->c.rbegin();
2073 return this->c.rend();
2077 this->c.reserve(m_maxSize);
2085 return this->size() == m_maxSize;
2088 inline void push(
const typename Base::value_type & v) {
2089 if (this->size() < m_maxSize) {
2091 }
else if( this->comp(v,this->top()) ) {
2097 template<
typename It>
2100 auto s = this->size();
2101 while(s < m_maxSize && it!=end) {
2108 if( this->comp(*it,this->top()) ) {
2117 template<
typename Iterator>
2120 this->c.insert(this->c.begin(),begin, end);
2121 std::make_heap(this->c.begin(), this->c.end(), this->comp );
2135 typename TContainer = StdVecAligned<typename NodeDataType::PointListType::value_type>
2150 template<
typename N,
typename C>
2152 static const bool value =
true;
2157 template<
typename TKNNTraits>
2164 if(!this->m_root || kNearest.maxSize() == 0) {
2170 typename TKNNTraits::DistCompType & distComp = kNearest.getComperator();
2177 std::vector< ParentInfo > parents;
2178 parents.reserve(m_statistics.m_treeDepth);
2180 parents.emplace_back(
nullptr,
false,
false);
2181 NodeType * currNode = this->m_root;
2184 while(!currNode->isLeaf()) {
2186 if(distComp.m_ref(currNode->m_splitAxis) >= currNode->m_splitPosition) {
2187 parents.emplace_back( currNode,
false,
true );
2188 currNode = currNode->rightNode();
2190 parents.emplace_back( currNode,
true,
false );
2191 currNode = currNode->leftNode();
2198 PREC maxDistSq = 0.0;
2202 while(currNode!=
nullptr) {
2204 currParentInfo = &parents.back();
2207 if( !currNode->isLeaf()) {
2215 if( kNearest.full()) {
2217 d = currParentInfo->
m_parent->m_splitPosition - distComp.m_ref(currParentInfo->
m_parent->m_splitAxis);
2220 if( d*d >= maxDistSq) {
2228 currNode = currNode->leftNode();
2230 if (!currNode->isLeaf()) {
2232 parents.emplace_back(currNode);
2241 if( kNearest.full()) {
2242 d = currParentInfo->
m_parent->m_splitPosition - distComp.m_ref(currParentInfo->
m_parent->m_splitAxis);
2245 if( d*d > maxDistSq) {
2253 currNode = currNode->rightNode();
2255 if (!currNode->isLeaf()) {
2257 parents.emplace_back( currNode );
2266 currNode = parents.back().m_parent;
2275 if(currNode->size()>0) {
2276 kNearest.push(currNode->data()->begin(),currNode->data()->end());
2278 maxDistSq = distComp(kNearest.top());
2281 currNode = currParentInfo->
m_parent;
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(),
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)
2312 std::stringstream s;
2313 auto t = getStatistics();
2314 std::string h = m_heuristic.getStatisticsString();
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" 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;
2340 unsigned int m_maxTreeDepth = 50;
2341 unsigned int m_maxLeafs = std::numeric_limits<unsigned int>::max();
2348 m_statistics.
reset();
2349 m_heuristic.resetStatistics();
2352 m_statistics.
average(this->m_nodes.size(),this->m_leafs.size());
2357 template<
typename NeighbourMap>
2360 if(n.size() != this->m_leafs.size()) {
2361 ApproxMVBB_ERRORMSG(
"Safety check for neighbours failed!: size:" << n.size() <<
","<<this->m_leafs.size())
2365 for(
auto * l: this->m_leafs) {
2371 auto it = n.find(l->getIdx());
2376 for(
const auto & idx : it->second ) {
2377 if(this->getLeaf(idx) ==
nullptr) {
2381 if( ! t.
overlaps( this->m_leafs[idx]->aabb() ) ) {
2382 ApproxMVBB_ERRORMSG(
"Safety check: Leaf idx: " << idx <<
" does not overlap " << l->getIdx())
2385 auto nIt = n.find(idx);
2386 if(nIt == n.end()) {
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")
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());
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!")
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() )
2418 template<
typename TTraits = KdTree::DefaultPo
intDataTraits<> >
2423 static const unsigned int Dim = PointDataTraits::Dimension;
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) {
2445 inline std::tuple<std::size_t,PREC,std::size_t>
2448 return std::make_tuple(m_kNeighboursMean,m_stdDevMult,m_allowSplitAboveNPoints);
2453 std::size_t allowSplitAboveNPoints)
2455 m_kNeighboursMean = kNeighboursMean;
2456 m_stdDevMult = stdDevMult;
2457 m_allowSplitAboveNPoints = allowSplitAboveNPoints;
2468 template<
typename Container,
2470 typename =
typename std::enable_if<ContainerTags::has_randomAccessIterator<Container>::value>::type
2472 void filter(Container & points,
const AABB<Dim> & aabb, Container & output,
bool invert=
false) {
2475 typename PointListType::value_type>::value),
2476 "Container value_type needs to be the same as value_type of PointDataTraits!")
2481 typename SplitHeuristicType::QualityEvaluator qual(0.0,
2485 PREC minExtent = 0.0;
2486 tree.
initSplitHeuristic( std::initializer_list<typename SplitHeuristicType::Method> {
2489 SplitHeuristicType::Method::MIDPOINT
2491 m_allowSplitAboveNPoints, minExtent,
2492 SplitHeuristicType::SearchCriteria::FIND_FIRST, qual,
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 , inf );
2501 using KNNTraits =
typename Tree::template KNNTraits<DistSq>;
2502 typename KNNTraits::PrioQueue kNearest(m_kNeighboursMean+1);
2503 typename KNNTraits::DistCompType & compDist = kNearest.getComperator();
2507 m_nearestDists.assign(points.size(),0.0);
2510 std::size_t validPoints = 0;
2511 typename KNNTraits::PrioQueue::iterator it;
2512 typename KNNTraits::PrioQueue::iterator e;
2514 auto nPoints = points.size();
2515 for(std::size_t i = 0; i < nPoints; ++i) {
2518 kNearest.getComperator().m_ref = PointGetter::get(points[i]);
2519 tree.template getKNearestNeighbours<KNNTraits>(kNearest);
2527 if( kNearest.size() > 1) {
2530 for(it=++kNearest.begin(); it!=e; ++it) {
2531 sum += std::sqrt(compDist(*it));
2534 m_nearestDists[i] = sum / (kNearest.size()-1);
2543 for (std::size_t i = 0; i < nPoints; ++i) {
2544 sum += m_nearestDists[i];
2545 sumSq += m_nearestDists[i] * m_nearestDists[i];
2547 m_mean = sum / validPoints;
2548 m_stdDev = std::sqrt( (sumSq - sum*sum/validPoints) / validPoints );
2551 PREC distanceThreshold = m_mean + m_stdDevMult * m_stdDev;
2555 output.resize(points.size());
2556 std::size_t nPointsOut = 0;
2558 for(std::size_t i = 0; i < nPoints; ++i) {
2559 if (m_nearestDists[i] < distanceThreshold) {
2561 output[nPointsOut] = points[i];
2566 for(std::size_t i = 0; i < nPoints; ++i) {
2567 if (m_nearestDists[i] >= distanceThreshold) {
2569 output[nPointsOut] = points[i];
2574 output.resize(nPointsOut);
2588 return m_nearestDists;
2595 return std::make_pair(m_mean,m_stdDev);
std::pair< PointData *, PointData * > split(iterator splitRightIt) const
#define ApproxMVBB_ASSERTMSG(condition, message)
An Assert Macro to use within C++ code.
std::vector< PREC > & getNearestDists()
const_iterator end() const
std::string getStatisticsString()
std::vector< PREC > NearestDistancesType
typename Traits::const_iterator const_iterator
std::vector< SplitAxisType > m_splitAxes
typename NodeType::SplitAxisType SplitAxisType
KNearestPrioQueue(std::size_t maxSize)
typename Traits::PointType PointType
std::string getStatisticsString()
std::tuple< std::size_t, std::size_t > getStatistics()
void setSplitAxis(SplitAxisType splitAxis)
NodeContainerType m_leafs
Only leaf nodes , continously index ordered: leafs[idx]->getIdx() < leafs[idx+1]->getIdx();.
const BoundaryInfoType & getBoundaries() const
void setLevel(unsigned int level)
VectorStat< Dim > m_minPoint
NearestDistancesType m_nearestDists
BoundaryInfoType & getBoundaries()
bool operator()(const T &p1, const T &p2)
bool split(TSplitHeuristic &s, std::size_t startIdx=0)
void safetyCheckNeighbours(const NeighbourMap &n, PREC minExtent)
These are some container definitions.
NodeSimple(const NodeSimple &t)
typename PointDataType::iterator iterator
std::size_t getIdx() const
DistanceComp< TPoint, TPointGetter > DistanceComp
BoundaryInformation BoundaryInfoType
PREC m_avgSplitPercentage
const NodeType * getRootNode()
LinearQualityEvaluator(PREC ws=0.0, PREC wp=0.0, PREC we=1.0)
const DerivedNode * parent() const
LeafNeighbourMapType buildLeafNeighboursAutomatic()
typename Traits::iterator iterator
typename Container::iterator iterator
PREC getGeometricMean(unsigned int axis)
std::size_t m_minLeafDataSize
LeafNeighbourMapType buildLeafNeighbours(PREC minExtent)
#define ApproxMVBB_ERRORMSG(message)
void setBoundaryInfo(const BoundaryInfoType &b)
NodeSimple(std::size_t idx, const AABB< Dimension > &aabb)
const_iterator begin() const
DistanceComp(const T &ref)
void push(const typename Base::value_type &v)
Node(const Node< Traits > &n)
typename NodeDataType::template DistanceComp< DistSqType > DistCompType
void setSplitPosition(PREC splitPos)
PREC computeExtentRatio(AABB< Dimension > &aabb)
bool overlaps(const AABB &box) const
NodeBase(NodeBase< Derived, Dimension > &&n)
void build(const AABB< Dimension > &aabb, std::unique_ptr< NodeDataType > data, unsigned int maxTreeDepth=50, unsigned int maxLeafs=std::numeric_limits< unsigned int >::max())
typename Traits::PointGetter PointGetter
Tree(const Tree< T > &tree)
NearestNeighbourFilter(std::size_t kNeighboursMean=20, PREC stdDevMult=1.0, std::size_t allowSplitAboveNPoints=10)
DerivedNode * rightNode()
VectorStat< Dim > m_maxPoint
TNode< BaseTraits > NodeType
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()
iterator m_end
The actual range of m_points which this node contains.
~TreeBase()
Prohibit the use of this base polymophically.
SplitAxisType m_bestSplitAxis
TSplitHeuristic< BaseTraits > SplitHeuristicType
void getKNearestNeighbours(typename TKNNTraits::PrioQueue &kNearest) const
typename Traits::SplitHeuristicType SplitHeuristicType
std::size_t m_maxNeighbours
void setLevel(unsigned int l) const
bool computeSplitPosition(NodeType *node, unsigned int tries=1)
NodeSimple(const Node< T > &t)
void setup(const Node< T > *t, const NodeVector &nodes)
ArrayStat< Dimension > m_extent
const NodeType * getLeaf(const std::size_t &leafIndex) const
void average(std::size_t nodes, std::size_t leafs)
void replace(Iterator begin, Iterator end)
typename PointDataTraits::PointListType PointListType
std::string getPointString()
typename TTraits::BaseTraits BaseTraits
TreeBase(const TreeBase< T > &t)
unsigned int getLevel() const
PREC getSplitPosition() const
TQualityEvaluator QualityEvaluator
PREC operator()(const T &p1)
void filter(Container &points, const AABB< Dim > &aabb, Container &output, bool invert=false)
std::size_t m_kNeighboursMean
const NodeType * getLeaf(const MatrixBase< Derived > &point) const
Base::BoundaryInfoType m_bound
meta::if_< details::isDefault< TPointGetter >, PointGetterImpl< typename PointListType::value_type >, TPointGetter > PointGetter
#define DEFINE_KDTREE_BASETYPES(__Traits__)
NodeDataType PointDataType
typename Tree::NodeDataType NodeDataType
const BoundaryInfoType & getBoundaries() const
TreeBase(const TreeBase &t)
void setChilds(DerivedNode *r, DerivedNode *l)
SplitAxisType m_splitAxis
-1 indicates leaf node
std::string getStatisticsString()
typename details::select< PD, NodeSimple< TTraits, PD > >::type DerivedType
bool hasLeftChildren() const
#define ApproxMVBB_STATIC_ASSERT(B)
typename Traits::PointListType PointListType
const DerivedNode * leftNode() const
NodeBase(const NodeBase< Derived, Dimension > &n)
bool m_computedNeighbourStats
void getNeighbourLeafsIdx(NeighbourIdxMap &neigbourIdx, PREC minExtent)
typename PointDataType::PointType PointType
meta::invoke< meta::bind_front< meta::quote< SplitHeuristicPointData >, LinearQualityEvaluator >, Traits > SplitHeuristicPointDataDefault
const NodeContainerType & getNodes()
std::pair< PREC, PREC > getMoments()
std::size_t m_idx
node index
void setSettings(std::size_t kNeighboursMean, PREC stdDevMult, std::size_t allowSplitAboveNPoints)
std::size_t m_maxLeafDataSize
meta::if_< details::isDefault< TDistanceCompTraits >, DefaultDistanceCompTraits< PointType, PointGetter >, TDistanceCompTraits > DistCompTraits
void initSplitHeuristic(T &&...t)
ParentInfo(NodeType *p, bool l=false, bool r=false)
typename Tree::SplitHeuristicType SplitHeuristicType
typename PointDataTraits::PointType PointType
typename TTraits::BaseTraits BaseTraits
SplitHeuristicPointData()
#define ApproxMVBB_DEFINE_POINTS_CONFIG_TYPES
void build(NodeType *root, NodeMap &c, NodeToChildMap &links)
TreeSimple(const Tree< Traits > &tree)
void push(It beg, It end)
NodeBase(std::size_t idx, const AABB< Dimension > &aabb, SplitAxisType axis, PREC splitPos)
TreeSimple(const TreeSimple< Traits > &tree)
Compare & getComperator()
const NodeType * getLowestCommonAncestor(const NodeType *a, const NodeType *b)
bool checkPosition(AABB< Dimension > &aabb)
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()
TreeStatistics m_statistics
PREC computePointRatio(NodeDataType *data)
BoundaryInfoType & getBoundaries()
typename PointListType::iterator iterator
PointData(iterator begin, iterator end, std::unique_ptr< PointListType > points=nullptr)
void copyFrom(const TreeBase< T > &tree)
SplitAxisType getSplitAxis() const
std::pair< NodeDataType *, NodeDataType * > doSplit(NodeType *node, SplitAxisType &splitAxis, PREC &splitPosition)
std::array< DerivedNode *, 2 > m_child
typename PointDataTraits::PointGetter PointGetter
TreeSimple(TreeSimple< Traits > &&tree)
std::size_t m_allowSplitAboveNPoints
SplitAxisType m_splitAxis
const LeafContainerType & getLeafs()
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)
const DerivedNode * rightNode() const
PREC compute(const PREC &splitRatio, const PREC &pointRatio, const PREC &minMaxExtentRatio)
typename Traits::DistCompTraits::template DistanceComp< TDistSq > DistanceComp
const NodeDataType * data() const
std::tuple< std::size_t, PREC, std::size_t > getSettings()
typename NodeDataType::PointListType PointListType
typename PointDataType::PointGetter PointGetter
meta::or_< meta::_t< std::is_same< T, TakeDefault > >, meta::_t< std::is_same< T, void > > > isDefault
void cleanUp(bool data=true)
SearchCriteria m_searchCriteria
NodeContainerType m_nodes
All nodes, continously index ordered, with first element = m_root.
typename Container::reverse_iterator reverse_iterator
Eigen::Matrix< Scalar, 3, 1 > Vector3
TreeStatistics m_statistics
NodeBase(std::size_t idx, const AABB< Dimension > &aabb, unsigned int treeLevel=0)
bool overlapsSubSpace(const AABB &box, unsigned int fixedAxis) const
AABB< Dimension > & aabb()
std::vector< Method > m_methods
StdVecAligned< TValue > PointListType
static Derived::Scalar apply(const MatrixBase< Derived > &p)
#define ApproxMVBB_STATIC_ASSERTM(B, COMMENT)
QualityEvaluator m_qualityEval
#define DEFINE_KDTREE_BASENODETYPES(_Base_)
#define ApproxMVBB_DEFINE_MATRIX_TYPES
PREC getSplitRatio() const
NodeType * m_root
Root node, has index 0!
const NodeType * getNode(const std::size_t &globalIndex) const
ArrayStat< Dim > extent() const
NodeSimple(NodeSimple &&t)
void setIdx(std::size_t i)
typename Container::value_type value_type
PREC computeSplitRatio(AABB< Dimension > &aabb)
iterator m_bestSplitRightIt
const AABB< Dimension > & aabb() const
std::size_t m_minNeighbours
TNode< BaseTraits > NodeType
SplitHeuristicType m_heuristic
reverse_iterator rbegin()
typename PointListType::const_iterator const_iterator