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 ARACHNE_DEBUG
|
||||
|
||||
namespace boost::polygon {
|
||||
|
||||
template<> struct geometry_concept<Slic3r::Arachne::PolygonsSegmentIndex>
|
||||
@ -46,6 +44,71 @@ template<> struct segment_traits<Slic3r::Arachne::PolygonsSegmentIndex>
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
#ifdef ARACHNE_DEBUG
|
||||
this->outline = polys;
|
||||
#endif
|
||||
|
||||
// Check self intersections.
|
||||
assert([&polys]() -> bool {
|
||||
EdgeGrid::Grid grid;
|
||||
@ -517,7 +584,7 @@ void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
|
||||
Geometry::VoronoiDiagram voronoi_diagram;
|
||||
construct_voronoi(segments.begin(), segments.end(), &voronoi_diagram);
|
||||
|
||||
#ifdef ARACHNE_DEBUG
|
||||
#ifdef ARACHNE_DEBUG_VORONOI
|
||||
{
|
||||
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));
|
||||
@ -694,45 +761,62 @@ void SkeletalTrapezoidation::separatePointyQuadEndNodes()
|
||||
// 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)
|
||||
{
|
||||
#ifdef ARACHNE_DEBUG
|
||||
static int iRun = 0;
|
||||
#endif
|
||||
|
||||
p_generated_toolpaths = &generated_toolpaths;
|
||||
|
||||
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);
|
||||
|
||||
#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)
|
||||
filterOuterCentral();
|
||||
|
||||
updateBeadCount();
|
||||
|
||||
#ifdef ARACHNE_DEBUG
|
||||
export_graph_to_svg(debug_out_path("ST-updateBeadCount-final-%d.svg", iRun), this->graph, this->outline);
|
||||
#endif
|
||||
|
||||
filterNoncentralRegions();
|
||||
|
||||
#ifdef ARACHNE_DEBUG
|
||||
export_graph_to_svg(debug_out_path("ST-filterNoncentralRegions-final-%d.svg", iRun), this->graph, this->outline);
|
||||
#endif
|
||||
|
||||
generateTransitioningRibs();
|
||||
|
||||
#ifdef ARACHNE_DEBUG
|
||||
export_graph_to_svg(debug_out_path("ST-generateTransitioningRibs-final-%d.svg", iRun), this->graph, this->outline);
|
||||
#endif
|
||||
|
||||
generateExtraRibs();
|
||||
|
||||
#ifdef ARACHNE_DEBUG
|
||||
export_graph_to_svg(debug_out_path("ST-generateExtraRibs-final-%d.svg", iRun), this->graph, this->outline);
|
||||
#endif
|
||||
|
||||
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()
|
||||
@ -944,11 +1028,24 @@ void SkeletalTrapezoidation::generateTransitioningRibs()
|
||||
|
||||
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
|
||||
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);
|
||||
// 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
|
||||
}
|
||||
|
||||
|
||||
@ -1669,16 +1766,37 @@ 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);
|
||||
|
||||
#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);
|
||||
|
||||
#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
|
||||
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);
|
||||
|
||||
generateLocalMaximaSingleBeads();
|
||||
|
||||
#ifdef ARACHNE_DEBUG
|
||||
++iRun;
|
||||
#endif
|
||||
}
|
||||
|
||||
SkeletalTrapezoidation::edge_t* SkeletalTrapezoidation::getQuadMaxRedgeTo(edge_t* quad_start_edge)
|
||||
|
@ -20,6 +20,9 @@
|
||||
#include "SkeletalTrapezoidationGraph.hpp"
|
||||
#include "../Geometry/Voronoi.hpp"
|
||||
|
||||
//#define ARACHNE_DEBUG
|
||||
//#define ARACHNE_DEBUG_VORONOI
|
||||
|
||||
namespace Slic3r::Arachne
|
||||
{
|
||||
|
||||
@ -123,6 +126,10 @@ public:
|
||||
*/
|
||||
void generateToolpaths(std::vector<VariableWidthLines> &generated_toolpaths, bool filter_outermost_central_edges = false);
|
||||
|
||||
#ifdef ARACHNE_DEBUG
|
||||
Polygons outline;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/*!
|
||||
* Auxiliary for referencing one transition along an edge which may contain multiple transitions
|
||||
|
@ -12,6 +12,13 @@
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
|
||||
//#define ARACHNE_DEBUG
|
||||
|
||||
#ifdef ARACHNE_DEBUG
|
||||
#include "SVG.hpp"
|
||||
#include "Utils.hpp"
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#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
|
||||
// "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling"
|
||||
void PerimeterGenerator::process_arachne()
|
||||
@ -578,6 +606,13 @@ void PerimeterGenerator::process_arachne()
|
||||
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
|
||||
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.
|
||||
// But in rare cases, Arachne produce ExtrusionLine marked as closed but without
|
||||
// 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)
|
||||
{
|
||||
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_y(float(pt.y() - origin.y())),
|
||||
font_size,
|
||||
color);
|
||||
fprintf(this->f,
|
||||
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