Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::Arachne::WallToolPaths Class Reference

#include <src/libslic3r/Arachne/WallToolPaths.hpp>

+ Collaboration diagram for Slic3r::Arachne::WallToolPaths:

Public Types

using ExtrusionLineSet = ankerl::unordered_dense::set< std::pair< const ExtrusionLine *, const ExtrusionLine * >, boost::hash< std::pair< const ExtrusionLine *, const ExtrusionLine * > > >
 

Public Member Functions

 WallToolPaths (const Polygons &outline, coord_t bead_width_0, coord_t bead_width_x, size_t inset_count, coord_t wall_0_inset, coordf_t layer_height, const PrintObjectConfig &print_object_config, const PrintConfig &print_config)
 
const std::vector< VariableWidthLines > & generate ()
 
const std::vector< VariableWidthLines > & getToolPaths ()
 
void separateOutInnerContour ()
 
const PolygonsgetInnerContour ()
 

Static Public Member Functions

static bool removeEmptyToolPaths (std::vector< VariableWidthLines > &toolpaths)
 
static ExtrusionLineSet getRegionOrder (const std::vector< ExtrusionLine * > &input, bool outer_to_inner)
 

Static Protected Member Functions

static void stitchToolPaths (std::vector< VariableWidthLines > &toolpaths, coord_t bead_width_x)
 
static void removeSmallLines (std::vector< VariableWidthLines > &toolpaths)
 
static void simplifyToolPaths (std::vector< VariableWidthLines > &toolpaths)
 

Private Attributes

const Polygonsoutline
 
coord_t bead_width_0
 
coord_t bead_width_x
 
size_t inset_count
 
coord_t wall_0_inset
 
coordf_t layer_height
 
bool print_thin_walls
 
coord_t min_feature_size
 
coord_t min_bead_width
 
double small_area_length
 
coord_t wall_transition_filter_deviation
 The allowed line width deviation induced by filtering.
 
coord_t wall_transition_length
 
float min_nozzle_diameter
 
bool toolpaths_generated
 
std::vector< VariableWidthLinestoolpaths
 
Polygons inner_contour
 
const PrintObjectConfigprint_object_config
 

Detailed Description

Member Typedef Documentation

◆ ExtrusionLineSet

using Slic3r::Arachne::WallToolPaths::ExtrusionLineSet = ankerl::unordered_dense::set<std::pair<const ExtrusionLine *, const ExtrusionLine *>, boost::hash<std::pair<const ExtrusionLine *, const ExtrusionLine *> >>

Constructor & Destructor Documentation

◆ WallToolPaths()

Slic3r::Arachne::WallToolPaths::WallToolPaths ( const Polygons outline,
coord_t  bead_width_0,
coord_t  bead_width_x,
size_t  inset_count,
coord_t  wall_0_inset,
coordf_t  layer_height,
const PrintObjectConfig print_object_config,
const PrintConfig &  print_config 
)

A class that creates the toolpaths given an outline, nominal bead width and maximum amount of walls

Parameters
outlineAn outline of the area in which the ToolPaths are to be generated
bead_width_0The bead width of the first wall used in the generation of the toolpaths
bead_width_xThe bead width of the inner walls used in the generation of the toolpaths
inset_countThe maximum number of parallel extrusion lines that make up the wall
wall_0_insetHow far to inset the outer wall, to make it adhere better to other walls.
35 , min_feature_size(scaled<coord_t>(print_object_config.min_feature_size.value))
36 , min_bead_width(scaled<coord_t>(print_object_config.min_bead_width.value))
37 , small_area_length(static_cast<double>(bead_width_0) / 2.)
38 , wall_transition_filter_deviation(scaled<coord_t>(print_object_config.wall_transition_filter_deviation.value))
39 , wall_transition_length(scaled<coord_t>(print_object_config.wall_transition_length.value))
40 , toolpaths_generated(false)
42{
43 assert(!print_config.nozzle_diameter.empty());
44 this->min_nozzle_diameter = float(*std::min_element(print_config.nozzle_diameter.values.begin(), print_config.nozzle_diameter.values.end()));
45
46 if (const auto &min_feature_size_opt = print_object_config.min_feature_size; min_feature_size_opt.percent)
47 this->min_feature_size = scaled<coord_t>(min_feature_size_opt.value * 0.01 * this->min_nozzle_diameter);
48
49 if (const auto &min_bead_width_opt = print_object_config.min_bead_width; min_bead_width_opt.percent)
50 this->min_bead_width = scaled<coord_t>(min_bead_width_opt.value * 0.01 * this->min_nozzle_diameter);
51
52 if (const auto &wall_transition_filter_deviation_opt = print_object_config.wall_transition_filter_deviation; wall_transition_filter_deviation_opt.percent)
53 this->wall_transition_filter_deviation = scaled<coord_t>(wall_transition_filter_deviation_opt.value * 0.01 * this->min_nozzle_diameter);
54
55 if (const auto &wall_transition_length_opt = print_object_config.wall_transition_length; wall_transition_length_opt.percent)
56 this->wall_transition_length = scaled<coord_t>(wall_transition_length_opt.value * 0.01 * this->min_nozzle_diameter);
57}
float min_nozzle_diameter
Definition WallToolPaths.hpp:122
const Polygons & outline
Definition WallToolPaths.hpp:110
coord_t min_feature_size
Definition WallToolPaths.hpp:117
coord_t bead_width_x
Definition WallToolPaths.hpp:112
coord_t bead_width_0
Definition WallToolPaths.hpp:111
size_t inset_count
Definition WallToolPaths.hpp:113
coordf_t layer_height
Definition WallToolPaths.hpp:115
coord_t min_bead_width
Definition WallToolPaths.hpp:118
coord_t wall_transition_filter_deviation
The allowed line width deviation induced by filtering.
Definition WallToolPaths.hpp:120
const PrintObjectConfig & print_object_config
Definition WallToolPaths.hpp:126
coord_t wall_0_inset
Definition WallToolPaths.hpp:114
bool print_thin_walls
Definition WallToolPaths.hpp:116
double small_area_length
Definition WallToolPaths.hpp:119
coord_t wall_transition_length
Definition WallToolPaths.hpp:121
bool toolpaths_generated
Definition WallToolPaths.hpp:123
constexpr bool fill_outline_gaps
Definition WallToolPaths.hpp:19

References Slic3r::Arachne, min_bead_width, min_feature_size, min_nozzle_diameter, print_object_config, wall_transition_filter_deviation, and wall_transition_length.

Member Function Documentation

◆ generate()

const std::vector< VariableWidthLines > & Slic3r::Arachne::WallToolPaths::generate ( )

Generates the Toolpaths

Returns
A reference to the newly create ToolPaths
451{
452 if (this->inset_count < 1)
453 return toolpaths;
454
457 const coord_t epsilon_offset = (allowed_distance / 2) - 1;
458 const double transitioning_angle = Geometry::deg2rad(this->print_object_config.wall_transition_angle.value);
459 constexpr coord_t discretization_step_size = scaled<coord_t>(0.8);
460
461 // Simplify outline for boost::voronoi consumption. Absolutely no self intersections or near-self intersections allowed:
462 // TODO: Open question: Does this indeed fix all (or all-but-one-in-a-million) cases for manifold but otherwise possibly complex polygons?
463 Polygons prepared_outline = offset(offset(offset(outline, -epsilon_offset), epsilon_offset * 2), -epsilon_offset);
464 simplify(prepared_outline, smallest_segment, allowed_distance);
465 fixSelfIntersections(epsilon_offset, prepared_outline);
466 removeDegenerateVerts(prepared_outline);
467 removeColinearEdges(prepared_outline, 0.005);
468 // Removing collinear edges may introduce self intersections, so we need to fix them again
469 fixSelfIntersections(epsilon_offset, prepared_outline);
470 removeDegenerateVerts(prepared_outline);
471 removeSmallAreas(prepared_outline, small_area_length * small_area_length, false);
472
473 // The functions above could produce intersecting polygons that could cause a crash inside Arachne.
474 // Applying Clipper union should be enough to get rid of this issue.
475 // Clipper union also fixed an issue in Arachne that in post-processing Voronoi diagram, some edges
476 // didn't have twin edges. (a non-planar Voronoi diagram probably caused this).
477 prepared_outline = union_(prepared_outline);
478
479 if (area(prepared_outline) <= 0) {
480 assert(toolpaths.empty());
481 return toolpaths;
482 }
483
484 const float external_perimeter_extrusion_width = Flow::rounded_rectangle_extrusion_width_from_spacing(unscale<float>(bead_width_0), float(this->layer_height));
485 const float perimeter_extrusion_width = Flow::rounded_rectangle_extrusion_width_from_spacing(unscale<float>(bead_width_x), float(this->layer_height));
486
487 const double wall_split_middle_threshold = std::clamp(2. * unscaled<double>(this->min_bead_width) / external_perimeter_extrusion_width - 1., 0.01, 0.99); // For an uneven nr. of lines: When to split the middle wall into two.
488 const double wall_add_middle_threshold = std::clamp(unscaled<double>(this->min_bead_width) / perimeter_extrusion_width, 0.01, 0.99); // For an even nr. of lines: When to add a new middle in between the innermost two walls.
489
490 const int wall_distribution_count = this->print_object_config.wall_distribution_count.value;
491 const size_t max_bead_count = (inset_count < std::numeric_limits<coord_t>::max() / 2) ? 2 * inset_count : std::numeric_limits<coord_t>::max();
492 const auto beading_strat = BeadingStrategyFactory::makeStrategy
493 (
497 transitioning_angle,
501 wall_split_middle_threshold,
502 wall_add_middle_threshold,
503 max_bead_count,
505 wall_distribution_count
506 );
507 const coord_t transition_filter_dist = scaled<coord_t>(100.f);
508 const coord_t allowed_filter_deviation = wall_transition_filter_deviation;
509 SkeletalTrapezoidation wall_maker
510 (
511 prepared_outline,
512 *beading_strat,
513 beading_strat->getTransitioningAngle(),
514 discretization_step_size,
515 transition_filter_dist,
516 allowed_filter_deviation,
518 );
519 wall_maker.generateToolpaths(toolpaths);
520
522
524
526
528
530 assert(std::is_sorted(toolpaths.cbegin(), toolpaths.cend(),
531 [](const VariableWidthLines& l, const VariableWidthLines& r)
532 {
533 return l.front().inset_idx < r.front().inset_idx;
534 }) && "WallToolPaths should be sorted from the outer 0th to inner_walls");
535 toolpaths_generated = true;
536 return toolpaths;
537}
static BeadingStrategyPtr makeStrategy(coord_t preferred_bead_width_outer=scaled< coord_t >(0.0005), coord_t preferred_bead_width_inner=scaled< coord_t >(0.0005), coord_t preferred_transition_length=scaled< coord_t >(0.0004), float transitioning_angle=M_PI/4.0, bool print_thin_walls=false, coord_t min_bead_width=0, coord_t min_feature_size=0, double wall_split_middle_threshold=0.5, double wall_add_middle_threshold=0.5, coord_t max_bead_count=0, coord_t outer_wall_offset=0, int inward_distributed_center_wall_count=2, double minimum_variable_line_width=0.5)
Definition BeadingStrategyFactory.cpp:18
static bool removeEmptyToolPaths(std::vector< VariableWidthLines > &toolpaths)
Definition WallToolPaths.cpp:752
static void stitchToolPaths(std::vector< VariableWidthLines > &toolpaths, coord_t bead_width_x)
Definition WallToolPaths.cpp:539
std::vector< VariableWidthLines > toolpaths
Definition WallToolPaths.hpp:124
void separateOutInnerContour()
Definition WallToolPaths.cpp:688
static void simplifyToolPaths(std::vector< VariableWidthLines > &toolpaths)
Definition WallToolPaths.cpp:667
static void removeSmallLines(std::vector< VariableWidthLines > &toolpaths)
Definition WallToolPaths.cpp:650
static float rounded_rectangle_extrusion_width_from_spacing(float spacing, float height)
Definition Flow.cpp:194
int32_t coord_t
Definition libslic3r.h:39
std::vector< ExtrusionLine > VariableWidthLines
Definition ExtrusionLine.hpp:295
constexpr coord_t meshfix_maximum_resolution
Definition WallToolPaths.hpp:20
void removeSmallAreas(Polygons &thiss, const double min_area_size, const bool remove_holes)
Definition WallToolPaths.cpp:321
void removeDegenerateVerts(Polygons &thiss)
Definition WallToolPaths.cpp:282
constexpr coord_t meshfix_maximum_deviation
Definition WallToolPaths.hpp:21
void fixSelfIntersections(const coord_t epsilon, Polygons &thiss)
Definition WallToolPaths.cpp:232
void removeColinearEdges(Polygon &poly, const double max_deviation_angle)
Definition WallToolPaths.cpp:375
void simplify(Polygon &thiss, const int64_t smallest_line_segment_squared, const int64_t allowed_error_distance_squared)
Definition WallToolPaths.cpp:59
constexpr T deg2rad(const T angle)
Definition Geometry.hpp:289
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:15
Slic3r::Polygons union_(const Slic3r::Polygons &subject)
Definition ClipperUtils.cpp:704
double area(const ExPolygon &poly)
Definition ExPolygon.hpp:467
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:416

References Slic3r::area(), bead_width_0, bead_width_x, Slic3r::Geometry::deg2rad(), Slic3r::Arachne::fixSelfIntersections(), Slic3r::Arachne::SkeletalTrapezoidation::generateToolpaths(), inset_count, layer_height, Slic3r::Arachne::BeadingStrategyFactory::makeStrategy(), Slic3r::Arachne::meshfix_maximum_deviation, Slic3r::Arachne::meshfix_maximum_resolution, min_bead_width, min_feature_size, Slic3r::offset(), outline, print_object_config, print_thin_walls, Slic3r::Arachne::removeColinearEdges(), Slic3r::Arachne::removeDegenerateVerts(), removeEmptyToolPaths(), Slic3r::Arachne::removeSmallAreas(), removeSmallLines(), Slic3r::Flow::rounded_rectangle_extrusion_width_from_spacing(), separateOutInnerContour(), Slic3r::Arachne::simplify(), simplifyToolPaths(), small_area_length, stitchToolPaths(), toolpaths, toolpaths_generated, Slic3r::union_(), wall_0_inset, wall_transition_filter_deviation, and wall_transition_length.

Referenced by getInnerContour(), and getToolPaths().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getInnerContour()

const Polygons & Slic3r::Arachne::WallToolPaths::getInnerContour ( )

Gets the inner contour of the area which is inside of the generated tool paths.

If the walls haven't been generated yet, this will lazily call the generate() function to generate the walls with variable width. The resulting polygon will snugly match the inside of the variable-width walls where the walls get limited by the LimitedBeadingStrategy to a maximum wall count. If there are no walls, the outline will be returned.

Returns
The inner contour of the generated walls.
740{
742 {
743 generate();
744 }
745 else if(inset_count == 0)
746 {
747 return outline;
748 }
749 return inner_contour;
750}
Polygons inner_contour
Definition WallToolPaths.hpp:125
const std::vector< VariableWidthLines > & generate()
Definition WallToolPaths.cpp:450

References generate(), inner_contour, inset_count, outline, and toolpaths_generated.

Referenced by Slic3r::PerimeterGenerator::process_arachne().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getRegionOrder()

WallToolPaths::ExtrusionLineSet Slic3r::Arachne::WallToolPaths::getRegionOrder ( const std::vector< ExtrusionLine * > &  input,
bool  outer_to_inner 
)
static

Get the order constraints of the insets when printing walls per region / hole. Each returned pair consists of adjacent wall lines where the left has an inset_idx one lower than the right.

Odd walls should always go after their enclosing wall polygons.

Parameters
outer_to_innerWhether the wall polygons with a lower inset_idx should go before those with a higher one.
770{
771 ExtrusionLineSet order_requirements;
772
773 // We build a grid where we map toolpath vertex locations to toolpaths,
774 // so that we can easily find which two toolpaths are next to each other,
775 // which is the requirement for there to be an order constraint.
776 //
777 // We use a PointGrid rather than a LineGrid to save on computation time.
778 // In very rare cases two insets might lie next to each other without having neighboring vertices, e.g.
779 // \ .
780 // | / .
781 // | / .
782 // || .
783 // | \ .
784 // | \ .
785 // / .
786 // However, because of how Arachne works this will likely never be the case for two consecutive insets.
787 // On the other hand one could imagine that two consecutive insets of a very large circle
788 // could be simplify()ed such that the remaining vertices of the two insets don't align.
789 // In those cases the order requirement is not captured,
790 // which means that the PathOrderOptimizer *might* result in a violation of the user set path order.
791 // This problem is expected to be not so severe and happen very sparsely.
792
793 coord_t max_line_w = 0u;
794 for (const ExtrusionLine *line : input) // compute max_line_w
795 for (const ExtrusionJunction &junction : *line)
796 max_line_w = std::max(max_line_w, junction.w);
797 if (max_line_w == 0u)
798 return order_requirements;
799
800 struct LineLoc
801 {
802 ExtrusionJunction j;
803 const ExtrusionLine *line;
804 };
805 struct Locator
806 {
807 Point operator()(const LineLoc &elem) { return elem.j.p; }
808 };
809
810 // How much farther two verts may be apart due to corners.
811 // This distance must be smaller than 2, because otherwise
812 // we could create an order requirement between e.g.
813 // wall 2 of one region and wall 3 of another region,
814 // while another wall 3 of the first region would lie in between those two walls.
815 // However, higher values are better against the limitations of using a PointGrid rather than a LineGrid.
816 constexpr float diagonal_extension = 1.9f;
817 const auto searching_radius = coord_t(max_line_w * diagonal_extension);
818 using GridT = SparsePointGrid<LineLoc, Locator>;
819 GridT grid(searching_radius);
820
821 for (const ExtrusionLine *line : input)
822 for (const ExtrusionJunction &junction : *line) grid.insert(LineLoc{junction, line});
823 for (const std::pair<const SquareGrid::GridPoint, LineLoc> &pair : grid) {
824 const LineLoc &lineloc_here = pair.second;
825 const ExtrusionLine *here = lineloc_here.line;
826 Point loc_here = pair.second.j.p;
827 std::vector<LineLoc> nearby_verts = grid.getNearby(loc_here, searching_radius);
828 for (const LineLoc &lineloc_nearby : nearby_verts) {
829 const ExtrusionLine *nearby = lineloc_nearby.line;
830 if (nearby == here)
831 continue;
832 if (nearby->inset_idx == here->inset_idx)
833 continue;
834 if (nearby->inset_idx > here->inset_idx + 1)
835 continue; // not directly adjacent
836 if (here->inset_idx > nearby->inset_idx + 1)
837 continue; // not directly adjacent
838 if (!shorter_then(loc_here - lineloc_nearby.j.p, (lineloc_here.j.w + lineloc_nearby.j.w) / 2 * diagonal_extension))
839 continue; // points are too far away from each other
840 if (here->is_odd || nearby->is_odd) {
841 if (here->is_odd && !nearby->is_odd && nearby->inset_idx < here->inset_idx)
842 order_requirements.emplace(std::make_pair(nearby, here));
843 if (nearby->is_odd && !here->is_odd && here->inset_idx < nearby->inset_idx)
844 order_requirements.emplace(std::make_pair(here, nearby));
845 } else if ((nearby->inset_idx < here->inset_idx) == outer_to_inner) {
846 order_requirements.emplace(std::make_pair(nearby, here));
847 } else {
848 assert((nearby->inset_idx > here->inset_idx) == outer_to_inner);
849 order_requirements.emplace(std::make_pair(here, nearby));
850 }
851 }
852 }
853 return order_requirements;
854}
ankerl::unordered_dense::set< std::pair< const ExtrusionLine *, const ExtrusionLine * >, boost::hash< std::pair< const ExtrusionLine *, const ExtrusionLine * > > > ExtrusionLineSet
Definition WallToolPaths.hpp:77
#define const
Definition getopt.c:38
static int input(void)
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half() max(const half &a, const half &b)
Definition Half.h:516
bool shorter_then(const Point &p0, const coord_t len)
Definition Point.hpp:301
std::vector< ArithmeticOnly< T > > grid(const T &start, const T &stop, const T &stride)
A set of equidistant values starting from 'start' (inclusive), ending in the closest multiple of 'str...
Definition MTUtils.hpp:125
STL namespace.
Kernel::Point_2 Point
Definition point_areas.cpp:20

References Slic3r::grid(), and input().

Referenced by Slic3r::PerimeterGenerator::process_arachne().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getToolPaths()

const std::vector< VariableWidthLines > & Slic3r::Arachne::WallToolPaths::getToolPaths ( )

Gets the toolpaths, if this called before generate() it will first generate the Toolpaths

Returns
a reference to the toolpaths
682{
684 return generate();
685 return toolpaths;
686}

References generate(), toolpaths, and toolpaths_generated.

Referenced by Slic3r::FillConcentric::_fill_surface_single(), and Slic3r::PerimeterGenerator::process_arachne().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ removeEmptyToolPaths()

bool Slic3r::Arachne::WallToolPaths::removeEmptyToolPaths ( std::vector< VariableWidthLines > &  toolpaths)
static

Removes empty paths from the toolpaths

Parameters
toolpathsthe VariableWidthPaths generated with generate()
Returns
true if there are still paths left. If all toolpaths were removed it returns false
753{
754 toolpaths.erase(std::remove_if(toolpaths.begin(), toolpaths.end(), [](const VariableWidthLines& lines)
755 {
756 return lines.empty();
757 }), toolpaths.end());
758 return toolpaths.empty();
759}

References toolpaths.

Referenced by generate().

+ Here is the caller graph for this function:

◆ removeSmallLines()

void Slic3r::Arachne::WallToolPaths::removeSmallLines ( std::vector< VariableWidthLines > &  toolpaths)
staticprotected

Remove polylines shorter than half the smallest line width along that polyline.

651{
652 for (VariableWidthLines &inset : toolpaths) {
653 for (size_t line_idx = 0; line_idx < inset.size(); line_idx++) {
654 ExtrusionLine &line = inset[line_idx];
655 coord_t min_width = std::numeric_limits<coord_t>::max();
656 for (const ExtrusionJunction &j : line)
657 min_width = std::min(min_width, j.w);
658 if (line.is_odd && !line.is_closed && shorterThan(line, min_width / 2)) { // remove line
659 line = std::move(inset.back());
660 inset.erase(--inset.end());
661 line_idx--; // reconsider the current position
662 }
663 }
664 }
665}
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half() min(const half &a, const half &b)
Definition Half.h:507
bool shorterThan(const T &shape, const coord_t check_length)
Definition WallToolPaths.cpp:637

References Slic3r::Arachne::ExtrusionLine::is_closed, Slic3r::Arachne::ExtrusionLine::is_odd, Slic3r::Arachne::shorterThan(), and toolpaths.

Referenced by generate().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ separateOutInnerContour()

void Slic3r::Arachne::WallToolPaths::separateOutInnerContour ( )

Compute the inner contour of the walls. This contour indicates where the walled area ends and its infill begins. The inside can then be filled, e.g. with skin/infill for the walls of a part, or with a pattern in the case of infill with extra infill walls.

689{
690 //We'll remove all 0-width paths from the original toolpaths and store them separately as polygons.
691 std::vector<VariableWidthLines> actual_toolpaths;
692 actual_toolpaths.reserve(toolpaths.size()); //A bit too much, but the correct order of magnitude.
693 std::vector<VariableWidthLines> contour_paths;
694 contour_paths.reserve(toolpaths.size() / inset_count);
695 inner_contour.clear();
696 for (const VariableWidthLines &inset : toolpaths) {
697 if (inset.empty())
698 continue;
699 bool is_contour = false;
700 for (const ExtrusionLine &line : inset) {
701 for (const ExtrusionJunction &j : line) {
702 if (j.w == 0)
703 is_contour = true;
704 else
705 is_contour = false;
706 break;
707 }
708 }
709
710 if (is_contour) {
711#ifdef DEBUG
712 for (const ExtrusionLine &line : inset)
713 for (const ExtrusionJunction &j : line)
714 assert(j.w == 0);
715#endif // DEBUG
716 for (const ExtrusionLine &line : inset) {
717 if (line.is_odd)
718 continue; // odd lines don't contribute to the contour
719 else if (line.is_closed) // sometimes an very small even polygonal wall is not stitched into a polygon
720 inner_contour.emplace_back(line.toPolygon());
721 }
722 } else {
723 actual_toolpaths.emplace_back(inset);
724 }
725 }
726 if (!actual_toolpaths.empty())
727 toolpaths = std::move(actual_toolpaths); // Filtered out the 0-width paths.
728 else
729 toolpaths.clear();
730
731 //The output walls from the skeletal trapezoidation have no known winding order, especially if they are joined together from polylines.
732 //They can be in any direction, clockwise or counter-clockwise, regardless of whether the shapes are positive or negative.
733 //To get a correct shape, we need to make the outside contour positive and any holes inside negative.
734 //This can be done by applying the even-odd rule to the shape. This rule is not sensitive to the winding order of the polygon.
735 //The even-odd rule would be incorrect if the polygon self-intersects, but that should never be generated by the skeletal trapezoidation.
737}
@ pftEvenOdd
Definition clipper.hpp:81

References inner_contour, inset_count, ClipperLib::pftEvenOdd, toolpaths, and Slic3r::union_().

Referenced by generate().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ simplifyToolPaths()

void Slic3r::Arachne::WallToolPaths::simplifyToolPaths ( std::vector< VariableWidthLines > &  toolpaths)
staticprotected

Simplifies the variable-width toolpaths by calling the simplify on every line in the toolpath using the provided settings.

Parameters
settingsThe settings as provided by the user
Returns
668{
669 for (size_t toolpaths_idx = 0; toolpaths_idx < toolpaths.size(); ++toolpaths_idx)
670 {
671 const int64_t maximum_resolution = Slic3r::Arachne::meshfix_maximum_resolution;
672 const int64_t maximum_deviation = Slic3r::Arachne::meshfix_maximum_deviation;
673 const int64_t maximum_extrusion_area_deviation = Slic3r::Arachne::meshfix_maximum_extrusion_area_deviation; // unit: μm²
674 for (auto& line : toolpaths[toolpaths_idx])
675 {
676 line.simplify(maximum_resolution * maximum_resolution, maximum_deviation * maximum_deviation, maximum_extrusion_area_deviation);
677 }
678 }
679}
constexpr coord_t meshfix_maximum_extrusion_area_deviation
Definition WallToolPaths.hpp:22
__int64 int64_t
Definition unistd.h:76

References Slic3r::Arachne::meshfix_maximum_deviation, Slic3r::Arachne::meshfix_maximum_extrusion_area_deviation, Slic3r::Arachne::meshfix_maximum_resolution, and toolpaths.

Referenced by generate().

+ Here is the caller graph for this function:

◆ stitchToolPaths()

void Slic3r::Arachne::WallToolPaths::stitchToolPaths ( std::vector< VariableWidthLines > &  toolpaths,
coord_t  bead_width_x 
)
staticprotected

Stitch the polylines together and form closed polygons.

Works on both toolpaths and inner contours simultaneously.

540{
541 const coord_t stitch_distance = bead_width_x - 1; //In 0-width contours, junctions can cause up to 1-line-width gaps. Don't stitch more than 1 line width.
542
543 for (unsigned int wall_idx = 0; wall_idx < toolpaths.size(); wall_idx++) {
544 VariableWidthLines& wall_lines = toolpaths[wall_idx];
545
546 VariableWidthLines stitched_polylines;
547 VariableWidthLines closed_polygons;
548 PolylineStitcher<VariableWidthLines, ExtrusionLine, ExtrusionJunction>::stitch(wall_lines, stitched_polylines, closed_polygons, stitch_distance);
549#ifdef ARACHNE_STITCH_PATCH_DEBUG
550 for (const ExtrusionLine& line : stitched_polylines) {
551 if ( ! line.is_odd && line.polylineLength() > 3 * stitch_distance && line.size() > 3) {
552 BOOST_LOG_TRIVIAL(error) << "Some even contour lines could not be closed into polygons!";
553 assert(false && "Some even contour lines could not be closed into polygons!");
554 BoundingBox aabb;
555 for (auto line2 : wall_lines)
556 for (auto j : line2)
557 aabb.merge(j.p);
558 {
559 static int iRun = 0;
560 SVG svg(debug_out_path("contours_before.svg-%d.png", iRun), aabb);
561 std::array<const char *, 8> colors = {"gray", "black", "blue", "green", "lime", "purple", "red", "yellow"};
562 size_t color_idx = 0;
563 for (auto& inset : toolpaths)
564 for (auto& line2 : inset) {
565 // svg.writePolyline(line2.toPolygon(), col);
566
567 Polygon poly = line2.toPolygon();
568 Point last = poly.front();
569 for (size_t idx = 1 ; idx < poly.size(); idx++) {
570 Point here = poly[idx];
571 svg.draw(Line(last, here), colors[color_idx]);
572// svg.draw_text((last + here) / 2, std::to_string(line2.junctions[idx].region_id).c_str(), "black");
573 last = here;
574 }
575 svg.draw(poly[0], colors[color_idx]);
576 // svg.nextLayer();
577 // svg.writePoints(poly, true, 0.1);
578 // svg.nextLayer();
579 color_idx = (color_idx + 1) % colors.size();
580 }
581 }
582 {
583 static int iRun = 0;
584 SVG svg(debug_out_path("contours-%d.svg", iRun), aabb);
585 for (auto& inset : toolpaths)
586 for (auto& line2 : inset)
587 svg.draw_outline(line2.toPolygon(), "gray");
588 for (auto& line2 : stitched_polylines) {
589 const char *col = line2.is_odd ? "gray" : "red";
590 if ( ! line2.is_odd)
591 std::cerr << "Non-closed even wall of size: " << line2.size() << " at " << line2.front().p << "\n";
592 if ( ! line2.is_odd)
593 svg.draw(line2.front().p);
594 Polygon poly = line2.toPolygon();
595 Point last = poly.front();
596 for (size_t idx = 1 ; idx < poly.size(); idx++)
597 {
598 Point here = poly[idx];
599 svg.draw(Line(last, here), col);
600 last = here;
601 }
602 }
603 for (auto line2 : closed_polygons)
604 svg.draw(line2.toPolygon());
605 }
606 }
607 }
608#endif // ARACHNE_STITCH_PATCH_DEBUG
609 wall_lines = stitched_polylines; // replace input toolpaths with stitched polylines
610
611 for (ExtrusionLine& wall_polygon : closed_polygons)
612 {
613 if (wall_polygon.junctions.empty())
614 {
615 continue;
616 }
617
618 // PolylineStitcher, in some cases, produced closed extrusion (polygons),
619 // but the endpoints differ by a small distance. So we reconnect them.
620 // FIXME Lukas H.: Investigate more deeply why it is happening.
621 if (wall_polygon.junctions.front().p != wall_polygon.junctions.back().p &&
622 (wall_polygon.junctions.back().p - wall_polygon.junctions.front().p).cast<double>().norm() < stitch_distance) {
623 wall_polygon.junctions.emplace_back(wall_polygon.junctions.front());
624 }
625 wall_polygon.is_closed = true;
626 wall_lines.emplace_back(std::move(wall_polygon)); // add stitched polygons to result
627 }
628#ifdef DEBUG
629 for (ExtrusionLine& line : wall_lines)
630 {
631 assert(line.inset_idx == wall_idx);
632 }
633#endif // DEBUG
634 }
635}
EIGEN_DEVICE_FUNC ColXpr col(Index i)
This is the const version of col().
Definition BlockMethods.h:838
static void stitch(const Paths &lines, Paths &result_lines, Paths &result_polygons, coord_t max_stitch_distance=scaled< coord_t >(0.1), coord_t snap_distance=scaled< coord_t >(0.01))
Definition PolylineStitcher.hpp:52
const Point & front() const
Definition MultiPoint.hpp:36
void draw(const IconManager::Icon &icon, const ImVec2 &size, const ImVec4 &tint_col, const ImVec4 &border_col)
Draw imgui image with icon.
Definition IconManager.cpp:164
std::string debug_out_path(const char *name,...)
Definition utils.cpp:218
TMultiShape< PolygonImpl > merge(const TMultiShape< PolygonImpl > &shapes)
Definition geometries.hpp:259
Slic3r::Polygon Polygon
Definition Emboss.cpp:34
static char error[256]
Definition tga.cpp:50

References bead_width_x, col(), Slic3r::debug_out_path(), Slic3r::SVG::draw(), Slic3r::SVG::draw_outline(), error, Slic3r::MultiPoint::front(), Slic3r::BoundingBoxBase< PointType, APointsType >::merge(), Slic3r::MultiPoint::size(), Slic3r::Arachne::PolylineStitcher< Paths, Path, Junction >::stitch(), and toolpaths.

Referenced by generate().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ bead_width_0

coord_t Slic3r::Arachne::WallToolPaths::bead_width_0
private

Referenced by generate().

◆ bead_width_x

coord_t Slic3r::Arachne::WallToolPaths::bead_width_x
private

Referenced by generate(), and stitchToolPaths().

◆ inner_contour

Polygons Slic3r::Arachne::WallToolPaths::inner_contour
private

◆ inset_count

size_t Slic3r::Arachne::WallToolPaths::inset_count
private

◆ layer_height

coordf_t Slic3r::Arachne::WallToolPaths::layer_height
private

Referenced by generate().

◆ min_bead_width

coord_t Slic3r::Arachne::WallToolPaths::min_bead_width
private

Referenced by WallToolPaths(), and generate().

◆ min_feature_size

coord_t Slic3r::Arachne::WallToolPaths::min_feature_size
private

Referenced by WallToolPaths(), and generate().

◆ min_nozzle_diameter

float Slic3r::Arachne::WallToolPaths::min_nozzle_diameter
private

Referenced by WallToolPaths().

◆ outline

const Polygons& Slic3r::Arachne::WallToolPaths::outline
private

Referenced by generate(), and getInnerContour().

◆ print_object_config

const PrintObjectConfig& Slic3r::Arachne::WallToolPaths::print_object_config
private

Referenced by WallToolPaths(), and generate().

◆ print_thin_walls

bool Slic3r::Arachne::WallToolPaths::print_thin_walls
private

Referenced by generate().

◆ small_area_length

double Slic3r::Arachne::WallToolPaths::small_area_length
private

Referenced by generate().

◆ toolpaths

std::vector<VariableWidthLines> Slic3r::Arachne::WallToolPaths::toolpaths
private

◆ toolpaths_generated

bool Slic3r::Arachne::WallToolPaths::toolpaths_generated
private

◆ wall_0_inset

coord_t Slic3r::Arachne::WallToolPaths::wall_0_inset
private

Referenced by generate().

◆ wall_transition_filter_deviation

coord_t Slic3r::Arachne::WallToolPaths::wall_transition_filter_deviation
private

The allowed line width deviation induced by filtering.

Referenced by WallToolPaths(), and generate().

◆ wall_transition_length

coord_t Slic3r::Arachne::WallToolPaths::wall_transition_length
private

Referenced by WallToolPaths(), and generate().


The documentation for this class was generated from the following files: