#226 Moar Wipe on external perimeters

This commit is contained in:
supermerill 2020-05-11 23:58:15 +02:00
parent cbc01a1a7e
commit a0ff5c3fec
5 changed files with 77 additions and 19 deletions

View File

@ -3117,7 +3117,6 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
//exclude if min_layer_height * 2 > layer_height (increase from 2 to 3 because it's working but uses in-between)
&& this->m_layer->height >= EXTRUDER_CONFIG(min_layer_height) * 2 - EPSILON
) {
std::cout << " ok, loop vase @"<< this->m_layer->id()<<", "<< this->m_layer->print_z<<"\n";
return extrude_loop_vase(original_loop, description, speed, lower_layer_edge_grid);
}
@ -3189,21 +3188,65 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
if (m_wipe.enable)
m_wipe.path = paths.front().polyline; // TODO: don't limit wipe to last path
// make a little move inwards before leaving loop
if (paths.back().role() == erExternalPerimeter && m_layer != NULL && m_config.perimeters.value > 1 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 3) {
//wipe for External Perimeter
if (paths.back().role() == erExternalPerimeter && m_layer != NULL && m_config.perimeters.value > 1 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 2) {
//get points for wipe
Point prev_point = *(paths.back().polyline.points.end() - 2); // second to last point
// *(paths.back().polyline.points.end() - 2) this is the same as (or should be) as paths.front().first_point();
Point current_point = paths.front().first_point();
Point next_point = paths.front().polyline.points[1]; // second point
//extra wipe before the little move.
if (EXTRUDER_CONFIG(wipe_extra_perimeter) > 0) {
coord_t wipe_dist = scale_(EXTRUDER_CONFIG(wipe_extra_perimeter));
ExtrusionPaths paths_wipe;
for (int i = 0; i < paths.size(); i++) {
ExtrusionPath& path = paths[i];
if (path.length() < wipe_dist) {
wipe_dist -= path.length();
paths_wipe.push_back(path);
} else {
paths_wipe.push_back(path);
paths_wipe.back().clip_end(path.length() - wipe_dist);
ExtrusionPath next_point_path = path;
next_point_path.reverse();
next_point_path.clip_end(wipe_dist);
next_point_path.reverse();
if (next_point_path.size() > 1) {
next_point = next_point_path.polyline.points[1];
} else if (i + 1 < paths.size()) {
next_point = paths[i + 1].first_point();
} else {
next_point = paths[0].first_point();
}
break;
}
}
//move
for (ExtrusionPath& path : paths_wipe) {
for (Point& pt : path.polyline.points) {
prev_point = current_point;
current_point = pt;
gcode += m_writer.travel_to_xy(this->point_to_gcode(pt), config().gcode_comments ? "; extra wipe" : "");
}
}
}
// make a little move inwards before leaving loop
// detect angle between last and first segment
// the side depends on the original winding order of the polygon (left for contours, right for holes)
//FIXME improve the algorithm in case the loop is tiny.
//FIXME improve the algorithm in case the loop is split into segments with a low number of points (see the Point b query).
Point a = paths.front().polyline.points[1]; // second point
Point b = *(paths.back().polyline.points.end()-3); // second to last point
//FIXME improve the algorithm in case the loop is tiny.
//FIXME improve the algorithm in case the loop is split into segments with a low number of points (see the Point b query).
Point a = next_point; // second point
Point b = prev_point; // second to last point
if (is_hole_loop ? loop.polygon().is_counter_clockwise() : loop.polygon().is_clockwise()) {
// swap points
Point c = a; a = b; b = c;
}
double angle = paths.front().first_point().ccw_angle(a, b) / 3;
double angle = current_point.ccw_angle(a, b) / 3;
// turn left if contour, turn right if hole
if (is_hole_loop ? loop.polygon().is_counter_clockwise() : loop.polygon().is_clockwise()) angle *= -1;
@ -3211,15 +3254,15 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
// create the destination point along the first segment and rotate it
// we make sure we don't exceed the segment length because we don't know
// the rotation of the second segment so we might cross the object boundary
Vec2d p1 = paths.front().polyline.points.front().cast<double>();
Vec2d p2 = paths.front().polyline.points[1].cast<double>();
Vec2d v = p2 - p1;
Vec2d current_pos = current_point.cast<double>();
Vec2d next_pos = next_point.cast<double>();
Vec2d vec_dist = next_pos - current_pos;
double nd = scale_(EXTRUDER_CONFIG(nozzle_diameter));
double l2 = v.squaredNorm();
double l2 = vec_dist.squaredNorm();
// Shift by no more than a nozzle diameter.
//FIXME Hiding the seams will not work nicely for very densely discretized contours!
Point pt = ((nd * nd >= l2) ? p2 : (p1 + v * (nd / sqrt(l2)))).cast<coord_t>();
pt.rotate(angle, paths.front().polyline.points.front());
Point pt = ((nd * nd >= l2) ? next_pos : (current_pos + vec_dist * (nd / sqrt(l2)))).cast<coord_t>();
pt.rotate(angle, current_point);
// generate the travel move
gcode += m_writer.travel_to_xy(this->point_to_gcode(pt), "move inwards before travel");
}

View File

@ -150,7 +150,8 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
"use_relative_e_distances",
"use_volumetric_e",
"variable_layer_height",
"wipe"
"wipe",
"wipe_extra_perimeter"
};
static std::unordered_set<std::string> steps_ignore;

View File

@ -3255,10 +3255,20 @@ void PrintConfigDef::init_fff_params()
def->category = OptionCategory::wipe;
def->label = L("Wipe into this object");
def->tooltip = L("Object will be used to purge the nozzle after a toolchange to save material "
"that would otherwise end up in the wipe tower and decrease print time. "
"Colours of the objects will be mixed as a result.");
"that would otherwise end up in the wipe tower and decrease print time. "
"Colours of the objects will be mixed as a result.");
def->set_default_value(new ConfigOptionBool(false));
def = this->add("wipe_extra_perimeter", coFloats);
def->category = OptionCategory::extruders;
def->label = L("Extra Wipe for external perimeters");
def->tooltip = L("When the external perimeter loop extrusion end, a wipe is done, going a bit inside the print."
" The number put in this setting increase the wipe by moving the nozzle again along the loop before the final wipe.");
def->min = 0;
def->sidetext = L("mm");
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloats{ 0.f });
def = this->add("wipe_tower_bridging", coFloat);
def->label = L("Maximal bridging distance");
def->tooltip = L("Maximal distance between supports on sparse infill sections. ");
@ -3353,6 +3363,7 @@ void PrintConfigDef::init_extruder_option_keys()
"retract_restart_extra",
"retract_before_travel",
"wipe",
"wipe_extra_perimeter",
"retract_layer_change",
"retract_length_toolchange",
"retract_restart_extra_toolchange",

View File

@ -860,6 +860,7 @@ public:
ConfigOptionBool wipe_advanced;
ConfigOptionFloat wipe_advanced_nozzle_melted_volume;
ConfigOptionFloat wipe_advanced_multiplier;
ConfigOptionFloats wipe_extra_perimeter;
ConfigOptionEnum<WipeAlgo> wipe_advanced_algo;
std::string get_extrusion_axis() const
@ -954,6 +955,7 @@ protected:
OPT_PTR(wipe_advanced_nozzle_melted_volume);
OPT_PTR(wipe_advanced_multiplier);
OPT_PTR(wipe_advanced_algo);
OPT_PTR(wipe_extra_perimeter);
}
};

View File

@ -2975,6 +2975,7 @@ void TabPrinter::build_unregular_pages()
optgroup->append_single_option_line("retract_layer_change", extruder_idx);
optgroup->append_single_option_line("wipe", extruder_idx);
optgroup->append_single_option_line("retract_before_wipe", extruder_idx);
optgroup->append_single_option_line("wipe_extra_perimeter", extruder_idx);
optgroup = page->new_optgroup(_(L("Retraction when tool is disabled (advanced settings for multi-extruder setups)")));
optgroup->append_single_option_line("retract_length_toolchange", extruder_idx);