Node data constructor deosnt have own logic

Calculation of Parabola length by sum of line segments
This commit is contained in:
Filip Sykala 2021-02-25 20:50:20 +01:00 committed by Lukas Matena
parent dd505eab82
commit 18d58da6ea
8 changed files with 126 additions and 63 deletions

View File

@ -52,19 +52,20 @@ public:
VoronoiGraph::ExPath & result,
const VoronoiGraph::Node *node,
double distance_to_node,
const VoronoiGraph::Path &prev_path)
VoronoiGraph::Path &&act_path,
std::set<const VoronoiGraph::Node *> &&skip_nodes
)
: result(result)
, node(node)
, distance_to_node(distance_to_node)
, act_path(std::move(act_path)) // copy prev and append actual node
, skip_nodes(std::move(skip_nodes))
{
// TODO: process it before constructor or in factory
const VoronoiGraph::Node *prev_node = (prev_path.path.size() >= 1) ?
prev_path.path.back() :
nullptr;
skip_nodes = {prev_node};
// append actual node
act_path = prev_path; // copy
act_path.append(node, distance_to_node); // increase path
//prev_path.extend(node, distance_to_node)
//const VoronoiGraph::Node *prev_node = (prev_path.nodes.size() >= 1) ?
// prev_path.nodes.back() :
// nullptr;
//skip_nodes = {prev_node};
}
};

View File

@ -7,11 +7,11 @@ using namespace Slic3r::sla;
void PostProcessNeighbor::process()
{
bool is_circle_neighbor = false;
if (neighbor_path.path.empty()) { // neighbor node is on circle
if (neighbor_path.nodes.empty()) { // neighbor node is on circle
for (VoronoiGraph::Circle &circle : neighbor_path.circles) {
const auto &circle_item = std::find(circle.path.begin(),
circle.path.end(), data.node);
if (circle_item == circle.path.end())
const auto &circle_item = std::find(circle.nodes.begin(),
circle.nodes.end(), data.node);
if (circle_item == circle.nodes.end())
continue; // node is NOT on circle
size_t next_circle_index = &circle -
@ -21,7 +21,7 @@ void PostProcessNeighbor::process()
data.circle_indexes.push_back(circle_index);
// check if this node is end of circle
if (circle_item == circle.path.begin()) {
if (circle_item == circle.nodes.begin()) {
data.end_circle_indexes.push_back(circle_index);
// !! this FIX circle lenght because at detection of
@ -29,7 +29,7 @@ void PostProcessNeighbor::process()
circle.length -= data.act_path.length;
// skip twice checking of circle
data.skip_nodes.insert(circle.path.back());
data.skip_nodes.insert(circle.nodes.back());
}
is_circle_neighbor = true;
}

View File

@ -44,7 +44,7 @@ void PostProcessNeighbors::process()
if (!side_branches.empty()) {
result.side_branches[node] = side_branches;
}
longest_path.path.insert(longest_path.path.begin(), node);
result.path = std::move(longest_path.path);
longest_path.nodes.insert(longest_path.nodes.begin(), node);
result.nodes = std::move(longest_path.nodes);
result.length = distance_to_node + longest_path.length;
}

View File

@ -19,7 +19,11 @@ public:
const VoronoiGraph::Path &prev_path =
VoronoiGraph::Path({}, 0.) // make copy
)
: NodeDataWithResult(result, node, distance_to_node, prev_path)
: NodeDataWithResult(
result, node, distance_to_node,
prev_path.extend(node, distance_to_node),
prepare_skip_nodes(prev_path)
)
{}
virtual void process([[maybe_unused]] CallStack &call_stack)
@ -28,6 +32,14 @@ public:
}
private:
static std::set<const VoronoiGraph::Node *> prepare_skip_nodes(
const VoronoiGraph::Path &prev_path)
{
if (prev_path.nodes.empty()) return {};
const VoronoiGraph::Node *prev_node = prev_path.nodes.back();
return {prev_node};
}
void process();
};

View File

@ -71,24 +71,30 @@ public:
struct VoronoiGraph::Path
{
// row of neighbor Nodes
VoronoiGraph::Nodes path; // TODO: rename to nodes
VoronoiGraph::Nodes nodes;
// length of path
// when circle contain length from back to front;
double length;
public:
Path() : path(), length(0.) {}
Path(const VoronoiGraph::Node *node) : path({node}), length(0.) {}
Path() : nodes(), length(0.) {}
Path(const VoronoiGraph::Node *node) : nodes({node}), length(0.) {}
Path(VoronoiGraph::Nodes nodes, double length)
: path(std::move(nodes)), length(length)
: nodes(std::move(nodes)), length(length)
{}
void append(const VoronoiGraph::Node *node, double length)
{
path.push_back(node);
nodes.push_back(node);
this->length += length;
}
Path extend(const VoronoiGraph::Node *node, double length) const {
Path result(*this); // make copy
result.append(node, length);
return result;
}
struct OrderLengthFromShortest{
bool operator()(const VoronoiGraph::Path &path1,

View File

@ -4,6 +4,8 @@
#include "IStackFunction.hpp"
#include "EvaluateNeighbor.hpp"
#include <libslic3r/VoronoiVisualUtils.hpp>
using namespace Slic3r::sla;
VoronoiGraph::Node *VoronoiGraphUtils::getNode(VoronoiGraph & graph,
@ -32,11 +34,45 @@ VoronoiGraph::Node *VoronoiGraphUtils::getNode(VoronoiGraph & graph,
return &iterator->second;
}
double VoronoiGraphUtils::calculate_length_of_parabola(
const VD::edge_type & edge,
const std::vector<Voronoi::Internal::segment_type> &segments)
{
// TODO: len by param not sampling of parabola
double discretization_step = 0.0002 * 1e7;
Points points; // voronoi created by line segments only
std::vector<Voronoi::Internal::point_type> samples;
samples.push_back(Voronoi::Internal::point_type(edge.vertex0()->x(),
edge.vertex0()->y()));
samples.push_back(Voronoi::Internal::point_type(edge.vertex1()->x(),
edge.vertex1()->y()));
Voronoi::Internal::sample_curved_edge(points, segments, edge, samples,
discretization_step);
double sumLength = 0;
for (size_t index = 1; index < samples.size(); ++index) {
double diffX = samples[index - 1].x() - samples[index].x();
double diffY = samples[index - 1].y() - samples[index].y();
double length = sqrt(diffX * diffX + diffY * diffY);
sumLength += length;
}
return sumLength;
}
VoronoiGraph VoronoiGraphUtils::getSkeleton(const VD &vd, const Lines &lines)
{
// vd should be annotated.
// assert(Voronoi::debug::verify_inside_outside_annotations(vd));
std::vector<Voronoi::Internal::segment_type> segments;
for (Lines::const_iterator it = lines.begin(); it != lines.end(); ++it)
segments.push_back(Voronoi::Internal::segment_type(
Voronoi::Internal::point_type(double(it->a(0)), double(it->a(1))),
Voronoi::Internal::point_type(double(it->b(0)),
double(it->b(1)))));
VoronoiGraph skeleton;
const VD::edge_type *first_edge = &vd.edges().front();
for (const VD::edge_type &edge : vd.edges()) {
@ -72,8 +108,8 @@ VoronoiGraph VoronoiGraphUtils::getSkeleton(const VD &vd, const Lines &lines)
double diffY = v0->y() - v1->y();
length = sqrt(diffX * diffX + diffY * diffY);
} else { // if (edge.is_curved())
// TODO: len of parabola
length = 1.0;
assert(edge.is_curved());
length = calculate_length_of_parabola(edge, segments);
}
VoronoiGraph::Node *node0 = getNode(skeleton, v0, &edge, lines);
@ -139,7 +175,7 @@ VoronoiGraph::Path VoronoiGraphUtils::find_longest_path_on_circle(
bool is_short_revers_direction = false;
// find longest side branch
const VoronoiGraph::Node *prev_circle_node = nullptr;
for (const VoronoiGraph::Node *circle_node : circle.path) {
for (const VoronoiGraph::Node *circle_node : circle.nodes) {
if (prev_circle_node != nullptr)
distance_on_circle += get_neighbor_distance(circle_node,
prev_circle_node);
@ -172,20 +208,20 @@ VoronoiGraph::Path VoronoiGraphUtils::find_longest_path_on_circle(
// circle.path.front()); assert(distance_on_circle == circle.length);
// circlePath
auto circle_iterator = std::find(circle.path.begin(), circle.path.end(),
auto circle_iterator = std::find(circle.nodes.begin(), circle.nodes.end(),
longest_circle_node);
VoronoiGraph::Nodes circle_path;
if (is_longest_revers_direction) {
circle_path = VoronoiGraph::Nodes(circle_iterator, circle.path.end());
circle_path = VoronoiGraph::Nodes(circle_iterator, circle.nodes.end());
std::reverse(circle_path.begin(), circle_path.end());
} else {
if (longest_circle_node != circle.path.front())
circle_path = VoronoiGraph::Nodes(circle.path.begin() + 1,
if (longest_circle_node != circle.nodes.front())
circle_path = VoronoiGraph::Nodes(circle.nodes.begin() + 1,
circle_iterator + 1);
}
// append longest side branch
circle_path.insert(circle_path.end(), longest_circle_branch->path.begin(),
longest_circle_branch->path.end());
circle_path.insert(circle_path.end(), longest_circle_branch->nodes.begin(),
longest_circle_branch->nodes.end());
return {circle_path, longest_branch_length};
}
@ -210,10 +246,10 @@ VoronoiGraph::Path VoronoiGraphUtils::find_longest_path_on_circles(
// collect all circle ndoes
std::set<const VoronoiGraph::Node *> nodes;
nodes.insert(circle.path.begin(), circle.path.end());
nodes.insert(circle.nodes.begin(), circle.nodes.end());
for (size_t circle_index : connected_circles) {
const auto &circle = circles[circle_index];
nodes.insert(circle.path.begin(), circle.path.end());
nodes.insert(circle.nodes.begin(), circle.nodes.end());
}
// nodes are path throw circles
@ -233,7 +269,7 @@ VoronoiGraph::Path VoronoiGraphUtils::find_longest_path_on_circles(
// shortest path from input_node
VoronoiGraph::Path path(std::move(search_queue.top()));
search_queue.pop();
const VoronoiGraph::Node &node = *path.path.back();
const VoronoiGraph::Node &node = *path.nodes.back();
if (done.find(&node) != done.end()) { // already checked
continue;
}
@ -254,24 +290,24 @@ VoronoiGraph::Path VoronoiGraphUtils::find_longest_path_on_circles(
double length = longest_branch.length + neighbor_path.length;
if (longest_path.length < length) {
longest_path.length = length;
longest_path.path = neighbor_path.path; // copy path
longest_path.nodes = neighbor_path.nodes; // copy path
}
}
}
// create result path
assert(!longest_path.path.empty());
longest_path.path.erase(longest_path.path.begin()); // remove input_node
assert(!longest_path.path.empty());
auto branches_item = ex_path.side_branches.find(longest_path.path.back());
assert(!longest_path.nodes.empty());
longest_path.nodes.erase(longest_path.nodes.begin()); // remove input_node
assert(!longest_path.nodes.empty());
auto branches_item = ex_path.side_branches.find(longest_path.nodes.back());
if (branches_item == ex_path.side_branches.end()) {
// longest path ends on circle
return longest_path;
}
const VoronoiGraph::Path &longest_branch = branches_item->second.top();
longest_path.path.insert(longest_path.path.end(),
longest_branch.path.begin(),
longest_branch.path.end());
longest_path.nodes.insert(longest_path.nodes.end(),
longest_branch.nodes.begin(),
longest_branch.nodes.end());
return longest_path;
}
@ -279,7 +315,7 @@ std::optional<VoronoiGraph::Circle> VoronoiGraphUtils::create_circle(
const VoronoiGraph::Path & path,
const VoronoiGraph::Node::Neighbor &neighbor)
{
VoronoiGraph::Nodes passed_nodes = path.path;
VoronoiGraph::Nodes passed_nodes = path.nodes;
// detection of circle
// not neccesary to check last one in path
auto end_find = passed_nodes.end() - 1;
@ -350,11 +386,11 @@ void VoronoiGraphUtils::append_neighbor_branch(
void VoronoiGraphUtils::reshape_longest_path(VoronoiGraph::ExPath &path)
{
assert(path.path.size() >= 1);
assert(path.nodes.size() >= 1);
double actual_length = 0.;
const VoronoiGraph::Node *prev_node = nullptr;
VoronoiGraph::Nodes origin_path = path.path; // make copy
VoronoiGraph::Nodes origin_path = path.nodes; // make copy
// index to path
size_t path_index = 0;
for (const VoronoiGraph::Node *node : origin_path) {
@ -373,24 +409,24 @@ void VoronoiGraphUtils::reshape_longest_path(VoronoiGraph::ExPath &path)
if (actual_length >= branches.top().length)
continue; // no longer branch
auto end_path = path.path.begin() + path_index;
VoronoiGraph::Path side_branch({path.path.begin(), end_path},
auto end_path = path.nodes.begin() + path_index;
VoronoiGraph::Path side_branch({path.nodes.begin(), end_path},
actual_length);
std::reverse(side_branch.path.begin(), side_branch.path.end());
std::reverse(side_branch.nodes.begin(), side_branch.nodes.end());
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.nodes.begin(), new_main_branch.nodes.end());
// add old main path store into side branches - may be it is not neccessary
branches.push(std::move(side_branch));
// swap side branch with main branch
path.path.erase(path.path.begin(), end_path);
path.path.insert(path.path.begin(), new_main_branch.path.begin(),
new_main_branch.path.end());
path.nodes.erase(path.nodes.begin(), end_path);
path.nodes.insert(path.nodes.begin(), new_main_branch.nodes.begin(),
new_main_branch.nodes.end());
path.length += new_main_branch.length;
path.length -= actual_length;
path_index = new_main_branch.path.size();
path_index = new_main_branch.nodes.size();
actual_length = new_main_branch.length;
}
}
@ -492,7 +528,7 @@ std::vector<Slic3r::Point> VoronoiGraphUtils::sample_voronoi_graph(
config.max_length_for_one_support_point) { // create only one
// point in center
// sample in center of voronoi
return {get_center_of_path(longest_path.path, longest_path.length)};
return {get_center_of_path(longest_path.nodes, longest_path.length)};
}
std::vector<Point> points;
@ -554,14 +590,14 @@ void VoronoiGraphUtils::draw(SVG & svg,
const char *mainPathColor = "red";
for (auto &circle : path.circles) {
draw(svg, circle.path, width, circlePathColor, true);
draw(svg, circle.nodes, width, circlePathColor, true);
Point center(0, 0);
for (auto p : circle.path) {
for (auto p : circle.nodes) {
center.x() += p->vertex->x();
center.y() += p->vertex->y();
}
center.x() /= circle.path.size();
center.y() /= circle.path.size();
center.x() /= circle.nodes.size();
center.y() /= circle.nodes.size();
svg.draw_text(center,
("C" + std::to_string(&circle - &path.circles.front()))
@ -573,12 +609,12 @@ void VoronoiGraphUtils::draw(SVG & svg,
auto tmp = branches.second; // copy
while (!tmp.empty()) {
const auto &branch = tmp.top();
auto path = branch.path;
auto path = branch.nodes;
path.insert(path.begin(), branches.first);
draw(svg, path, width, sideBranchesColor);
tmp.pop();
}
}
draw(svg, path.path, width, mainPathColor);
draw(svg, path.nodes, width, mainPathColor);
}

View File

@ -30,7 +30,15 @@ public:
const VD::edge_type * edge,
const Lines & lines
);
/// <summary>
/// Calculate length
/// </summary>
/// <param name="edge">curved edge</param>
/// <returns>edge length</returns>
static double calculate_length_of_parabola(const VD::edge_type &edge,
const std::vector<VD::segment_type> &segments);
/// <summary>
/// calculate distances to border of island and length on skeleton
/// </summary>

View File

@ -191,7 +191,7 @@ ExPolygons createTestIslands(double size)
{4 * size5, size5},
{3 * size5, size5}}};
size_t count_cirlce_lines = 1000; // test stack overfrow
size_t count_cirlce_lines = 16; // test stack overfrow
double r_CCW = size / 2;
double r_CW = r_CCW - size / 6;
// CCW: couter clock wise, CW: clock wise