mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-07-31 16:52:01 +08:00
#493 separate bridge fan/speed for overhang from bridge flow for overhangs.
This commit is contained in:
parent
5e65b9416b
commit
c75d4904f9
@ -40,9 +40,9 @@ group:Quality
|
||||
setting:thin_walls_merge
|
||||
end_line
|
||||
group:Overhangs
|
||||
line:On perimeters
|
||||
setting:sidetext_width$1:overhangs
|
||||
setting:width$5:overhangs_width
|
||||
line:threshold for
|
||||
setting:label$bridge speed and fan:width$5:overhangs_width_speed
|
||||
setting:label$bridge flow:width$5:overhangs_width
|
||||
end_line
|
||||
line:Extrusion direction
|
||||
setting:sidetext_width$1:overhangs_reverse
|
||||
|
@ -153,7 +153,7 @@ void Layer::make_perimeters()
|
||||
&& config.infill_dense_algo == other_config.infill_dense_algo
|
||||
&& config.no_perimeter_unsupported_algo == other_config.no_perimeter_unsupported_algo
|
||||
&& config.only_one_perimeter_top == other_config.only_one_perimeter_top
|
||||
&& config.overhangs == other_config.overhangs
|
||||
&& config.overhangs_width_speed == other_config.overhangs_width_speed
|
||||
&& config.overhangs_width == other_config.overhangs_width
|
||||
&& config.overhangs_reverse == other_config.overhangs_reverse
|
||||
&& config.overhangs_reverse_threshold == other_config.overhangs_reverse_threshold
|
||||
|
@ -97,12 +97,16 @@ void PerimeterGenerator::process()
|
||||
coord_t ext_min_spacing = (coord_t)( ext_perimeter_spacing2 * (1 - 0.05/*INSET_OVERLAP_TOLERANCE*/) );
|
||||
|
||||
// prepare grown lower layer slices for overhang detection
|
||||
if (this->lower_slices != NULL && this->config->overhangs) {
|
||||
if (this->lower_slices != NULL && this->config->overhangs_width > 0) {
|
||||
// We consider overhang any part where the entire nozzle diameter is not supported by the
|
||||
// lower layer, so we take lower slices and offset them by half the nozzle diameter used
|
||||
// lower layer, so we take lower slices and offset them by overhangs_width of the nozzle diameter used
|
||||
// in the current layer
|
||||
double offset_val = double(scale_(config->overhangs_width.get_abs_value(nozzle_diameter))) - (float)(ext_perimeter_width / 2);
|
||||
this->_lower_slices_p = offset(*this->lower_slices, offset_val);
|
||||
this->_lower_slices_bridge_flow = offset(*this->lower_slices, offset_val);
|
||||
}
|
||||
if (this->lower_slices != NULL && this->config->overhangs_width_speed > 0) {
|
||||
double offset_val = double(scale_(config->overhangs_width_speed.get_abs_value(nozzle_diameter))) - (float)(ext_perimeter_width / 2);
|
||||
this->_lower_slices_bridge_speed = offset(*this->lower_slices, offset_val);
|
||||
}
|
||||
|
||||
// have to grown the perimeters if mill post-process
|
||||
@ -942,6 +946,69 @@ void PerimeterGenerator::process()
|
||||
} // for each island
|
||||
}
|
||||
|
||||
template<typename LINE>
|
||||
ExtrusionPaths PerimeterGenerator::create_overhangs(LINE loop_polygons, ExtrusionRole role, bool is_external) const {
|
||||
ExtrusionPaths paths;
|
||||
double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->perimeter_extruder - 1);
|
||||
if (this->config->overhangs_width.get_abs_value(nozzle_diameter) > this->config->overhangs_width_speed.get_abs_value(nozzle_diameter)) {
|
||||
// get non-overhang paths by intersecting this loop with the grown lower slices
|
||||
extrusion_paths_append(
|
||||
paths,
|
||||
intersection_pl(loop_polygons, this->_lower_slices_bridge_speed),
|
||||
role,
|
||||
is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm,
|
||||
is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width,
|
||||
(float)this->layer->height);
|
||||
|
||||
// get overhang paths by checking what parts of this loop fall
|
||||
// outside the grown lower slices
|
||||
Polylines poly_speed = diff_pl(loop_polygons, this->_lower_slices_bridge_speed);
|
||||
|
||||
extrusion_paths_append(
|
||||
paths,
|
||||
intersection_pl(poly_speed, this->_lower_slices_bridge_flow),
|
||||
erOverhangPerimeter,
|
||||
is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm,
|
||||
is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width,
|
||||
(float)this->layer->height);
|
||||
|
||||
extrusion_paths_append(
|
||||
paths,
|
||||
diff_pl(poly_speed, this->_lower_slices_bridge_flow),
|
||||
erOverhangPerimeter,
|
||||
this->_mm3_per_mm_overhang,
|
||||
this->overhang_flow.width,
|
||||
this->overhang_flow.height);
|
||||
|
||||
} else {
|
||||
|
||||
// get non-overhang paths by intersecting this loop with the grown lower slices
|
||||
extrusion_paths_append(
|
||||
paths,
|
||||
intersection_pl(loop_polygons, this->_lower_slices_bridge_flow),
|
||||
role,
|
||||
is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm,
|
||||
is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width,
|
||||
(float)this->layer->height);
|
||||
|
||||
// get overhang paths by checking what parts of this loop fall
|
||||
// outside the grown lower slices
|
||||
extrusion_paths_append(
|
||||
paths,
|
||||
diff_pl(loop_polygons, this->_lower_slices_bridge_flow),
|
||||
erOverhangPerimeter,
|
||||
this->_mm3_per_mm_overhang,
|
||||
this->overhang_flow.width,
|
||||
this->overhang_flow.height);
|
||||
}
|
||||
|
||||
// reapply the nearest point search for starting point
|
||||
// We allow polyline reversal because Clipper may have randomly reversed polylines during clipping.
|
||||
if(!paths.empty())
|
||||
chain_and_reorder_extrusion_paths(paths, &paths.front().first_point());
|
||||
return paths;
|
||||
}
|
||||
|
||||
ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
|
||||
const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls) const
|
||||
{
|
||||
@ -971,31 +1038,9 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
|
||||
|
||||
// detect overhanging/bridging perimeters
|
||||
ExtrusionPaths paths;
|
||||
if (this->config->overhangs && this->layer->id() > 0
|
||||
if ( this->config->overhangs_width_speed > 0 && this->layer->id() > 0
|
||||
&& !(this->object_config->support_material && this->object_config->support_material_contact_distance_type.value == zdNone)) {
|
||||
// get non-overhang paths by intersecting this loop with the grown lower slices
|
||||
extrusion_paths_append(
|
||||
paths,
|
||||
intersection_pl(loop.polygon, this->_lower_slices_p),
|
||||
role,
|
||||
is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm,
|
||||
is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width,
|
||||
(float) this->layer->height);
|
||||
|
||||
// get overhang paths by checking what parts of this loop fall
|
||||
// outside the grown lower slices (thus where the distance between
|
||||
// the loop centerline and original lower slices is >= half nozzle diameter
|
||||
extrusion_paths_append(
|
||||
paths,
|
||||
diff_pl(loop.polygon, this->_lower_slices_p),
|
||||
erOverhangPerimeter,
|
||||
this->_mm3_per_mm_overhang,
|
||||
this->overhang_flow.width,
|
||||
this->overhang_flow.height);
|
||||
|
||||
// reapply the nearest point search for starting point
|
||||
// We allow polyline reversal because Clipper may have randomly reversed polylines during clipping.
|
||||
chain_and_reorder_extrusion_paths(paths, &paths.front().first_point());
|
||||
paths = this->create_overhangs(loop.polygon, role, is_external);
|
||||
} else {
|
||||
ExtrusionPath path(role);
|
||||
path.polyline = loop.polygon.split_at_first_point();
|
||||
@ -1423,35 +1468,9 @@ PerimeterGenerator::_extrude_and_cut_loop(const PerimeterGeneratorLoop &loop, co
|
||||
}
|
||||
|
||||
// detect overhanging/bridging perimeters
|
||||
if (this->config->overhangs && this->layer->id() > 0
|
||||
if ( this->config->overhangs_width_speed > 0 && this->layer->id() > 0
|
||||
&& !(this->object_config->support_material && this->object_config->support_material_contact_distance_type.value == zdNone)) {
|
||||
ExtrusionPaths paths;
|
||||
// get non-overhang paths by intersecting this loop with the grown lower slices
|
||||
extrusion_paths_append(
|
||||
paths,
|
||||
intersection_pl(initial_polyline, this->_lower_slices_p),
|
||||
role,
|
||||
is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm,
|
||||
is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width,
|
||||
(float) this->layer->height);
|
||||
|
||||
// get overhang paths by checking what parts of this loop fall
|
||||
// outside the grown lower slices (thus where the distance between
|
||||
// the loop centerline and original lower slices is >= half nozzle diameter
|
||||
extrusion_paths_append(
|
||||
paths,
|
||||
diff_pl(initial_polyline, this->_lower_slices_p),
|
||||
erOverhangPerimeter,
|
||||
this->_mm3_per_mm_overhang,
|
||||
this->overhang_flow.width,
|
||||
this->overhang_flow.height);
|
||||
|
||||
// reapply the nearest point search for starting point
|
||||
// We allow polyline reversal because Clipper may have randomly
|
||||
// reversed polylines during clipping.
|
||||
if (!paths.empty())
|
||||
chain_and_reorder_extrusion_paths(paths, &paths.front().first_point());
|
||||
|
||||
ExtrusionPaths paths = this->create_overhangs(initial_polyline, role, is_external);
|
||||
|
||||
if (direction.length() > 0) {
|
||||
Polyline direction_polyline;
|
||||
|
@ -96,7 +96,11 @@ private:
|
||||
double _ext_mm3_per_mm;
|
||||
double _mm3_per_mm;
|
||||
double _mm3_per_mm_overhang;
|
||||
Polygons _lower_slices_p;
|
||||
Polygons _lower_slices_bridge_flow;
|
||||
Polygons _lower_slices_bridge_speed;
|
||||
|
||||
template<typename LINE>
|
||||
ExtrusionPaths create_overhangs(LINE loop_polygons, ExtrusionRole role, bool is_external) const;
|
||||
|
||||
// transform loops into ExtrusionEntityCollection, adding also thin walls into it.
|
||||
ExtrusionEntityCollection _traverse_loops(const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls) const;
|
||||
|
@ -2345,23 +2345,29 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionString("[input_filename_base].gcode"));
|
||||
|
||||
def = this->add("overhangs", coBool);
|
||||
def->label = L("As bridge");
|
||||
def->full_label = L("Overhangs as bridge");
|
||||
def = this->add("overhangs_width_speed", coFloatOrPercent);
|
||||
def->label = L("'As bridge' speed threshold");
|
||||
def->full_label = L("Overhang bridge speed threshold");
|
||||
def->category = OptionCategory::perimeter;
|
||||
def->tooltip = L("Option to adjust flow for overhangs (bridge flow will be used), "
|
||||
"to apply bridge speed to them and enable fan.");
|
||||
def->tooltip = L("Minimum unsupported width for an extrusion to apply the bridge speed & fan to this overhang."
|
||||
" Can be in mm or in a % of the nozzle diameter."
|
||||
" Set to 0 to deactivate.");
|
||||
def->ratio_over = "nozzle_diameter";
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(50,true));
|
||||
|
||||
def = this->add("overhangs_width", coFloatOrPercent);
|
||||
def->label = L("'As bridge' threshold");
|
||||
def->full_label = L("Overhang bridge threshold");
|
||||
def->label = L("'As bridge' flow threshold");
|
||||
def->full_label = L("Overhang bridge flow threshold");
|
||||
def->category = OptionCategory::perimeter;
|
||||
def->tooltip = L("Minimum unsupported width for an extrusion to be considered an overhang. Can be in mm or in a % of the nozzle diameter.");
|
||||
def->tooltip = L("Minimum unsupported width for an extrusion to apply the bridge flow to this overhang."
|
||||
" Can be in mm or in a % of the nozzle diameter."
|
||||
" Set to 0 to deactivate.");
|
||||
def->ratio_over = "nozzle_diameter";
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(50, true));
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(75, true));
|
||||
|
||||
def = this->add("overhangs_reverse", coBool);
|
||||
def->label = L("Reverse on odd");
|
||||
@ -4629,6 +4635,12 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
||||
value = "notconnected";
|
||||
else
|
||||
value = "connected";
|
||||
} else if (opt_key == "overhangs") {
|
||||
opt_key = "overhangs_width_speed";
|
||||
if (value == "1")
|
||||
value = "50%";
|
||||
else
|
||||
value = "0";
|
||||
}
|
||||
|
||||
// Ignore the following obsolete configuration keys:
|
||||
|
@ -694,8 +694,8 @@ public:
|
||||
ConfigOptionFloat milling_speed;
|
||||
ConfigOptionFloatOrPercent min_width_top_surface;
|
||||
// Detect bridging perimeters
|
||||
ConfigOptionBool overhangs;
|
||||
ConfigOptionFloatOrPercent overhangs_width;
|
||||
ConfigOptionFloatOrPercent overhangs_width_speed;
|
||||
ConfigOptionBool overhangs_reverse;
|
||||
ConfigOptionFloatOrPercent overhangs_reverse_threshold;
|
||||
ConfigOptionEnum<NoPerimeterUnsupportedAlgo> no_perimeter_unsupported_algo;
|
||||
@ -786,8 +786,8 @@ protected:
|
||||
OPT_PTR(milling_post_process);
|
||||
OPT_PTR(milling_speed);
|
||||
OPT_PTR(min_width_top_surface);
|
||||
OPT_PTR(overhangs);
|
||||
OPT_PTR(overhangs_width);
|
||||
OPT_PTR(overhangs_width_speed);
|
||||
OPT_PTR(overhangs_reverse);
|
||||
OPT_PTR(overhangs_reverse_threshold);
|
||||
OPT_PTR(no_perimeter_unsupported_algo);
|
||||
|
@ -614,7 +614,7 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
||||
opt_key == "gap_fill"
|
||||
|| opt_key == "gap_fill_min_area"
|
||||
|| opt_key == "only_one_perimeter_top"
|
||||
|| opt_key == "overhangs"
|
||||
|| opt_key == "overhangs_width_speed"
|
||||
|| opt_key == "overhangs_width"
|
||||
|| opt_key == "overhangs_reverse"
|
||||
|| opt_key == "overhangs_reverse_threshold"
|
||||
|
@ -2130,7 +2130,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
|
||||
polygons_append(polygons_trimming,
|
||||
offset(to_expolygons(region->fill_surfaces.filter_by_type(stPosBottom | stDensSolid | stModBridge)),
|
||||
gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
if (region->region()->config().overhangs.value)
|
||||
if (region->region()->config().overhangs_width.value > 0)
|
||||
SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters.entities, gap_xy_scaled, polygons_trimming);
|
||||
}
|
||||
if (! some_region_overlaps)
|
||||
|
@ -210,7 +210,7 @@ void CalibrationRetractionDialog::create_geometry(wxCommandEvent& event_args) {
|
||||
model.objects[objs_idx[i]]->config.set_key_value("fill_density", new ConfigOptionPercent(0));
|
||||
//model.objects[objs_idx[i]]->config.set_key_value("fill_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinear));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("only_one_perimeter_top", new ConfigOptionBool(false));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("overhangs", new ConfigOptionBool(false));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("overhangs_width_speed", new ConfigOptionFloatOrPercent(0,false));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("thin_walls", new ConfigOptionBool(true));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("thin_walls_min_width", new ConfigOptionFloatOrPercent(2,true));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("gap_fill", new ConfigOptionBool(false));
|
||||
|
@ -276,9 +276,9 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
||||
// Ask only once.
|
||||
if (!support_material_overhangs_queried) {
|
||||
support_material_overhangs_queried = true;
|
||||
if (!config->opt_bool("overhangs")/* != 1*/) {
|
||||
if (config->option<ConfigOptionFloatOrPercent>("overhangs_width_speed") == 0) {
|
||||
wxString msg_text = _(L("Supports work better, if the following feature is enabled:\n"
|
||||
"- Detect bridging perimeters"));
|
||||
"- overhangs with bridge speed & fan"));
|
||||
if (is_global_config) {
|
||||
msg_text += "\n\n" + _(L("Shall I adjust those settings for supports?"));
|
||||
wxMessageDialog dialog(nullptr, msg_text, _(L("Support Generator")),
|
||||
@ -287,7 +287,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
||||
auto answer = dialog.ShowModal();
|
||||
if (!is_global_config || answer == wxID_YES) {
|
||||
// Enable "detect bridging perimeters".
|
||||
new_conf.set_key_value("overhangs", new ConfigOptionBool(true));
|
||||
new_conf.set_key_value("overhangs_width_speed", new ConfigOptionFloatOrPercent(50, true));
|
||||
} else if (answer == wxID_NO) {
|
||||
// Do nothing, leave supports on and "detect bridging perimeters" off.
|
||||
} else if (answer == wxID_CANCEL) {
|
||||
@ -362,7 +362,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
||||
"perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "perimeter_loop", "perimeter_loop_seam" })
|
||||
toggle_field(el, have_perimeters);
|
||||
|
||||
toggle_field("overhangs_width", config->opt_bool("overhangs"));
|
||||
toggle_field("overhangs_width", config->option<ConfigOptionFloatOrPercent>("overhangs_width_speed")->value > 0);
|
||||
toggle_field("overhangs_reverse_threshold", config->opt_bool("overhangs_reverse"));
|
||||
toggle_field("min_width_top_surface", config->opt_bool("only_one_perimeter_top"));
|
||||
toggle_field("thin_perimeters_all", config->opt_bool("thin_perimeters"));
|
||||
|
@ -439,8 +439,9 @@ const std::vector<std::string>& Preset::print_options()
|
||||
"avoid_crossing_perimeters",
|
||||
"avoid_crossing_not_first_layer",
|
||||
"thin_perimeters", "thin_perimeters_all",
|
||||
"thin_walls", "overhangs",
|
||||
"thin_walls",
|
||||
"overhangs_width",
|
||||
"overhangs_width_speed",
|
||||
"overhangs_reverse",
|
||||
"overhangs_reverse_threshold",
|
||||
"seam_position",
|
||||
|
Loading…
x
Reference in New Issue
Block a user