mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-16 10:25:55 +08:00
Replace KDTreeIndirect with boost::rtree for queries of PointCloud
- rtree can be populated with junction points gradually - Use repeated queries of 5 nearest reachable points in branching tree alg
This commit is contained in:
parent
d7c5243300
commit
36ec731adf
@ -11,35 +11,42 @@ namespace Slic3r { namespace branchingtree {
|
|||||||
|
|
||||||
bool build_tree(PointCloud &nodes, Builder &builder)
|
bool build_tree(PointCloud &nodes, Builder &builder)
|
||||||
{
|
{
|
||||||
|
constexpr size_t ReachablesToExamine = 5;
|
||||||
|
|
||||||
auto ptsqueue = nodes.start_queue();
|
auto ptsqueue = nodes.start_queue();
|
||||||
auto &properties = nodes.properties();
|
auto &properties = nodes.properties();
|
||||||
|
|
||||||
struct NodeDistance { size_t node_id; float distance; };
|
struct NodeDistance { size_t node_id = Node::ID_NONE; float distance = NaNf; };
|
||||||
auto distances = reserve_vector<NodeDistance>(nodes.reachable_count());
|
auto distances = reserve_vector<NodeDistance>(ReachablesToExamine);
|
||||||
|
double prev_dist_max = 0.;
|
||||||
|
|
||||||
while (!ptsqueue.empty()) {
|
while (!ptsqueue.empty()) {
|
||||||
size_t node_id = ptsqueue.top();
|
size_t node_id = ptsqueue.top();
|
||||||
ptsqueue.pop();
|
|
||||||
|
|
||||||
Node node = nodes.get(node_id);
|
Node node = nodes.get(node_id);
|
||||||
nodes.mark_unreachable(node_id);
|
nodes.mark_unreachable(node_id);
|
||||||
|
|
||||||
distances.clear();
|
distances.clear();
|
||||||
distances.reserve(nodes.reachable_count());
|
|
||||||
|
|
||||||
nodes.foreach_reachable(node.pos, [&distances](size_t id, float distance) {
|
nodes.foreach_reachable<ReachablesToExamine>(
|
||||||
if (!std::isinf(distance))
|
node.pos,
|
||||||
|
[&distances](size_t id, float distance) {
|
||||||
distances.emplace_back(NodeDistance{id, distance});
|
distances.emplace_back(NodeDistance{id, distance});
|
||||||
});
|
},
|
||||||
|
prev_dist_max);
|
||||||
|
|
||||||
std::sort(distances.begin(), distances.end(),
|
std::sort(distances.begin(), distances.end(),
|
||||||
[](auto &a, auto &b) { return a.distance < b.distance; });
|
[](auto &a, auto &b) { return a.distance < b.distance; });
|
||||||
|
|
||||||
if (distances.empty()) {
|
if (distances.empty()) {
|
||||||
builder.report_unroutable(node);
|
builder.report_unroutable(node);
|
||||||
|
ptsqueue.pop();
|
||||||
|
prev_dist_max = 0.;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prev_dist_max = distances.back().distance;
|
||||||
|
|
||||||
auto closest_it = distances.begin();
|
auto closest_it = distances.begin();
|
||||||
bool routed = false;
|
bool routed = false;
|
||||||
while (closest_it != distances.end() && !routed) {
|
while (closest_it != distances.end() && !routed) {
|
||||||
@ -136,8 +143,11 @@ bool build_tree(PointCloud &nodes, Builder &builder)
|
|||||||
++closest_it;
|
++closest_it;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!routed)
|
if (routed) {
|
||||||
builder.report_unroutable(node);
|
ptsqueue.pop();
|
||||||
|
prev_dist_max = 0.;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -142,16 +142,23 @@ PointCloud::PointCloud(std::vector<Node> meshpts,
|
|||||||
, m_searchable_indices(JUNCTIONS_BEGIN + m_junctions.size(), true)
|
, m_searchable_indices(JUNCTIONS_BEGIN + m_junctions.size(), true)
|
||||||
, m_queue_indices(JUNCTIONS_BEGIN + m_junctions.size(), Unqueued)
|
, m_queue_indices(JUNCTIONS_BEGIN + m_junctions.size(), Unqueued)
|
||||||
, m_reachable_cnt{JUNCTIONS_BEGIN + m_junctions.size()}
|
, m_reachable_cnt{JUNCTIONS_BEGIN + m_junctions.size()}
|
||||||
, m_ktree{CoordFn{this}, LEAFS_BEGIN} // Only for bed and mesh points
|
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < m_bedpoints.size(); ++i)
|
for (size_t i = 0; i < m_bedpoints.size(); ++i) {
|
||||||
m_bedpoints[i].id = int(i);
|
m_bedpoints[i].id = int(i);
|
||||||
|
m_ktree.insert({m_bedpoints[i].pos, i});
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < m_meshpoints.size(); ++i)
|
for (size_t i = 0; i < m_meshpoints.size(); ++i) {
|
||||||
m_meshpoints[i].id = int(MESHPTS_BEGIN + i);
|
Node &n = m_meshpoints[i];
|
||||||
|
n.id = int(MESHPTS_BEGIN + i);
|
||||||
|
m_ktree.insert({n.pos, n.id});
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < m_leafs.size(); ++i)
|
for (size_t i = 0; i < m_leafs.size(); ++i) {
|
||||||
m_leafs[i].id = int(LEAFS_BEGIN + i);
|
Node &n = m_leafs[i];
|
||||||
|
n.id = int(LEAFS_BEGIN + i);
|
||||||
|
m_ktree.insert({n.pos, n.id});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float PointCloud::get_distance(const Vec3f &p, size_t node_id) const
|
float PointCloud::get_distance(const Vec3f &p, size_t node_id) const
|
||||||
|
@ -6,9 +6,11 @@
|
|||||||
#include "BranchingTree.hpp"
|
#include "BranchingTree.hpp"
|
||||||
|
|
||||||
#include "libslic3r/Execution/Execution.hpp"
|
#include "libslic3r/Execution/Execution.hpp"
|
||||||
#include "libslic3r/KDTreeIndirect.hpp"
|
|
||||||
#include "libslic3r/MutablePriorityQueue.hpp"
|
#include "libslic3r/MutablePriorityQueue.hpp"
|
||||||
|
|
||||||
|
#include "libslic3r/BoostAdapter.hpp"
|
||||||
|
#include "boost/geometry/index/rtree.hpp"
|
||||||
|
|
||||||
namespace Slic3r { namespace branchingtree {
|
namespace Slic3r { namespace branchingtree {
|
||||||
|
|
||||||
std::optional<Vec3f> find_merge_pt(const Vec3f &A,
|
std::optional<Vec3f> find_merge_pt(const Vec3f &A,
|
||||||
@ -57,7 +59,11 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
KDTreeIndirect<3, float, CoordFn> m_ktree;
|
using PointIndexEl = std::pair<Vec3f, unsigned>;
|
||||||
|
|
||||||
|
boost::geometry::index::
|
||||||
|
rtree<PointIndexEl, boost::geometry::index::rstar<16, 4> /* ? */>
|
||||||
|
m_ktree;
|
||||||
|
|
||||||
bool is_outside_support_cone(const Vec3f &supp, const Vec3f &pt) const
|
bool is_outside_support_cone(const Vec3f &supp, const Vec3f &pt) const
|
||||||
{
|
{
|
||||||
@ -97,9 +103,9 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PointCloud(const indexed_triangle_set & M,
|
PointCloud(const indexed_triangle_set &M,
|
||||||
std::vector<Node> support_leafs,
|
std::vector<Node> support_leafs,
|
||||||
const Properties & props);
|
const Properties &props);
|
||||||
|
|
||||||
PointCloud(std::vector<Node> meshpts,
|
PointCloud(std::vector<Node> meshpts,
|
||||||
std::vector<Node> bedpts,
|
std::vector<Node> bedpts,
|
||||||
@ -154,6 +160,7 @@ public:
|
|||||||
size_t new_id = next_junction_id();
|
size_t new_id = next_junction_id();
|
||||||
m_junctions.emplace_back(p);
|
m_junctions.emplace_back(p);
|
||||||
m_junctions.back().id = int(new_id);
|
m_junctions.back().id = int(new_id);
|
||||||
|
m_ktree.insert({m_junctions.back().pos, new_id});
|
||||||
m_searchable_indices.emplace_back(true);
|
m_searchable_indices.emplace_back(true);
|
||||||
m_queue_indices.emplace_back(Unqueued);
|
m_queue_indices.emplace_back(Unqueued);
|
||||||
++m_reachable_cnt;
|
++m_reachable_cnt;
|
||||||
@ -178,21 +185,32 @@ public:
|
|||||||
|
|
||||||
size_t reachable_count() const { return m_reachable_cnt; }
|
size_t reachable_count() const { return m_reachable_cnt; }
|
||||||
|
|
||||||
template<class Fn> void foreach_reachable(const Vec3f &pos, Fn &&visitor)
|
template<size_t K, class Fn>
|
||||||
|
void foreach_reachable(const Vec3f &pos, Fn &&visitor, double min_dist = 0.)
|
||||||
{
|
{
|
||||||
auto closest_anchors =
|
// Fake output iterator
|
||||||
find_closest_points<5>(m_ktree, pos, [this, &pos](size_t id) {
|
struct Output {
|
||||||
return m_searchable_indices[id] &&
|
const PointCloud *self;
|
||||||
!is_outside_support_cone(pos, get(id).pos);
|
Vec3f p;
|
||||||
});
|
Fn &visitorfn;
|
||||||
|
|
||||||
for (size_t anchor : closest_anchors)
|
Output& operator *() { return *this; }
|
||||||
if (anchor != m_ktree.npos)
|
void operator=(const PointIndexEl &el) {
|
||||||
visitor(anchor, get_distance(pos, anchor));
|
visitorfn(el.second, self->get_distance(p, el.second));
|
||||||
|
}
|
||||||
|
Output& operator++() { return *this; }
|
||||||
|
};
|
||||||
|
|
||||||
for (size_t i = LEAFS_BEGIN; i < m_searchable_indices.size(); ++i)
|
namespace bgi = boost::geometry::index;
|
||||||
if (m_searchable_indices[i])
|
|
||||||
visitor(i, get_distance(pos, i));
|
size_t cnt = 0;
|
||||||
|
auto filter = bgi::satisfies([this, &pos, min_dist, &cnt](const PointIndexEl &e) {
|
||||||
|
double d = get_distance(pos, e.second);
|
||||||
|
cnt++;
|
||||||
|
return m_searchable_indices[e.second] && !isinf(d) && d > min_dist;
|
||||||
|
});
|
||||||
|
|
||||||
|
m_ktree.query(bgi::nearest(pos, K) && filter, Output{this, pos, visitor});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto start_queue()
|
auto start_queue()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user