Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scarf joint seam enhancement: conditional scarf joint and slowdown for scarf joint only #4317

Merged
merged 11 commits into from Mar 8, 2024
59 changes: 59 additions & 0 deletions src/libslic3r/ExtrusionEntity.cpp
Expand Up @@ -7,6 +7,7 @@
#include <cmath>
#include <limits>
#include <sstream>
#include "Utils.hpp"

#define L(s) (s)

Expand Down Expand Up @@ -340,6 +341,64 @@ double ExtrusionLoop::min_mm3_per_mm() const
return min_mm3_per_mm;
}

// Orca: This function is used to check if the loop is smooth(continuous) or not.
// TODO: the main logic is largly copied from the calculate_polygon_angles_at_vertices function in SeamPlacer file. Need to refactor the code in the future.
bool ExtrusionLoop::is_smooth(double angle_threshold, double min_arm_length) const
{
// go through all the points in the loop and check if the angle between two segments(AB and BC) is less than the threshold
size_t idx_prev = 0;
size_t idx_curr = 0;
size_t idx_next = 0;

float distance_to_prev = 0;
float distance_to_next = 0;

const auto _polyline = as_polyline();
const Points& points = _polyline.points;

std::vector<float> lengths{};
for (size_t point_idx = 0; point_idx < points.size() - 1; ++point_idx) {
lengths.push_back((unscale(points[point_idx]) - unscale(points[point_idx + 1])).norm());
}
lengths.push_back(std::max((unscale(points[0]) - unscale(points[points.size() - 1])).norm(), 0.1));

// push idx_prev far enough back as initialization
while (distance_to_prev < min_arm_length) {
idx_prev = Slic3r::prev_idx_modulo(idx_prev, points.size());
distance_to_prev += lengths[idx_prev];
}

for (size_t _i = 0; _i < points.size(); ++_i) {
// pull idx_prev to current as much as possible, while respecting the min_arm_length
while (distance_to_prev - lengths[idx_prev] > min_arm_length) {
distance_to_prev -= lengths[idx_prev];
idx_prev = Slic3r::next_idx_modulo(idx_prev, points.size());
}

// push idx_next forward as far as needed
while (distance_to_next < min_arm_length) {
distance_to_next += lengths[idx_next];
idx_next = Slic3r::next_idx_modulo(idx_next, points.size());
}

// Calculate angle between idx_prev, idx_curr, idx_next.
const Point& p0 = points[idx_prev];
const Point& p1 = points[idx_curr];
const Point& p2 = points[idx_next];
if (abs(angle(p1 - p0, p2 - p1)) > angle_threshold) {
return false;
}

// increase idx_curr by one
float curr_distance = lengths[idx_curr];
idx_curr++;
distance_to_prev += curr_distance;
distance_to_next -= curr_distance;
}

return true;
}

ExtrusionLoopSloped::ExtrusionLoopSloped(ExtrusionPaths& original_paths,
double seam_gap,
double slope_min_length,
Expand Down
3 changes: 2 additions & 1 deletion src/libslic3r/ExtrusionEntity.hpp
Expand Up @@ -479,7 +479,8 @@ class ExtrusionLoop : public ExtrusionEntity
append(dst, p.polyline.points);
}
double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; }

// check if the loop is smooth, angle_threshold is in radians, default is 10 degrees
bool is_smooth(double angle_threshold = 0.174, double min_arm_length = 0.025) const;
//static inline std::string role_to_string(ExtrusionLoopRole role);

#ifndef NDEBUG
Expand Down
6 changes: 5 additions & 1 deletion src/libslic3r/GCode.cpp
Expand Up @@ -4557,11 +4557,15 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
loop.split_at(last_pos, false);

const auto seam_scarf_type = m_config.seam_slope_type.value;
const bool enable_seam_slope = ((seam_scarf_type == SeamScarfType::External && !is_hole) || seam_scarf_type == SeamScarfType::All) &&
bool enable_seam_slope = ((seam_scarf_type == SeamScarfType::External && !is_hole) || seam_scarf_type == SeamScarfType::All) &&
!m_config.spiral_mode &&
(loop.role() == erExternalPerimeter || (loop.role() == erPerimeter && m_config.seam_slope_inner_walls)) &&
layer_id() > 0;

if (enable_seam_slope && m_config.seam_slope_conditional.value) {
enable_seam_slope = enable_seam_slope &&
SoftFever marked this conversation as resolved.
Show resolved Hide resolved
loop.is_smooth((180 - m_config.scarf_angle_threshold.value) * M_PI / 180., EXTRUDER_CONFIG(nozzle_diameter));
}
// 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
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/Layer.cpp
Expand Up @@ -186,6 +186,8 @@ void Layer::make_perimeters()
&& config.fuzzy_skin_point_distance == other_config.fuzzy_skin_point_distance
&& config.fuzzy_skin_first_layer == other_config.fuzzy_skin_first_layer
&& 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.seam_slope_start_height == other_config.seam_slope_start_height
&& config.seam_slope_entire_loop == other_config.seam_slope_entire_loop
&& config.seam_slope_min_length == other_config.seam_slope_min_length
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/Preset.cpp
Expand Up @@ -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",
"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_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", "seam_slope_start_height", "seam_slope_entire_loop", "seam_slope_min_length", "seam_slope_steps", "seam_slope_inner_walls",
};

static std::vector<std::string> s_Preset_filament_options {
Expand Down
19 changes: 18 additions & 1 deletion src/libslic3r/PrintConfig.cpp
Expand Up @@ -3547,7 +3547,24 @@ def = this->add("filament_loading_speed", coFloats);
def->enum_labels.push_back(L("Contour and hole"));
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<SeamScarfType>(SeamScarfType::None));


def = this->add("seam_slope_conditional", coBool);
def->label = L("Conditional scarf joint");
def->tooltip = L("Apply scarf joints only to smooth perimeters where traditional seams do not conceal the seams at sharp corners effectively.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));

def = this->add("scarf_angle_threshold", coInt);
def->label = L("Conditional angle threshold");
def->tooltip = L(
"This option sets the threshold angle for applying a conditional scarf joint seam.\nIf the maximum angle within the perimeter loop "
"exceeds this value (indicating the absence of sharp corners), a scarf joint seam will be used. The default value is 155°.");
def->mode = comAdvanced;
def->sidetext = L("°");
def->min = 0;
def->max = 180;
def->set_default_value(new ConfigOptionInt(155));

def = this->add("seam_slope_start_height", coFloatOrPercent);
def->label = L("Scarf start height");
def->tooltip = L("Start height of the scarf.\n"
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/PrintConfig.hpp
Expand Up @@ -953,6 +953,8 @@ PRINT_CONFIG_CLASS_DEFINE(

// Orca: seam slopes
((ConfigOptionEnum<SeamScarfType>, seam_slope_type))
((ConfigOptionBool, seam_slope_conditional))
((ConfigOptionInt, scarf_angle_threshold))
((ConfigOptionFloatOrPercent, seam_slope_start_height))
((ConfigOptionBool, seam_slope_entire_loop))
((ConfigOptionFloat, seam_slope_min_length))
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/PrintObject.cpp
Expand Up @@ -1143,6 +1143,8 @@ bool PrintObject::invalidate_state_by_config_options(
} else if (
opt_key == "seam_position"
|| opt_key == "seam_slope_type"
|| opt_key == "seam_slope_conditional"
|| opt_key == "scarf_angle_threshold"
|| opt_key == "seam_slope_start_height"
|| opt_key == "seam_slope_entire_loop"
|| opt_key == "seam_slope_min_length"
Expand Down
2 changes: 2 additions & 0 deletions src/slic3r/GUI/ConfigManipulation.cpp
Expand Up @@ -756,12 +756,14 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co

toggle_field("seam_slope_type", !has_spiral_vase);
bool has_seam_slope = !has_spiral_vase && config->opt_enum<SeamScarfType>("seam_slope_type") != SeamScarfType::None;
toggle_line("seam_slope_conditional", has_seam_slope);
toggle_line("seam_slope_start_height", has_seam_slope);
toggle_line("seam_slope_entire_loop", has_seam_slope);
toggle_line("seam_slope_min_length", has_seam_slope);
toggle_line("seam_slope_steps", has_seam_slope);
toggle_line("seam_slope_inner_walls", 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"));
}

void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/)
Expand Down
2 changes: 2 additions & 0 deletions src/slic3r/GUI/Tab.cpp
Expand Up @@ -1977,6 +1977,8 @@ void TabPrint::build()
optgroup->append_single_option_line("staggered_inner_seams", "seam");
optgroup->append_single_option_line("seam_gap","seam");
optgroup->append_single_option_line("seam_slope_type");
optgroup->append_single_option_line("seam_slope_conditional");
optgroup->append_single_option_line("scarf_angle_threshold");
optgroup->append_single_option_line("seam_slope_start_height");
optgroup->append_single_option_line("seam_slope_entire_loop");
optgroup->append_single_option_line("seam_slope_min_length");
Expand Down