Added a lot of debugging outputs (SVG) into SkeletalTrapezoidation.
This commit is contained in:
parent
4d19eb9ace
commit
e838acdcd1
@ -22,8 +22,6 @@
|
|||||||
|
|
||||||
#define SKELETAL_TRAPEZOIDATION_BEAD_SEARCH_MAX 1000 //A limit to how long it'll keep searching for adjacent beads. Increasing will re-use beadings more often (saving performance), but search longer for beading (costing performance).
|
#define SKELETAL_TRAPEZOIDATION_BEAD_SEARCH_MAX 1000 //A limit to how long it'll keep searching for adjacent beads. Increasing will re-use beadings more often (saving performance), but search longer for beading (costing performance).
|
||||||
|
|
||||||
//#define ARACHNE_DEBUG
|
|
||||||
|
|
||||||
namespace boost::polygon {
|
namespace boost::polygon {
|
||||||
|
|
||||||
template<> struct geometry_concept<Slic3r::Arachne::PolygonsSegmentIndex>
|
template<> struct geometry_concept<Slic3r::Arachne::PolygonsSegmentIndex>
|
||||||
@ -46,6 +44,71 @@ template<> struct segment_traits<Slic3r::Arachne::PolygonsSegmentIndex>
|
|||||||
namespace Slic3r::Arachne
|
namespace Slic3r::Arachne
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
static void export_graph_to_svg(const std::string &path,
|
||||||
|
SkeletalTrapezoidationGraph &graph,
|
||||||
|
const Polygons &polys,
|
||||||
|
const std::vector<std::shared_ptr<LineJunctions>> &edge_junctions = {},
|
||||||
|
const bool beat_count = true,
|
||||||
|
const bool transition_middles = true,
|
||||||
|
const bool transition_ends = true)
|
||||||
|
{
|
||||||
|
const std::vector<std::string> colors = {"blue", "cyan", "red", "orange", "magenta", "pink", "purple", "green", "yellow"};
|
||||||
|
coordf_t stroke_width = scale_(0.03);
|
||||||
|
BoundingBox bbox = get_extents(polys);
|
||||||
|
for (const auto &node : graph.nodes)
|
||||||
|
bbox.merge(node.p);
|
||||||
|
|
||||||
|
bbox.offset(scale_(1.));
|
||||||
|
|
||||||
|
::Slic3r::SVG svg(path.c_str(), bbox);
|
||||||
|
for (const auto &line : to_lines(polys))
|
||||||
|
svg.draw(line, "gray", stroke_width);
|
||||||
|
|
||||||
|
for (const auto &edge : graph.edges)
|
||||||
|
svg.draw(Line(edge.from->p, edge.to->p), (edge.data.centralIsSet() && edge.data.isCentral()) ? "blue" : "cyan", stroke_width);
|
||||||
|
|
||||||
|
for (const auto &line_junction : edge_junctions)
|
||||||
|
for (const auto &extrusion_junction : *line_junction)
|
||||||
|
svg.draw(extrusion_junction.p, "orange", coord_t(stroke_width * 2.));
|
||||||
|
|
||||||
|
if (beat_count) {
|
||||||
|
for (const auto &node : graph.nodes) {
|
||||||
|
svg.draw(node.p, "red", coord_t(stroke_width * 1.6));
|
||||||
|
svg.draw_text(node.p, std::to_string(node.data.bead_count).c_str(), "black", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transition_middles) {
|
||||||
|
for (auto &edge : graph.edges) {
|
||||||
|
if (std::shared_ptr<std::list<SkeletalTrapezoidationEdge::TransitionMiddle>> transitions = edge.data.getTransitions(); transitions) {
|
||||||
|
for (auto &transition : *transitions) {
|
||||||
|
Line edge_line = Line(edge.to->p, edge.from->p);
|
||||||
|
double edge_length = edge_line.length();
|
||||||
|
Point pt = edge_line.a + (edge_line.vector().cast<double>() * (double(transition.pos) / edge_length)).cast<coord_t>();
|
||||||
|
svg.draw(pt, "magenta", coord_t(stroke_width * 1.5));
|
||||||
|
svg.draw_text(pt, std::to_string(transition.lower_bead_count).c_str(), "black", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transition_ends) {
|
||||||
|
for (auto &edge : graph.edges) {
|
||||||
|
if (std::shared_ptr<std::list<SkeletalTrapezoidationEdge::TransitionEnd>> transitions = edge.data.getTransitionEnds(); transitions) {
|
||||||
|
for (auto &transition : *transitions) {
|
||||||
|
Line edge_line = Line(edge.to->p, edge.from->p);
|
||||||
|
double edge_length = edge_line.length();
|
||||||
|
Point pt = edge_line.a + (edge_line.vector().cast<double>() * (double(transition.pos) / edge_length)).cast<coord_t>();
|
||||||
|
svg.draw(pt, transition.is_lower_end ? "green" : "lime", coord_t(stroke_width * 1.5));
|
||||||
|
svg.draw_text(pt, std::to_string(transition.lower_bead_count).c_str(), "black", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SkeletalTrapezoidation::node_t& SkeletalTrapezoidation::makeNode(vd_t::vertex_type& vd_node, Point p)
|
SkeletalTrapezoidation::node_t& SkeletalTrapezoidation::makeNode(vd_t::vertex_type& vd_node, Point p)
|
||||||
{
|
{
|
||||||
auto he_node_it = vd_node_to_he_node.find(&vd_node);
|
auto he_node_it = vd_node_to_he_node.find(&vd_node);
|
||||||
@ -489,6 +552,10 @@ inline static void rotate_back_skeletal_trapezoidation_graph_after_fix(SkeletalT
|
|||||||
|
|
||||||
void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
|
void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
|
||||||
{
|
{
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
this->outline = polys;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Check self intersections.
|
// Check self intersections.
|
||||||
assert([&polys]() -> bool {
|
assert([&polys]() -> bool {
|
||||||
EdgeGrid::Grid grid;
|
EdgeGrid::Grid grid;
|
||||||
@ -517,7 +584,7 @@ void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
|
|||||||
Geometry::VoronoiDiagram voronoi_diagram;
|
Geometry::VoronoiDiagram voronoi_diagram;
|
||||||
construct_voronoi(segments.begin(), segments.end(), &voronoi_diagram);
|
construct_voronoi(segments.begin(), segments.end(), &voronoi_diagram);
|
||||||
|
|
||||||
#ifdef ARACHNE_DEBUG
|
#ifdef ARACHNE_DEBUG_VORONOI
|
||||||
{
|
{
|
||||||
static int iRun = 0;
|
static int iRun = 0;
|
||||||
dump_voronoi_to_svg(debug_out_path("arachne_voronoi-diagram-%d.svg", iRun++).c_str(), voronoi_diagram, to_points(polys), to_lines(polys));
|
dump_voronoi_to_svg(debug_out_path("arachne_voronoi-diagram-%d.svg", iRun++).c_str(), voronoi_diagram, to_points(polys), to_lines(polys));
|
||||||
@ -694,45 +761,62 @@ void SkeletalTrapezoidation::separatePointyQuadEndNodes()
|
|||||||
// vvvvvvvvvvvvvvvvvvvvv
|
// vvvvvvvvvvvvvvvvvvvvv
|
||||||
//
|
//
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void export_graph_to_svg(const std::string &path, const SkeletalTrapezoidationGraph &graph, const Polygons &polys)
|
|
||||||
{
|
|
||||||
const std::vector<std::string> colors = {"blue", "cyan", "red", "orange", "magenta", "pink", "purple", "green", "yellow"};
|
|
||||||
coordf_t stroke_width = scale_(0.05);
|
|
||||||
BoundingBox bbox;
|
|
||||||
for (const auto &node : graph.nodes)
|
|
||||||
bbox.merge(node.p);
|
|
||||||
|
|
||||||
bbox.offset(scale_(1.));
|
|
||||||
::Slic3r::SVG svg(path.c_str(), bbox);
|
|
||||||
for (const auto &line : to_lines(polys))
|
|
||||||
svg.draw(line, "red", stroke_width);
|
|
||||||
|
|
||||||
for (const auto &edge : graph.edges)
|
|
||||||
svg.draw(Line(edge.from->p, edge.to->p), "cyan", scale_(0.01));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void SkeletalTrapezoidation::generateToolpaths(std::vector<VariableWidthLines> &generated_toolpaths, bool filter_outermost_central_edges)
|
void SkeletalTrapezoidation::generateToolpaths(std::vector<VariableWidthLines> &generated_toolpaths, bool filter_outermost_central_edges)
|
||||||
{
|
{
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
static int iRun = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
p_generated_toolpaths = &generated_toolpaths;
|
p_generated_toolpaths = &generated_toolpaths;
|
||||||
|
|
||||||
updateIsCentral();
|
updateIsCentral();
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
export_graph_to_svg(debug_out_path("ST-updateIsCentral-final-%d.svg", iRun), this->graph, this->outline);
|
||||||
|
#endif
|
||||||
|
|
||||||
filterCentral(central_filter_dist);
|
filterCentral(central_filter_dist);
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
export_graph_to_svg(debug_out_path("ST-filterCentral-final-%d.svg", iRun), this->graph, this->outline);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (filter_outermost_central_edges)
|
if (filter_outermost_central_edges)
|
||||||
filterOuterCentral();
|
filterOuterCentral();
|
||||||
|
|
||||||
updateBeadCount();
|
updateBeadCount();
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
export_graph_to_svg(debug_out_path("ST-updateBeadCount-final-%d.svg", iRun), this->graph, this->outline);
|
||||||
|
#endif
|
||||||
|
|
||||||
filterNoncentralRegions();
|
filterNoncentralRegions();
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
export_graph_to_svg(debug_out_path("ST-filterNoncentralRegions-final-%d.svg", iRun), this->graph, this->outline);
|
||||||
|
#endif
|
||||||
|
|
||||||
generateTransitioningRibs();
|
generateTransitioningRibs();
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
export_graph_to_svg(debug_out_path("ST-generateTransitioningRibs-final-%d.svg", iRun), this->graph, this->outline);
|
||||||
|
#endif
|
||||||
|
|
||||||
generateExtraRibs();
|
generateExtraRibs();
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
export_graph_to_svg(debug_out_path("ST-generateExtraRibs-final-%d.svg", iRun), this->graph, this->outline);
|
||||||
|
#endif
|
||||||
|
|
||||||
generateSegments();
|
generateSegments();
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
export_graph_to_svg(debug_out_path("ST-generateSegments-final-%d.svg", iRun), this->graph, this->outline);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
++iRun;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletalTrapezoidation::updateIsCentral()
|
void SkeletalTrapezoidation::updateIsCentral()
|
||||||
@ -944,11 +1028,24 @@ void SkeletalTrapezoidation::generateTransitioningRibs()
|
|||||||
|
|
||||||
filterTransitionMids();
|
filterTransitionMids();
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
static int iRun = 0;
|
||||||
|
export_graph_to_svg(debug_out_path("ST-generateTransitioningRibs-mids-%d.svg", iRun++), this->graph, this->outline);
|
||||||
|
#endif
|
||||||
|
|
||||||
ptr_vector_t<std::list<TransitionEnd>> edge_transition_ends; // We only map the half edge in the upward direction. mapped items are not sorted
|
ptr_vector_t<std::list<TransitionEnd>> edge_transition_ends; // We only map the half edge in the upward direction. mapped items are not sorted
|
||||||
generateAllTransitionEnds(edge_transition_ends);
|
generateAllTransitionEnds(edge_transition_ends);
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
export_graph_to_svg(debug_out_path("ST-generateTransitioningRibs-ends-%d.svg", iRun++), this->graph, this->outline);
|
||||||
|
#endif
|
||||||
|
|
||||||
applyTransitions(edge_transition_ends);
|
applyTransitions(edge_transition_ends);
|
||||||
// Note that the shared pointer lists will be out of scope and thus destroyed here, since the remaining refs are weak_ptr.
|
// Note that the shared pointer lists will be out of scope and thus destroyed here, since the remaining refs are weak_ptr.
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
++iRun;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1668,17 +1765,38 @@ void SkeletalTrapezoidation::generateSegments()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
static int iRun = 0;
|
||||||
|
export_graph_to_svg(debug_out_path("ST-generateSegments-before-propagation-%d.svg", iRun), this->graph, this->outline);
|
||||||
|
#endif
|
||||||
|
|
||||||
propagateBeadingsUpward(upward_quad_mids, node_beadings);
|
propagateBeadingsUpward(upward_quad_mids, node_beadings);
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
export_graph_to_svg(debug_out_path("ST-generateSegments-upward-propagation-%d.svg", iRun), this->graph, this->outline);
|
||||||
|
#endif
|
||||||
|
|
||||||
propagateBeadingsDownward(upward_quad_mids, node_beadings);
|
propagateBeadingsDownward(upward_quad_mids, node_beadings);
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
export_graph_to_svg(debug_out_path("ST-generateSegments-downward-propagation-%d.svg", iRun), this->graph, this->outline);
|
||||||
|
#endif
|
||||||
|
|
||||||
ptr_vector_t<LineJunctions> edge_junctions; // junctions ordered high R to low R
|
ptr_vector_t<LineJunctions> edge_junctions; // junctions ordered high R to low R
|
||||||
generateJunctions(node_beadings, edge_junctions);
|
generateJunctions(node_beadings, edge_junctions);
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
export_graph_to_svg(debug_out_path("ST-generateSegments-junctions-%d.svg", iRun), this->graph, this->outline, edge_junctions);
|
||||||
|
#endif
|
||||||
|
|
||||||
connectJunctions(edge_junctions);
|
connectJunctions(edge_junctions);
|
||||||
|
|
||||||
generateLocalMaximaSingleBeads();
|
generateLocalMaximaSingleBeads();
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
++iRun;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SkeletalTrapezoidation::edge_t* SkeletalTrapezoidation::getQuadMaxRedgeTo(edge_t* quad_start_edge)
|
SkeletalTrapezoidation::edge_t* SkeletalTrapezoidation::getQuadMaxRedgeTo(edge_t* quad_start_edge)
|
||||||
|
@ -20,6 +20,9 @@
|
|||||||
#include "SkeletalTrapezoidationGraph.hpp"
|
#include "SkeletalTrapezoidationGraph.hpp"
|
||||||
#include "../Geometry/Voronoi.hpp"
|
#include "../Geometry/Voronoi.hpp"
|
||||||
|
|
||||||
|
//#define ARACHNE_DEBUG
|
||||||
|
//#define ARACHNE_DEBUG_VORONOI
|
||||||
|
|
||||||
namespace Slic3r::Arachne
|
namespace Slic3r::Arachne
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -123,6 +126,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
void generateToolpaths(std::vector<VariableWidthLines> &generated_toolpaths, bool filter_outermost_central_edges = false);
|
void generateToolpaths(std::vector<VariableWidthLines> &generated_toolpaths, bool filter_outermost_central_edges = false);
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
Polygons outline;
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/*!
|
/*!
|
||||||
* Auxiliary for referencing one transition along an edge which may contain multiple transitions
|
* Auxiliary for referencing one transition along an edge which may contain multiple transitions
|
||||||
|
@ -12,6 +12,13 @@
|
|||||||
#include <stack>
|
#include <stack>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
//#define ARACHNE_DEBUG
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
#include "SVG.hpp"
|
||||||
|
#include "Utils.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance)
|
ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance)
|
||||||
@ -537,6 +544,27 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &p
|
|||||||
return extrusion_coll;
|
return extrusion_coll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
static void export_perimeters_to_svg(const std::string &path, const Polygons &contours, const std::vector<Arachne::VariableWidthLines> &perimeters, const ExPolygons &infill_area)
|
||||||
|
{
|
||||||
|
coordf_t stroke_width = scale_(0.03);
|
||||||
|
BoundingBox bbox = get_extents(contours);
|
||||||
|
bbox.offset(scale_(1.));
|
||||||
|
::Slic3r::SVG svg(path.c_str(), bbox);
|
||||||
|
|
||||||
|
svg.draw(infill_area, "cyan");
|
||||||
|
|
||||||
|
for (const Arachne::VariableWidthLines &perimeter : perimeters)
|
||||||
|
for (const Arachne::ExtrusionLine &extrusion_line : perimeter) {
|
||||||
|
ThickPolyline thick_polyline = to_thick_polyline(extrusion_line);
|
||||||
|
svg.draw({thick_polyline}, "green", "blue", stroke_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const Line &line : to_lines(contours))
|
||||||
|
svg.draw(line, "red", stroke_width);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper
|
// Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper
|
||||||
// "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling"
|
// "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling"
|
||||||
void PerimeterGenerator::process_arachne()
|
void PerimeterGenerator::process_arachne()
|
||||||
@ -578,6 +606,13 @@ void PerimeterGenerator::process_arachne()
|
|||||||
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
|
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
|
||||||
loop_number = int(perimeters.size()) - 1;
|
loop_number = int(perimeters.size()) - 1;
|
||||||
|
|
||||||
|
#ifdef ARACHNE_DEBUG
|
||||||
|
{
|
||||||
|
static int iRun = 0;
|
||||||
|
export_perimeters_to_svg(debug_out_path("arachne-perimeters-%d-%d.svg", layer_id, iRun++), to_polygons(last), perimeters, union_ex(wallToolPaths.getInnerContour()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// All closed ExtrusionLine should have the same the first and the last point.
|
// All closed ExtrusionLine should have the same the first and the last point.
|
||||||
// But in rare cases, Arachne produce ExtrusionLine marked as closed but without
|
// But in rare cases, Arachne produce ExtrusionLine marked as closed but without
|
||||||
// equal the first and the last point.
|
// equal the first and the last point.
|
||||||
|
@ -287,9 +287,10 @@ void SVG::draw_text(const Point &pt, const char *text, const char *color, const
|
|||||||
void SVG::draw_legend(const Point &pt, const char *text, const char *color, const coordf_t font_size)
|
void SVG::draw_legend(const Point &pt, const char *text, const char *color, const coordf_t font_size)
|
||||||
{
|
{
|
||||||
fprintf(this->f,
|
fprintf(this->f,
|
||||||
R"(<circle cx="%f" cy="%f" r="10" fill="%s"/>)",
|
R"(<circle cx="%f" cy="%f" r="%f" fill="%s"/>)",
|
||||||
to_svg_x(float(pt.x() - origin.x())),
|
to_svg_x(float(pt.x() - origin.x())),
|
||||||
to_svg_y(float(pt.y() - origin.y())),
|
to_svg_y(float(pt.y() - origin.y())),
|
||||||
|
font_size,
|
||||||
color);
|
color);
|
||||||
fprintf(this->f,
|
fprintf(this->f,
|
||||||
R"(<text x="%f" y="%f" font-family="sans-serif" font-size="%fpx" fill="%s">%s</text>)",
|
R"(<text x="%f" y="%f" font-family="sans-serif" font-size="%fpx" fill="%s">%s</text>)",
|
||||||
|
Loading…
Reference in New Issue
Block a user