Skip to content

Commit

Permalink
Reverse extrusion directions
Browse files Browse the repository at this point in the history
  • Loading branch information
vovodroid committed Jan 25, 2024
1 parent 97c3679 commit e504ff2
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 12 deletions.
2 changes: 2 additions & 0 deletions src/libslic3r/ExtrusionRole.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ struct ExtrusionRole : public ExtrusionRoleModifiers

bool is_perimeter() const { return this->ExtrusionRoleModifiers::has(ExtrusionRoleModifier::Perimeter); }
bool is_external_perimeter() const { return this->is_perimeter() && this->is_external(); }
bool is_internal_perimeter() const { return is_perimeter() && !this->is_external(); }
bool is_overhang_perimeter() const { return this->is_perimeter() && ExtrusionRoleModifiers::has(ExtrusionRoleModifier::Bridge); }
bool is_infill() const { return this->ExtrusionRoleModifiers::has(ExtrusionRoleModifier::Infill); }
bool is_solid_infill() const { return this->is_infill() && this->ExtrusionRoleModifiers::has(ExtrusionRoleModifier::Solid); }
bool is_sparse_infill() const { return this->is_infill() && ! this->ExtrusionRoleModifiers::has(ExtrusionRoleModifier::Solid); }
Expand Down
32 changes: 24 additions & 8 deletions src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2795,7 +2795,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 @@ -2807,7 +2807,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 @@ -2854,7 +2854,7 @@ std::string GCodeGenerator::extrude_skirt(
{
assert(loop_src.is_counter_clockwise());
GCode::SmoothPath smooth_path = smooth_path_cache.resolve_or_fit_split_with_seam(
loop_src, false, m_scaled_resolution, this->last_pos(), scaled<double>(0.0015));
loop_src, this->m_layer->id() % 2 == 1, m_scaled_resolution, this->last_pos(), 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 @@ -2912,9 +2912,24 @@ 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_internal_perimeter() && this->config().internal_perimeters_reverse ||
role.is_infill() && this->config().infill_reverse)
||
role.is_internal_perimeter() && this->config().internal_perimeters_reverse && this->config().perimeters == 2;

if (this->config().overhangs_reverse) {
for (ExtrusionPath el: loop->paths)
if (el.role().is_overhang_perimeter() && 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 @@ -2945,10 +2960,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 @@ -372,7 +372,7 @@ class GCodeGenerator {
const bool spiral_vase_enabled
);
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
3 changes: 2 additions & 1 deletion src/libslic3r/Preset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ static std::vector<std::string> s_Preset_print_options {
"wipe_tower_width", "wipe_tower_cone_angle", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width",
"mmu_segmented_region_interlocking_depth", "wipe_tower_extruder", "wipe_tower_no_sparse_layers", "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"
"wall_distribution_count", "min_feature_size", "min_bead_width",
"overhangs_reverse", "internal_perimeters_reverse", "infill_reverse"
};

static std::vector<std::string> s_Preset_filament_options {
Expand Down
21 changes: 21 additions & 0 deletions src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3482,6 +3482,27 @@ void PrintConfigDef::init_fff_params()
def->min = 0;
def->set_default_value(new ConfigOptionFloatOrPercent(85, true));

def = this->add("overhangs_reverse", coBool);
def->label = L("Reverse overhang perimeters directions 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("internal_perimeters_reverse", coBool);
def->label = L("Reverse internal perimeter directions every layer");
def->category = L("Advanced");
def->tooltip = L("Extrude each layer internal perimeters in opposite direction, reduce internal stress and warping.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));

def = this->add("infill_reverse", 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 @@ -599,6 +599,10 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, thick_bridges))
((ConfigOptionFloat, xy_size_compensation))
((ConfigOptionBool, wipe_into_objects))
//Perimeters reverse
((ConfigOptionBool, overhangs_reverse))
((ConfigOptionBool, internal_perimeters_reverse))
((ConfigOptionBool, infill_reverse))
)

PRINT_CONFIG_CLASS_DEFINE(
Expand Down
7 changes: 5 additions & 2 deletions 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 == "overhangs_reverse"
|| opt_key == "internal_perimeters_reverse") {
steps.emplace_back(posPerimeters);
} else if (
opt_key == "gap_fill_enabled"
Expand Down Expand Up @@ -826,7 +828,8 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "infill_anchor"
|| opt_key == "infill_anchor_max"
|| opt_key == "top_infill_extrusion_width"
|| opt_key == "first_layer_extrusion_width") {
|| opt_key == "first_layer_extrusion_width"
|| opt_key == "infill_reverse" ) {
steps.emplace_back(posInfill);
} else if (opt_key == "fill_pattern") {
steps.emplace_back(posPrepareInfill);
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 @@ -1689,6 +1689,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("overhangs_reverse");
optgroup->append_single_option_line("internal_perimeters_reverse");
optgroup->append_single_option_line("infill_reverse");

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 e504ff2

Please sign in to comment.