Reworked the "new" bridging to respect the bridge_flow_ratio

by maintaining extrusion spacing, but modifying the extrusion width
and / or height.
This commit is contained in:
Vojtech Bubnik 2021-03-09 12:30:31 +01:00
parent 8e27e355c2
commit f01f02154c
12 changed files with 173 additions and 134 deletions

View file

@ -6,12 +6,6 @@
#include <boost/algorithm/string/predicate.hpp>
// Overlap factor of perimeter lines. Currently no overlap.
// #define HAS_PERIMETER_LINE_OVERLAP
#ifdef HAS_PERIMETER_LINE_OVERLAP
#define PERIMETER_LINE_OVERLAP_FACTOR 1.0
#endif
// Mark string for localization and translate.
#define L(s) Slic3r::I18N::translate(s)
@ -142,62 +136,82 @@ Flow Flow::new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent
w = float(width.get_abs_value(height));
}
return Flow(w, height, nozzle_diameter, false);
return Flow(w, height, rounded_rectangle_extrusion_spacing(w, height), nozzle_diameter, false);
}
// This constructor builds a Flow object from a given centerline spacing.
Flow Flow::new_from_spacing(float spacing, float nozzle_diameter, float height)
// Adjust extrusion flow for new extrusion line spacing, maintaining the old spacing between extrusions.
Flow Flow::with_spacing(float new_spacing) const
{
if (height <= 0)
throw Slic3r::InvalidArgument("Invalid flow height supplied to new_from_spacing()");
// Calculate width from spacing.
// For normal extrusons, extrusion width is wider than the spacing due to the rounding and squishing of the extrusions.
float width = float(
#ifdef HAS_PERIMETER_LINE_OVERLAP
(spacing + PERIMETER_LINE_OVERLAP_FACTOR * height * (1. - 0.25 * PI));
#else
(spacing + height * (1. - 0.25 * PI)));
#endif
return Flow(width, height, nozzle_diameter);
Flow out = *this;
if (m_bridge) {
// Diameter of the rounded extrusion.
assert(m_width == m_height);
float gap = m_spacing - m_width;
auto new_diameter = new_spacing - gap;
out.m_width = out.m_height = new_diameter;
} else {
out.m_width += new_spacing - m_spacing;
if (out.m_width < out.m_height)
throw Slic3r::InvalidArgument("Invalid spacing supplied to Flow::with_spacing()");
}
out.m_spacing = new_spacing;
return out;
}
// This method returns the centerline spacing between two adjacent extrusions
// having the same extrusion width (and other properties).
float Flow::spacing() const
// Adjust the width / height of a rounded extrusion model to reach the prescribed cross section area while maintaining extrusion spacing.
Flow Flow::with_cross_section(float area_new) const
{
#ifdef HAS_PERIMETER_LINE_OVERLAP
if (m_bridge)
return m_width + BRIDGE_EXTRA_SPACING;
// rectangle with semicircles at the ends
float min_flow_spacing = m_width - m_height * (1. - 0.25 * PI);
float res = m_width - PERIMETER_LINE_OVERLAP_FACTOR * (m_width - min_flow_spacing);
#else
float res = float(m_bridge ? (m_width + BRIDGE_EXTRA_SPACING) : (m_width - m_height * (1. - 0.25 * PI)));
#endif
// assert(res > 0.f);
if (res <= 0.f)
throw FlowErrorNegativeSpacing();
return res;
assert(! m_bridge);
assert(flow.width() >= flow.height());
// Adjust for bridge_flow_ratio, maintain the extrusion spacing.
float area = this->mm3_per_mm();
if (area_new > area + EPSILON) {
// Increasing the flow rate.
float new_full_spacing = area_new / m_height;
if (new_full_spacing > m_spacing) {
// Filling up the spacing without an air gap. Grow the extrusion in height.
float height = area_new / m_spacing;
return Flow(rounded_rectangle_extrusion_width_from_spacing(m_spacing, height), height, m_spacing, m_nozzle_diameter, false);
} else {
return this->with_width(rounded_rectangle_extrusion_width_from_spacing(area / m_height, m_height));
}
} else if (area_new < area - EPSILON) {
// Decreasing the flow rate.
float width_new = m_width - (area - area_new) / m_height;
assert(width_dif > 0);
if (width_new > m_height) {
// Shrink the extrusion width.
return this->with_width(width_new);
} else {
// Create a rounded extrusion.
auto dmr = float(sqrt(area_new / M_PI));
return Flow(dmr, dmr, m_spacing, m_nozzle_diameter, false);
}
} else
return *this;
}
// This method returns the centerline spacing between an extrusion using this
// flow and another one using another flow.
// this->spacing(other) shall return the same value as other.spacing(*this)
float Flow::spacing(const Flow &other) const
float Flow::rounded_rectangle_extrusion_spacing(float width, float height)
{
assert(m_height == other.m_height);
assert(m_bridge == other.m_bridge);
float res = float(m_bridge ?
0.5 * m_width + 0.5 * other.m_width + BRIDGE_EXTRA_SPACING :
0.5 * this->spacing() + 0.5 * other.spacing());
// assert(res > 0.f);
if (res <= 0.f)
throw FlowErrorNegativeSpacing();
return res;
auto out = width - height * float(1. - 0.25 * PI);
if (out <= 0.f)
throw FlowErrorNegativeSpacing();
return out;
}
float Flow::rounded_rectangle_extrusion_width_from_spacing(float spacing, float height)
{
return float(spacing + height * (1. - 0.25 * PI));
}
float Flow::bridge_extrusion_spacing(float dmr)
{
return dmr + BRIDGE_EXTRA_SPACING;
}
// This method returns extrusion volume per head move unit.
double Flow::mm3_per_mm() const
double Flow::mm3_per_mm() const
{
float res = m_bridge ?
// Area of a circle with dmr of this->width.