mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-31 20:12:02 +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) : role{ role } {}
|
||||||
ExtrusionAttributes(ExtrusionRole role, const Flow &flow) : role{ role }, ExtrusionFlow{ flow } {}
|
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) : 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?
|
// What is the role / purpose of this extrusion?
|
||||||
ExtrusionRole role{ ExtrusionRole::None };
|
ExtrusionRole role{ ExtrusionRole::None };
|
||||||
|
bool maybe_self_crossing{false};
|
||||||
// OVerhangAttributes are currently computed for perimeters if dynamic overhangs are enabled.
|
// OVerhangAttributes are currently computed for perimeters if dynamic overhangs are enabled.
|
||||||
// They are used to control fan and print speed in export.
|
// They are used to control fan and print speed in export.
|
||||||
std::optional<OverhangAttributes> overhang_attributes;
|
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.
|
// When prefer_clockwise_movements is true, we have to ensure that extrusion paths will not be reversed during path planning.
|
||||||
extrusion_entities_append_paths(
|
extrusion_entities_append_paths(
|
||||||
eec->entities, std::move(polylines),
|
eec->entities, std::move(polylines),
|
||||||
ExtrusionAttributes{ surface_fill.params.extrusion_role,
|
ExtrusionAttributes{
|
||||||
ExtrusionFlow{ flow_mm3_per_mm, float(flow_width), surface_fill.params.flow.height() }
|
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);
|
}, !params.prefer_clockwise_movements);
|
||||||
layerm.m_fills.entities.push_back(eec);
|
layerm.m_fills.entities.push_back(eec);
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ public:
|
|||||||
|
|
||||||
// require bridge flow since most of this pattern hangs in air
|
// require bridge flow since most of this pattern hangs in air
|
||||||
bool use_bridge_flow() const override { return true; }
|
bool use_bridge_flow() const override { return true; }
|
||||||
|
bool is_self_crossing() override { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _fill_surface_single(
|
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
|
// 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.
|
// lines to which the short infill lines are supposed to anchor.
|
||||||
bool no_sort() const override { return false; }
|
bool no_sort() const override { return false; }
|
||||||
|
bool is_self_crossing() override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace FillAdaptive
|
} // namespace FillAdaptive
|
||||||
|
@ -123,6 +123,8 @@ public:
|
|||||||
// Do not sort the fill lines to optimize the print head path?
|
// Do not sort the fill lines to optimize the print head path?
|
||||||
virtual bool no_sort() const { return false; }
|
virtual bool no_sort() const { return false; }
|
||||||
|
|
||||||
|
virtual bool is_self_crossing() = 0;
|
||||||
|
|
||||||
// Perform the fill.
|
// Perform the fill.
|
||||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
||||||
virtual ThickPolylines fill_surface_arachne(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:
|
public:
|
||||||
~FillConcentric() override = default;
|
~FillConcentric() override = default;
|
||||||
|
bool is_self_crossing() override { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Fill* clone() const override { return new FillConcentric(*this); };
|
Fill* clone() const override { return new FillConcentric(*this); };
|
||||||
|
@ -23,6 +23,7 @@ public:
|
|||||||
{
|
{
|
||||||
return make_fill_polylines(this, surface, params, true, true, true);
|
return make_fill_polylines(this, surface, params, true, true, true);
|
||||||
};
|
};
|
||||||
|
bool is_self_crossing() override { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void fill_surface_single_arachne(const Surface &surface, const FillParams ¶ms, ThickPolylines &thick_polylines_out);
|
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
|
// require bridge flow since most of this pattern hangs in air
|
||||||
bool use_bridge_flow() const override { return false; }
|
bool use_bridge_flow() const override { return false; }
|
||||||
|
bool is_self_crossing() override { return false; }
|
||||||
|
|
||||||
// Correction applied to regular infill angle to maximize printing
|
// Correction applied to regular infill angle to maximize printing
|
||||||
// speed in default configuration (degrees)
|
// speed in default configuration (degrees)
|
||||||
|
@ -22,6 +22,7 @@ class FillHoneycomb : public Fill
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~FillHoneycomb() override {}
|
~FillHoneycomb() override {}
|
||||||
|
bool is_self_crossing() override { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Fill* clone() const override { return new FillHoneycomb(*this); };
|
Fill* clone() const override { return new FillHoneycomb(*this); };
|
||||||
|
@ -24,8 +24,10 @@ class Filler : public Slic3r::Fill
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~Filler() override = default;
|
~Filler() override = default;
|
||||||
|
bool is_self_crossing() override { return false; }
|
||||||
|
|
||||||
Generator *generator { nullptr };
|
Generator *generator { nullptr };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Fill* clone() const override { return new Filler(*this); }
|
Fill* clone() const override { return new Filler(*this); }
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ class FillLine : public Fill
|
|||||||
public:
|
public:
|
||||||
Fill* clone() const override { return new FillLine(*this); };
|
Fill* clone() const override { return new FillLine(*this); };
|
||||||
~FillLine() override = default;
|
~FillLine() override = default;
|
||||||
|
bool is_self_crossing() override { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _fill_surface_single(
|
void _fill_surface_single(
|
||||||
|
@ -26,6 +26,7 @@ class FillPlanePath : public Fill
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~FillPlanePath() override = default;
|
~FillPlanePath() override = default;
|
||||||
|
bool is_self_crossing() override { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _fill_surface_single(
|
void _fill_surface_single(
|
||||||
|
@ -26,6 +26,7 @@ public:
|
|||||||
Fill* clone() const override { return new FillRectilinear(*this); }
|
Fill* clone() const override { return new FillRectilinear(*this); }
|
||||||
~FillRectilinear() override = default;
|
~FillRectilinear() override = default;
|
||||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||||
|
bool is_self_crossing() override { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Fill by single directional lines, interconnect the lines along perimeters.
|
// Fill by single directional lines, interconnect the lines along perimeters.
|
||||||
@ -75,6 +76,7 @@ public:
|
|||||||
Fill* clone() const override { return new FillGrid(*this); }
|
Fill* clone() const override { return new FillGrid(*this); }
|
||||||
~FillGrid() override = default;
|
~FillGrid() override = default;
|
||||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||||
|
bool is_self_crossing() override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
// 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); }
|
Fill* clone() const override { return new FillTriangles(*this); }
|
||||||
~FillTriangles() override = default;
|
~FillTriangles() override = default;
|
||||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||||
|
bool is_self_crossing() override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
// 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); }
|
Fill* clone() const override { return new FillStars(*this); }
|
||||||
~FillStars() override = default;
|
~FillStars() override = default;
|
||||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||||
|
bool is_self_crossing() override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
// 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); }
|
Fill* clone() const override { return new FillCubic(*this); }
|
||||||
~FillCubic() override = default;
|
~FillCubic() override = default;
|
||||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||||
|
bool is_self_crossing() override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
// 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 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};
|
const double general_volumetric_cap{config.max_volumetric_speed.value};
|
||||||
if (general_cap > 0) {
|
if (general_volumetric_cap > 0) {
|
||||||
speed = std::min(speed, general_cap / mm3_per_mm);
|
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)};
|
const double filament_volumetric_cap{config.filament_max_volumetric_speed.get_at(extruder_id)};
|
||||||
if (filament_cap > 0) {
|
if (filament_volumetric_cap > 0) {
|
||||||
speed = std::min(speed, filament_cap / mm3_per_mm);
|
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;
|
return speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3411,7 +3421,7 @@ std::string GCodeGenerator::_extrude(
|
|||||||
if (external_perim_reference_speed == 0)
|
if (external_perim_reference_speed == 0)
|
||||||
external_perim_reference_speed = m_volumetric_speed / path_attr.mm3_per_mm;
|
external_perim_reference_speed = m_volumetric_speed / path_attr.mm3_per_mm;
|
||||||
external_perim_reference_speed = cap_speed(
|
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(),
|
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)
|
// 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
|
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 {
|
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",
|
"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_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",
|
"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_volume"
|
||||||
|| opt_key == "filament_multitool_ramming_flow"
|
|| opt_key == "filament_multitool_ramming_flow"
|
||||||
|| opt_key == "filament_max_volumetric_speed"
|
|| 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 == "gcode_flavor"
|
||||||
|| opt_key == "high_current_on_filament_swap"
|
|| opt_key == "high_current_on_filament_swap"
|
||||||
|| opt_key == "infill_first"
|
|| opt_key == "infill_first"
|
||||||
|
@ -1137,6 +1137,26 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloats { 0. });
|
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 = this->add("filament_loading_speed", coFloats);
|
||||||
def->label = L("Loading speed");
|
def->label = L("Loading speed");
|
||||||
def->tooltip = L("Speed used for loading the filament on the wipe tower.");
|
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_cost))
|
||||||
((ConfigOptionFloats, filament_spool_weight))
|
((ConfigOptionFloats, filament_spool_weight))
|
||||||
((ConfigOptionFloats, filament_max_volumetric_speed))
|
((ConfigOptionFloats, filament_max_volumetric_speed))
|
||||||
|
((ConfigOptionFloats, filament_infill_max_speed))
|
||||||
|
((ConfigOptionFloats, filament_infill_max_crossing_speed))
|
||||||
((ConfigOptionFloats, filament_loading_speed))
|
((ConfigOptionFloats, filament_loading_speed))
|
||||||
((ConfigOptionFloats, filament_loading_speed_start))
|
((ConfigOptionFloats, filament_loading_speed_start))
|
||||||
((ConfigOptionFloats, filament_load_time))
|
((ConfigOptionFloats, filament_load_time))
|
||||||
|
@ -2238,6 +2238,9 @@ void TabFilament::build()
|
|||||||
};
|
};
|
||||||
optgroup->append_line(line);
|
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 = page->new_optgroup(L("Shrinkage compensation"));
|
||||||
optgroup->append_single_option_line("filament_shrinkage_compensation_xy");
|
optgroup->append_single_option_line("filament_shrinkage_compensation_xy");
|
||||||
optgroup->append_single_option_line("filament_shrinkage_compensation_z");
|
optgroup->append_single_option_line("filament_shrinkage_compensation_z");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user