OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::CornerSmoother Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Fill/FillCornerSmoothing.hpp>

Collaboration diagram for Slic3r::CornerSmoother:

Public Member Functions

 CornerSmoother (const CornerSmoothing &smoothing, double max_corner_distance=0., CornerFilter corner_filter={})
bool enabled () const
template<typename Emit>
void push (const Vec2d &point, Emit &emit)
template<typename Emit>
void flush (Emit &emit)

Private Member Functions

template<typename Emit>
void emit_corner (const Vec2d &previous, const Vec2d &corner, const Vec2d &next, Emit &emit)
void round_corner (const Vec2d &previous, const Vec2d &corner, const Vec2d &next)
const std::vector< Vec2d > * corner_vertices (double reach, double cosine) const

Static Private Member Functions

static bool is_on_straight_run (const Vec2d &previous, const Vec2d &vertex, const Vec2d &next)

Private Attributes

const CornerSmoothing m_smoothing
const double m_corner_distance_ratio
const double m_max_corner_distance
const CornerFilter m_corner_filter
std::vector< Vec2d > m_corner_points
std::array< Vec2d, 3 > m_window { Vec2d::Zero(), Vec2d::Zero(), Vec2d::Zero() }
int m_held { 0 }

Detailed Description

Constructor & Destructor Documentation

◆ CornerSmoother()

Slic3r::CornerSmoother::CornerSmoother ( const CornerSmoothing & smoothing,
double max_corner_distance = 0.,
CornerFilter corner_filter = {} )
inline
51 {})
52 : m_smoothing(smoothing)
53 , m_corner_distance_ratio(0.5 * sanitize_smooth_factor(smoothing.factor))
54 , m_max_corner_distance(max_corner_distance)
55 , m_corner_filter(std::move(corner_filter))
56 {}
const CornerFilter m_corner_filter
Definition FillCornerSmoothing.hpp:116
const CornerSmoothing m_smoothing
Definition FillCornerSmoothing.hpp:111
const double m_max_corner_distance
Definition FillCornerSmoothing.hpp:115
const double m_corner_distance_ratio
Definition FillCornerSmoothing.hpp:114
double sanitize_smooth_factor(double smooth_factor)
Definition FillCornerSmoothing.hpp:18

Member Function Documentation

◆ corner_vertices()

const std::vector< Vec2d > * Slic3r::CornerSmoother::corner_vertices ( double reach,
double cosine ) const
private
173{
174 const double tolerance = m_smoothing.tolerance > 0. && std::isfinite(m_smoothing.tolerance) ? m_smoothing.tolerance : EPSILON;
175 const double turn = std::acos(std::clamp(cosine, -1., 1.));
176 const double curvature = peak_curvature_by_reach(cosine) / reach;
177 // Simplifying the path to the tolerance drops a vertex standing out of the chord of its neighbours by less,
178 // which the sharpest vertex of the curve does at finer steps than this.
179 const size_t most = size_t(std::min(double(max_corner_vertices), turn / std::sqrt(2. * curvature * tolerance)));
180 // The count an arc of the peak curvature takes; the flatter parts of the curve may need more.
181 size_t count = std::min(most, size_t(std::ceil(turn / std::sqrt(8. * curvature * tolerance) - EPSILON)));
182 if (count < 2)
183 return nullptr;
184 for (;;) {
185 const double deviation = reach * unit_corner(cosine, count).deviation;
186 if (deviation <= tolerance || count >= most)
187 break;
188 // The deviation falls about with the square of the count.
189 count = std::min(most, std::max(count + 1, size_t(std::ceil(double(count) * std::sqrt(deviation / tolerance)))));
190 }
191 return &unit_corner(cosine, count).vertices;
192}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246
#define EPSILON
Definition ColorUtils.cpp:64
std::vector< Vec2d > vertices
Definition FillCornerSmoothing.cpp:69
static constexpr const size_t max_corner_vertices
Definition FillCornerSmoothing.cpp:26
static const UnitCorner & unit_corner(const double cosine, const size_t count)
Definition FillCornerSmoothing.cpp:159
static double peak_curvature_by_reach(const double cosine)
Definition FillCornerSmoothing.cpp:83
double deviation
Definition FillCornerSmoothing.cpp:70

References count, Slic3r::UnitCorner::deviation, EPSILON, m_smoothing, Slic3r::max_corner_vertices, Slic3r::peak_curvature_by_reach(), Slic3r::unit_corner(), and Slic3r::UnitCorner::vertices.

Referenced by round_corner().

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

◆ emit_corner()

template<typename Emit>
void Slic3r::CornerSmoother::emit_corner ( const Vec2d & previous,
const Vec2d & corner,
const Vec2d & next,
Emit & emit )
inlineprivate
96 {
97 round_corner(previous, corner, next);
98 for (const Vec2d &corner_point : m_corner_points)
99 emit(corner_point);
100 }
std::vector< Vec2d > m_corner_points
Definition FillCornerSmoothing.hpp:117
void round_corner(const Vec2d &previous, const Vec2d &corner, const Vec2d &next)
Definition FillCornerSmoothing.cpp:210
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67

References m_corner_points, and round_corner().

Referenced by flush(), and push().

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

◆ enabled()

bool Slic3r::CornerSmoother::enabled ( ) const
inline
58{ return m_corner_distance_ratio > 0.; }

References m_corner_distance_ratio.

Referenced by Slic3r::smooth_polygons_corners(), and Slic3r::smooth_polyline_corners().

Here is the caller graph for this function:

◆ flush()

template<typename Emit>
void Slic3r::CornerSmoother::flush ( Emit & emit)
inline
86 {
87 if (m_held > 2)
88 emit_corner(m_window[0], m_window[1], m_window[2], emit);
89 if (m_held > 1)
90 emit(m_window[m_held - 1]);
91 m_held = 0;
92 }
void emit_corner(const Vec2d &previous, const Vec2d &corner, const Vec2d &next, Emit &emit)
Definition FillCornerSmoothing.hpp:95
int m_held
Definition FillCornerSmoothing.hpp:123
std::array< Vec2d, 3 > m_window
Definition FillCornerSmoothing.hpp:121

References emit_corner(), m_held, and m_window.

Referenced by Slic3r::smooth_corners().

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

◆ is_on_straight_run()

bool Slic3r::CornerSmoother::is_on_straight_run ( const Vec2d & previous,
const Vec2d & vertex,
const Vec2d & next )
staticprivate
195{
196 const Vec2d incoming_leg = vertex - previous;
197 const Vec2d outgoing_leg = next - vertex;
198 const double incoming_length = incoming_leg.norm();
199 const double outgoing_length = outgoing_leg.norm();
200 // A vertex repeating one of its neighbours carries no direction of its own.
201 if (incoming_length < EPSILON || outgoing_length < EPSILON)
202 return true;
203
204 const Vec2d incoming = incoming_leg / incoming_length;
205 const Vec2d outgoing = outgoing_leg / outgoing_length;
206 return incoming.dot(outgoing) > 0. &&
207 std::abs(incoming.x() * outgoing.y() - incoming.y() * outgoing.x()) < EPSILON;
208}

References EPSILON.

Referenced by push().

Here is the caller graph for this function:

◆ push()

template<typename Emit>
void Slic3r::CornerSmoother::push ( const Vec2d & point,
Emit & emit )
inline
61 {
62 if (m_held == 0) {
63 // The first point of a path is an end, not a corner, and stays where it is.
64 emit(point);
65 m_window[m_held++] = point;
66 return;
67 }
68 if (m_held > 1 && is_on_straight_run(m_window[m_held - 2], m_window[m_held - 1], point)) {
69 // The newest vertex only splits a straight leg, so the leg runs on to this point instead.
70 m_window[m_held - 1] = point;
71 return;
72 }
73 if (m_held < 3) {
74 m_window[m_held++] = point;
75 return;
76 }
77 // Both legs of the middle vertex are complete now, so its curve can no longer grow.
78 emit_corner(m_window[0], m_window[1], m_window[2], emit);
79 m_window[0] = m_window[1];
80 m_window[1] = m_window[2];
81 m_window[2] = point;
82 }
static bool is_on_straight_run(const Vec2d &previous, const Vec2d &vertex, const Vec2d &next)
Definition FillCornerSmoothing.cpp:194

References emit_corner(), is_on_straight_run(), m_held, and m_window.

Referenced by Slic3r::smooth_corners().

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

◆ round_corner()

void Slic3r::CornerSmoother::round_corner ( const Vec2d & previous,
const Vec2d & corner,
const Vec2d & next )
private
211{
212 m_corner_points.clear();
213
214 const Vec2d incoming_leg = corner - previous;
215 const Vec2d outgoing_leg = next - corner;
216 const double incoming_length = incoming_leg.norm();
217 const double outgoing_length = outgoing_leg.norm();
218 if (incoming_length < EPSILON || outgoing_length < EPSILON) {
219 m_corner_points.emplace_back(corner);
220 return;
221 }
222
223 const Vec2d incoming = incoming_leg / incoming_length;
224 const Vec2d outgoing = outgoing_leg / outgoing_length;
225 const double cross = incoming.x() * outgoing.y() - incoming.y() * outgoing.x();
226 // Snapped, so that the corners of one turn share the cached shapes whatever rounding their legs carry.
227 const double cosine = std::round(incoming.dot(outgoing) * 1e12) * 1e-12;
228 // A collinear vertex is no corner at all, and a hairpin cannot be rounded, see above.
229 if (std::abs(cross) < EPSILON || cosine < min_smoothed_turn_cosine) {
230 m_corner_points.emplace_back(corner);
231 return;
232 }
233
234 // Consuming at most half of the shorter leg keeps the curves of two adjacent corners apart.
235 double reach = m_corner_distance_ratio * std::min(incoming_length, outgoing_length);
236 if (m_max_corner_distance > 0.)
237 reach = std::min(reach, m_max_corner_distance);
238
239 const std::vector<Vec2d> *vertices = corner_vertices(reach, cosine);
240 if (vertices == nullptr || (m_corner_filter && !m_corner_filter(corner - reach * incoming, corner + reach * outgoing))) {
241 m_corner_points.emplace_back(corner);
242 return;
243 }
244
245 m_corner_points.reserve(vertices->size());
246 for (const Vec2d &vertex : *vertices)
247 m_corner_points.emplace_back(corner + reach * (vertex.x() * incoming + vertex.y() * outgoing));
248}
const std::vector< Vec2d > * corner_vertices(double reach, double cosine) const
Definition FillCornerSmoothing.cpp:172
T cross(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:168
static constexpr const double min_smoothed_turn_cosine
Definition FillCornerSmoothing.cpp:20

References corner_vertices(), Slic3r::cross(), EPSILON, m_corner_distance_ratio, m_corner_filter, m_corner_points, m_max_corner_distance, and Slic3r::min_smoothed_turn_cosine.

Referenced by emit_corner().

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

Member Data Documentation

◆ m_corner_distance_ratio

const double Slic3r::CornerSmoother::m_corner_distance_ratio
private

Referenced by enabled(), and round_corner().

◆ m_corner_filter

const CornerFilter Slic3r::CornerSmoother::m_corner_filter
private

Referenced by round_corner().

◆ m_corner_points

std::vector<Vec2d> Slic3r::CornerSmoother::m_corner_points
private

Referenced by emit_corner(), and round_corner().

◆ m_held

int Slic3r::CornerSmoother::m_held { 0 }
private
123{ 0 };

Referenced by flush(), and push().

◆ m_max_corner_distance

const double Slic3r::CornerSmoother::m_max_corner_distance
private

Referenced by round_corner().

◆ m_smoothing

const CornerSmoothing Slic3r::CornerSmoother::m_smoothing
private

Referenced by corner_vertices().

◆ m_window

std::array<Vec2d, 3> Slic3r::CornerSmoother::m_window { Vec2d::Zero(), Vec2d::Zero(), Vec2d::Zero() }
private
121{ Vec2d::Zero(), Vec2d::Zero(), Vec2d::Zero() };

Referenced by flush(), and push().


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