mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-07 23:17:35 -06:00
Add overhang threshold for scarf joint seam (#4725)
add overhang threshold for scarf joint seam
This commit is contained in:
parent
116169ea03
commit
dcb8d09af6
10 changed files with 41 additions and 12 deletions
|
@ -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
|
// find the point of the loop that is closest to the current extruder position
|
||||||
// or randomize if requested
|
// or randomize if requested
|
||||||
Point last_pos = this->last_pos();
|
Point last_pos = this->last_pos();
|
||||||
|
float seam_overhang = std::numeric_limits<float>::lowest();
|
||||||
if (!m_config.spiral_mode && description == "perimeter") {
|
if (!m_config.spiral_mode && description == "perimeter") {
|
||||||
assert(m_layer != nullptr);
|
assert(m_layer != nullptr);
|
||||||
bool is_outer_wall_first = m_config.wall_sequence == WallSequence::OuterInner;
|
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
|
} else
|
||||||
loop.split_at(last_pos, false);
|
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 &&
|
!m_config.spiral_mode &&
|
||||||
(loop.role() == erExternalPerimeter || (loop.role() == erPerimeter && m_config.seam_slope_inner_walls)) &&
|
(loop.role() == erExternalPerimeter || (loop.role() == erPerimeter && m_config.seam_slope_inner_walls)) &&
|
||||||
layer_id() > 0;
|
layer_id() > 0;
|
||||||
|
const auto nozzle_diameter = EXTRUDER_CONFIG(nozzle_diameter);
|
||||||
if (enable_seam_slope && m_config.seam_slope_conditional.value) {
|
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;
|
// 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
|
// if polyline was shorter than the clipping distance we'd get a null polyline, so
|
||||||
// we discard it in that case
|
// 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;
|
const double clip_length = m_enable_loop_clipping && !enable_seam_slope ? seam_gap : 0;
|
||||||
|
|
||||||
// get paths
|
// 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) {
|
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();
|
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();
|
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"
|
// note: previous & next are inverted to extrude "in the opposite direction, and we are "rewinding"
|
||||||
Point previous_point = paths.front().polyline.points[1];
|
Point previous_point = paths.front().polyline.points[1];
|
||||||
|
|
|
@ -1067,15 +1067,18 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po)
|
||||||
std::unique_ptr<PerimeterDistancer> current_layer_distancer = std::make_unique<PerimeterDistancer>(
|
std::unique_ptr<PerimeterDistancer> current_layer_distancer = std::make_unique<PerimeterDistancer>(
|
||||||
to_unscaled_linesf(po->layers()[layer_idx]->lslices));
|
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>() };
|
Vec2f point = Vec2f { perimeter_point.position.head<2>() };
|
||||||
if (prev_layer_distancer.get() != nullptr) {
|
if (prev_layer_distancer.get() != nullptr) {
|
||||||
perimeter_point.overhang = prev_layer_distancer->distance_from_lines<true>(point.cast<double>())
|
const auto _dist = prev_layer_distancer->distance_from_lines<true>(point.cast<double>());
|
||||||
|
perimeter_point.overhang = _dist
|
||||||
+ 0.6f * perimeter_point.perimeter.flow_width
|
+ 0.6f * perimeter_point.perimeter.flow_width
|
||||||
- tan(SeamPlacer::overhang_angle_threshold)
|
- tan(SeamPlacer::overhang_angle_threshold)
|
||||||
* po->layers()[layer_idx]->height;
|
* po->layers()[layer_idx]->height;
|
||||||
perimeter_point.overhang =
|
perimeter_point.overhang =
|
||||||
perimeter_point.overhang < 0.0f ? 0.0f : 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)
|
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<void(void)> throw_if_can
|
||||||
}
|
}
|
||||||
|
|
||||||
void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first,
|
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;
|
using namespace SeamPlacerImpl;
|
||||||
const PrintObject *po = layer->object();
|
const PrintObject *po = layer->object();
|
||||||
// Must not be called with supprot layer.
|
// 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());
|
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
|
if (loop.role() == ExtrusionRole::erPerimeter) { //Hopefully inner perimeter
|
||||||
const SeamCandidate &perimeter_point = layer_perimeters.points[seam_index];
|
const SeamCandidate &perimeter_point = layer_perimeters.points[seam_index];
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef libslic3r_SeamPlacer_hpp_
|
#ifndef libslic3r_SeamPlacer_hpp_
|
||||||
#define libslic3r_SeamPlacer_hpp_
|
#define libslic3r_SeamPlacer_hpp_
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -66,6 +67,7 @@ struct SeamCandidate {
|
||||||
Perimeter &perimeter;
|
Perimeter &perimeter;
|
||||||
float visibility;
|
float visibility;
|
||||||
float overhang;
|
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)
|
// 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
|
// Negative sign means inside the print, comes from EdgeGrid structure
|
||||||
float embedded_distance;
|
float embedded_distance;
|
||||||
|
@ -141,8 +143,7 @@ public:
|
||||||
|
|
||||||
void init(const Print &print, std::function<void(void)> throw_if_canceled_func);
|
void init(const Print &print, std::function<void(void)> 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:
|
private:
|
||||||
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
||||||
void calculate_candidates_visibility(const PrintObject *po,
|
void calculate_candidates_visibility(const PrintObject *po,
|
||||||
|
|
|
@ -188,6 +188,7 @@ void Layer::make_perimeters()
|
||||||
&& config.seam_slope_type == other_config.seam_slope_type
|
&& config.seam_slope_type == other_config.seam_slope_type
|
||||||
&& config.seam_slope_conditional == other_config.seam_slope_conditional
|
&& config.seam_slope_conditional == other_config.seam_slope_conditional
|
||||||
&& config.scarf_angle_threshold == other_config.scarf_angle_threshold
|
&& 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_speed == other_config.scarf_joint_speed
|
||||||
&& config.scarf_joint_flow_ratio == other_config.scarf_joint_flow_ratio
|
&& config.scarf_joint_flow_ratio == other_config.scarf_joint_flow_ratio
|
||||||
&& config.seam_slope_start_height == other_config.seam_slope_start_height
|
&& config.seam_slope_start_height == other_config.seam_slope_start_height
|
||||||
|
|
|
@ -820,7 +820,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||||
"wipe_tower_rotation_angle", "tree_support_branch_distance_organic", "tree_support_branch_diameter_organic", "tree_support_branch_angle_organic",
|
"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",
|
"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",
|
"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<std::string> s_Preset_filament_options {
|
static std::vector<std::string> s_Preset_filament_options {
|
||||||
|
|
|
@ -3588,6 +3588,17 @@ def = this->add("filament_loading_speed", coFloats);
|
||||||
def->max = 180;
|
def->max = 180;
|
||||||
def->set_default_value(new ConfigOptionInt(155));
|
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 = this->add("scarf_joint_speed", coFloatOrPercent);
|
||||||
def->label = L("Scarf joint speed");
|
def->label = L("Scarf joint speed");
|
||||||
def->category = L("Quality");
|
def->category = L("Quality");
|
||||||
|
@ -3605,7 +3616,7 @@ def = this->add("filament_loading_speed", coFloats);
|
||||||
def = this->add("scarf_joint_flow_ratio", coFloat);
|
def = this->add("scarf_joint_flow_ratio", coFloat);
|
||||||
def->label = L("Scarf joint flow ratio");
|
def->label = L("Scarf joint flow ratio");
|
||||||
def->tooltip = L("This factor affects the amount of material for scarf joints.");
|
def->tooltip = L("This factor affects the amount of material for scarf joints.");
|
||||||
def->mode = comAdvanced;
|
def->mode = comDevelop;
|
||||||
def->max = 2;
|
def->max = 2;
|
||||||
def->set_default_value(new ConfigOptionFloat(1));
|
def->set_default_value(new ConfigOptionFloat(1));
|
||||||
|
|
||||||
|
|
|
@ -969,6 +969,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||||
((ConfigOptionBool, seam_slope_inner_walls))
|
((ConfigOptionBool, seam_slope_inner_walls))
|
||||||
((ConfigOptionFloatOrPercent, scarf_joint_speed))
|
((ConfigOptionFloatOrPercent, scarf_joint_speed))
|
||||||
((ConfigOptionFloat, scarf_joint_flow_ratio))
|
((ConfigOptionFloat, scarf_joint_flow_ratio))
|
||||||
|
((ConfigOptionPercent, scarf_overhang_threshold))
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -1145,6 +1145,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||||
|| opt_key == "seam_slope_type"
|
|| opt_key == "seam_slope_type"
|
||||||
|| opt_key == "seam_slope_conditional"
|
|| opt_key == "seam_slope_conditional"
|
||||||
|| opt_key == "scarf_angle_threshold"
|
|| opt_key == "scarf_angle_threshold"
|
||||||
|
|| opt_key == "scarf_overhang_threshold"
|
||||||
|| opt_key == "scarf_joint_speed"
|
|| opt_key == "scarf_joint_speed"
|
||||||
|| opt_key == "scarf_joint_flow_ratio"
|
|| opt_key == "scarf_joint_flow_ratio"
|
||||||
|| opt_key == "seam_slope_start_height"
|
|| opt_key == "seam_slope_start_height"
|
||||||
|
|
|
@ -764,6 +764,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
||||||
toggle_line("scarf_joint_flow_ratio", has_seam_slope);
|
toggle_line("scarf_joint_flow_ratio", has_seam_slope);
|
||||||
toggle_field("seam_slope_min_length", !config->opt_bool("seam_slope_entire_loop"));
|
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_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*/)
|
void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/)
|
||||||
|
|
|
@ -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_type", "seam#scarf-joint-seam");
|
||||||
optgroup->append_single_option_line("seam_slope_conditional", "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_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("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_start_height", "seam#scarf-joint-seam");
|
||||||
optgroup->append_single_option_line("seam_slope_entire_loop", "seam#scarf-joint-seam");
|
optgroup->append_single_option_line("seam_slope_entire_loop", "seam#scarf-joint-seam");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue