diff --git a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp index 1839afc16df..22ca7def4f4 100644 --- a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp +++ b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp @@ -265,17 +265,17 @@ double ExtrusionLine::area() const } // namespace Slic3r::Arachne namespace Slic3r { -void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow) +void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow, float max_width) { for (const ClipperLib_Z::Path &extrusion_path : extrusion_paths) { ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion_path); - Slic3r::append(dst, PerimeterGenerator::thick_polyline_to_multi_path(thick_polyline, role, flow, scaled(0.05), float(SCALED_EPSILON)).paths); + Slic3r::append(dst, PerimeterGenerator::thick_polyline_to_multi_path(thick_polyline, role, flow, scaled(0.05), float(SCALED_EPSILON), max_width).paths); } } -void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow) +void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow, float max_width) { ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion); - Slic3r::append(dst, PerimeterGenerator::thick_polyline_to_multi_path(thick_polyline, role, flow, scaled(0.05), float(SCALED_EPSILON)).paths); + Slic3r::append(dst, PerimeterGenerator::thick_polyline_to_multi_path(thick_polyline, role, flow, scaled(0.05), float(SCALED_EPSILON), max_width).paths); } } // namespace Slic3r diff --git a/src/libslic3r/Arachne/utils/ExtrusionLine.hpp b/src/libslic3r/Arachne/utils/ExtrusionLine.hpp index d39e1e07b9c..c1d792cc011 100644 --- a/src/libslic3r/Arachne/utils/ExtrusionLine.hpp +++ b/src/libslic3r/Arachne/utils/ExtrusionLine.hpp @@ -298,8 +298,8 @@ using VariableWidthLines = std::vector; //spacing)); - ExtrusionMultiPath multi_path = PerimeterGenerator::thick_polyline_to_multi_path(thick_polyline, surface_fill.params.extrusion_role, new_flow, scaled(0.05), float(SCALED_EPSILON)); + assert(!this->object()->print()->config().nozzle_diameter.empty()); + float min_nozzle_diameter = float(*std::min_element(this->object()->print()->config().nozzle_diameter.values.begin(), this->object()->print()->config().nozzle_diameter.values.end())); + float max_bead_width = this->object()->config().max_bead_width.value; + if (const auto &max_bead_width_opt = this->object()->config().max_bead_width; max_bead_width_opt.percent) + max_bead_width = (max_bead_width_opt.value * 0.01 * min_nozzle_diameter); + + ExtrusionMultiPath multi_path = PerimeterGenerator::thick_polyline_to_multi_path(thick_polyline, surface_fill.params.extrusion_role, new_flow, scaled(0.05), float(SCALED_EPSILON), max_bead_width); // Append paths to collection. if (!multi_path.empty()) { if (multi_path.paths.front().first_point() == multi_path.paths.back().last_point()) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index d8681439282..8bc0ebee8a3 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -64,7 +64,7 @@ namespace Slic3r { -ExtrusionMultiPath PerimeterGenerator::thick_polyline_to_multi_path(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance) +ExtrusionMultiPath PerimeterGenerator::thick_polyline_to_multi_path(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance, float max_width) { ExtrusionMultiPath multi_path; ExtrusionPath path(role); @@ -124,7 +124,7 @@ ExtrusionMultiPath PerimeterGenerator::thick_polyline_to_multi_path(const ThickP continue; } - const double w = fmax(line.a_width, line.b_width); + const double w = fmin(fmax(line.a_width, line.b_width),scale_(max_width - flow.height() * float(1. - 0.25 * PI))); const Flow new_flow = (role.is_bridge() && flow.bridge()) ? flow : flow.with_width(unscale(w) + flow.height() * float(1. - 0.25 * PI)); if (path.empty()) { // Convert from spacing to extrusion width based on the extrusion model @@ -512,7 +512,7 @@ struct PerimeterGeneratorArachneExtrusion bool fuzzify = false; }; -static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::Parameters ¶ms, const Polygons &lower_slices_polygons_cache, std::vector &pg_extrusions) +static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::Parameters ¶ms, const Polygons &lower_slices_polygons_cache, std::vector &pg_extrusions, float max_bead_widh = FLT_MAX) { ExtrusionEntityCollection extrusion_coll; for (PerimeterGeneratorArachneExtrusion &pg_extrusion : pg_extrusions) { @@ -561,13 +561,13 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P // get non-overhang paths by intersecting this loop with the grown lower slices extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctIntersection), role_normal, - is_external ? params.ext_perimeter_flow : params.perimeter_flow); + is_external ? params.ext_perimeter_flow : params.perimeter_flow, max_bead_widh); // 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, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctDifference), role_overhang, - params.overhang_flow); + params.overhang_flow, max_bead_widh); // Reapply the nearest point search for starting point. // We allow polyline reversal because Clipper may have randomly reversed polylines during clipping. @@ -607,7 +607,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P chain_and_reorder_extrusion_paths(paths, &start_point); } } else { - extrusion_paths_append(paths, *extrusion, role_normal, is_external ? params.ext_perimeter_flow : params.perimeter_flow); + extrusion_paths_append(paths, *extrusion, role_normal, is_external ? params.ext_perimeter_flow : params.perimeter_flow, max_bead_widh); } // Append paths to collection. @@ -1329,8 +1329,16 @@ void PerimeterGenerator::process_arachne( } } } + + assert(!params.print_config.nozzle_diameter.empty()); + float min_nozzle_diameter = float(*std::min_element(params.print_config.nozzle_diameter.values.begin(), params.print_config.nozzle_diameter.values.end())); + + float max_bead_width = params.object_config.max_bead_width.value; + + if (const auto &max_bead_width_opt = params.object_config.max_bead_width; max_bead_width_opt.percent) + max_bead_width = (max_bead_width_opt.value * 0.01 * min_nozzle_diameter); - if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(params, lower_slices_polygons_cache, ordered_extrusions); !extrusion_coll.empty()) { + if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(params, lower_slices_polygons_cache, ordered_extrusions, max_bead_width); !extrusion_coll.empty()) { if (params.config.internal_first_on_overhangs) for (ExtrusionEntity* ent : extrusion_coll) if (ent->is_loop()) diff --git a/src/libslic3r/PerimeterGenerator.hpp b/src/libslic3r/PerimeterGenerator.hpp index 1fc9e0c6ec5..5e9d85f1659 100644 --- a/src/libslic3r/PerimeterGenerator.hpp +++ b/src/libslic3r/PerimeterGenerator.hpp @@ -103,7 +103,7 @@ void process_arachne( // Infills without the gap fills ExPolygons &out_fill_expolygons); -ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, float tolerance, float merge_tolerance); +ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, float tolerance, float merge_tolerance, float max_width = FLT_MAX); void split_top_surfaces(const Parameters ¶ms, const ExPolygons *lower_slices,const ExPolygons *upper_slices, const ExPolygons &orig_polygons, ExPolygons &top_fills, ExPolygons &non_top_polygons, ExPolygons &fill_clip); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index c3d736415d5..cfa816d1f8a 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -472,7 +472,7 @@ static std::vector s_Preset_print_options { "wipe_tower_width", "wipe_tower_cone_angle", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width", "mmu_segmented_region_interlocking_depth", "wipe_tower_extruder", "wipe_tower_no_sparse_layers", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits", "perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", - "wall_distribution_count", "min_feature_size", "min_bead_width", + "wall_distribution_count", "min_feature_size", "min_bead_width", "max_bead_width", // SuperSlicer "only_one_perimeter_top", "min_width_top_surface", "overhangs_reverse", "external_perimeters_reverse", "internal_perimeters_reverse", "infill_reverse" diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 28fc3361863..6e2dd47b7aa 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3658,6 +3658,16 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->set_default_value(new ConfigOptionFloatOrPercent(85, true)); + def = this->add("max_bead_width", coFloatOrPercent); + def->label = L("Maximum perimeter width"); + def->category = L("Advanced"); + def->tooltip = L("Maximum width of the perimeter. " + "If expressed as a percentage (for example 85%), it will be computed based on the nozzle diameter."); + def->sidetext = L("mm or %"); + def->mode = comExpert; + def->min = 0; + def->set_default_value(new ConfigOptionFloatOrPercent(250, true)); + def = this->add("make_overhang_printable", coBool); def->label = L("Make overhang printable"); def->category = L("Advanced"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 4cf5c951f79..745e32088f0 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -556,6 +556,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionInt, wall_distribution_count)) ((ConfigOptionFloatOrPercent, min_feature_size)) ((ConfigOptionFloatOrPercent, min_bead_width)) + ((ConfigOptionFloatOrPercent, max_bead_width)) ((ConfigOptionBool, support_material)) // Automatic supports (generated based fdm support point generator). ((ConfigOptionBool, support_material_auto)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 1428eb8ce3d..03576ee9b3a 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -900,7 +900,8 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "wall_transition_angle" || opt_key == "wall_distribution_count" || opt_key == "min_feature_size" - || opt_key == "min_bead_width") { + || opt_key == "min_bead_width" + || opt_key == "max_bead_width") { steps.emplace_back(posSlice); } else if ( opt_key == "seam_position" diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 3d55530484f..2398555fd24 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -369,6 +369,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) toggle_field("wall_distribution_count", have_arachne); toggle_field("min_feature_size", have_arachne); toggle_field("min_bead_width", have_arachne); + toggle_field("max_bead_width", have_arachne); toggle_field("thin_walls", !have_arachne); toggle_field("only_one_perimeter_first", have_perimeters); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 5f3ee0aa5ef..a59908cfaad 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1727,6 +1727,7 @@ void TabPrint::build() optgroup->append_single_option_line("wall_transition_length"); optgroup->append_single_option_line("wall_distribution_count"); optgroup->append_single_option_line("min_bead_width"); + optgroup->append_single_option_line("max_bead_width"); optgroup->append_single_option_line("min_feature_size"); page = add_options_page(L("Output options"), "output+page_white");