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.;
|
||||
// Angle as provided by the region config, in radians.
|
||||
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.
|
||||
float bridge_angle = 0.f;
|
||||
|
||||
@ -73,18 +75,19 @@ struct SurfaceFillParams
|
||||
RETURN_COMPARE_NON_EQUAL(flow.width());
|
||||
RETURN_COMPARE_NON_EQUAL(flow.height());
|
||||
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 false;
|
||||
}
|
||||
|
||||
bool operator==(const SurfaceFillParams &rhs) const {
|
||||
return this->extruder == rhs.extruder &&
|
||||
this->pattern == rhs.pattern &&
|
||||
this->pattern == rhs.pattern &&
|
||||
this->spacing == rhs.spacing &&
|
||||
// this->overlap == rhs.overlap &&
|
||||
this->angle == rhs.angle &&
|
||||
this->bridge == rhs.bridge &&
|
||||
// this->bridge_angle == rhs.bridge_angle &&
|
||||
this->density == rhs.density &&
|
||||
// this->dont_adjust == rhs.dont_adjust &&
|
||||
this->anchor_length == rhs.anchor_length &&
|
||||
@ -128,6 +131,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
||||
|
||||
if (surface.is_solid()) {
|
||||
params.density = 100.f;
|
||||
//FIXME for non-thick bridges, shall we allow a bottom surface pattern?
|
||||
params.pattern = (surface.is_external() && ! is_bridge) ?
|
||||
(surface.is_top() ? region_config.top_fill_pattern.value : region_config.bottom_fill_pattern.value) :
|
||||
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));
|
||||
|
||||
// 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.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.
|
||||
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
|
||||
// misaligned infill on first layer because of different extrusion width and
|
||||
// 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:
|
||||
params.anchor_length = float(region_config.infill_anchor);
|
||||
if (region_config.infill_anchor.percent)
|
||||
@ -278,7 +283,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
||||
params.extrusion_role = erInternalInfill;
|
||||
params.angle = float(Geometry::deg2rad(layerm.region()->config().fill_angle.value));
|
||||
// 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();
|
||||
surface_fills.emplace_back(params);
|
||||
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;
|
||||
|
||||
// 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.;
|
||||
if (! surface_fill.params.flow.bridge()) {
|
||||
if (! surface_fill.params.bridge) {
|
||||
#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());
|
||||
// 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
|
||||
// been applied to f->spacing
|
||||
} else {
|
||||
Flow new_flow = surface_fill.params.flow.bridge() ?
|
||||
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 new_flow = surface_fill.params.flow.with_spacing(float(f->spacing));
|
||||
flow_mm3_per_mm = new_flow.mm3_per_mm();
|
||||
flow_width = new_flow.width();
|
||||
}
|
||||
@ -601,9 +604,9 @@ void Layer::make_ironing()
|
||||
fill.spacing = ironing_params.line_spacing;
|
||||
fill.angle = float(ironing_params.angle + 0.25 * M_PI);
|
||||
fill.link_max_length = (coord_t)scale_(3. * fill.spacing);
|
||||
double height = ironing_params.height * fill.spacing / nozzle_dmr;
|
||||
Flow flow = Flow::new_from_spacing(float(nozzle_dmr), 0., float(height));
|
||||
double flow_mm3_per_mm = flow.mm3_per_mm();
|
||||
double extrusion_height = ironing_params.height * fill.spacing / nozzle_dmr;
|
||||
float extrusion_width = Flow::rounded_rectangle_extrusion_width_from_spacing(float(nozzle_dmr), float(extrusion_height));
|
||||
double flow_mm3_per_mm = nozzle_dmr * extrusion_height;
|
||||
Surface surface_fill(stTop, ExPolygon());
|
||||
for (ExPolygon &expoly : ironing_areas) {
|
||||
surface_fill.expolygon = std::move(expoly);
|
||||
@ -621,7 +624,7 @@ void Layer::make_ironing()
|
||||
extrusion_entities_append_paths(
|
||||
eec->entities, std::move(polylines),
|
||||
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>
|
||||
|
||||
// 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,58 +136,78 @@ 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.
|
||||
|
@ -51,26 +51,26 @@ public:
|
||||
class Flow
|
||||
{
|
||||
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.
|
||||
// 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.
|
||||
// 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.
|
||||
float nozzle_diameter() const { return m_nozzle_diameter; }
|
||||
float nozzle_diameter() const { return m_nozzle_diameter; }
|
||||
// Is it a bridge?
|
||||
bool bridge() const { return m_bridge; }
|
||||
|
||||
Flow() = default;
|
||||
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))); }
|
||||
bool bridge() const { return m_bridge; }
|
||||
// Cross section area of the extrusion.
|
||||
double mm3_per_mm() const;
|
||||
|
||||
// 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.
|
||||
@ -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; }
|
||||
|
||||
Flow with_width (float width) const { assert(! m_bridge); return Flow(width, m_height, m_nozzle_diameter, m_bridge); }
|
||||
Flow with_height(float height) const { assert(! m_bridge); return Flow(m_width, height, m_nozzle_diameter, m_bridge); }
|
||||
Flow with_width (float width) const {
|
||||
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_from_spacing(float spacing, float nozzle_diameter)
|
||||
{ auto dmr = spacing - float(BRIDGE_EXTRA_SPACING); 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 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
|
||||
// to fit a region with integer number of lines.
|
||||
static Flow new_from_spacing(float spacing, float nozzle_diameter, float height);
|
||||
|
||||
// Spacing of extrusions with rounded extrusion model.
|
||||
static float rounded_rectangle_extrusion_spacing(float width, 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.
|
||||
// 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);
|
||||
|
||||
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_height { 0 };
|
||||
float m_spacing { 0 };
|
||||
float m_nozzle_diameter { 0 };
|
||||
bool m_bridge { false };
|
||||
};
|
||||
|
@ -60,6 +60,7 @@ public:
|
||||
ExtrusionEntityCollection fills;
|
||||
|
||||
Flow flow(FlowRole role) const;
|
||||
Flow flow(FlowRole role, double layer_height) const;
|
||||
Flow bridging_flow(FlowRole role) const;
|
||||
|
||||
void slices_to_fill_surfaces_clipped();
|
||||
|
@ -17,12 +17,29 @@ namespace Slic3r {
|
||||
|
||||
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
|
||||
{
|
||||
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.
|
||||
|
@ -286,7 +286,7 @@ void PerimeterGenerator::process()
|
||||
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_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
|
||||
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.
|
||||
unsigned int extruder(FlowRole role) 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.
|
||||
coordf_t nozzle_dmr_avg(const PrintConfig &print_config) const;
|
||||
// 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];
|
||||
|
||||
// skip bridging in case there are no voids
|
||||
if (region.config().fill_density.value == 100) continue;
|
||||
|
||||
// get bridge flow
|
||||
Flow bridge_flow = region.bridging_flow(frSolidInfill);
|
||||
if (region.config().fill_density.value == 100)
|
||||
continue;
|
||||
|
||||
for (LayerPtrs::iterator layer_it = m_layers.begin(); layer_it != m_layers.end(); ++ layer_it) {
|
||||
// skip first layer
|
||||
if (layer_it == m_layers.begin())
|
||||
continue;
|
||||
|
||||
Layer* layer = *layer_it;
|
||||
LayerRegion* layerm = layer->m_regions[region_id];
|
||||
Layer *layer = *layer_it;
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
Flow bridge_flow = layerm->bridging_flow(frSolidInfill);
|
||||
|
||||
// extract the stInternalSolid surfaces that might be transformed into bridges
|
||||
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));
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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)
|
||||
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.
|
||||
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.
|
||||
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)
|
||||
if (! object->region_volumes[region_id].empty())
|
||||
external_perimeter_width = std::max(external_perimeter_width,
|
||||
(coordf_t)object->print()->get_region(region_id)->flow(*object, frExternalPerimeter, slicing_params.layer_height).width());
|
||||
if (! object->region_volumes[region_id].empty()) {
|
||||
++ num_nonempty_regions;
|
||||
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);
|
||||
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;
|
||||
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,
|
||||
// so we take the largest value and also apply safety offset to be ensure no gaps
|
||||
// are left in between
|
||||
Flow bridge_flow = layerm->bridging_flow(frPerimeter);
|
||||
float w = float(std::max(bridge_flow.scaled_width(), bridge_flow.scaled_spacing()));
|
||||
Flow perimeter_bridge_flow = layerm->bridging_flow(frPerimeter);
|
||||
float w = float(std::max(perimeter_bridge_flow.scaled_width(), perimeter_bridge_flow.scaled_spacing()));
|
||||
for (Polyline &polyline : overhang_perimeters)
|
||||
if (polyline.is_straight()) {
|
||||
// This is a bridge
|
||||
@ -1879,13 +1889,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
||||
layer_new.height = m_slicing_params.soluble_interface ?
|
||||
// Align the interface layer with the object's layer height.
|
||||
object.layers()[layer_id + 1]->height :
|
||||
// Place a bridge flow interface layer over the top surface.
|
||||
//FIXME Check whether the bottom bridging surfaces are extruded correctly (no bridging flow correction applied?)
|
||||
// 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;
|
||||
// Place a bridge flow interface layer or the normal flow interface layer over the top surface.
|
||||
m_support_material_bottom_interface_flow.height();
|
||||
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_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 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);
|
||||
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.
|
||||
interface_spacing = support_spacing;
|
||||
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);
|
||||
if (layer_ex.empty() || layer_ex.polygons_to_extrude().empty())
|
||||
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
|
||||
// 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 ?
|
||||
Flow::bridging_flow(layer_ex.layer->height, m_support_material_interface_flow.nozzle_diameter()) :
|
||||
Flow(interface_as_base ? m_support_material_flow.width() : m_support_material_interface_flow.width(),
|
||||
float(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()) :
|
||||
(interface_as_base ? &m_support_material_flow : &m_support_material_interface_flow)->with_height(float(layer_ex.layer->height));
|
||||
filler_interface->angle = interface_as_base ?
|
||||
// If zero interface layers are configured, use the same angle as for the base layers.
|
||||
angles[support_layer_id % angles.size()] :
|
||||
|
@ -244,6 +244,7 @@ private:
|
||||
Flow m_first_layer_flow;
|
||||
Flow m_support_material_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?
|
||||
bool m_can_merge_support_regions;
|
||||
|
||||
|
@ -16,8 +16,6 @@
|
||||
float nozzle_diameter();
|
||||
bool bridge();
|
||||
float spacing();
|
||||
float spacing_to(Flow* other)
|
||||
%code{% RETVAL = THIS->spacing(*other); %};
|
||||
int scaled_width();
|
||||
int scaled_spacing();
|
||||
double mm3_per_mm();
|
||||
|
Loading…
Reference in New Issue
Block a user