From 6dba0d31ac07997867a8aa354695679d83f0e5f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Csik=C3=B3s=20Attila?= Date: Sun, 26 Nov 2023 22:42:54 +0100 Subject: [PATCH] Issue: #9 (KNN misses few neighborer nodes) --- octree.h | 12 +++++---- unittests/general.tests.cpp | 50 +++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/octree.h b/octree.h index 29eea86..e438ef1 100644 --- a/octree.h +++ b/octree.h @@ -1753,7 +1753,7 @@ namespace OrthoTree private: // K Nearest Neighbor helpers - static geometry_type getBoxWallDistanceMax(vector_type const& pt, box_type const& box) noexcept + static geometry_type getBoxWallDistance(vector_type const& pt, box_type const& box) noexcept { autoc& ptMin = AD::box_min_c(box); autoc& ptMax = AD::box_max_c(box); @@ -1771,7 +1771,7 @@ namespace OrthoTree return 0.0; } - return *std::min_element(begin(vDist), end(vDist)); + return *std::ranges::min_element(vDist); } @@ -1807,9 +1807,10 @@ namespace OrthoTree if (base::IsValidKey(kSmallestNode)) { autoc& nodeSmallest = cont_at(this->m_nodes, kSmallestNode); + autoc wallDist = getBoxWallDistance(pt, nodeSmallest.box); createEntityDistance(nodeSmallest, pt, vpt, setEntity); if (!nodeSmallest.IsAnyChildExist()) - if (getFarestDistance(setEntity, k) < getBoxWallDistanceMax(pt, nodeSmallest.box)) + if (getFarestDistance(setEntity, k) < wallDist) return convertEntityDistanceToList(setEntity, k); } @@ -1837,7 +1838,7 @@ namespace OrthoTree if (!setNodeDist.empty()) { - auto rLatestNodeDist = std::begin(setNodeDist)->distance; + auto rLatestNodeDist = setEntity.size() > k ? next(setEntity.begin(), k)->distance : std::numeric_limits::max(); for (autoc& nodeDist : setNodeDist) { autoc n = setEntity.size(); @@ -1845,7 +1846,8 @@ namespace OrthoTree break; createEntityDistance(nodeDist.node, pt, vpt, setEntity); - rLatestNodeDist = nodeDist.distance; + if (setEntity.size() > k) + rLatestNodeDist = next(setEntity.begin(), k)->distance; } } diff --git a/unittests/general.tests.cpp b/unittests/general.tests.cpp index 734443d..34e669b 100644 --- a/unittests/general.tests.cpp +++ b/unittests/general.tests.cpp @@ -1709,6 +1709,56 @@ namespace Tree2DTest Assert::IsTrue(std::ranges::is_permutation(vector{0, 1, 5, 6, 11}, vnn)); } + + TEST_METHOD(Issue9) + { + autoc poses = vector> + { + { 78.2619, 77.843 }, + { 90.3005, 90.5172 }, + { 69.8652, 12.2467 }, + { 48.4675, 48.4948 }, + { 36.3226, 68.4619 }, + { 98.8799, 42.7149 }, + { 31.412, 38.6866 }, + { 63.2748, 77.0524 }, + { 62.8844, 17.0536 }, + { 80.8931, 39.8099 }, + { 77.426, 64.9844 }, + { 81.9552, 25.009 }, + { 87.6088, 51.319 }, + { 78.5609, 80.4623 }, + { 51.3967, 39.5269 }, + { 32.2042, 81.8779 }, + { 79.1739, 81.5467 }, + { 95.2619, 40.4742 }, + { 86.437, 92.4406 }, + { 3.95388, 60.2327 }, + { 31.1283, 44.4917 }, + { 35.6778, 79.8545 }, + { 50.9926, 66.1373 }, + { 3.16271, 65.2519 }, + { 56.3665, 45.3819 } + }; + + + autoce search_point = array{ 43.6406, 57.5691 }; + using AD = OrthoTree::AdaptorGeneral<2, array, OrthoTree::BoundingBox2D>; + autoc itMin = std::ranges::min_element(poses, [&search_point](autoc& lhs, autoc& rhs) { return AD::distance2(lhs, search_point) < AD::distance2(rhs, search_point); }); + + std::array inspection_space_min = { 0.0, 0.0 }; + std::array inspection_space_max = { 100.0, 100.0 }; + OrthoTree::BoundingBox2D inspection_space; + inspection_space.Min = inspection_space_min; + inspection_space.Max = inspection_space_max; + //Standard Tree + auto tree = QuadtreePointC(poses, 9, inspection_space); + + auto neighbors = tree.GetNearestNeighbors(search_point, 1); + Assert::AreEqual(std::distance(poses.begin(), itMin), neighbors[0]); + } + + }; TEST_CLASS(Box_General)