mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-30 22:42:03 +08:00
Add two parameters for infill speed limiting.
One for infills that cross itself and one for the others.
This commit is contained in:
parent
0e175136cf
commit
2b667ffb6b
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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 ¶ms);
|
||||
virtual ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams ¶ms);
|
||||
|
@ -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); };
|
||||
|
@ -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 ¶ms, ThickPolylines &thick_polylines_out);
|
||||
|
@ -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)
|
||||
|
@ -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); };
|
||||
|
@ -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); }
|
||||
|
||||
|
@ -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(
|
||||
|
@ -26,6 +26,7 @@ class FillPlanePath : public Fill
|
||||
{
|
||||
public:
|
||||
~FillPlanePath() override = default;
|
||||
bool is_self_crossing() override { return false; }
|
||||
|
||||
protected:
|
||||
void _fill_surface_single(
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
Fill* clone() const override { return new FillRectilinear(*this); }
|
||||
~FillRectilinear() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) 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 ¶ms) 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 ¶ms) 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 ¶ms) 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 ¶ms) 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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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"
|
||||
|
@ -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.");
|
||||
|
@ -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))
|
||||
|
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user