Add two parameters for infill speed limiting.

One for infills that cross itself and one for the others.
This commit is contained in:
Martin Šach 2024-06-10 12:25:03 +02:00 committed by Lukas Matena
parent 0e175136cf
commit 2b667ffb6b
19 changed files with 71 additions and 12 deletions

View File

@ -134,9 +134,12 @@ struct ExtrusionAttributes : ExtrusionFlow
ExtrusionAttributes(ExtrusionRole role) : role{ role } {}
ExtrusionAttributes(ExtrusionRole role, const Flow &flow) : role{ role }, ExtrusionFlow{ flow } {}
ExtrusionAttributes(ExtrusionRole role, const ExtrusionFlow &flow) : role{ role }, ExtrusionFlow{ flow } {}
ExtrusionAttributes(ExtrusionRole role, const ExtrusionFlow &flow, const bool maybe_self_crossing)
: role{role}, ExtrusionFlow{flow}, maybe_self_crossing(maybe_self_crossing) {}
// What is the role / purpose of this extrusion?
ExtrusionRole role{ ExtrusionRole::None };
bool maybe_self_crossing{false};
// OVerhangAttributes are currently computed for perimeters if dynamic overhangs are enabled.
// They are used to control fan and print speed in export.
std::optional<OverhangAttributes> overhang_attributes;

View File

@ -573,8 +573,10 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
// When prefer_clockwise_movements is true, we have to ensure that extrusion paths will not be reversed during path planning.
extrusion_entities_append_paths(
eec->entities, std::move(polylines),
ExtrusionAttributes{ surface_fill.params.extrusion_role,
ExtrusionFlow{ flow_mm3_per_mm, float(flow_width), surface_fill.params.flow.height() }
ExtrusionAttributes{
surface_fill.params.extrusion_role,
ExtrusionFlow{ flow_mm3_per_mm, float(flow_width), surface_fill.params.flow.height() },
f->is_self_crossing()
}, !params.prefer_clockwise_movements);
layerm.m_fills.entities.push_back(eec);
}

View File

@ -22,6 +22,7 @@ public:
// require bridge flow since most of this pattern hangs in air
bool use_bridge_flow() const override { return true; }
bool is_self_crossing() override { return false; }
protected:
void _fill_surface_single(

View File

@ -75,6 +75,7 @@ protected:
// may not be optimal as the internal infill lines may get extruded before the long infill
// lines to which the short infill lines are supposed to anchor.
bool no_sort() const override { return false; }
bool is_self_crossing() override { return true; }
};
} // namespace FillAdaptive

View File

@ -123,6 +123,8 @@ public:
// Do not sort the fill lines to optimize the print head path?
virtual bool no_sort() const { return false; }
virtual bool is_self_crossing() = 0;
// Perform the fill.
virtual Polylines fill_surface(const Surface *surface, const FillParams &params);
virtual ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams &params);

View File

@ -19,6 +19,7 @@ class FillConcentric : public Fill
{
public:
~FillConcentric() override = default;
bool is_self_crossing() override { return false; }
protected:
Fill* clone() const override { return new FillConcentric(*this); };

View File

@ -23,6 +23,7 @@ public:
{
return make_fill_polylines(this, surface, params, true, true, true);
};
bool is_self_crossing() override { return false; }
protected:
void fill_surface_single_arachne(const Surface &surface, const FillParams &params, ThickPolylines &thick_polylines_out);

View File

@ -20,6 +20,7 @@ public:
// require bridge flow since most of this pattern hangs in air
bool use_bridge_flow() const override { return false; }
bool is_self_crossing() override { return false; }
// Correction applied to regular infill angle to maximize printing
// speed in default configuration (degrees)

View File

@ -22,6 +22,7 @@ class FillHoneycomb : public Fill
{
public:
~FillHoneycomb() override {}
bool is_self_crossing() override { return false; }
protected:
Fill* clone() const override { return new FillHoneycomb(*this); };

View File

@ -24,8 +24,10 @@ class Filler : public Slic3r::Fill
{
public:
~Filler() override = default;
bool is_self_crossing() override { return false; }
Generator *generator { nullptr };
protected:
Fill* clone() const override { return new Filler(*this); }

View File

@ -19,6 +19,7 @@ class FillLine : public Fill
public:
Fill* clone() const override { return new FillLine(*this); };
~FillLine() override = default;
bool is_self_crossing() override { return false; }
protected:
void _fill_surface_single(

View File

@ -26,6 +26,7 @@ class FillPlanePath : public Fill
{
public:
~FillPlanePath() override = default;
bool is_self_crossing() override { return false; }
protected:
void _fill_surface_single(

View File

@ -26,6 +26,7 @@ public:
Fill* clone() const override { return new FillRectilinear(*this); }
~FillRectilinear() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override;
bool is_self_crossing() override { return false; }
protected:
// Fill by single directional lines, interconnect the lines along perimeters.
@ -75,6 +76,7 @@ public:
Fill* clone() const override { return new FillGrid(*this); }
~FillGrid() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override;
bool is_self_crossing() override { return true; }
protected:
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
@ -87,6 +89,7 @@ public:
Fill* clone() const override { return new FillTriangles(*this); }
~FillTriangles() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override;
bool is_self_crossing() override { return true; }
protected:
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
@ -99,6 +102,7 @@ public:
Fill* clone() const override { return new FillStars(*this); }
~FillStars() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override;
bool is_self_crossing() override { return true; }
protected:
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
@ -111,6 +115,7 @@ public:
Fill* clone() const override { return new FillCubic(*this); }
~FillCubic() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override;
bool is_self_crossing() override { return true; }
protected:
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.

View File

@ -3270,16 +3270,26 @@ std::string GCodeGenerator::travel_to_first_position(const Vec3crd& point, const
}
double cap_speed(
double speed, const double mm3_per_mm, const FullPrintConfig &config, int extruder_id
double speed, const FullPrintConfig &config, int extruder_id, const ExtrusionAttributes &path_attr
) {
const double general_cap{config.max_volumetric_speed.value};
if (general_cap > 0) {
speed = std::min(speed, general_cap / mm3_per_mm);
const double general_volumetric_cap{config.max_volumetric_speed.value};
if (general_volumetric_cap > 0) {
speed = std::min(speed, general_volumetric_cap / path_attr.mm3_per_mm);
}
const double filament_cap{config.filament_max_volumetric_speed.get_at(extruder_id)};
if (filament_cap > 0) {
speed = std::min(speed, filament_cap / mm3_per_mm);
const double filament_volumetric_cap{config.filament_max_volumetric_speed.get_at(extruder_id)};
if (filament_volumetric_cap > 0) {
speed = std::min(speed, filament_volumetric_cap / path_attr.mm3_per_mm);
}
if (path_attr.role == ExtrusionRole::InternalInfill) {
const double infill_cap{
path_attr.maybe_self_crossing ?
config.filament_infill_max_crossing_speed.get_at(extruder_id) :
config.filament_infill_max_speed.get_at(extruder_id)};
if (infill_cap > 0) {
speed = std::min(speed, infill_cap);
}
}
return speed;
}
@ -3411,7 +3421,7 @@ std::string GCodeGenerator::_extrude(
if (external_perim_reference_speed == 0)
external_perim_reference_speed = m_volumetric_speed / path_attr.mm3_per_mm;
external_perim_reference_speed = cap_speed(
external_perim_reference_speed, path_attr.mm3_per_mm, m_config, m_writer.extruder()->id()
external_perim_reference_speed, m_config, m_writer.extruder()->id(), path_attr
);
dynamic_speed_and_fan_speed = ExtrusionProcessor::calculate_overhang_speed(path_attr, this->m_config, m_writer.extruder()->id(),
@ -3423,7 +3433,7 @@ std::string GCodeGenerator::_extrude(
}
// cap speed with max_volumetric_speed anyway (even if user is not using autospeed)
speed = cap_speed(speed, path_attr.mm3_per_mm, m_config, m_writer.extruder()->id());
speed = cap_speed(speed, m_config, m_writer.extruder()->id(), path_attr);
double F = speed * 60; // convert mm/sec to mm/min

View File

@ -486,7 +486,7 @@ static std::vector<std::string> s_Preset_print_options {
};
static std::vector<std::string> s_Preset_filament_options {
"filament_colour", "filament_diameter", "filament_type", "filament_soluble", "filament_notes", "filament_max_volumetric_speed",
"filament_colour", "filament_diameter", "filament_type", "filament_soluble", "filament_notes", "filament_max_volumetric_speed", "filament_infill_max_speed", "filament_infill_max_crossing_speed",
"extrusion_multiplier", "filament_density", "filament_cost", "filament_spool_weight", "filament_loading_speed", "filament_loading_speed_start", "filament_load_time",
"filament_unloading_speed", "filament_unloading_speed_start", "filament_unload_time", "filament_toolchange_delay", "filament_cooling_moves", "filament_stamping_loading_speed", "filament_stamping_distance",
"filament_cooling_initial_speed", "filament_purge_multiplier", "filament_cooling_final_speed", "filament_ramming_parameters", "filament_minimal_purge_on_wipe_tower",

View File

@ -235,6 +235,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "filament_multitool_ramming_volume"
|| opt_key == "filament_multitool_ramming_flow"
|| opt_key == "filament_max_volumetric_speed"
|| opt_key == "filament_infill_max_speed"
|| opt_key == "filament_infill_max_crossing_speed"
|| opt_key == "gcode_flavor"
|| opt_key == "high_current_on_filament_swap"
|| opt_key == "infill_first"

View File

@ -1137,6 +1137,26 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloats { 0. });
def = this->add("filament_infill_max_speed", coFloats);
def->label = L("Max simple infill speed");
def->tooltip = L("Maximum speed allowed for this filament while printing simple infill. "
"The term \"simple infill\" means infill without any self intersections in a single layer. "
"Set to zero for no limit.");
def->sidetext = L("mm/s");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloats { 0. });
def = this->add("filament_infill_max_crossing_speed", coFloats);
def->label = L("Max crossing infill speed");
def->tooltip = L("Maximum speed allowed for this filament while printing crossing infill. "
"The term \"crossing infill\" means infill with self intersections in a single layer. "
"Set to zero for no limit.");
def->sidetext = L("mm/s");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloats { 0. });
def = this->add("filament_loading_speed", coFloats);
def->label = L("Loading speed");
def->tooltip = L("Speed used for loading the filament on the wipe tower.");

View File

@ -762,6 +762,8 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloats, filament_cost))
((ConfigOptionFloats, filament_spool_weight))
((ConfigOptionFloats, filament_max_volumetric_speed))
((ConfigOptionFloats, filament_infill_max_speed))
((ConfigOptionFloats, filament_infill_max_crossing_speed))
((ConfigOptionFloats, filament_loading_speed))
((ConfigOptionFloats, filament_loading_speed_start))
((ConfigOptionFloats, filament_load_time))

View File

@ -2238,6 +2238,9 @@ void TabFilament::build()
};
optgroup->append_line(line);
optgroup->append_single_option_line("filament_infill_max_speed", "max-simple-infill-speed");
optgroup->append_single_option_line("filament_infill_max_crossing_speed", "max-crossing-infill-speed");
optgroup = page->new_optgroup(L("Shrinkage compensation"));
optgroup->append_single_option_line("filament_shrinkage_compensation_xy");
optgroup->append_single_option_line("filament_shrinkage_compensation_z");