mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-18 03:35:58 +08:00
side branches are stored inside priority_queue
This commit is contained in:
parent
3ea090d75b
commit
4baac072df
@ -2031,6 +2031,25 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct OrderLengthFromShortest
|
||||||
|
{
|
||||||
|
bool operator()(const VoronoiGraph::Path &path1,
|
||||||
|
const VoronoiGraph::Path &path2)
|
||||||
|
{
|
||||||
|
return path1.length > path2.length;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrderLengthFromLongest
|
||||||
|
{
|
||||||
|
bool operator()(const VoronoiGraph::Path &path1,
|
||||||
|
const VoronoiGraph::Path &path2)
|
||||||
|
{
|
||||||
|
return path1.length < path2.length;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Data object
|
/// Data object
|
||||||
/// extends path with circles and side branches
|
/// extends path with circles and side branches
|
||||||
@ -2039,8 +2058,10 @@ struct VoronoiGraph::ExPath : public VoronoiGraph::Path
|
|||||||
{
|
{
|
||||||
// not main path is stored in secondary paths
|
// not main path is stored in secondary paths
|
||||||
// key is pointer to source node
|
// key is pointer to source node
|
||||||
using SideBranches = std::map<const VoronoiGraph::Node *, std::vector<VoronoiGraph::Path>>;
|
using SideBranches = std::priority_queue<
|
||||||
SideBranches side_branches;
|
VoronoiGraph::Path, std::vector<VoronoiGraph::Path>, OrderLengthFromLongest>;
|
||||||
|
using SideBranchesMap = std::map<const VoronoiGraph::Node *, SideBranches>;
|
||||||
|
SideBranchesMap side_branches;
|
||||||
// circles
|
// circles
|
||||||
std::vector<VoronoiGraph::Circle> circles;
|
std::vector<VoronoiGraph::Circle> circles;
|
||||||
|
|
||||||
@ -2167,7 +2188,7 @@ double get_neighbor_distance(const VoronoiGraph::Node *from,
|
|||||||
/// <returns>Longest nodes path and its length</returns>
|
/// <returns>Longest nodes path and its length</returns>
|
||||||
VoronoiGraph::Path find_longest_path_on_circle(
|
VoronoiGraph::Path find_longest_path_on_circle(
|
||||||
const VoronoiGraph::Circle &circle,
|
const VoronoiGraph::Circle &circle,
|
||||||
const VoronoiGraph::ExPath::SideBranches &side_branches)
|
const VoronoiGraph::ExPath::SideBranchesMap &side_branches)
|
||||||
{
|
{
|
||||||
double half_circle_length = circle.length / 2.;
|
double half_circle_length = circle.length / 2.;
|
||||||
double distance_on_circle = 0;
|
double distance_on_circle = 0;
|
||||||
@ -2190,7 +2211,7 @@ VoronoiGraph::Path find_longest_path_on_circle(
|
|||||||
// side_branches should be sorted by length
|
// side_branches should be sorted by length
|
||||||
if (distance_on_circle > half_circle_length)
|
if (distance_on_circle > half_circle_length)
|
||||||
is_short_revers_direction = true;
|
is_short_revers_direction = true;
|
||||||
const auto &longest_node_branch = side_branches_item->second.front();
|
const auto &longest_node_branch = side_branches_item->second.top();
|
||||||
double circle_branch_length = longest_node_branch.length +
|
double circle_branch_length = longest_node_branch.length +
|
||||||
((is_short_revers_direction) ?
|
((is_short_revers_direction) ?
|
||||||
(circle.length -
|
(circle.length -
|
||||||
@ -2231,14 +2252,6 @@ VoronoiGraph::Path find_longest_path_on_circle(
|
|||||||
return {circle_path, longest_branch_length};
|
return {circle_path, longest_branch_length};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OrderByLength
|
|
||||||
{
|
|
||||||
bool operator()(const VoronoiGraph::Path &path1, const VoronoiGraph::Path &path2)
|
|
||||||
{
|
|
||||||
return path1.length > path2.length;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
VoronoiGraph::Path find_longest_path_on_circles(
|
VoronoiGraph::Path find_longest_path_on_circles(
|
||||||
const VoronoiGraph::Node &input_node,
|
const VoronoiGraph::Node &input_node,
|
||||||
size_t finished_circle_index,
|
size_t finished_circle_index,
|
||||||
@ -2270,11 +2283,11 @@ VoronoiGraph::Path find_longest_path_on_circles(
|
|||||||
VoronoiGraph::Path longest_path;
|
VoronoiGraph::Path longest_path;
|
||||||
|
|
||||||
// wide search by shortest distance for path over circle's node
|
// wide search by shortest distance for path over circle's node
|
||||||
// !! do NOT use recursion, may cause stack overflow
|
// !! Do NOT use recursion, may cause stack overflow
|
||||||
std::set<const VoronoiGraph::Node*> done; // all ready checked
|
std::set<const VoronoiGraph::Node*> done; // all ready checked
|
||||||
// on top is shortest path
|
// on top is shortest path
|
||||||
std::priority_queue<VoronoiGraph::Path, std::vector<VoronoiGraph::Path>,
|
std::priority_queue<VoronoiGraph::Path, std::vector<VoronoiGraph::Path>,
|
||||||
OrderByLength> search_queue;
|
OrderLengthFromShortest> search_queue;
|
||||||
VoronoiGraph::Path start_path({&input_node}, 0.);
|
VoronoiGraph::Path start_path({&input_node}, 0.);
|
||||||
search_queue.emplace(start_path);
|
search_queue.emplace(start_path);
|
||||||
while (!search_queue.empty()) {
|
while (!search_queue.empty()) {
|
||||||
@ -2297,7 +2310,7 @@ VoronoiGraph::Path find_longest_path_on_circles(
|
|||||||
// exist side from this neighbor node ?
|
// exist side from this neighbor node ?
|
||||||
if (branches_item == ex_path.side_branches.end()) continue;
|
if (branches_item == ex_path.side_branches.end()) continue;
|
||||||
const VoronoiGraph::Path &longest_branch =
|
const VoronoiGraph::Path &longest_branch =
|
||||||
branches_item->second.front();
|
branches_item->second.top();
|
||||||
double length = longest_branch.length + neighbor_path.length;
|
double length = longest_branch.length + neighbor_path.length;
|
||||||
if (longest_path.length < length) {
|
if (longest_path.length < length) {
|
||||||
longest_path.length = length;
|
longest_path.length = length;
|
||||||
@ -2308,29 +2321,20 @@ VoronoiGraph::Path find_longest_path_on_circles(
|
|||||||
|
|
||||||
// create result path
|
// create result path
|
||||||
assert(!longest_path.path.empty());
|
assert(!longest_path.path.empty());
|
||||||
longest_path.path.erase(longest_path.path.begin()); // remove start of circle
|
longest_path.path.erase(longest_path.path.begin()); // remove input_node
|
||||||
assert(!longest_path.path.empty());
|
assert(!longest_path.path.empty());
|
||||||
auto branches_item = ex_path.side_branches.find(longest_path.path.back());
|
auto branches_item = ex_path.side_branches.find(longest_path.path.back());
|
||||||
if (branches_item == ex_path.side_branches.end()) {
|
if (branches_item == ex_path.side_branches.end()) {
|
||||||
// longest path ends on circle
|
// longest path ends on circle
|
||||||
return longest_path;
|
return longest_path;
|
||||||
}
|
}
|
||||||
const VoronoiGraph::Path &longest_branch = branches_item->second.front();
|
const VoronoiGraph::Path &longest_branch = branches_item->second.top();
|
||||||
longest_path.path.insert(longest_path.path.end(),
|
longest_path.path.insert(longest_path.path.end(),
|
||||||
longest_branch.path.begin(),
|
longest_branch.path.begin(),
|
||||||
longest_branch.path.end());
|
longest_branch.path.end());
|
||||||
return longest_path;
|
return longest_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort_path_by_length(std::vector<VoronoiGraph::Path> &paths)
|
|
||||||
{
|
|
||||||
if (paths.size() <= 1) return;
|
|
||||||
std::sort(paths.begin(), paths.end(),
|
|
||||||
[](const VoronoiGraph::Path &path1, const VoronoiGraph::Path &path2) {
|
|
||||||
return path1.length > path2.length;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// function for detection circle in passed path
|
/// function for detection circle in passed path
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -2441,8 +2445,11 @@ VoronoiGraph::ExPath create_longest_branch_from_node(
|
|||||||
|
|
||||||
const std::vector<VoronoiGraph::Node::Neighbor> &neighbors = node.neighbors;
|
const std::vector<VoronoiGraph::Node::Neighbor> &neighbors = node.neighbors;
|
||||||
size_t neighbor_count = neighbors.size();
|
size_t neighbor_count = neighbors.size();
|
||||||
std::vector<VoronoiGraph::Path> side_branches;
|
std::priority_queue<VoronoiGraph::Path, std::vector<VoronoiGraph::Path>,
|
||||||
side_branches.reserve(neighbor_count - 1); // one neighbor is prev node
|
OrderLengthFromLongest>
|
||||||
|
side_branches;
|
||||||
|
|
||||||
|
//side_branches.reserve(neighbor_count - 1); // one neighbor is prev node
|
||||||
|
|
||||||
|
|
||||||
// skip node on circle when circle start at this node
|
// skip node on circle when circle start at this node
|
||||||
@ -2474,7 +2481,7 @@ VoronoiGraph::ExPath create_longest_branch_from_node(
|
|||||||
// is next node leaf ?
|
// is next node leaf ?
|
||||||
if (next_node.neighbors.size() == 1) {
|
if (next_node.neighbors.size() == 1) {
|
||||||
VoronoiGraph::Path side_branch({&next_node}, neighbor.edge_length);
|
VoronoiGraph::Path side_branch({&next_node}, neighbor.edge_length);
|
||||||
side_branches.emplace_back(std::move(side_branch));
|
side_branches.push(std::move(side_branch));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2509,8 +2516,7 @@ VoronoiGraph::ExPath create_longest_branch_from_node(
|
|||||||
|
|
||||||
append_neighbor_branch(result, next_path);
|
append_neighbor_branch(result, next_path);
|
||||||
|
|
||||||
if (!is_circle_neighbor)
|
if (!is_circle_neighbor) side_branches.push(std::move(next_path));
|
||||||
side_branches.emplace_back(std::move(next_path));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remember connected circle
|
// remember connected circle
|
||||||
@ -2527,7 +2533,7 @@ VoronoiGraph::ExPath create_longest_branch_from_node(
|
|||||||
if (!end_circle_indexes.empty() &&
|
if (!end_circle_indexes.empty() &&
|
||||||
end_circle_indexes.size() == circle_indexes.size()) {
|
end_circle_indexes.size() == circle_indexes.size()) {
|
||||||
size_t circle_index = circle_indexes.front(); // possible any of them
|
size_t circle_index = circle_indexes.front(); // possible any of them
|
||||||
side_branches.push_back(
|
side_branches.push(
|
||||||
find_longest_path_on_circles(node, circle_index, result));
|
find_longest_path_on_circles(node, circle_index, result));
|
||||||
|
|
||||||
circle_indexes.clear(); // resolved circles
|
circle_indexes.clear(); // resolved circles
|
||||||
@ -2538,9 +2544,6 @@ VoronoiGraph::ExPath create_longest_branch_from_node(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// from longest path
|
|
||||||
sort_path_by_length(side_branches);
|
|
||||||
|
|
||||||
// is node on unresolved circle?
|
// is node on unresolved circle?
|
||||||
if (!circle_indexes.empty()) {
|
if (!circle_indexes.empty()) {
|
||||||
// not search for longest path, it will eval on end of circle
|
// not search for longest path, it will eval on end of circle
|
||||||
@ -2548,8 +2551,8 @@ VoronoiGraph::ExPath create_longest_branch_from_node(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
VoronoiGraph::Path longest_path(std::move(side_branches.front()));
|
VoronoiGraph::Path longest_path(std::move(side_branches.top()));
|
||||||
side_branches.erase(side_branches.begin());
|
side_branches.pop();
|
||||||
if (!side_branches.empty()) {
|
if (!side_branches.empty()) {
|
||||||
result.side_branches[&node] = side_branches;
|
result.side_branches[&node] = side_branches;
|
||||||
}
|
}
|
||||||
@ -2596,21 +2599,19 @@ void reshape_longest_path(VoronoiGraph::ExPath& path) {
|
|||||||
auto side_branches_item = path.side_branches.find(node);
|
auto side_branches_item = path.side_branches.find(node);
|
||||||
if (side_branches_item == path.side_branches.end())
|
if (side_branches_item == path.side_branches.end())
|
||||||
continue; // no side branches
|
continue; // no side branches
|
||||||
std::vector<VoronoiGraph::Path> &branches = side_branches_item->second;
|
VoronoiGraph::ExPath::SideBranches &branches = side_branches_item->second;
|
||||||
VoronoiGraph::Path &longest_branch = branches.front(); // branches are sorted
|
if (actual_length >= branches.top().length)
|
||||||
if (actual_length >= longest_branch.length)
|
|
||||||
continue; // no longer branch
|
continue; // no longer branch
|
||||||
|
|
||||||
auto end_path = path.path.begin() + path_index;
|
auto end_path = path.path.begin() + path_index;
|
||||||
VoronoiGraph::Path side_branch({path.path.begin(), end_path},
|
VoronoiGraph::Path side_branch({path.path.begin(), end_path},
|
||||||
actual_length);
|
actual_length);
|
||||||
std::reverse(side_branch.path.begin(), side_branch.path.end());
|
std::reverse(side_branch.path.begin(), side_branch.path.end());
|
||||||
VoronoiGraph::Path new_main_branch(std::move(longest_branch));
|
VoronoiGraph::Path new_main_branch(std::move(branches.top()));
|
||||||
|
branches.pop();
|
||||||
std::reverse(new_main_branch.path.begin(), new_main_branch.path.end());
|
std::reverse(new_main_branch.path.begin(), new_main_branch.path.end());
|
||||||
// add old main path store into side branches - may be it is not neccessary
|
// add old main path store into side branches - may be it is not neccessary
|
||||||
branches.erase(branches.begin());
|
branches.push(std::move(side_branch));
|
||||||
branches.emplace_back(std::move(side_branch));
|
|
||||||
sort_path_by_length(branches);
|
|
||||||
|
|
||||||
// swap side branch with main branch
|
// swap side branch with main branch
|
||||||
path.path.erase(path.path.begin(), end_path);
|
path.path.erase(path.path.begin(), end_path);
|
||||||
@ -2633,6 +2634,9 @@ void reshape_longest_path(VoronoiGraph::ExPath& path) {
|
|||||||
VoronoiGraph::ExPath create_longest_path(const VoronoiGraph::Node *start_node)
|
VoronoiGraph::ExPath create_longest_path(const VoronoiGraph::Node *start_node)
|
||||||
{
|
{
|
||||||
VoronoiGraph::ExPath longest_path = create_longest_branch_from_node(*start_node);
|
VoronoiGraph::ExPath longest_path = create_longest_branch_from_node(*start_node);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
reshape_longest_path(longest_path);
|
reshape_longest_path(longest_path);
|
||||||
// after reshape it shoud be longest path for whole Voronoi Graph
|
// after reshape it shoud be longest path for whole Voronoi Graph
|
||||||
return longest_path;
|
return longest_path;
|
||||||
@ -2809,11 +2813,15 @@ void draw(SVG &svg, const VoronoiGraph::ExPath &path, coord_t width) {
|
|||||||
svg.draw_text(center, ("C"+std::to_string(&circle - &path.circles.front())).c_str(), circlePathColor);
|
svg.draw_text(center, ("C"+std::to_string(&circle - &path.circles.front())).c_str(), circlePathColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& branches : path.side_branches)
|
for (const auto &branches : path.side_branches) {
|
||||||
for (auto &branch : branches.second) {
|
auto tmp = branches.second; // copy
|
||||||
|
while (!tmp.empty()){
|
||||||
|
const auto &branch = tmp.top();
|
||||||
auto path = branch.path;
|
auto path = branch.path;
|
||||||
path.insert(path.begin(), branches.first);
|
path.insert(path.begin(), branches.first);
|
||||||
draw(svg, path, width, sideBranchesColor);
|
draw(svg, path, width, sideBranchesColor);
|
||||||
|
tmp.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(svg, path.path, width, mainPathColor);
|
draw(svg, path.path, width, mainPathColor);
|
||||||
@ -3017,7 +3025,7 @@ TEST_CASE("Sample small islands", "[VoronoiSkeleton]")
|
|||||||
, triangle_with_hole
|
, triangle_with_hole
|
||||||
, rect_with_4_hole
|
, rect_with_4_hole
|
||||||
, mountains
|
, mountains
|
||||||
//, double_circle
|
, double_circle
|
||||||
//, frog_leg
|
//, frog_leg
|
||||||
};
|
};
|
||||||
for (auto &island : islands) {
|
for (auto &island : islands) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user