From 8ab0d7d7ab06befd4f8c29c95656b0b70d11d06f Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 4 Dec 2020 16:34:23 +0100 Subject: [PATCH] Bugfix: custom seam identification Bounding boxes of polygons could overlap. Ask the AABB tree for all possible candidates. Might be faster than searching for the closest triangle, that requires traversing the whole depth of the tree every time. --- src/libslic3r/AABBTreeIndirect.hpp | 37 ++++++++++++++---------------- src/libslic3r/GCode/SeamPlacer.cpp | 12 ++++++---- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/libslic3r/AABBTreeIndirect.hpp b/src/libslic3r/AABBTreeIndirect.hpp index 19fbf137807..87d1ee9dba4 100644 --- a/src/libslic3r/AABBTreeIndirect.hpp +++ b/src/libslic3r/AABBTreeIndirect.hpp @@ -730,29 +730,26 @@ inline bool is_any_triangle_in_radius( // Traverse the tree and return the index of an entity whose bounding box // contains a given point. Returns size_t(-1) when the point is outside. template -size_t get_candidate_idx(const TreeType& tree, const VectorType& v) +void get_candidate_idxs(const TreeType& tree, const VectorType& v, std::vector& candidates, size_t node_idx = 0) { - if (tree.empty() || ! tree.node(0).bbox.contains(v)) - return size_t(-1); + if (tree.empty() || ! tree.node(node_idx).bbox.contains(v)) + return; - size_t node_idx = 0; - while (true) { - decltype(tree.node(node_idx)) node = tree.node(node_idx); - static_assert(std::is_reference::value, - "Nodes shall be addressed by reference."); - assert(node.is_valid()); - assert(node.bbox.contains(v)); + decltype(tree.node(node_idx)) node = tree.node(node_idx); + static_assert(std::is_reference::value, + "Nodes shall be addressed by reference."); + assert(node.is_valid()); + assert(node.bbox.contains(v)); - if (! node.is_leaf()) { - if (tree.left_child(node_idx).bbox.contains(v)) - node_idx = tree.left_child_idx(node_idx); - else if (tree.right_child(node_idx).bbox.contains(v)) - node_idx = tree.right_child_idx(node_idx); - else - return size_t(-1); - } else - return node.idx; - } + if (! node.is_leaf()) { + if (tree.left_child(node_idx).bbox.contains(v)) + get_candidate_idxs(tree, v, candidates, tree.left_child_idx(node_idx)); + if (tree.right_child(node_idx).bbox.contains(v)) + get_candidate_idxs(tree, v, candidates, tree.right_child_idx(node_idx)); + } else + candidates.push_back(node.idx); + + return; } diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 5df2cc7e483..4b74391e80e 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -569,11 +569,13 @@ void SeamPlacer::get_enforcers_and_blockers(size_t layer_id, auto is_inside = [](const Point& pt, const CustomTrianglesPerLayer& custom_data) -> bool { assert(! custom_data.polys.empty()); - // Now ask the AABB tree which polygon we should check and check it. - size_t candidate = AABBTreeIndirect::get_candidate_idx(custom_data.tree, pt); - if (candidate != size_t(-1) - && custom_data.polys[candidate].contains(pt)) - return true; + // Now ask the AABB tree which polygons we should check and check them. + std::vector candidates; + AABBTreeIndirect::get_candidate_idxs(custom_data.tree, pt, candidates); + if (! candidates.empty()) + for (size_t idx : candidates) + if (custom_data.polys[idx].contains(pt)) + return true; return false; };