diff --git a/Ponca/src/SpatialPartitioning/KdTree/kdTree.h b/Ponca/src/SpatialPartitioning/KdTree/kdTree.h index df9aaf24..9a063db1 100644 --- a/Ponca/src/SpatialPartitioning/KdTree/kdTree.h +++ b/Ponca/src/SpatialPartitioning/KdTree/kdTree.h @@ -282,7 +282,8 @@ public : // Utilities --------------------------------------------------------------- public: - inline bool valid() const; + /// \param ignore_duplicates By default, valid KdTree can have duplicated samples. + inline bool valid(bool ignore_duplicates = true) const; inline void print(std::ostream& os, bool verbose = false) const; // Data -------------------------------------------------------------------- diff --git a/Ponca/src/SpatialPartitioning/KdTree/kdTree.hpp b/Ponca/src/SpatialPartitioning/KdTree/kdTree.hpp index 255d6f07..b2fd5aed 100644 --- a/Ponca/src/SpatialPartitioning/KdTree/kdTree.hpp +++ b/Ponca/src/SpatialPartitioning/KdTree/kdTree.hpp @@ -25,11 +25,13 @@ void KdTreeBase::clear() } template -bool KdTreeBase::valid() const +bool KdTreeBase::valid(bool ignore_duplicates) const { + // Check if point container is empty if (m_points.empty()) return m_nodes.empty() && m_indices.empty(); + // Check that at least one node has been created, and index container is not empty if(m_nodes.empty() || m_indices.empty()) { return false; @@ -38,7 +40,7 @@ bool KdTreeBase::valid() const std::vector b(point_count(), false); for(IndexType idx : m_indices) { - if(idx < 0 || point_count() <= idx || b[idx]) + if(idx < 0 || point_count() <= idx || ( ignore_duplicates ? false : b[idx])) { return false; } @@ -154,6 +156,8 @@ void KdTreeBase::build_rec(NodeIndexType node_id, IndexType start, Index node.set_is_leaf( end-start <= m_min_cell_size || level >= Traits::MAX_DEPTH || + // Stop descending if the content of the node is not one unique point + aabb.diagonal().squaredNorm() <= Eigen::NumTraits::epsilon() || // Since we add 2 nodes per inner node we need to stop if we can't add // them both (NodeIndexType)m_nodes.size() > MAX_NODE_COUNT - 2); diff --git a/tests/src/kdtree.cpp b/tests/src/kdtree.cpp index aac0b096..82022721 100644 --- a/tests/src/kdtree.cpp +++ b/tests/src/kdtree.cpp @@ -71,6 +71,35 @@ void testKdtreeWithDuplicate() test_tree(points, ids, cellSize); } + // Generate a small part of duplicates by extending the index container + { + const int nbDuplicates = N; + + ids.resize(nbDuplicates+N); + std::generate(ids.begin()+N, ids.end(), [N]() {return Eigen::internal::random(0,N-1); }); + + test_tree(points, ids, cellSize); + } + + // Generate duplicated coordinates samples TODO + // { +// const int nbDuplicates = N/10; +// const int nbUniques = N; +// +// auto points = VectorContainer(nbUniques); +// std::generate(points.begin(), points.end(), []() {return DataPoint(VectorType::Random()); }); +// +// typename KdTreeDense::IndexContainer ids(nbUniques); +// std::iota(ids.begin(), ids.end(), 0); +// ids.resize(nbDuplicates*nbUniques); +// +// for (int i = 1; i < nbDuplicates; ++i) +// { +// std::copy(ids.begin(), ids.begin() + nbUniques, ids.begin()+(nbUniques*i)); +// } +// test_tree(points, ids, cellSize); +// } + } template