ENH: Port of "wipe inside before extruding an external perimeter" feature from super slicer (#3287)

* Wipe Inside at Start of perimeter

Co-Authored-By: Merill <6536403+supermerill@users.noreply.github.com>

* Cleaned up code and linked it to the wipe on loop parameter

* Trigger build

* Introduced wipe before external loop parameter.

* Removed redundant functions

---------

Co-authored-by: Merill <6536403+supermerill@users.noreply.github.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
Ioannis Giannakas 2023-12-27 11:21:33 +00:00 committed by GitHub
parent 90dd67e4e4
commit 7ab2fabe6a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 1 deletions

View file

@ -4437,6 +4437,58 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// extrude along the path
std::string gcode;
// Port of "wipe inside before extruding an external perimeter" feature from super slicer
if (m_config.wipe_before_external_loop.value && !paths.empty() && paths.front().size() > 1 && paths.back().size() > 1 && paths.front().role() == erExternalPerimeter) {
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();
const double nozzle_diam = EXTRUDER_CONFIG(nozzle_diameter);
// note: previous & next are inverted to extrude "in the opposite direction, and we are "rewinding"
Point previous_point = paths.front().polyline.points[1];
Point current_point = paths.front().polyline.points.front();
Point next_point = paths.back().polyline.points.back();
// can happen if seam_gap is null
if (next_point == current_point) {
next_point = paths.back().polyline.points[paths.back().polyline.points.size() - 2];
}
Point a = next_point; // second point
Point b = previous_point; // second to last point
if ((is_hole_loop ? !is_full_loop_ccw : is_full_loop_ccw)) {
// swap points
std::swap(a, b);
}
double angle = current_point.ccw_angle(a, b) / 3;
// turn outwards if contour, turn inwwards if hole
if (is_hole_loop ? !is_full_loop_ccw : is_full_loop_ccw) angle *= -1;
Vec2d current_pos = current_point.cast<double>();
Vec2d next_pos = next_point.cast<double>();
Vec2d vec_dist = next_pos - current_pos;
double vec_norm = vec_dist.norm();
// Offset distance is the minimum between half the nozzle diameter or half the line width for the upcomming perimeter
// This is to mimimize potential instances where the de-retraction is performed on top of a neighbouring
// thin perimeter due to arachne reducing line width.
coordf_t dist = std::min(scaled(nozzle_diam) * 0.5, scaled(paths.front().width) * 0.5);
// FIXME Hiding the seams will not work nicely for very densely discretized contours!
Point pt = (current_pos + vec_dist * (2 * dist / vec_norm)).cast<coord_t>();
pt.rotate(angle, current_point);
pt = (current_pos + vec_dist * (2 * dist / vec_norm)).cast<coord_t>();
pt.rotate(angle, current_point);
// use extrude instead of travel_to_xy to trigger the unretract
ExtrusionPath fake_path_wipe(Polyline{pt, current_point}, paths.front());
fake_path_wipe.mm3_per_mm = 0;
gcode += extrude_path(fake_path_wipe, "move inwards before retraction/seam", speed);
}
bool is_small_peri = false;
for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) {
// description += ExtrusionLoop::role_to_string(loop.loop_role());

View file

@ -808,7 +808,7 @@ static std::vector<std::string> s_Preset_print_options {
"small_perimeter_speed", "small_perimeter_threshold","bridge_angle", "filter_out_gap_fill", "travel_acceleration","inner_wall_acceleration", "min_width_top_surface",
"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk","travel_jerk",
"top_solid_infill_flow_ratio","bottom_solid_infill_flow_ratio","only_one_wall_first_layer", "print_flow_ratio", "seam_gap",
"role_based_wipe_speed", "wipe_speed", "accel_to_decel_enable", "accel_to_decel_factor", "wipe_on_loops",
"role_based_wipe_speed", "wipe_speed", "accel_to_decel_enable", "accel_to_decel_factor", "wipe_on_loops", "wipe_before_external_loop",
"bridge_density", "precise_outer_wall", "overhang_speed_classic", "bridge_acceleration",
"sparse_infill_acceleration", "internal_solid_infill_acceleration", "tree_support_adaptive_layer_height", "tree_support_auto_brim",
"tree_support_brim_width", "gcode_comments", "gcode_label_objects",

View file

@ -3327,6 +3327,12 @@ def = this->add("filament_loading_speed", coFloats);
def->tooltip = L("To minimize the visibility of the seam in a closed loop extrusion, a small inward movement is executed before the extruder leaves the loop.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("wipe_before_external_loop", coBool);
def->label = L("Wipe before external loop");
def->tooltip = L("To minimise visibility of potential overextrusion at the start of an external perimeter when printing with Outer/Inner or Inner/Outer/Inner wall print order, the deretraction is performed slightly on the inside from the start of the external perimeter. Thatway any potential over extrusion is hidden from the outside surface. \n\nThis is useful when printing with Outer/Inner or Inner/Outer/Inner wall print order as in these modes it is more likely an external perimeter is printed immediately after a deretraction move.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("wipe_speed", coFloatOrPercent);
def->label = L("Wipe speed");

View file

@ -880,6 +880,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, role_based_wipe_speed))
((ConfigOptionFloatOrPercent, wipe_speed))
((ConfigOptionBool, wipe_on_loops))
((ConfigOptionBool, wipe_before_external_loop))
((ConfigOptionEnum<WallInfillOrder>, wall_infill_order))
((ConfigOptionBool, precise_outer_wall))
((ConfigOptionBool, overhang_speed_classic))

View file

@ -1924,6 +1924,7 @@ void TabPrint::build()
optgroup->append_single_option_line("role_based_wipe_speed","seam");
optgroup->append_single_option_line("wipe_speed", "seam");
optgroup->append_single_option_line("wipe_on_loops","seam");
optgroup->append_single_option_line("wipe_before_external_loop","seam");
optgroup = page->new_optgroup(L("Precision"), L"param_precision");