diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index f1c129df60..3f16dc8667 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -4549,10 +4549,11 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou // find the point of the loop that is closest to the current extruder position // or randomize if requested Point last_pos = this->last_pos(); + float seam_overhang = std::numeric_limits::lowest(); if (!m_config.spiral_mode && description == "perimeter") { assert(m_layer != nullptr); bool is_outer_wall_first = m_config.wall_sequence == WallSequence::OuterInner; - m_seam_placer.place_seam(m_layer, loop, is_outer_wall_first, this->last_pos()); + m_seam_placer.place_seam(m_layer, loop, is_outer_wall_first, this->last_pos(), seam_overhang); } else loop.split_at(last_pos, false); @@ -4561,14 +4562,21 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou !m_config.spiral_mode && (loop.role() == erExternalPerimeter || (loop.role() == erPerimeter && m_config.seam_slope_inner_walls)) && layer_id() > 0; - + const auto nozzle_diameter = EXTRUDER_CONFIG(nozzle_diameter); if (enable_seam_slope && m_config.seam_slope_conditional.value) { - enable_seam_slope = loop.is_smooth(m_config.scarf_angle_threshold.value * M_PI / 180., EXTRUDER_CONFIG(nozzle_diameter)); + enable_seam_slope = loop.is_smooth(m_config.scarf_angle_threshold.value * M_PI / 180., nozzle_diameter); } + + if (enable_seam_slope && m_config.seam_slope_conditional.value && m_config.scarf_overhang_threshold.value > 0.0f) { + const auto _line_width = loop.role() == erExternalPerimeter ? m_config.outer_wall_line_width.get_abs_value(nozzle_diameter) : + m_config.inner_wall_line_width.get_abs_value(nozzle_diameter); + enable_seam_slope = seam_overhang < m_config.scarf_overhang_threshold.value * 0.01f * _line_width; + } + // clip the path to avoid the extruder to get exactly on the first point of the loop; // if polyline was shorter than the clipping distance we'd get a null polyline, so // we discard it in that case - const double seam_gap = scale_(m_config.seam_gap.get_abs_value(EXTRUDER_CONFIG(nozzle_diameter))); + const double seam_gap = scale_(m_config.seam_gap.get_abs_value(nozzle_diameter)); const double clip_length = m_enable_loop_clipping && !enable_seam_slope ? seam_gap : 0; // get paths @@ -4596,7 +4604,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou if (m_config.wipe_before_external_loop.value && !paths.empty() && paths.front().size() > 1 && paths.back().size() > 1 && paths.front().role() == erExternalPerimeter && region_perimeters.size() > 1) { const bool is_full_loop_ccw = loop.polygon().is_counter_clockwise(); bool is_hole_loop = (loop.loop_role() & ExtrusionLoopRole::elrHole) != 0; // loop.make_counter_clockwise(); - const double nozzle_diam = EXTRUDER_CONFIG(nozzle_diameter); + const double nozzle_diam = nozzle_diameter; // note: previous & next are inverted to extrude "in the opposite direction, and we are "rewinding" Point previous_point = paths.front().polyline.points[1]; diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index cf5b9c5080..301759d29b 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -1067,15 +1067,18 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) std::unique_ptr current_layer_distancer = std::make_unique( to_unscaled_linesf(po->layers()[layer_idx]->lslices)); - for (SeamCandidate &perimeter_point : layers[layer_idx].points) { + auto& layer_seams = layers[layer_idx]; + for (SeamCandidate &perimeter_point : layer_seams.points) { Vec2f point = Vec2f { perimeter_point.position.head<2>() }; if (prev_layer_distancer.get() != nullptr) { - perimeter_point.overhang = prev_layer_distancer->distance_from_lines(point.cast()) + const auto _dist = prev_layer_distancer->distance_from_lines(point.cast()); + perimeter_point.overhang = _dist + 0.6f * perimeter_point.perimeter.flow_width - tan(SeamPlacer::overhang_angle_threshold) * po->layers()[layer_idx]->height; perimeter_point.overhang = perimeter_point.overhang < 0.0f ? 0.0f : perimeter_point.overhang; + perimeter_point.unsupported_dist = _dist + 0.4f * perimeter_point.perimeter.flow_width; } if (should_compute_layer_embedding) { // search for embedded perimeter points (points hidden inside the print ,e.g. multimaterial join, best position for seam) @@ -1484,7 +1487,7 @@ void SeamPlacer::init(const Print &print, std::function throw_if_can } void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, - const Point &last_pos) const { + const Point &last_pos, float& overhang) const { using namespace SeamPlacerImpl; const PrintObject *po = layer->object(); // Must not be called with supprot layer. @@ -1546,6 +1549,7 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern } Point seam_point = Point::new_scale(seam_position.x(), seam_position.y()); + overhang = layer_perimeters.points[seam_index].unsupported_dist; if (loop.role() == ExtrusionRole::erPerimeter) { //Hopefully inner perimeter const SeamCandidate &perimeter_point = layer_perimeters.points[seam_index]; diff --git a/src/libslic3r/GCode/SeamPlacer.hpp b/src/libslic3r/GCode/SeamPlacer.hpp index a7bb12f4f4..430cccf957 100644 --- a/src/libslic3r/GCode/SeamPlacer.hpp +++ b/src/libslic3r/GCode/SeamPlacer.hpp @@ -1,6 +1,7 @@ #ifndef libslic3r_SeamPlacer_hpp_ #define libslic3r_SeamPlacer_hpp_ +#include #include #include #include @@ -66,6 +67,7 @@ struct SeamCandidate { Perimeter &perimeter; float visibility; float overhang; + float unsupported_dist; // distance inside the merged layer regions, for detecting perimeter points which are hidden indside the print (e.g. multimaterial join) // Negative sign means inside the print, comes from EdgeGrid structure float embedded_distance; @@ -141,8 +143,7 @@ public: void init(const Print &print, std::function throw_if_canceled_func); - void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const; - + void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos, float& overhang) const; private: void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info); void calculate_candidates_visibility(const PrintObject *po, diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index 6487ddb40a..e92eb0a2ba 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -188,6 +188,7 @@ void Layer::make_perimeters() && config.seam_slope_type == other_config.seam_slope_type && config.seam_slope_conditional == other_config.seam_slope_conditional && config.scarf_angle_threshold == other_config.scarf_angle_threshold + && config.scarf_overhang_threshold == other_config.scarf_overhang_threshold && config.scarf_joint_speed == other_config.scarf_joint_speed && config.scarf_joint_flow_ratio == other_config.scarf_joint_flow_ratio && config.seam_slope_start_height == other_config.seam_slope_start_height diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 31e1c4acff..a9995c15d6 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -820,7 +820,7 @@ static std::vector s_Preset_print_options { "wipe_tower_rotation_angle", "tree_support_branch_distance_organic", "tree_support_branch_diameter_organic", "tree_support_branch_angle_organic", "hole_to_polyhole", "hole_to_polyhole_threshold", "hole_to_polyhole_twisted", "mmu_segmented_region_max_width", "mmu_segmented_region_interlocking_depth", "small_area_infill_flow_compensation", "small_area_infill_flow_compensation_model", - "seam_slope_type", "seam_slope_conditional", "scarf_angle_threshold", "scarf_joint_speed", "scarf_joint_flow_ratio", "seam_slope_start_height", "seam_slope_entire_loop", "seam_slope_min_length", "seam_slope_steps", "seam_slope_inner_walls", + "seam_slope_type", "seam_slope_conditional", "scarf_angle_threshold", "scarf_joint_speed", "scarf_joint_flow_ratio", "seam_slope_start_height", "seam_slope_entire_loop", "seam_slope_min_length", "seam_slope_steps", "seam_slope_inner_walls", "scarf_overhang_threshold" }; static std::vector s_Preset_filament_options { diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 268dba2589..34a7833e0f 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3588,6 +3588,17 @@ def = this->add("filament_loading_speed", coFloats); def->max = 180; def->set_default_value(new ConfigOptionInt(155)); + def = this->add("scarf_overhang_threshold", coPercent); + def->label = L("Conditional overhang threshold"); + def->category = L("Quality"); + def->tooltip = L("This option determines the overhang threshold for the application of scarf joint seams. If the unsupported portion " + "of the perimeter is less than this threshold, scarf joint seams will be applied. The default threshold is set at 40% " + "of the external wall's width. Due to performance considerations, the degree of overhang is estimated."); + def->sidetext = L("%"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionPercent(40)); + def = this->add("scarf_joint_speed", coFloatOrPercent); def->label = L("Scarf joint speed"); def->category = L("Quality"); @@ -3605,7 +3616,7 @@ def = this->add("filament_loading_speed", coFloats); def = this->add("scarf_joint_flow_ratio", coFloat); def->label = L("Scarf joint flow ratio"); def->tooltip = L("This factor affects the amount of material for scarf joints."); - def->mode = comAdvanced; + def->mode = comDevelop; def->max = 2; def->set_default_value(new ConfigOptionFloat(1)); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index b3739ddfc8..28e9d00923 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -969,6 +969,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionBool, seam_slope_inner_walls)) ((ConfigOptionFloatOrPercent, scarf_joint_speed)) ((ConfigOptionFloat, scarf_joint_flow_ratio)) + ((ConfigOptionPercent, scarf_overhang_threshold)) ) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 26c5d24f57..f8ed199bf5 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1145,6 +1145,7 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "seam_slope_type" || opt_key == "seam_slope_conditional" || opt_key == "scarf_angle_threshold" + || opt_key == "scarf_overhang_threshold" || opt_key == "scarf_joint_speed" || opt_key == "scarf_joint_flow_ratio" || opt_key == "seam_slope_start_height" diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 42106b214e..d9405e76b8 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -764,6 +764,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co toggle_line("scarf_joint_flow_ratio", has_seam_slope); toggle_field("seam_slope_min_length", !config->opt_bool("seam_slope_entire_loop")); toggle_line("scarf_angle_threshold", has_seam_slope && config->opt_bool("seam_slope_conditional")); + toggle_line("scarf_overhang_threshold", has_seam_slope && config->opt_bool("seam_slope_conditional")); } void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index f4f17909ca..c6144e2237 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1979,6 +1979,7 @@ void TabPrint::build() optgroup->append_single_option_line("seam_slope_type", "seam#scarf-joint-seam"); optgroup->append_single_option_line("seam_slope_conditional", "seam#scarf-joint-seam"); optgroup->append_single_option_line("scarf_angle_threshold", "seam#scarf-joint-seam"); + optgroup->append_single_option_line("scarf_overhang_threshold", "seam#scarf-joint-seam"); optgroup->append_single_option_line("scarf_joint_speed", "seam#scarf-joint-seam"); optgroup->append_single_option_line("seam_slope_start_height", "seam#scarf-joint-seam"); optgroup->append_single_option_line("seam_slope_entire_loop", "seam#scarf-joint-seam");