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:
parent
8e27e355c2
commit
f01f02154c
@ -28,6 +28,8 @@ struct SurfaceFillParams
|
|||||||
// coordf_t overlap = 0.;
|
// coordf_t overlap = 0.;
|
||||||
// Angle as provided by the region config, in radians.
|
// Angle as provided by the region config, in radians.
|
||||||
float angle = 0.f;
|
float angle = 0.f;
|
||||||
|
// Is bridging used for this fill? Bridging parameters may be used even if this->flow.bridge() is not set.
|
||||||
|
bool bridge;
|
||||||
// Non-negative for a bridge.
|
// Non-negative for a bridge.
|
||||||
float bridge_angle = 0.f;
|
float bridge_angle = 0.f;
|
||||||
|
|
||||||
@ -73,18 +75,19 @@ struct SurfaceFillParams
|
|||||||
RETURN_COMPARE_NON_EQUAL(flow.width());
|
RETURN_COMPARE_NON_EQUAL(flow.width());
|
||||||
RETURN_COMPARE_NON_EQUAL(flow.height());
|
RETURN_COMPARE_NON_EQUAL(flow.height());
|
||||||
RETURN_COMPARE_NON_EQUAL(flow.nozzle_diameter());
|
RETURN_COMPARE_NON_EQUAL(flow.nozzle_diameter());
|
||||||
RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, flow.bridge());
|
RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, bridge);
|
||||||
RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, extrusion_role);
|
RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, extrusion_role);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const SurfaceFillParams &rhs) const {
|
bool operator==(const SurfaceFillParams &rhs) const {
|
||||||
return this->extruder == rhs.extruder &&
|
return this->extruder == rhs.extruder &&
|
||||||
this->pattern == rhs.pattern &&
|
|
||||||
this->pattern == rhs.pattern &&
|
this->pattern == rhs.pattern &&
|
||||||
this->spacing == rhs.spacing &&
|
this->spacing == rhs.spacing &&
|
||||||
// this->overlap == rhs.overlap &&
|
// this->overlap == rhs.overlap &&
|
||||||
this->angle == rhs.angle &&
|
this->angle == rhs.angle &&
|
||||||
|
this->bridge == rhs.bridge &&
|
||||||
|
// this->bridge_angle == rhs.bridge_angle &&
|
||||||
this->density == rhs.density &&
|
this->density == rhs.density &&
|
||||||
// this->dont_adjust == rhs.dont_adjust &&
|
// this->dont_adjust == rhs.dont_adjust &&
|
||||||
this->anchor_length == rhs.anchor_length &&
|
this->anchor_length == rhs.anchor_length &&
|
||||||
@ -128,6 +131,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
|||||||
|
|
||||||
if (surface.is_solid()) {
|
if (surface.is_solid()) {
|
||||||
params.density = 100.f;
|
params.density = 100.f;
|
||||||
|
//FIXME for non-thick bridges, shall we allow a bottom surface pattern?
|
||||||
params.pattern = (surface.is_external() && ! is_bridge) ?
|
params.pattern = (surface.is_external() && ! is_bridge) ?
|
||||||
(surface.is_top() ? region_config.top_fill_pattern.value : region_config.bottom_fill_pattern.value) :
|
(surface.is_top() ? region_config.top_fill_pattern.value : region_config.bottom_fill_pattern.value) :
|
||||||
region_config.top_fill_pattern == ipMonotonic ? ipMonotonic : ipRectilinear;
|
region_config.top_fill_pattern == ipMonotonic ? ipMonotonic : ipRectilinear;
|
||||||
@ -144,9 +148,10 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
|||||||
params.angle = float(Geometry::deg2rad(region_config.fill_angle.value));
|
params.angle = float(Geometry::deg2rad(region_config.fill_angle.value));
|
||||||
|
|
||||||
// Calculate the actual flow we'll be using for this infill.
|
// Calculate the actual flow we'll be using for this infill.
|
||||||
params.flow = is_bridge || Fill::use_bridge_flow(params.pattern) ?
|
params.bridge = is_bridge || Fill::use_bridge_flow(params.pattern);
|
||||||
|
params.flow = params.bridge ?
|
||||||
layerm.bridging_flow(extrusion_role) :
|
layerm.bridging_flow(extrusion_role) :
|
||||||
layerm.region()->flow(*layer.object(), extrusion_role, (surface.thickness == -1) ? layer.height : surface.thickness, layer.id() == 0);
|
layerm.flow(extrusion_role, (surface.thickness == -1) ? layer.height : surface.thickness);
|
||||||
|
|
||||||
// Calculate flow spacing for infill pattern generation.
|
// Calculate flow spacing for infill pattern generation.
|
||||||
if (surface.is_solid() || is_bridge) {
|
if (surface.is_solid() || is_bridge) {
|
||||||
@ -159,7 +164,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
|||||||
// for all layers, for avoiding the ugly effect of
|
// for all layers, for avoiding the ugly effect of
|
||||||
// misaligned infill on first layer because of different extrusion width and
|
// misaligned infill on first layer because of different extrusion width and
|
||||||
// layer height
|
// layer height
|
||||||
params.spacing = layerm.region()->flow(*layer.object(), frInfill, layer.object()->config().layer_height).spacing();
|
params.spacing = layerm.flow(frInfill, layer.object()->config().layer_height).spacing();
|
||||||
// Anchor a sparse infill to inner perimeters with the following anchor length:
|
// Anchor a sparse infill to inner perimeters with the following anchor length:
|
||||||
params.anchor_length = float(region_config.infill_anchor);
|
params.anchor_length = float(region_config.infill_anchor);
|
||||||
if (region_config.infill_anchor.percent)
|
if (region_config.infill_anchor.percent)
|
||||||
@ -278,7 +283,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
|||||||
params.extrusion_role = erInternalInfill;
|
params.extrusion_role = erInternalInfill;
|
||||||
params.angle = float(Geometry::deg2rad(layerm.region()->config().fill_angle.value));
|
params.angle = float(Geometry::deg2rad(layerm.region()->config().fill_angle.value));
|
||||||
// calculate the actual flow we'll be using for this infill
|
// calculate the actual flow we'll be using for this infill
|
||||||
params.flow = layerm.region()->flow(*layer.object(), frSolidInfill, layer.height, layer.id() == 0);
|
params.flow = layerm.flow(frSolidInfill);
|
||||||
params.spacing = params.flow.spacing();
|
params.spacing = params.flow.spacing();
|
||||||
surface_fills.emplace_back(params);
|
surface_fills.emplace_back(params);
|
||||||
surface_fills.back().surface.surface_type = stInternalSolid;
|
surface_fills.back().surface.surface_type = stInternalSolid;
|
||||||
@ -346,9 +351,9 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree;
|
f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree;
|
||||||
|
|
||||||
// calculate flow spacing for infill pattern generation
|
// calculate flow spacing for infill pattern generation
|
||||||
bool using_internal_flow = ! surface_fill.surface.is_solid() && ! surface_fill.params.flow.bridge();
|
bool using_internal_flow = ! surface_fill.surface.is_solid() && ! surface_fill.params.bridge;
|
||||||
double link_max_length = 0.;
|
double link_max_length = 0.;
|
||||||
if (! surface_fill.params.flow.bridge()) {
|
if (! surface_fill.params.bridge) {
|
||||||
#if 0
|
#if 0
|
||||||
link_max_length = layerm.region()->config().get_abs_value(surface.is_external() ? "external_fill_link_max_length" : "fill_link_max_length", flow.spacing());
|
link_max_length = layerm.region()->config().get_abs_value(surface.is_external() ? "external_fill_link_max_length" : "fill_link_max_length", flow.spacing());
|
||||||
// printf("flow spacing: %f, is_external: %d, link_max_length: %lf\n", flow.spacing(), int(surface.is_external()), link_max_length);
|
// printf("flow spacing: %f, is_external: %d, link_max_length: %lf\n", flow.spacing(), int(surface.is_external()), link_max_length);
|
||||||
@ -389,9 +394,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
// so we can safely ignore the slight variation that might have
|
// so we can safely ignore the slight variation that might have
|
||||||
// been applied to f->spacing
|
// been applied to f->spacing
|
||||||
} else {
|
} else {
|
||||||
Flow new_flow = surface_fill.params.flow.bridge() ?
|
Flow new_flow = surface_fill.params.flow.with_spacing(float(f->spacing));
|
||||||
Flow::bridging_flow_from_spacing(float(f->spacing), surface_fill.params.flow.nozzle_diameter()) :
|
|
||||||
Flow::new_from_spacing(float(f->spacing), surface_fill.params.flow.nozzle_diameter(), surface_fill.params.flow.height());
|
|
||||||
flow_mm3_per_mm = new_flow.mm3_per_mm();
|
flow_mm3_per_mm = new_flow.mm3_per_mm();
|
||||||
flow_width = new_flow.width();
|
flow_width = new_flow.width();
|
||||||
}
|
}
|
||||||
@ -601,9 +604,9 @@ void Layer::make_ironing()
|
|||||||
fill.spacing = ironing_params.line_spacing;
|
fill.spacing = ironing_params.line_spacing;
|
||||||
fill.angle = float(ironing_params.angle + 0.25 * M_PI);
|
fill.angle = float(ironing_params.angle + 0.25 * M_PI);
|
||||||
fill.link_max_length = (coord_t)scale_(3. * fill.spacing);
|
fill.link_max_length = (coord_t)scale_(3. * fill.spacing);
|
||||||
double height = ironing_params.height * fill.spacing / nozzle_dmr;
|
double extrusion_height = ironing_params.height * fill.spacing / nozzle_dmr;
|
||||||
Flow flow = Flow::new_from_spacing(float(nozzle_dmr), 0., float(height));
|
float extrusion_width = Flow::rounded_rectangle_extrusion_width_from_spacing(float(nozzle_dmr), float(extrusion_height));
|
||||||
double flow_mm3_per_mm = flow.mm3_per_mm();
|
double flow_mm3_per_mm = nozzle_dmr * extrusion_height;
|
||||||
Surface surface_fill(stTop, ExPolygon());
|
Surface surface_fill(stTop, ExPolygon());
|
||||||
for (ExPolygon &expoly : ironing_areas) {
|
for (ExPolygon &expoly : ironing_areas) {
|
||||||
surface_fill.expolygon = std::move(expoly);
|
surface_fill.expolygon = std::move(expoly);
|
||||||
@ -621,7 +624,7 @@ void Layer::make_ironing()
|
|||||||
extrusion_entities_append_paths(
|
extrusion_entities_append_paths(
|
||||||
eec->entities, std::move(polylines),
|
eec->entities, std::move(polylines),
|
||||||
erIroning,
|
erIroning,
|
||||||
flow_mm3_per_mm, float(flow.width()), float(height));
|
flow_mm3_per_mm, extrusion_width, float(extrusion_height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,6 @@
|
|||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#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.
|
// Mark string for localization and translate.
|
||||||
#define L(s) Slic3r::I18N::translate(s)
|
#define L(s) Slic3r::I18N::translate(s)
|
||||||
|
|
||||||
@ -142,58 +136,78 @@ Flow Flow::new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent
|
|||||||
w = float(width.get_abs_value(height));
|
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.
|
// Adjust extrusion flow for new extrusion line spacing, maintaining the old spacing between extrusions.
|
||||||
Flow Flow::new_from_spacing(float spacing, float nozzle_diameter, float height)
|
Flow Flow::with_spacing(float new_spacing) const
|
||||||
{
|
{
|
||||||
if (height <= 0)
|
Flow out = *this;
|
||||||
throw Slic3r::InvalidArgument("Invalid flow height supplied to new_from_spacing()");
|
if (m_bridge) {
|
||||||
// Calculate width from spacing.
|
// Diameter of the rounded extrusion.
|
||||||
// For normal extrusons, extrusion width is wider than the spacing due to the rounding and squishing of the extrusions.
|
assert(m_width == m_height);
|
||||||
float width = float(
|
float gap = m_spacing - m_width;
|
||||||
#ifdef HAS_PERIMETER_LINE_OVERLAP
|
auto new_diameter = new_spacing - gap;
|
||||||
(spacing + PERIMETER_LINE_OVERLAP_FACTOR * height * (1. - 0.25 * PI));
|
out.m_width = out.m_height = new_diameter;
|
||||||
#else
|
} else {
|
||||||
(spacing + height * (1. - 0.25 * PI)));
|
out.m_width += new_spacing - m_spacing;
|
||||||
#endif
|
if (out.m_width < out.m_height)
|
||||||
return Flow(width, height, nozzle_diameter);
|
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
|
// Adjust the width / height of a rounded extrusion model to reach the prescribed cross section area while maintaining extrusion spacing.
|
||||||
// having the same extrusion width (and other properties).
|
Flow Flow::with_cross_section(float area_new) const
|
||||||
float Flow::spacing() const
|
|
||||||
{
|
{
|
||||||
#ifdef HAS_PERIMETER_LINE_OVERLAP
|
assert(! m_bridge);
|
||||||
if (m_bridge)
|
assert(flow.width() >= flow.height());
|
||||||
return m_width + BRIDGE_EXTRA_SPACING;
|
|
||||||
// rectangle with semicircles at the ends
|
// Adjust for bridge_flow_ratio, maintain the extrusion spacing.
|
||||||
float min_flow_spacing = m_width - m_height * (1. - 0.25 * PI);
|
float area = this->mm3_per_mm();
|
||||||
float res = m_width - PERIMETER_LINE_OVERLAP_FACTOR * (m_width - min_flow_spacing);
|
if (area_new > area + EPSILON) {
|
||||||
#else
|
// Increasing the flow rate.
|
||||||
float res = float(m_bridge ? (m_width + BRIDGE_EXTRA_SPACING) : (m_width - m_height * (1. - 0.25 * PI)));
|
float new_full_spacing = area_new / m_height;
|
||||||
#endif
|
if (new_full_spacing > m_spacing) {
|
||||||
// assert(res > 0.f);
|
// Filling up the spacing without an air gap. Grow the extrusion in height.
|
||||||
if (res <= 0.f)
|
float height = area_new / m_spacing;
|
||||||
throw FlowErrorNegativeSpacing();
|
return Flow(rounded_rectangle_extrusion_width_from_spacing(m_spacing, height), height, m_spacing, m_nozzle_diameter, false);
|
||||||
return res;
|
} 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
|
float Flow::rounded_rectangle_extrusion_spacing(float width, float height)
|
||||||
// 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
|
|
||||||
{
|
{
|
||||||
assert(m_height == other.m_height);
|
auto out = width - height * float(1. - 0.25 * PI);
|
||||||
assert(m_bridge == other.m_bridge);
|
if (out <= 0.f)
|
||||||
float res = float(m_bridge ?
|
throw FlowErrorNegativeSpacing();
|
||||||
0.5 * m_width + 0.5 * other.m_width + BRIDGE_EXTRA_SPACING :
|
return out;
|
||||||
0.5 * this->spacing() + 0.5 * other.spacing());
|
}
|
||||||
// assert(res > 0.f);
|
|
||||||
if (res <= 0.f)
|
float Flow::rounded_rectangle_extrusion_width_from_spacing(float spacing, float height)
|
||||||
throw FlowErrorNegativeSpacing();
|
{
|
||||||
return res;
|
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.
|
// This method returns extrusion volume per head move unit.
|
||||||
|
@ -51,26 +51,26 @@ public:
|
|||||||
class Flow
|
class Flow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Flow() = default;
|
||||||
|
Flow(float width, float height, float nozzle_diameter) :
|
||||||
|
Flow(width, height, rounded_rectangle_extrusion_spacing(width, height), nozzle_diameter, false) {}
|
||||||
|
|
||||||
// Non bridging flow: Maximum width of an extrusion with semicircles at the ends.
|
// Non bridging flow: Maximum width of an extrusion with semicircles at the ends.
|
||||||
// Bridging flow: Bridge thread diameter.
|
// Bridging flow: Bridge thread diameter.
|
||||||
float width() const { return m_width; }
|
float width() const { return m_width; }
|
||||||
|
coord_t scaled_width() const { return coord_t(scale_(m_width)); }
|
||||||
// Non bridging flow: Layer height.
|
// Non bridging flow: Layer height.
|
||||||
// Bridging flow: Bridge thread diameter = layer height.
|
// Bridging flow: Bridge thread diameter = layer height.
|
||||||
float height() const { return m_height; }
|
float height() const { return m_height; }
|
||||||
|
// Spacing between the extrusion centerlines.
|
||||||
|
float spacing() const { return m_spacing; }
|
||||||
|
coord_t scaled_spacing() const { return coord_t(scale_(m_spacing)); }
|
||||||
// Nozzle diameter.
|
// Nozzle diameter.
|
||||||
float nozzle_diameter() const { return m_nozzle_diameter; }
|
float nozzle_diameter() const { return m_nozzle_diameter; }
|
||||||
// Is it a bridge?
|
// Is it a bridge?
|
||||||
bool bridge() const { return m_bridge; }
|
bool bridge() const { return m_bridge; }
|
||||||
|
// Cross section area of the extrusion.
|
||||||
Flow() = default;
|
double mm3_per_mm() const;
|
||||||
Flow(float w, float h, float nozzle_diameter) : Flow(w, h, nozzle_diameter, false) {}
|
|
||||||
|
|
||||||
float spacing() const;
|
|
||||||
float spacing(const Flow &other) const;
|
|
||||||
double mm3_per_mm() const;
|
|
||||||
coord_t scaled_width() const { return coord_t(scale_(m_width)); }
|
|
||||||
coord_t scaled_spacing() const { return coord_t(scale_(this->spacing())); }
|
|
||||||
coord_t scaled_spacing(const Flow &other) const { return coord_t(scale_(this->spacing(other))); }
|
|
||||||
|
|
||||||
// Elephant foot compensation spacing to be used to detect narrow parts, where the elephant foot compensation cannot be applied.
|
// Elephant foot compensation spacing to be used to detect narrow parts, where the elephant foot compensation cannot be applied.
|
||||||
// To be used on frExternalPerimeter only.
|
// To be used on frExternalPerimeter only.
|
||||||
@ -80,18 +80,30 @@ public:
|
|||||||
|
|
||||||
bool operator==(const Flow &rhs) const { return m_width == rhs.m_width && m_height == rhs.m_height && m_nozzle_diameter == rhs.m_nozzle_diameter && m_bridge == rhs.m_bridge; }
|
bool operator==(const Flow &rhs) const { return m_width == rhs.m_width && m_height == rhs.m_height && m_nozzle_diameter == rhs.m_nozzle_diameter && m_bridge == rhs.m_bridge; }
|
||||||
|
|
||||||
Flow with_width (float width) const { assert(! m_bridge); return Flow(width, m_height, m_nozzle_diameter, m_bridge); }
|
Flow with_width (float width) const {
|
||||||
Flow with_height(float height) const { assert(! m_bridge); return Flow(m_width, height, m_nozzle_diameter, m_bridge); }
|
assert(! m_bridge);
|
||||||
|
return Flow(width, m_height, rounded_rectangle_extrusion_spacing(width, m_height), m_nozzle_diameter, m_bridge);
|
||||||
|
}
|
||||||
|
Flow with_height(float height) const {
|
||||||
|
assert(! m_bridge);
|
||||||
|
return Flow(m_width, height, rounded_rectangle_extrusion_spacing(m_width, height), m_nozzle_diameter, m_bridge);
|
||||||
|
}
|
||||||
|
// Adjust extrusion flow for new extrusion line spacing, maintaining the old spacing between extrusions.
|
||||||
|
Flow with_spacing(float spacing) const;
|
||||||
|
// Adjust the width / height of a rounded extrusion model to reach the prescribed cross section area while maintaining extrusion spacing.
|
||||||
|
Flow with_cross_section(float area) const;
|
||||||
|
Flow with_flow_ratio(double ratio) const { return this->with_cross_section(this->mm3_per_mm() * ratio); }
|
||||||
|
|
||||||
static Flow bridging_flow(float dmr, float nozzle_diameter) { return Flow { dmr, dmr, nozzle_diameter, true }; }
|
static Flow bridging_flow(float dmr, float nozzle_diameter) { return Flow { dmr, dmr, bridge_extrusion_spacing(dmr), nozzle_diameter, true }; }
|
||||||
static Flow bridging_flow_from_spacing(float spacing, float nozzle_diameter)
|
|
||||||
{ auto dmr = spacing - float(BRIDGE_EXTRA_SPACING); return Flow { dmr, dmr, nozzle_diameter, true }; }
|
|
||||||
|
|
||||||
static Flow new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height);
|
static Flow new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height);
|
||||||
// Create a flow from the spacing of extrusion lines.
|
|
||||||
// This method is used exclusively to calculate new flow of 100% infill, where the extrusion width was allowed to scale
|
// Spacing of extrusions with rounded extrusion model.
|
||||||
// to fit a region with integer number of lines.
|
static float rounded_rectangle_extrusion_spacing(float width, float height);
|
||||||
static Flow new_from_spacing(float spacing, float nozzle_diameter, float height);
|
// Width of extrusions with rounded extrusion model.
|
||||||
|
static float rounded_rectangle_extrusion_width_from_spacing(float spacing, float height);
|
||||||
|
// Spacing of round thread extrusions.
|
||||||
|
static float bridge_extrusion_spacing(float dmr);
|
||||||
|
|
||||||
// Sane extrusion width defautl based on nozzle diameter.
|
// Sane extrusion width defautl based on nozzle diameter.
|
||||||
// The defaults were derived from manual Prusa MK3 profiles.
|
// The defaults were derived from manual Prusa MK3 profiles.
|
||||||
@ -104,10 +116,12 @@ public:
|
|||||||
static double extrusion_width(const std::string &opt_key, const ConfigOptionResolver &config, const unsigned int first_printing_extruder = 0);
|
static double extrusion_width(const std::string &opt_key, const ConfigOptionResolver &config, const unsigned int first_printing_extruder = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Flow(float w, float h, float nozzle_diameter, bool bridge) : m_width(w), m_height(h), m_nozzle_diameter(nozzle_diameter), m_bridge(bridge) {}
|
Flow(float width, float height, float spacing, float nozzle_diameter, bool bridge) :
|
||||||
|
m_width(width), m_height(height), m_spacing(spacing), m_nozzle_diameter(nozzle_diameter), m_bridge(bridge) {}
|
||||||
|
|
||||||
float m_width { 0 };
|
float m_width { 0 };
|
||||||
float m_height { 0 };
|
float m_height { 0 };
|
||||||
|
float m_spacing { 0 };
|
||||||
float m_nozzle_diameter { 0 };
|
float m_nozzle_diameter { 0 };
|
||||||
bool m_bridge { false };
|
bool m_bridge { false };
|
||||||
};
|
};
|
||||||
|
@ -60,6 +60,7 @@ public:
|
|||||||
ExtrusionEntityCollection fills;
|
ExtrusionEntityCollection fills;
|
||||||
|
|
||||||
Flow flow(FlowRole role) const;
|
Flow flow(FlowRole role) const;
|
||||||
|
Flow flow(FlowRole role, double layer_height) const;
|
||||||
Flow bridging_flow(FlowRole role) const;
|
Flow bridging_flow(FlowRole role) const;
|
||||||
|
|
||||||
void slices_to_fill_surfaces_clipped();
|
void slices_to_fill_surfaces_clipped();
|
||||||
|
@ -17,12 +17,29 @@ namespace Slic3r {
|
|||||||
|
|
||||||
Flow LayerRegion::flow(FlowRole role) const
|
Flow LayerRegion::flow(FlowRole role) const
|
||||||
{
|
{
|
||||||
return m_region->flow(*m_layer->object(), role, m_layer->height, m_layer->id() == 0);
|
return this->flow(role, m_layer->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
Flow LayerRegion::flow(FlowRole role, double layer_height) const
|
||||||
|
{
|
||||||
|
return m_region->flow(*m_layer->object(), role, layer_height, m_layer->id() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Flow LayerRegion::bridging_flow(FlowRole role) const
|
Flow LayerRegion::bridging_flow(FlowRole role) const
|
||||||
{
|
{
|
||||||
return this->layer()->object()->config().thick_bridges ? m_region->bridging_flow(role) : this->flow(role);
|
const PrintRegion ®ion = *this->region();
|
||||||
|
const PrintRegionConfig ®ion_config = region.config();
|
||||||
|
if (this->layer()->object()->config().thick_bridges) {
|
||||||
|
// The old Slic3r way (different from all other slicers): Use rounded extrusions.
|
||||||
|
// Get the configured nozzle_diameter for the extruder associated to the flow role requested.
|
||||||
|
// Here this->extruder(role) - 1 may underflow to MAX_INT, but then the get_at() will follback to zero'th element, so everything is all right.
|
||||||
|
auto nozzle_diameter = float(region.print()->config().nozzle_diameter.get_at(region.extruder(role) - 1));
|
||||||
|
// Applies default bridge spacing.
|
||||||
|
return Flow::bridging_flow(float(sqrt(region_config.bridge_flow_ratio)) * nozzle_diameter, nozzle_diameter);
|
||||||
|
} else {
|
||||||
|
// The same way as other slicers: Use normal extrusions. Apply bridge_flow_ratio while maintaining the original spacing.
|
||||||
|
return this->flow(role).with_flow_ratio(region_config.bridge_flow_ratio);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill in layerm->fill_surfaces by trimming the layerm->slices by the cummulative layerm->fill_surfaces.
|
// Fill in layerm->fill_surfaces by trimming the layerm->slices by the cummulative layerm->fill_surfaces.
|
||||||
|
@ -286,7 +286,7 @@ void PerimeterGenerator::process()
|
|||||||
m_ext_mm3_per_mm = this->ext_perimeter_flow.mm3_per_mm();
|
m_ext_mm3_per_mm = this->ext_perimeter_flow.mm3_per_mm();
|
||||||
coord_t ext_perimeter_width = this->ext_perimeter_flow.scaled_width();
|
coord_t ext_perimeter_width = this->ext_perimeter_flow.scaled_width();
|
||||||
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
|
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
|
||||||
coord_t ext_perimeter_spacing2 = this->ext_perimeter_flow.scaled_spacing(this->perimeter_flow);
|
coord_t ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing()));
|
||||||
|
|
||||||
// overhang perimeters
|
// overhang perimeters
|
||||||
m_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
|
m_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
|
||||||
|
@ -66,7 +66,6 @@ public:
|
|||||||
// 1-based extruder identifier for this region and role.
|
// 1-based extruder identifier for this region and role.
|
||||||
unsigned int extruder(FlowRole role) const;
|
unsigned int extruder(FlowRole role) const;
|
||||||
Flow flow(const PrintObject &object, FlowRole role, double layer_height, bool first_layer = false) const;
|
Flow flow(const PrintObject &object, FlowRole role, double layer_height, bool first_layer = false) const;
|
||||||
Flow bridging_flow(FlowRole role) const;
|
|
||||||
// Average diameter of nozzles participating on extruding this region.
|
// Average diameter of nozzles participating on extruding this region.
|
||||||
coordf_t nozzle_dmr_avg(const PrintConfig &print_config) const;
|
coordf_t nozzle_dmr_avg(const PrintConfig &print_config) const;
|
||||||
// Average diameter of nozzles participating on extruding this region.
|
// Average diameter of nozzles participating on extruding this region.
|
||||||
|
@ -1457,18 +1457,17 @@ void PrintObject::bridge_over_infill()
|
|||||||
const PrintRegion ®ion = *m_print->regions()[region_id];
|
const PrintRegion ®ion = *m_print->regions()[region_id];
|
||||||
|
|
||||||
// skip bridging in case there are no voids
|
// skip bridging in case there are no voids
|
||||||
if (region.config().fill_density.value == 100) continue;
|
if (region.config().fill_density.value == 100)
|
||||||
|
continue;
|
||||||
// get bridge flow
|
|
||||||
Flow bridge_flow = region.bridging_flow(frSolidInfill);
|
|
||||||
|
|
||||||
for (LayerPtrs::iterator layer_it = m_layers.begin(); layer_it != m_layers.end(); ++ layer_it) {
|
for (LayerPtrs::iterator layer_it = m_layers.begin(); layer_it != m_layers.end(); ++ layer_it) {
|
||||||
// skip first layer
|
// skip first layer
|
||||||
if (layer_it == m_layers.begin())
|
if (layer_it == m_layers.begin())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Layer* layer = *layer_it;
|
Layer *layer = *layer_it;
|
||||||
LayerRegion* layerm = layer->m_regions[region_id];
|
LayerRegion *layerm = layer->m_regions[region_id];
|
||||||
|
Flow bridge_flow = layerm->bridging_flow(frSolidInfill);
|
||||||
|
|
||||||
// extract the stInternalSolid surfaces that might be transformed into bridges
|
// extract the stInternalSolid surfaces that might be transformed into bridges
|
||||||
Polygons internal_solid;
|
Polygons internal_solid;
|
||||||
|
@ -48,17 +48,6 @@ Flow PrintRegion::flow(const PrintObject &object, FlowRole role, double layer_he
|
|||||||
return Flow::new_from_config_width(role, config_width, nozzle_diameter, float(layer_height));
|
return Flow::new_from_config_width(role, config_width, nozzle_diameter, float(layer_height));
|
||||||
}
|
}
|
||||||
|
|
||||||
Flow PrintRegion::bridging_flow(FlowRole role) const
|
|
||||||
{
|
|
||||||
// Get the configured nozzle_diameter for the extruder associated to the flow role requested.
|
|
||||||
// Here this->extruder(role) - 1 may underflow to MAX_INT, but then the get_at() will follback to zero'th element, so everything is all right.
|
|
||||||
auto nozzle_diameter = float(m_print->config().nozzle_diameter.get_at(this->extruder(role) - 1));
|
|
||||||
double bfr = m_config.bridge_flow_ratio;
|
|
||||||
if (bfr != 1.)
|
|
||||||
bfr = sqrt(bfr);
|
|
||||||
return Flow::bridging_flow(float(bfr) * nozzle_diameter, nozzle_diameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
coordf_t PrintRegion::nozzle_dmr_avg(const PrintConfig &print_config) const
|
coordf_t PrintRegion::nozzle_dmr_avg(const PrintConfig &print_config) const
|
||||||
{
|
{
|
||||||
return (print_config.nozzle_diameter.get_at(m_config.perimeter_extruder.value - 1) +
|
return (print_config.nozzle_diameter.get_at(m_config.perimeter_extruder.value - 1) +
|
||||||
|
@ -334,7 +334,7 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object
|
|||||||
for (auto lh : m_print_config->min_layer_height.values)
|
for (auto lh : m_print_config->min_layer_height.values)
|
||||||
m_support_layer_height_min = std::min(m_support_layer_height_min, std::max(0.01, lh));
|
m_support_layer_height_min = std::min(m_support_layer_height_min, std::max(0.01, lh));
|
||||||
|
|
||||||
if (m_object_config->support_material_interface_layers.value == 0) {
|
if (m_slicing_params.soluble_interface) {
|
||||||
// No interface layers allowed, print everything with the base support pattern.
|
// No interface layers allowed, print everything with the base support pattern.
|
||||||
m_support_material_interface_flow = m_support_material_flow;
|
m_support_material_interface_flow = m_support_material_flow;
|
||||||
}
|
}
|
||||||
@ -342,11 +342,21 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object
|
|||||||
// Evaluate the XY gap between the object outer perimeters and the support structures.
|
// Evaluate the XY gap between the object outer perimeters and the support structures.
|
||||||
// Evaluate the XY gap between the object outer perimeters and the support structures.
|
// Evaluate the XY gap between the object outer perimeters and the support structures.
|
||||||
coordf_t external_perimeter_width = 0.;
|
coordf_t external_perimeter_width = 0.;
|
||||||
|
size_t num_nonempty_regions = 0;
|
||||||
|
coordf_t bridge_flow_ratio = 0;
|
||||||
for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id)
|
for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id)
|
||||||
if (! object->region_volumes[region_id].empty())
|
if (! object->region_volumes[region_id].empty()) {
|
||||||
external_perimeter_width = std::max(external_perimeter_width,
|
++ num_nonempty_regions;
|
||||||
(coordf_t)object->print()->get_region(region_id)->flow(*object, frExternalPerimeter, slicing_params.layer_height).width());
|
const PrintRegion ®ion = *object->print()->get_region(region_id);
|
||||||
|
external_perimeter_width = std::max(external_perimeter_width, coordf_t(region.flow(*object, frExternalPerimeter, slicing_params.layer_height).width()));
|
||||||
|
bridge_flow_ratio += region.config().bridge_flow_ratio;
|
||||||
|
}
|
||||||
m_gap_xy = m_object_config->support_material_xy_spacing.get_abs_value(external_perimeter_width);
|
m_gap_xy = m_object_config->support_material_xy_spacing.get_abs_value(external_perimeter_width);
|
||||||
|
bridge_flow_ratio /= num_nonempty_regions;
|
||||||
|
|
||||||
|
m_support_material_bottom_interface_flow = m_slicing_params.soluble_interface || ! m_object_config->thick_bridges ?
|
||||||
|
m_support_material_interface_flow.with_flow_ratio(bridge_flow_ratio) :
|
||||||
|
Flow::bridging_flow(bridge_flow_ratio * m_support_material_interface_flow.nozzle_diameter(), m_support_material_interface_flow.nozzle_diameter());
|
||||||
|
|
||||||
m_can_merge_support_regions = m_object_config->support_material_extruder.value == m_object_config->support_material_interface_extruder.value;
|
m_can_merge_support_regions = m_object_config->support_material_extruder.value == m_object_config->support_material_interface_extruder.value;
|
||||||
if (! m_can_merge_support_regions && (m_object_config->support_material_extruder.value == 0 || m_object_config->support_material_interface_extruder.value == 0)) {
|
if (! m_can_merge_support_regions && (m_object_config->support_material_extruder.value == 0 || m_object_config->support_material_interface_extruder.value == 0)) {
|
||||||
@ -1231,8 +1241,8 @@ namespace SupportMaterialInternal {
|
|||||||
// since we're dealing with bridges, we can't assume width is larger than spacing,
|
// since we're dealing with bridges, we can't assume width is larger than spacing,
|
||||||
// so we take the largest value and also apply safety offset to be ensure no gaps
|
// so we take the largest value and also apply safety offset to be ensure no gaps
|
||||||
// are left in between
|
// are left in between
|
||||||
Flow bridge_flow = layerm->bridging_flow(frPerimeter);
|
Flow perimeter_bridge_flow = layerm->bridging_flow(frPerimeter);
|
||||||
float w = float(std::max(bridge_flow.scaled_width(), bridge_flow.scaled_spacing()));
|
float w = float(std::max(perimeter_bridge_flow.scaled_width(), perimeter_bridge_flow.scaled_spacing()));
|
||||||
for (Polyline &polyline : overhang_perimeters)
|
for (Polyline &polyline : overhang_perimeters)
|
||||||
if (polyline.is_straight()) {
|
if (polyline.is_straight()) {
|
||||||
// This is a bridge
|
// This is a bridge
|
||||||
@ -1879,13 +1889,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
|||||||
layer_new.height = m_slicing_params.soluble_interface ?
|
layer_new.height = m_slicing_params.soluble_interface ?
|
||||||
// Align the interface layer with the object's layer height.
|
// Align the interface layer with the object's layer height.
|
||||||
object.layers()[layer_id + 1]->height :
|
object.layers()[layer_id + 1]->height :
|
||||||
// Place a bridge flow interface layer over the top surface.
|
// Place a bridge flow interface layer or the normal flow interface layer over the top surface.
|
||||||
//FIXME Check whether the bottom bridging surfaces are extruded correctly (no bridging flow correction applied?)
|
m_support_material_bottom_interface_flow.height();
|
||||||
// According to Jindrich the bottom surfaces work well.
|
|
||||||
//FIXME test the bridging flow instead?
|
|
||||||
m_object_config->thick_bridges.value ? m_support_material_interface_flow.nozzle_diameter() :
|
|
||||||
// Take the default layer height.
|
|
||||||
m_object_config->layer_height;
|
|
||||||
layer_new.print_z = m_slicing_params.soluble_interface ? object.layers()[layer_id + 1]->print_z :
|
layer_new.print_z = m_slicing_params.soluble_interface ? object.layers()[layer_id + 1]->print_z :
|
||||||
layer.print_z + layer_new.height + m_object_config->support_material_contact_distance.value;
|
layer.print_z + layer_new.height + m_object_config->support_material_contact_distance.value;
|
||||||
layer_new.bottom_z = layer.print_z;
|
layer_new.bottom_z = layer.print_z;
|
||||||
@ -3497,7 +3502,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
coordf_t interface_density = std::min(1., m_support_material_interface_flow.spacing() / interface_spacing);
|
coordf_t interface_density = std::min(1., m_support_material_interface_flow.spacing() / interface_spacing);
|
||||||
coordf_t support_spacing = m_object_config->support_material_spacing.value + m_support_material_flow.spacing();
|
coordf_t support_spacing = m_object_config->support_material_spacing.value + m_support_material_flow.spacing();
|
||||||
coordf_t support_density = std::min(1., m_support_material_flow.spacing() / support_spacing);
|
coordf_t support_density = std::min(1., m_support_material_flow.spacing() / support_spacing);
|
||||||
if (m_object_config->support_material_interface_layers.value == 0) {
|
if (m_slicing_params.soluble_interface) {
|
||||||
// No interface layers allowed, print everything with the base support pattern.
|
// No interface layers allowed, print everything with the base support pattern.
|
||||||
interface_spacing = support_spacing;
|
interface_spacing = support_spacing;
|
||||||
interface_density = support_density;
|
interface_density = support_density;
|
||||||
@ -3738,13 +3743,12 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
MyLayerExtruded &layer_ex = (i == 0) ? top_contact_layer : (i == 1 ? bottom_contact_layer : interface_layer);
|
MyLayerExtruded &layer_ex = (i == 0) ? top_contact_layer : (i == 1 ? bottom_contact_layer : interface_layer);
|
||||||
if (layer_ex.empty() || layer_ex.polygons_to_extrude().empty())
|
if (layer_ex.empty() || layer_ex.polygons_to_extrude().empty())
|
||||||
continue;
|
continue;
|
||||||
bool interface_as_base = (&layer_ex == &interface_layer) && m_object_config->support_material_interface_layers.value == 0;
|
bool interface_as_base = (&layer_ex == &interface_layer) && m_slicing_params.soluble_interface;
|
||||||
//FIXME Bottom interfaces are extruded with the briding flow. Some bridging layers have its height slightly reduced, therefore
|
//FIXME Bottom interfaces are extruded with the briding flow. Some bridging layers have its height slightly reduced, therefore
|
||||||
// the bridging flow does not quite apply. Reduce the flow to area of an ellipse? (A = pi * a * b)
|
// the bridging flow does not quite apply. Reduce the flow to area of an ellipse? (A = pi * a * b)
|
||||||
auto interface_flow = layer_ex.layer->bridging ?
|
auto interface_flow = layer_ex.layer->bridging ?
|
||||||
Flow::bridging_flow(layer_ex.layer->height, m_support_material_interface_flow.nozzle_diameter()) :
|
Flow::bridging_flow(layer_ex.layer->height, m_support_material_bottom_interface_flow.nozzle_diameter()) :
|
||||||
Flow(interface_as_base ? m_support_material_flow.width() : m_support_material_interface_flow.width(),
|
(interface_as_base ? &m_support_material_flow : &m_support_material_interface_flow)->with_height(float(layer_ex.layer->height));
|
||||||
float(layer_ex.layer->height), m_support_material_interface_flow.nozzle_diameter());
|
|
||||||
filler_interface->angle = interface_as_base ?
|
filler_interface->angle = interface_as_base ?
|
||||||
// If zero interface layers are configured, use the same angle as for the base layers.
|
// If zero interface layers are configured, use the same angle as for the base layers.
|
||||||
angles[support_layer_id % angles.size()] :
|
angles[support_layer_id % angles.size()] :
|
||||||
|
@ -244,6 +244,7 @@ private:
|
|||||||
Flow m_first_layer_flow;
|
Flow m_first_layer_flow;
|
||||||
Flow m_support_material_flow;
|
Flow m_support_material_flow;
|
||||||
Flow m_support_material_interface_flow;
|
Flow m_support_material_interface_flow;
|
||||||
|
Flow m_support_material_bottom_interface_flow;
|
||||||
// Is merging of regions allowed? Could the interface & base support regions be printed with the same extruder?
|
// Is merging of regions allowed? Could the interface & base support regions be printed with the same extruder?
|
||||||
bool m_can_merge_support_regions;
|
bool m_can_merge_support_regions;
|
||||||
|
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
float nozzle_diameter();
|
float nozzle_diameter();
|
||||||
bool bridge();
|
bool bridge();
|
||||||
float spacing();
|
float spacing();
|
||||||
float spacing_to(Flow* other)
|
|
||||||
%code{% RETVAL = THIS->spacing(*other); %};
|
|
||||||
int scaled_width();
|
int scaled_width();
|
||||||
int scaled_spacing();
|
int scaled_spacing();
|
||||||
double mm3_per_mm();
|
double mm3_per_mm();
|
||||||
|
Loading…
Reference in New Issue
Block a user