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

Seam: use scarf joint to minimize seam visiblity #3839

Merged
merged 54 commits into from Mar 2, 2024
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
f4e8ff2
Remember z of previous layer
Noisyfox Jan 25, 2024
071274e
Support travel to middle of the layer z
Noisyfox Jan 25, 2024
85586d8
Support sloped extrusion
Noisyfox Jan 25, 2024
a69d796
Implement sloped seam
Noisyfox Jan 26, 2024
ed1ba2d
Reduce extra movements
Noisyfox Jan 26, 2024
b1393a1
Don't clip loop if sloped seam is enabled
Noisyfox Jan 26, 2024
467c68f
Fix wipe
Noisyfox Jan 26, 2024
51d11de
Ensure `slope_max_segment_length`
Noisyfox Jan 26, 2024
e3793c6
Add options
Noisyfox Jan 26, 2024
20365d5
Merge branch 'main' into dev/no-seam
Noisyfox Jan 27, 2024
4dba03e
Limit slope length to perimeter length
Noisyfox Jan 27, 2024
c502f0c
Fix slope segmentation
Noisyfox Jan 27, 2024
f3f0c82
Rename the option to scarf joint seam
Noisyfox Jan 27, 2024
ebbdc80
Merge branch 'main' into dev/no-seam
Noisyfox Jan 27, 2024
1d6b10d
Don't modify the slope option when turning on spiral vase
Noisyfox Jan 27, 2024
fa3383a
Add a few suggestions when turnning on scarf joint
Noisyfox Jan 27, 2024
5cd06dd
Add option to add scarf joint to inner walls
Noisyfox Jan 28, 2024
fbaf137
Apply seam gap at the end of the slope
Noisyfox Jan 28, 2024
65eae47
Merge branch 'main' into dev/no-seam
Noisyfox Jan 28, 2024
685b358
Merge branch 'main' into dev/no-seam
Noisyfox Jan 29, 2024
4280402
Add option to explicitly use the entire loop as scarf length
Noisyfox Jan 30, 2024
e1f76d9
Merge branch 'main' into dev/no-seam
Noisyfox Jan 30, 2024
1d422a1
Merge branch 'main' into dev/no-seam
Noisyfox Jan 30, 2024
fa6ee5c
Fix layer number
Noisyfox Jan 31, 2024
17bb717
Increase default scarf length to 20mm
Noisyfox Jan 31, 2024
8006927
Merge branch 'main' into dev/no-seam
Noisyfox Jan 31, 2024
ef90d48
Better way of storing the global scarf state
Noisyfox Feb 1, 2024
86c60e9
Better vase mode layer height recognition
Noisyfox Feb 2, 2024
590f733
Move id should exclude seams
Noisyfox Feb 2, 2024
b7c5b5f
Fix slope height with independent support layer height
Noisyfox Feb 2, 2024
a8e22b8
Fix linux build
Noisyfox Feb 3, 2024
b35c051
Merge branch 'main' into dev/no-seam
Noisyfox Feb 6, 2024
5a624a6
Merge branch 'main' into dev/no-seam
Noisyfox Feb 11, 2024
ebb5f9b
Merge branch 'main' into dev/no-seam
Noisyfox Feb 11, 2024
7466947
Allow controlling the scarf with modifier
Noisyfox Feb 11, 2024
ad8cfa2
Merge branch 'main' into dev/no-seam
Noisyfox Feb 19, 2024
5124fbd
Merge branch 'main' into dev/no-seam
SoftFever Feb 20, 2024
11e2893
Scarf start height default to 0
Noisyfox Feb 22, 2024
dcab21f
Allow enable scarf seam on contour only
Noisyfox Feb 22, 2024
7b71c5a
Merge branch 'main' into dev/no-seam
Noisyfox Feb 24, 2024
9a2b4c9
Merge branch 'main' into dev/no-seam
SoftFever Feb 25, 2024
5a95329
Merge branch 'main' into dev/no-seam
SoftFever Feb 25, 2024
3a0cf90
Fix type error
Noisyfox Feb 27, 2024
89e61a0
Move the creation of sloped loop into ExtrusionEntity.cpp
Noisyfox Feb 27, 2024
6e5f2d1
Fix error "vector too long"
Noisyfox Feb 27, 2024
163e8e8
Detect seams properly
Noisyfox Feb 27, 2024
cb5f994
Merge branch 'main' into dev/no-seam
Noisyfox Feb 27, 2024
05961f7
The correct way of calculating the rate limit
Noisyfox Feb 29, 2024
3b37595
The correct way of calculating the rate limit
Noisyfox Feb 29, 2024
9e2b14c
Merge branch 'main' into dev/no-seam
Noisyfox Feb 29, 2024
773cba7
Add pressure equalizer in print by object mode
Noisyfox Feb 29, 2024
dce7dd1
Merge branch 'bugfox/correct-pressure-equalizer' into dev/no-seam
Noisyfox Feb 29, 2024
2eebee8
Remove the settings recommendation as it varies a lot depends on prin…
Noisyfox Mar 2, 2024
c5c6683
Add a beta suffix
Noisyfox Mar 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/libslic3r/ExtrusionEntity.hpp
Expand Up @@ -301,6 +301,42 @@ class ExtrusionPath : public ExtrusionEntity
bool m_no_extrusion = false;
};

class ExtrusionPathSloped : public ExtrusionPath
SoftFever marked this conversation as resolved.
Show resolved Hide resolved
{
public:
struct Slope
{
double z_ratio{1.};
double e_ratio{1.};
};

Slope slope_begin;
Slope slope_end;

ExtrusionPathSloped(const ExtrusionPath& rhs, const Slope& begin, const Slope& end)
: ExtrusionPath(rhs), slope_begin(begin), slope_end(end)
{}
ExtrusionPathSloped(ExtrusionPath&& rhs, const Slope& begin, const Slope& end)
: ExtrusionPath(std::move(rhs)), slope_begin(begin), slope_end(end)
{}
ExtrusionPathSloped(const Polyline& polyline, const ExtrusionPath& rhs, const Slope& begin, const Slope& end)
: ExtrusionPath(polyline, rhs), slope_begin(begin), slope_end(end)
{}
ExtrusionPathSloped(Polyline&& polyline, const ExtrusionPath& rhs, const Slope& begin, const Slope& end)
: ExtrusionPath(std::move(polyline), rhs), slope_begin(begin), slope_end(end)
{}

Slope interpolate(const double ratio) const
{
return {
lerp(slope_begin.z_ratio, slope_end.z_ratio, ratio),
lerp(slope_begin.e_ratio, slope_end.e_ratio, ratio),
};
}

bool is_flat() const { return is_approx(slope_begin.z_ratio, slope_end.z_ratio); }
};

class ExtrusionPathOriented : public ExtrusionPath
{
public:
Expand Down
276 changes: 244 additions & 32 deletions src/libslic3r/GCode.cpp

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/libslic3r/GCode.hpp
Expand Up @@ -29,6 +29,7 @@
#include <map>
#include <set>
#include <string>
#include <cfloat>

namespace Slic3r {

Expand Down Expand Up @@ -219,7 +220,7 @@ class GCode {
void set_layer_count(unsigned int value) { m_layer_count = value; }
void apply_print_config(const PrintConfig &print_config);

std::string travel_to(const Point& point, ExtrusionRole role, std::string comment);
std::string travel_to(const Point& point, ExtrusionRole role, std::string comment, double z = DBL_MAX);
bool needs_retraction(const Polyline& travel, ExtrusionRole role, LiftType& lift_type);
std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::NormalLift);
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
Expand Down
38 changes: 29 additions & 9 deletions src/libslic3r/GCode/GCodeProcessor.cpp
Expand Up @@ -1080,7 +1080,11 @@ void GCodeProcessor::apply_config(const PrintConfig& config)

const ConfigOptionBool* spiral_vase = config.option<ConfigOptionBool>("spiral_mode");
if (spiral_vase != nullptr)
m_spiral_vase_active = spiral_vase->value;
m_detect_layer_based_on_tag = spiral_vase->value;

const ConfigOptionBool* has_scarf_joint_seam = config.option<ConfigOptionBool>("has_scarf_joint_seam");
if (has_scarf_joint_seam != nullptr)
m_detect_layer_based_on_tag = m_detect_layer_based_on_tag || has_scarf_joint_seam->value;

const ConfigOptionBool* manual_filament_change = config.option<ConfigOptionBool>("manual_filament_change");
if (manual_filament_change != nullptr)
Expand Down Expand Up @@ -1397,7 +1401,11 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)

const ConfigOptionBool* spiral_vase = config.option<ConfigOptionBool>("spiral_mode");
if (spiral_vase != nullptr)
m_spiral_vase_active = spiral_vase->value;
m_detect_layer_based_on_tag = spiral_vase->value;

const ConfigOptionBool* has_scarf_joint_seam = config.option<ConfigOptionBool>("has_scarf_joint_seam");
if (has_scarf_joint_seam != nullptr)
m_detect_layer_based_on_tag = m_detect_layer_based_on_tag || has_scarf_joint_seam->value;

const ConfigOptionEnumGeneric *bed_type = config.option<ConfigOptionEnumGeneric>("curr_bed_type");
if (bed_type != nullptr)
Expand Down Expand Up @@ -1479,7 +1487,9 @@ void GCodeProcessor::reset()

m_options_z_corrector.reset();

m_spiral_vase_active = false;
m_detect_layer_based_on_tag = false;

m_seams_count = 0;

#if ENABLE_GCODE_VIEWER_DATA_CHECKING
m_mm3_per_mm_compare.reset();
Expand Down Expand Up @@ -2344,12 +2354,12 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
// layer change tag
if (comment == reserved_tag(ETags::Layer_Change)) {
++m_layer_id;
if (m_spiral_vase_active) {
if (m_detect_layer_based_on_tag) {
if (m_result.moves.empty() || m_result.spiral_vase_layers.empty())
// add a placeholder for layer height. the actual value will be set inside process_G1() method
m_result.spiral_vase_layers.push_back({ FLT_MAX, { 0, 0 } });
else {
const size_t move_id = m_result.moves.size() - 1;
const size_t move_id = m_result.moves.size() - 1 - m_seams_count;
if (!m_result.spiral_vase_layers.empty())
m_result.spiral_vase_layers.back().second.second = move_id;
// add a placeholder for layer height. the actual value will be set inside process_G1() method
Expand Down Expand Up @@ -3250,12 +3260,18 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id] - plate_offset);
}

if (m_spiral_vase_active && !m_result.spiral_vase_layers.empty()) {
if (m_result.spiral_vase_layers.back().first == FLT_MAX && delta_pos[Z] >= 0.0)
if (m_detect_layer_based_on_tag && !m_result.spiral_vase_layers.empty()) {
if (delta_pos[Z] >= 0.0 && type == EMoveType::Extrude) {
const float current_z = static_cast<float>(m_end_position[Z]);
// replace layer height placeholder with correct value
m_result.spiral_vase_layers.back().first = static_cast<float>(m_end_position[Z]);
if (m_result.spiral_vase_layers.back().first == FLT_MAX) {
m_result.spiral_vase_layers.back().first = current_z;
} else {
m_result.spiral_vase_layers.back().first = std::max(m_result.spiral_vase_layers.back().first, current_z);
}
}
if (!m_result.moves.empty())
m_result.spiral_vase_layers.back().second.second = m_result.moves.size() - 1;
m_result.spiral_vase_layers.back().second.second = m_result.moves.size() - 1 - m_seams_count;
}

// store move
Expand Down Expand Up @@ -4267,6 +4283,10 @@ void GCodeProcessor::store_move_vertex(EMoveType type, EMovePathType path_type)
m_interpolation_points,
});

if (type == EMoveType::Seam) {
m_seams_count++;
}

// stores stop time placeholders for later use
if (type == EMoveType::Color_change || type == EMoveType::Pause_Print) {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
Expand Down
7 changes: 6 additions & 1 deletion src/libslic3r/GCode/GCodeProcessor.hpp
Expand Up @@ -700,7 +700,8 @@ namespace Slic3r {
SeamsDetector m_seams_detector;
OptionsZCorrector m_options_z_corrector;
size_t m_last_default_color_id;
bool m_spiral_vase_active;
bool m_detect_layer_based_on_tag {false};
int m_seams_count;
#if ENABLE_GCODE_VIEWER_STATISTICS
std::chrono::time_point<std::chrono::high_resolution_clock> m_start_time;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
Expand Down Expand Up @@ -770,6 +771,10 @@ namespace Slic3r {
//BBS: set offset for gcode writer
void set_xy_offset(double x, double y) { m_x_offset = x; m_y_offset = y; }

// Orca: if true, only change new layer if ETags::Layer_Change occurs
// otherwise when we got a lift of z during extrusion, a new layer will be added
void detect_layer_based_on_tag(bool enabled) { m_detect_layer_based_on_tag = enabled; }

private:
void apply_config(const DynamicPrintConfig& config);
void apply_config_simplify3d(const std::string& filename);
Expand Down
8 changes: 7 additions & 1 deletion src/libslic3r/Layer.cpp
Expand Up @@ -184,7 +184,13 @@ void Layer::make_perimeters()
&& config.fuzzy_skin == other_config.fuzzy_skin
&& config.fuzzy_skin_thickness == other_config.fuzzy_skin_thickness
&& config.fuzzy_skin_point_distance == other_config.fuzzy_skin_point_distance
&& config.fuzzy_skin_first_layer == other_config.fuzzy_skin_first_layer)
&& config.fuzzy_skin_first_layer == other_config.fuzzy_skin_first_layer
&& config.seam_slope_type == other_config.seam_slope_type
&& 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
&& config.seam_slope_steps == other_config.seam_slope_steps
&& config.seam_slope_inner_walls == other_config.seam_slope_inner_walls)
{
other_layerm->perimeters.clear();
other_layerm->fills.clear();
Expand Down
47 changes: 47 additions & 0 deletions src/libslic3r/Polyline.cpp
Expand Up @@ -309,6 +309,53 @@ bool Polyline::split_at_index(const size_t index, Polyline* p1, Polyline* p2) co
return true;
}

bool Polyline::split_at_length(const double length, Polyline* p1, Polyline* p2) const
{
if (this->points.empty()) return false;
if (length < 0 || length > this->length()) {
return false;
}

if (length < SCALED_EPSILON) {
p1->clear();
p1->append(this->first_point());
*p2 = *this;
} else if (is_approx(length, this->length(), SCALED_EPSILON)) {
p2->clear();
p2->append(this->last_point());
*p1 = *this;
} else {
// 1 find the line to split at
size_t line_idx = 0;
double acc_length = 0;
Point p = this->first_point();
for (const auto& l : this->lines()) {
p = l.b;

const double current_length = l.length();
if (acc_length + current_length >= length) {
p = lerp(l.a, l.b, (length - acc_length) / current_length);
break;
}
acc_length += current_length;
line_idx++;
}

//2 judge whether the cloest point is one vertex of polyline.
// and spilit the polyline at different index
int index = this->find_point(p);
if (index != -1) {
this->split_at_index(index, p1, p2);
} else {
Polyline temp;
this->split_at_index(line_idx, p1, &temp);
p1->append(p);
this->split_at_index(line_idx + 1, &temp, p2);
p2->append_before(p);
}
}
return true;
}

bool Polyline::is_straight() const
{
Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/Polyline.hpp
Expand Up @@ -130,6 +130,7 @@ class Polyline : public MultiPoint {
// template <class T> void simplify_by_visibility(const T &area);
void split_at(Point &point, Polyline* p1, Polyline* p2) const;
bool split_at_index(const size_t index, Polyline* p1, Polyline* p2) const;
bool split_at_length(const double length, Polyline* p1, Polyline* p2) const;

bool is_straight() const;
bool is_closed() const { return this->points.front() == this->points.back(); }
Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/Preset.cpp
Expand Up @@ -820,6 +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",
};

static std::vector<std::string> s_Preset_filament_options {
Expand Down
18 changes: 18 additions & 0 deletions src/libslic3r/PrintApply.cpp
Expand Up @@ -1041,6 +1041,24 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
else
m_support_used = false;

{
const auto& o = model.objects;
const auto opt_has_scarf_joint_seam = [](const DynamicConfig& c) {
return c.has("seam_slope_type") && c.opt_enum<SeamScarfType>("seam_slope_type") != SeamScarfType::None;
};
const bool has_scarf_joint_seam = std::any_of(o.begin(), o.end(), [&new_full_config, &opt_has_scarf_joint_seam](ModelObject* obj) {
return obj->get_config_value<ConfigOptionEnum<SeamScarfType>>(new_full_config, "seam_slope_type")->value != SeamScarfType::None ||
std::any_of(obj->volumes.begin(), obj->volumes.end(), [&opt_has_scarf_joint_seam](const ModelVolume* v) { return opt_has_scarf_joint_seam(v->config.get());}) ||
std::any_of(obj->layer_config_ranges.begin(), obj->layer_config_ranges.end(), [&opt_has_scarf_joint_seam](const auto& r) { return opt_has_scarf_joint_seam(r.second.get());});
});

if (has_scarf_joint_seam) {
new_full_config.set("has_scarf_joint_seam", true);
}

BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", has_scarf_joint_seam:" << has_scarf_joint_seam;
}

// Find modified keys of the various configs. Resolve overrides extruder retract values by filament profiles.
DynamicPrintConfig filament_overrides;
//BBS: add plate index
Expand Down
61 changes: 61 additions & 0 deletions src/libslic3r/PrintConfig.cpp
Expand Up @@ -263,6 +263,14 @@ static t_config_enum_values s_keys_map_SeamPosition {
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SeamPosition)

// Orca
static t_config_enum_values s_keys_map_SeamScarfType{
{ "none", int(SeamScarfType::None) },
{ "external", int(SeamScarfType::External) },
{ "all", int(SeamScarfType::All) },
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SeamScarfType)

// Orca
static t_config_enum_values s_keys_map_InternalBridgeFilter {
{ "disabled", ibfDisabled },
Expand Down Expand Up @@ -2790,6 +2798,10 @@ def = this->add("filament_loading_speed", coFloats);
def->height = 15;
def->set_default_value(new ConfigOptionStrings{"0,0", "\n0.2,0.4444", "\n0.4,0.6145", "\n0.6,0.7059", "\n0.8,0.7619", "\n1.5,0.8571", "\n2,0.8889", "\n3,0.9231", "\n5,0.9520", "\n10,1"});

def = this->add("has_scarf_joint_seam", coBool);
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));

{
struct AxisDefault {
std::string name;
Expand Down Expand Up @@ -3516,6 +3528,55 @@ def = this->add("filament_loading_speed", coFloats);
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(10,true));

def = this->add("seam_slope_type", coEnum);
def->label = L("Scarf joint seam");
def->tooltip = L("Use scarf joint to minimize seam visibility and increase seam strength.");
def->enum_keys_map = &ConfigOptionEnum<SeamScarfType>::get_enum_values();
def->enum_values.push_back("none");
def->enum_values.push_back("external");
def->enum_values.push_back("all");
def->enum_labels.push_back(L("None"));
def->enum_labels.push_back(L("Contour"));
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_start_height", coFloatOrPercent);
def->label = L("Scarf start height");
def->tooltip = L("Start height of the scarf.\n"
"This amount can be specified in millimeters or as a percentage of the current layer height. The default value for this parameter is 0.");
def->sidetext = L("mm or %");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false));

def = this->add("seam_slope_entire_loop", coBool);
def->label = L("Scarf around entire wall");
def->tooltip = L("The scarf extends to the entire length of the wall.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));

def = this->add("seam_slope_min_length", coFloat);
def->label = L("Scarf length");
def->tooltip = L("Length of the scarf. Setting this parameter to zero effectively disables the scarf.");
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(20));

def = this->add("seam_slope_steps", coInt);
def->label = L("Scarf steps");
def->tooltip = L("Minimum number of segments of each scarf.");
def->min = 1;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(10));

def = this->add("seam_slope_inner_walls", coBool);
def->label = L("Scarf joint for inner walls");
def->tooltip = L("Use scarf joint for inner walls as well.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));

def = this->add("role_based_wipe_speed", coBool);
def->label = L("Role base wipe speed");
def->tooltip = L("The wipe speed is determined by the speed of the current extrusion role."
Expand Down