Skip to content

Commit

Permalink
Reverse extrusion directions
Browse files Browse the repository at this point in the history
  • Loading branch information
vovodroid committed May 11, 2024
1 parent dba0377 commit 39da786
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 10 deletions.
30 changes: 22 additions & 8 deletions src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2952,7 +2952,7 @@ static inline bool validate_smooth_path(const GCode::SmoothPath &smooth_path, bo

static constexpr const double min_gcode_segment_length = 0.002;

std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed)
std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, bool reverse, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed)
{
// Extrude all loops CCW.
bool is_hole = loop_src.is_clockwise();
Expand All @@ -2964,7 +2964,7 @@ std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GC
// Because the G-code export has 1um resolution, don't generate segments shorter than 1.5 microns,
// thus empty path segments will not be produced by G-code export.
GCode::SmoothPath smooth_path = smooth_path_cache.resolve_or_fit_split_with_seam(
loop_src, is_hole, m_scaled_resolution, seam_point, scaled<double>(0.0015));
loop_src, reverse ^ is_hole, m_scaled_resolution, seam_point, scaled<double>(0.0015));

// 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
Expand Down Expand Up @@ -3012,7 +3012,7 @@ std::string GCodeGenerator::extrude_skirt(
assert(loop_src.is_counter_clockwise());
Point seam_point = this->last_position.has_value() ? *this->last_position : Point::Zero();
GCode::SmoothPath smooth_path = smooth_path_cache.resolve_or_fit_split_with_seam(
loop_src, false, m_scaled_resolution, seam_point, scaled<double>(0.0015));
loop_src, this->m_layer->id() % 2 == 1, m_scaled_resolution, seam_point, scaled<double>(0.0015));

// 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
Expand Down Expand Up @@ -3073,9 +3073,22 @@ std::string GCodeGenerator::extrude_entity(const ExtrusionEntityReference &entit
return this->extrude_path(*path, entity.flipped(), smooth_path_cache, description, speed);
else if (const ExtrusionMultiPath *multipath = dynamic_cast<const ExtrusionMultiPath*>(&entity.extrusion_entity()))
return this->extrude_multi_path(*multipath, entity.flipped(), smooth_path_cache, description, speed);
else if (const ExtrusionLoop *loop = dynamic_cast<const ExtrusionLoop*>(&entity.extrusion_entity()))
return this->extrude_loop(*loop, smooth_path_cache, description, speed);
else
else if (const ExtrusionLoop *loop = dynamic_cast<const ExtrusionLoop*>(&entity.extrusion_entity())) {
ExtrusionRole role = entity.extrusion_entity().role();
bool reverse =
this->m_layer->id() % 2 == 1 &&
(role.is_perimeter() && this->config().reverse_perimeters_even ||
role.is_infill() && this->config().reverse_infill_even);

if (this->config().reverse_overhangs) {
for (ExtrusionPath el: loop->paths)
if (el.role().is_perimeter() && el.role().is_bridge() && this->m_layer->id() % 2 == 1) {
reverse = true;
break;
}
}
return this->extrude_loop(*loop, reverse, smooth_path_cache, description, speed);
} else
throw Slic3r::InvalidArgument("Invalid argument supplied to extrude()");
return {};
}
Expand Down Expand Up @@ -3106,10 +3119,11 @@ std::string GCodeGenerator::extrude_support(const ExtrusionEntityReferences &sup
const auto label = (role == ExtrusionRole::SupportMaterial) ? support_label : support_interface_label;
const double speed = (role == ExtrusionRole::SupportMaterial) ? support_speed : support_interface_speed;
const ExtrusionPath *path = dynamic_cast<const ExtrusionPath*>(&eref.extrusion_entity());
bool reverse = (this->m_layer->id() % 2 == 1);
if (path)
gcode += this->extrude_path(*path, eref.flipped(), smooth_path_cache, label, speed);
gcode += this->extrude_path(*path, reverse ^ eref.flipped(), smooth_path_cache, label, speed);
else if (const ExtrusionMultiPath *multipath = dynamic_cast<const ExtrusionMultiPath*>(&eref.extrusion_entity()); multipath)
gcode += this->extrude_multi_path(*multipath, eref.flipped(), smooth_path_cache, label, speed);
gcode += this->extrude_multi_path(*multipath, reverse ^ eref.flipped(), smooth_path_cache, label, speed);
else {
const ExtrusionEntityCollection *eec = dynamic_cast<const ExtrusionEntityCollection*>(&eref.extrusion_entity());
assert(eec);
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/GCode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ class GCodeGenerator {
bool vase_mode
);
std::string extrude_entity(const ExtrusionEntityReference &entity, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.);
std::string extrude_loop(const ExtrusionLoop &loop, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.);
std::string extrude_loop(const ExtrusionLoop &loop, bool reverse, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed = -1.);
std::string extrude_skirt(const ExtrusionLoop &loop_src, const ExtrusionFlow &extrusion_flow_override,
const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed);

Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/Preset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ static std::vector<std::string> s_Preset_print_options {
"mmu_segmented_region_interlocking_depth", "wipe_tower_extruder", "wipe_tower_no_sparse_layers", "wipe_tower_extra_flow", "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"
"reverse_overhangs", "reverse_perimeters_even", "reverse_infill_even"
};

static std::vector<std::string> s_Preset_filament_options {
Expand Down
22 changes: 22 additions & 0 deletions src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2494,6 +2494,7 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));

def->sidetext = L("%");
#if 0
def = this->add("seam_preferred_direction", coFloat);
// def->gui_type = ConfigOptionDef::GUIType::slider;
Expand Down Expand Up @@ -3535,6 +3536,27 @@ void PrintConfigDef::init_fff_params()
def->min = 0;
def->set_default_value(new ConfigOptionFloatOrPercent(85, true));

def = this->add("reverse_overhangs", coBool);
def->label = L("Reverse external perimeters with overhang direction every layer");
def->category = L("Advanced");
def->tooltip = L("Extrude each layer overhang perimeters in opposite direction, improving quality.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));

def = this->add("reverse_perimeters_even", coBool);
def->label = L("Reverse perimeters directions on even layers");
def->category = L("Advanced");
def->tooltip = L("Extrude each layer perimeters in opposite direction, reduce internal stress and warping.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));

def = this->add("reverse_infill_even", coBool);
def->label = L("Reverse infill direction every layer");
def->category = L("Advanced");
def->tooltip = L("Extrude each layer infill in opposite direction, reduce internal stress and warping.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));

// Declare retract values for filament profile, overriding the printer's extruder profile.
for (const char *opt_key : {
// floats
Expand Down
4 changes: 4 additions & 0 deletions src/libslic3r/PrintConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,10 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, perimeter_speed))
// Total number of perimeters.
((ConfigOptionInt, perimeters))
//Perimeters reverse
((ConfigOptionBool, reverse_overhangs))
((ConfigOptionBool, reverse_perimeters_even))
((ConfigOptionBool, reverse_infill_even))
((ConfigOptionFloatOrPercent, small_perimeter_speed))
((ConfigOptionFloat, solid_infill_below_area))
((ConfigOptionInt, solid_infill_extruder))
Expand Down
4 changes: 3 additions & 1 deletion src/libslic3r/PrintObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,9 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "perimeter_extrusion_width"
|| opt_key == "infill_overlap"
|| opt_key == "external_perimeters_first"
|| opt_key == "arc_fitting") {
|| opt_key == "arc_fitting"
|| opt_key == "reverse_overhangs"
|| opt_key == "reverse_perimeters_even") {
steps.emplace_back(posPerimeters);
} else if (
opt_key == "gap_fill_enabled"
Expand Down
5 changes: 5 additions & 0 deletions src/slic3r/GUI/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1691,6 +1691,11 @@ void TabPrint::build()
optgroup->append_single_option_line("xy_size_compensation");
optgroup->append_single_option_line("elefant_foot_compensation", "elephant-foot-compensation_114487");

optgroup = page->new_optgroup(L("Extrusion direction reverse"));
optgroup->append_single_option_line("reverse_overhangs");
optgroup->append_single_option_line("reverse_perimeters_even");
optgroup->append_single_option_line("reverse_infill_even");

optgroup = page->new_optgroup(L("Arachne perimeter generator"));
optgroup->append_single_option_line("wall_transition_angle");
optgroup->append_single_option_line("wall_transition_filter_deviation");
Expand Down

0 comments on commit 39da786

Please sign in to comment.