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

#include <src/libslic3r/Arachne/BeadingStrategy/DistributedBeadingStrategy.hpp>

+ Inheritance diagram for Slic3r::Arachne::DistributedBeadingStrategy:
+ Collaboration diagram for Slic3r::Arachne::DistributedBeadingStrategy:

Public Member Functions

 DistributedBeadingStrategy (coord_t optimal_width, coord_t default_transition_length, double transitioning_angle, double wall_split_middle_threshold, double wall_add_middle_threshold, int distribution_radius)
 
 ~DistributedBeadingStrategy () override=default
 
Beading compute (coord_t thickness, coord_t bead_count) const override
 
coord_t getOptimalBeadCount (coord_t thickness) const override
 
virtual coord_t getOptimalThickness (coord_t bead_count) const
 
virtual coord_t getTransitionThickness (coord_t lower_bead_count) const
 
virtual coord_t getTransitioningLength (coord_t lower_bead_count) const
 
virtual float getTransitionAnchorPos (coord_t lower_bead_count) const
 
virtual std::vector< coord_tgetNonlinearThicknesses (coord_t lower_bead_count) const
 
virtual std::string toString () const
 
double getSplitMiddleThreshold () const
 
double getTransitioningAngle () const
 

Protected Attributes

float one_over_distribution_radius_squared
 
std::string name
 
coord_t optimal_width
 
double wall_split_middle_threshold
 Optimal bead width, nominal width off the walls in 'ideal' circumstances.
 
double wall_add_middle_threshold
 Threshold when a middle wall should be split into two, as a ratio of the optimal wall width.
 
coord_t default_transition_length
 Threshold when a new middle wall should be added between an even number of walls, as a ratio of the optimal wall width.
 
double transitioning_angle
 The length of the region to smoothly transfer between bead counts.
 

Detailed Description

This beading strategy chooses a wall count that would make the line width deviate the least from the optimal line width, and then distributes the lines evenly among the thickness available.

Constructor & Destructor Documentation

◆ DistributedBeadingStrategy()

Slic3r::Arachne::DistributedBeadingStrategy::DistributedBeadingStrategy ( coord_t  optimal_width,
coord_t  default_transition_length,
double  transitioning_angle,
double  wall_split_middle_threshold,
double  wall_add_middle_threshold,
int  distribution_radius 
)
Parameters
distribution_radiusthe radius (in number of beads) over which to distribute the discrepancy between the feature size and the optimal thickness
16{
17 if(distribution_radius >= 2)
18 one_over_distribution_radius_squared = 1.0f / (distribution_radius - 1) * 1.0f / (distribution_radius - 1);
19 else
20 one_over_distribution_radius_squared = 1.0f / 1 * 1.0f / 1;
21 name = "DistributedBeadingStrategy";
22}
double wall_add_middle_threshold
Threshold when a middle wall should be split into two, as a ratio of the optimal wall width.
Definition BeadingStrategy.hpp:103
coord_t optimal_width
Definition BeadingStrategy.hpp:99
std::string name
Definition BeadingStrategy.hpp:97
double transitioning_angle
The length of the region to smoothly transfer between bead counts.
Definition BeadingStrategy.hpp:111
double wall_split_middle_threshold
Optimal bead width, nominal width off the walls in 'ideal' circumstances.
Definition BeadingStrategy.hpp:101
BeadingStrategy(coord_t optimal_width, double wall_split_middle_threshold, double wall_add_middle_threshold, coord_t default_transition_length, float transitioning_angle=pi_div(3))
Definition BeadingStrategy.cpp:12
coord_t default_transition_length
Threshold when a new middle wall should be added between an even number of walls, as a ratio of the o...
Definition BeadingStrategy.hpp:105
float one_over_distribution_radius_squared
Definition DistributedBeadingStrategy.hpp:20

References Slic3r::Arachne::BeadingStrategy::name, and one_over_distribution_radius_squared.

◆ ~DistributedBeadingStrategy()

Slic3r::Arachne::DistributedBeadingStrategy::~DistributedBeadingStrategy ( )
overridedefault

Member Function Documentation

◆ compute()

DistributedBeadingStrategy::Beading Slic3r::Arachne::DistributedBeadingStrategy::compute ( coord_t  thickness,
coord_t  bead_count 
) const
overridevirtual

Retrieve the bead widths with which to cover a given thickness.

Requirement: Given a constant bead_count the output of each bead width must change gradually along with the thickness.

Note
The bead_count might be different from the BeadingStrategy::optimal_bead_count

Implements Slic3r::Arachne::BeadingStrategy.

25{
26 Beading ret;
27
28 ret.total_thickness = thickness;
29 if (bead_count > 2) {
30 const coord_t to_be_divided = thickness - bead_count * optimal_width;
31 const float middle = static_cast<float>(bead_count - 1) / 2;
32
33 const auto getWeight = [middle, this](coord_t bead_idx) {
34 const float dev_from_middle = bead_idx - middle;
35 return std::max(0.0f, 1.0f - one_over_distribution_radius_squared * dev_from_middle * dev_from_middle);
36 };
37
38 std::vector<float> weights;
39 weights.resize(bead_count);
40 for (coord_t bead_idx = 0; bead_idx < bead_count; bead_idx++)
41 weights[bead_idx] = getWeight(bead_idx);
42
43 const float total_weight = std::accumulate(weights.cbegin(), weights.cend(), 0.f);
44 coord_t accumulated_width = 0;
45 for (coord_t bead_idx = 0; bead_idx < bead_count; bead_idx++) {
46 const float weight_fraction = weights[bead_idx] / total_weight;
47 const coord_t splitup_left_over_weight = to_be_divided * weight_fraction;
48 const coord_t width = (bead_idx == bead_count - 1) ? thickness - accumulated_width : optimal_width + splitup_left_over_weight;
49
50 // Be aware that toolpath_locations is computed by dividing the width by 2, so toolpath_locations
51 // could be off by 1 because of rounding errors.
52 if (bead_idx == 0)
53 ret.toolpath_locations.emplace_back(width / 2);
54 else
55 ret.toolpath_locations.emplace_back(ret.toolpath_locations.back() + (ret.bead_widths.back() + width) / 2);
56 ret.bead_widths.emplace_back(width);
57 accumulated_width += width;
58 }
59 ret.left_over = 0;
60 assert((accumulated_width + ret.left_over) == thickness);
61 } else if (bead_count == 2) {
62 const coord_t outer_width = thickness / 2;
63 ret.bead_widths.emplace_back(outer_width);
64 ret.bead_widths.emplace_back(outer_width);
65 ret.toolpath_locations.emplace_back(outer_width / 2);
66 ret.toolpath_locations.emplace_back(thickness - outer_width / 2);
67 ret.left_over = 0;
68 } else if (bead_count == 1) {
69 const coord_t outer_width = thickness;
70 ret.bead_widths.emplace_back(outer_width);
71 ret.toolpath_locations.emplace_back(outer_width / 2);
72 ret.left_over = 0;
73 } else {
74 ret.left_over = thickness;
75 }
76
77 assert(([&ret = std::as_const(ret), thickness]() -> bool {
78 coord_t total_bead_width = 0;
79 for (const coord_t &bead_width : ret.bead_widths)
80 total_bead_width += bead_width;
81 return (total_bead_width + ret.left_over) == thickness;
82 }()));
83
84 return ret;
85}
int32_t coord_t
Definition libslic3r.h:39
coord_t width(const BoundingBox &box)
Definition Arrange.cpp:539

References Slic3r::Arachne::BeadingStrategy::Beading::bead_widths, Slic3r::Arachne::BeadingStrategy::Beading::left_over, one_over_distribution_radius_squared, Slic3r::Arachne::BeadingStrategy::optimal_width, Slic3r::Arachne::BeadingStrategy::Beading::toolpath_locations, and Slic3r::Arachne::BeadingStrategy::Beading::total_thickness.

◆ getNonlinearThicknesses()

std::vector< coord_t > Slic3r::Arachne::BeadingStrategy::getNonlinearThicknesses ( coord_t  lower_bead_count) const
virtualinherited

Get the locations in a bead count region where BeadingStrategy::compute exhibits a bend in the widths. Ordered from lower thickness to higher.

This is used to insert extra support bones into the skeleton, so that the resulting beads in long trapezoids don't linearly change between the two ends.

Reimplemented in Slic3r::Arachne::WideningBeadingStrategy.

47{
48 return {};
49}

Referenced by Slic3r::Arachne::SkeletalTrapezoidation::generateExtraRibs().

+ Here is the caller graph for this function:

◆ getOptimalBeadCount()

coord_t Slic3r::Arachne::DistributedBeadingStrategy::getOptimalBeadCount ( coord_t  thickness) const
overridevirtual

The number of beads should we ideally usefor a given model thickness

Implements Slic3r::Arachne::BeadingStrategy.

88{
89 const coord_t naive_count = thickness / optimal_width; // How many lines we can fit in for sure.
90 const coord_t remainder = thickness - naive_count * optimal_width; // Space left after fitting that many lines.
91 const coord_t minimum_line_width = optimal_width * (naive_count % 2 == 1 ? wall_split_middle_threshold : wall_add_middle_threshold);
92 return naive_count + (remainder >= minimum_line_width); // If there's enough space, fit an extra one.
93}

References Slic3r::Arachne::BeadingStrategy::optimal_width, Slic3r::Arachne::BeadingStrategy::wall_add_middle_threshold, and Slic3r::Arachne::BeadingStrategy::wall_split_middle_threshold.

◆ getOptimalThickness()

coord_t Slic3r::Arachne::BeadingStrategy::getOptimalThickness ( coord_t  bead_count) const
virtualinherited

The ideal thickness for a given

Parameters
bead_count

Reimplemented in Slic3r::Arachne::LimitedBeadingStrategy, Slic3r::Arachne::OuterWallInsetBeadingStrategy, Slic3r::Arachne::RedistributeBeadingStrategy, and Slic3r::Arachne::WideningBeadingStrategy.

67{
68 return optimal_width * bead_count;
69}

References Slic3r::Arachne::BeadingStrategy::optimal_width.

Referenced by Slic3r::Arachne::BeadingStrategy::getTransitionAnchorPos(), and Slic3r::Arachne::BeadingStrategy::getTransitionThickness().

+ Here is the caller graph for this function:

◆ getSplitMiddleThreshold()

double Slic3r::Arachne::BeadingStrategy::getSplitMiddleThreshold ( ) const
inherited

◆ getTransitionAnchorPos()

float Slic3r::Arachne::BeadingStrategy::getTransitionAnchorPos ( coord_t  lower_bead_count) const
virtualinherited

The fraction of the transition length to put between the lower end of the transition and the point where the unsmoothed bead count jumps.

Transitions are used to smooth out the jumps in integer bead count; the jumps turn into ramps which could be positioned relative to the jump location.

Reimplemented in Slic3r::Arachne::LimitedBeadingStrategy, Slic3r::Arachne::RedistributeBeadingStrategy, and Slic3r::Arachne::WideningBeadingStrategy.

39{
40 coord_t lower_optimum = getOptimalThickness(lower_bead_count);
41 coord_t transition_point = getTransitionThickness(lower_bead_count);
42 coord_t upper_optimum = getOptimalThickness(lower_bead_count + 1);
43 return 1.0 - float(transition_point - lower_optimum) / float(upper_optimum - lower_optimum);
44}
virtual coord_t getOptimalThickness(coord_t bead_count) const
Definition BeadingStrategy.cpp:66
virtual coord_t getTransitionThickness(coord_t lower_bead_count) const
Definition BeadingStrategy.cpp:71

References Slic3r::Arachne::BeadingStrategy::getOptimalThickness(), and Slic3r::Arachne::BeadingStrategy::getTransitionThickness().

Referenced by Slic3r::Arachne::SkeletalTrapezoidation::filterTransitionMids(), and Slic3r::Arachne::SkeletalTrapezoidation::generateTransitionEnds().

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

◆ getTransitioningAngle()

double Slic3r::Arachne::BeadingStrategy::getTransitioningAngle ( ) const
inherited
62{
64}

References Slic3r::Arachne::BeadingStrategy::transitioning_angle.

Referenced by Slic3r::Arachne::SkeletalTrapezoidation::updateIsCentral().

+ Here is the caller graph for this function:

◆ getTransitioningLength()

coord_t Slic3r::Arachne::BeadingStrategy::getTransitioningLength ( coord_t  lower_bead_count) const
virtualinherited

The length of the transitioning region along the marked / significant regions of the skeleton.

Transitions are used to smooth out the jumps in integer bead count; the jumps turn into ramps with some incline defined by their length.

Reimplemented in Slic3r::Arachne::LimitedBeadingStrategy, Slic3r::Arachne::OuterWallInsetBeadingStrategy, Slic3r::Arachne::RedistributeBeadingStrategy, and Slic3r::Arachne::WideningBeadingStrategy.

32{
33 if (lower_bead_count == 0)
34 return scaled<coord_t>(0.01);
36}

References Slic3r::Arachne::BeadingStrategy::default_transition_length.

Referenced by Slic3r::Arachne::SkeletalTrapezoidation::dissolveNearbyTransitions(), Slic3r::Arachne::SkeletalTrapezoidation::filterTransitionMids(), and Slic3r::Arachne::SkeletalTrapezoidation::generateTransitionEnds().

+ Here is the caller graph for this function:

◆ getTransitionThickness()

coord_t Slic3r::Arachne::BeadingStrategy::getTransitionThickness ( coord_t  lower_bead_count) const
virtualinherited

The model thickness at which BeadingStrategy::optimal_bead_count transitions from lower_bead_count to lower_bead_count + 1

Reimplemented in Slic3r::Arachne::LimitedBeadingStrategy, Slic3r::Arachne::OuterWallInsetBeadingStrategy, Slic3r::Arachne::RedistributeBeadingStrategy, and Slic3r::Arachne::WideningBeadingStrategy.

72{
73 const coord_t lower_ideal_width = getOptimalThickness(lower_bead_count);
74 const coord_t higher_ideal_width = getOptimalThickness(lower_bead_count + 1);
75 const double threshold = lower_bead_count % 2 == 1 ? wall_split_middle_threshold : wall_add_middle_threshold;
76 return lower_ideal_width + threshold * (higher_ideal_width - lower_ideal_width);
77}

References Slic3r::Arachne::BeadingStrategy::getOptimalThickness(), Slic3r::Arachne::BeadingStrategy::wall_add_middle_threshold, and Slic3r::Arachne::BeadingStrategy::wall_split_middle_threshold.

Referenced by Slic3r::Arachne::SkeletalTrapezoidation::generateTransitionMids(), Slic3r::Arachne::BeadingStrategy::getTransitionAnchorPos(), and Slic3r::Arachne::SkeletalTrapezoidation::updateIsCentral().

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

◆ toString()

std::string Slic3r::Arachne::BeadingStrategy::toString ( ) const
virtualinherited

Member Data Documentation

◆ default_transition_length

coord_t Slic3r::Arachne::BeadingStrategy::default_transition_length
protectedinherited

Threshold when a new middle wall should be added between an even number of walls, as a ratio of the optimal wall width.

Referenced by Slic3r::Arachne::BeadingStrategy::getTransitioningLength().

◆ name

◆ one_over_distribution_radius_squared

float Slic3r::Arachne::DistributedBeadingStrategy::one_over_distribution_radius_squared
protected

◆ optimal_width

◆ transitioning_angle

double Slic3r::Arachne::BeadingStrategy::transitioning_angle
protectedinherited

The length of the region to smoothly transfer between bead counts.

The maximum angle between outline segments smaller than which we are going to add transitions Equals 180 - the "limit bisector angle" from the paper

Referenced by Slic3r::Arachne::BeadingStrategy::getTransitioningAngle().

◆ wall_add_middle_threshold

double Slic3r::Arachne::BeadingStrategy::wall_add_middle_threshold
protectedinherited

Threshold when a middle wall should be split into two, as a ratio of the optimal wall width.

Referenced by getOptimalBeadCount(), and Slic3r::Arachne::BeadingStrategy::getTransitionThickness().

◆ wall_split_middle_threshold

double Slic3r::Arachne::BeadingStrategy::wall_split_middle_threshold
protectedinherited

Optimal bead width, nominal width off the walls in 'ideal' circumstances.

Referenced by getOptimalBeadCount(), Slic3r::Arachne::BeadingStrategy::getSplitMiddleThreshold(), and Slic3r::Arachne::BeadingStrategy::getTransitionThickness().


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