mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-15 23:15:56 +08:00
Fix 'avoid crossing perimeters' when wipe enabled.
Also add a new setting to say if the wipe is really needed if 'avoid crossing perimeters' activated & no crossing. supermerill/SuperSlicer#1069
This commit is contained in:
parent
5b2cda2e9c
commit
9198f9e26e
@ -33,6 +33,7 @@ group:Retraction wipe
|
||||
setting:idx:wipe
|
||||
setting:idx:wipe_speed
|
||||
setting:idx:retract_before_wipe
|
||||
setting:idx:wipe_only_crossing
|
||||
setting:idx:wipe_extra_perimeter
|
||||
setting:idx:seam_gap
|
||||
group:Retraction when tool is disabled (advanced settings for multi-extruder setups)
|
||||
|
@ -3382,6 +3382,7 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
|
||||
prev_point = current_point;
|
||||
current_point = pt;
|
||||
gcode += m_writer.travel_to_xy(this->point_to_gcode(pt), 0.0, config().gcode_comments ? "; extra wipe" : "");
|
||||
this->set_last_pos(pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3417,6 +3418,7 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
|
||||
pt.rotate(angle, current_point);
|
||||
// generate the travel move
|
||||
gcode += m_writer.travel_to_xy(this->point_to_gcode(pt), 0.0, "move inwards before travel");
|
||||
this->set_last_pos(pt);
|
||||
gcode += ";" + GCodeProcessor::Wipe_End_Tag + "\n";
|
||||
|
||||
// also shift the wipe on retract
|
||||
@ -3441,6 +3443,25 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best_sqr_dist == nd * nd * 2) {
|
||||
//try to find an edge
|
||||
for (size_t poly_idx = 0; poly_idx < polys.size(); poly_idx++) {
|
||||
Polygon& poly = polys[poly_idx];
|
||||
if (poly.is_clockwise() ^ original_polygon.is_clockwise())
|
||||
poly.reverse();
|
||||
poly.points.push_back(poly.points.front());
|
||||
for (size_t pt_idx = 0; pt_idx < poly.points.size()-1; pt_idx++) {
|
||||
if (Line{ poly.points[pt_idx], poly.points[pt_idx + 1] }.distance_to_squared(pt) < best_sqr_dist) {
|
||||
poly.points.insert(poly.points.begin() + pt_idx + 1, pt);
|
||||
best_sqr_dist = 0;
|
||||
best_poly_idx = poly_idx;
|
||||
best_pt_idx = pt_idx + 1;
|
||||
poly.points.erase(poly.points.end() - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best_sqr_dist == nd * nd * 2) {
|
||||
//can't find a path, use the old one
|
||||
//BOOST_LOG_TRIVIAL(warning) << "Warn: can't find a proper path for wipe on retract. Layer " << m_layer_index << ", pos " << this->point_to_gcode(pt).x() << " : " << this->point_to_gcode(pt).y() << " !";
|
||||
@ -4228,40 +4249,49 @@ Polyline GCode::travel_to(std::string &gcode, const Point &point, ExtrusionRole
|
||||
this->origin in order to get G-code coordinates. */
|
||||
Polyline travel { this->last_pos(), point };
|
||||
|
||||
// check / compute avoid_crossing_perimeters
|
||||
bool will_cross_perimeter = this->can_cross_perimeter(travel);
|
||||
// check whether wipe could be disabled without causing visible stringing
|
||||
bool could_be_wipe_disabled = false;
|
||||
|
||||
//can use the avoid crossing algo?
|
||||
bool can_avoid_cross_peri = m_config.avoid_crossing_perimeters
|
||||
&& !m_avoid_crossing_perimeters.disabled_once()
|
||||
&& m_avoid_crossing_perimeters.is_init()
|
||||
&& !(m_config.avoid_crossing_not_first_layer && this->on_first_layer());
|
||||
|
||||
// check / compute avoid_crossing_perimeters
|
||||
bool will_cross_perimeter = this->can_cross_perimeter(travel, can_avoid_cross_peri);
|
||||
|
||||
// if a retraction would be needed (with a low min_dist threshold), try to use avoid_crossing_perimeters to plan a
|
||||
// multi-hop travel path inside the configuration space
|
||||
if (will_cross_perimeter && this->needs_retraction(travel, role, scale_d(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0.4)) * 3)
|
||||
&& m_config.avoid_crossing_perimeters
|
||||
&& ! m_avoid_crossing_perimeters.disabled_once()
|
||||
&& m_avoid_crossing_perimeters.is_init()
|
||||
&& !(m_config.avoid_crossing_not_first_layer && this->on_first_layer())) {
|
||||
&& can_avoid_cross_peri) {
|
||||
travel = m_avoid_crossing_perimeters.travel_to(*this, point, &could_be_wipe_disabled);
|
||||
}
|
||||
if(can_avoid_cross_peri)
|
||||
will_cross_perimeter = this->can_cross_perimeter(travel, false);
|
||||
|
||||
// check whether a straight travel move would need retraction
|
||||
bool needs_retraction = this->needs_retraction(travel, role);
|
||||
if (m_config.only_retract_when_crossing_perimeters)
|
||||
needs_retraction = needs_retraction && will_cross_perimeter;
|
||||
|
||||
// Re-allow avoid_crossing_perimeters for the next travel moves
|
||||
m_avoid_crossing_perimeters.reset_once_modifiers();
|
||||
|
||||
// generate G-code for the travel move
|
||||
if (needs_retraction) {
|
||||
if (m_config.avoid_crossing_perimeters && could_be_wipe_disabled)
|
||||
if (m_config.avoid_crossing_perimeters && could_be_wipe_disabled && EXTRUDER_CONFIG_WITH_DEFAULT(wipe_only_crossing, true))
|
||||
m_wipe.reset_path();
|
||||
|
||||
Point last_post_before_retract = this->last_pos();
|
||||
gcode += this->retract();
|
||||
// When "Wipe while retracting" is enabled, then extruder moves to another position, and travel from this position can cross perimeters.
|
||||
// Because of it, it is necessary to call avoid crossing perimeters for the path between previous last_post and last_post after calling retraction()
|
||||
if (last_post_before_retract != this->last_pos() && m_config.avoid_crossing_perimeters) {
|
||||
Polyline retract_travel = m_avoid_crossing_perimeters.travel_to(*this, last_post_before_retract);
|
||||
append(retract_travel.points, travel.points);
|
||||
travel = std::move(retract_travel);
|
||||
if (last_post_before_retract != this->last_pos() && can_avoid_cross_peri) {
|
||||
// Is the distance is short enough to just shortcut it?
|
||||
if (last_post_before_retract.distance_to(this->last_pos()) > scale_d(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0.4)) * 2) {
|
||||
// Because of it, it is necessary to redo the thing
|
||||
travel = m_avoid_crossing_perimeters.travel_to(*this, point);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Reset the wipe path when traveling, so one would not wipe along an old path.
|
||||
@ -4369,7 +4399,7 @@ bool GCode::needs_retraction(const Polyline& travel, ExtrusionRole role /*=erNon
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GCode::can_cross_perimeter(const Polyline& travel)
|
||||
bool GCode::can_cross_perimeter(const Polyline& travel, bool offset)
|
||||
{
|
||||
if(m_layer != nullptr)
|
||||
if ( (m_config.only_retract_when_crossing_perimeters && m_config.fill_density.value > 0) || m_config.avoid_crossing_perimeters)
|
||||
@ -4388,13 +4418,13 @@ bool GCode::can_cross_perimeter(const Polyline& travel)
|
||||
//if (inside) {
|
||||
//contained inside at least one bb
|
||||
//construct m_layer_slices_offseted if needed
|
||||
if (m_layer_slices_offseted.layer != m_layer) {
|
||||
if (m_layer_slices_offseted.layer != m_layer && offset) {
|
||||
m_layer_slices_offseted.layer = m_layer;
|
||||
m_layer_slices_offseted.diameter = scale_t(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0.4));
|
||||
m_layer_slices_offseted.slices = offset_ex(m_layer->lslices, - m_layer_slices_offseted.diameter * 1.5);
|
||||
m_layer_slices_offseted.slices = offset_ex(m_layer->lslices, -m_layer_slices_offseted.diameter * 1.5f);
|
||||
}
|
||||
// test if a expoly contains the entire travel
|
||||
for (const ExPolygon &poly : m_layer_slices_offseted.slices)
|
||||
for (const ExPolygon &poly : offset ? m_layer_slices_offseted.slices : m_layer->lslices)
|
||||
if (poly.contains(travel)) {
|
||||
return false;
|
||||
}
|
||||
@ -4427,6 +4457,8 @@ std::string GCode::retract(bool toolchange)
|
||||
methods even if we performed wipe, since this will ensure the entire retraction
|
||||
length is honored in case wipe path was too short. */
|
||||
gcode += toolchange ? m_writer.retract_for_toolchange() : m_writer.retract();
|
||||
|
||||
//check if need to lift
|
||||
bool need_lift = !m_writer.tool_is_extruder() || toolchange
|
||||
|| (BOOL_EXTRUDER_CONFIG(retract_lift_first_layer) && m_config.print_retract_lift.value != 0 && this->m_layer_index == 0)
|
||||
|| this->m_writer.get_extra_lift() > 0;
|
||||
|
@ -318,7 +318,7 @@ private:
|
||||
|
||||
Polyline travel_to(std::string& gcode, const Point &point, ExtrusionRole role);
|
||||
void write_travel_to(std::string& gcode, const Polyline& travel, std::string comment);
|
||||
bool can_cross_perimeter(const Polyline& travel);
|
||||
bool can_cross_perimeter(const Polyline& travel, bool offset);
|
||||
bool needs_retraction(const Polyline& travel, ExtrusionRole role = erNone, coordf_t max_min_dist = 0);
|
||||
std::string retract(bool toolchange = false);
|
||||
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
|
||||
|
@ -697,7 +697,7 @@ const std::vector<std::string>& Preset::filament_options()
|
||||
"filament_retract_length", "filament_retract_lift", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_speed", "filament_deretract_speed", "filament_retract_restart_extra", "filament_retract_before_travel",
|
||||
"filament_retract_layer_change", "filament_retract_before_wipe",
|
||||
"filament_seam_gap",
|
||||
"filament_wipe", "filament_wipe_extra_perimeter", "filament_wipe_speed",
|
||||
"filament_wipe", "filament_wipe_only_crossing", "filament_wipe_extra_perimeter", "filament_wipe_speed",
|
||||
// Profile compatibility
|
||||
"filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits"
|
||||
//merill adds
|
||||
|
@ -185,6 +185,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|
||||
"use_volumetric_e",
|
||||
"variable_layer_height",
|
||||
"wipe",
|
||||
"wipe_only_crossing",
|
||||
"wipe_speed",
|
||||
"wipe_extra_perimeter"
|
||||
};
|
||||
|
@ -4579,6 +4579,14 @@ void PrintConfigDef::init_fff_params()
|
||||
def->is_vector_extruder = true;
|
||||
def->set_default_value(new ConfigOptionBools{ false });
|
||||
|
||||
def = this->add("wipe_only_crossing", coBools);
|
||||
def->label = L("Wipe only when crossing perimeters");
|
||||
def->category = OptionCategory::extruders;
|
||||
def->tooltip = L("Don't wipe when you don't cross a perimeter.");
|
||||
def->mode = comAdvanced;
|
||||
def->is_vector_extruder = true;
|
||||
def->set_default_value(new ConfigOptionBools{ true });
|
||||
|
||||
def = this->add("wipe_speed", coFloats);
|
||||
def->label = L("Wipe speed");
|
||||
def->category = OptionCategory::extruders;
|
||||
@ -4843,7 +4851,7 @@ void PrintConfigDef::init_fff_params()
|
||||
"retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed", "retract_restart_extra", "retract_before_travel",
|
||||
"wipe_extra_perimeter", "wipe_speed",
|
||||
// bools
|
||||
"retract_layer_change", "wipe",
|
||||
"retract_layer_change", "wipe", "wipe_only_crossing",
|
||||
// percents
|
||||
"retract_before_wipe",
|
||||
// floatsOrPercents
|
||||
@ -4896,6 +4904,7 @@ void PrintConfigDef::init_extruder_option_keys()
|
||||
"tool_name",
|
||||
"wipe",
|
||||
"wipe_extra_perimeter",
|
||||
"wipe_only_crossing",
|
||||
"wipe_speed",
|
||||
};
|
||||
|
||||
@ -4913,6 +4922,7 @@ void PrintConfigDef::init_extruder_option_keys()
|
||||
"seam_gap",
|
||||
"wipe",
|
||||
"wipe_extra_perimeter",
|
||||
"wipe_only_crossing",
|
||||
"wipe_speed",
|
||||
};
|
||||
assert(std::is_sorted(m_extruder_retract_keys.begin(), m_extruder_retract_keys.end()));
|
||||
@ -6112,6 +6122,7 @@ std::unordered_set<std::string> prusa_export_to_remove_keys = {
|
||||
"wipe_advanced_nozzle_melted_volume",
|
||||
"wipe_advanced",
|
||||
"wipe_extra_perimeter",
|
||||
"wipe_only_crossing",
|
||||
"wipe_speed",
|
||||
"wipe_tower_brim",
|
||||
"xy_inner_size_compensation",
|
||||
|
@ -1177,6 +1177,7 @@ public:
|
||||
ConfigOptionFloat wipe_advanced_multiplier;
|
||||
ConfigOptionFloats wipe_extra_perimeter;
|
||||
ConfigOptionEnum<WipeAlgo> wipe_advanced_algo;
|
||||
ConfigOptionBools wipe_only_crossing;
|
||||
ConfigOptionFloats wipe_speed;
|
||||
ConfigOptionFloat z_step;
|
||||
ConfigOptionString color_change_gcode;
|
||||
@ -1294,6 +1295,7 @@ protected:
|
||||
OPT_PTR(wipe_advanced_multiplier);
|
||||
OPT_PTR(wipe_advanced_algo);
|
||||
OPT_PTR(wipe_extra_perimeter);
|
||||
OPT_PTR(wipe_only_crossing);
|
||||
OPT_PTR(wipe_speed);
|
||||
OPT_PTR(z_step);
|
||||
OPT_PTR(color_change_gcode);
|
||||
|
@ -2348,6 +2348,7 @@ void TabFilament::add_filament_overrides_page()
|
||||
"filament_retract_layer_change",
|
||||
"filament_seam_gap",
|
||||
"filament_wipe",
|
||||
"filament_wipe_extra_perimeter",
|
||||
"filament_wipe_speed",
|
||||
"filament_wipe_extra_perimeter"
|
||||
})
|
||||
@ -2377,6 +2378,7 @@ void TabFilament::update_filament_overrides_page()
|
||||
"filament_retract_layer_change",
|
||||
"filament_seam_gap",
|
||||
"filament_wipe",
|
||||
"filament_wipe_extra_perimeter",
|
||||
"filament_wipe_speed",
|
||||
"filament_wipe_extra_perimeter"
|
||||
};
|
||||
@ -2923,11 +2925,21 @@ void TabPrinter::clear_pages()
|
||||
|
||||
void TabPrinter::toggle_options()
|
||||
{
|
||||
if (!m_active_page || m_presets->get_edited_preset().printer_technology() == ptSLA)
|
||||
if (!m_active_page || m_presets->get_edited_preset().printer_technology() != ptFFF)
|
||||
return;
|
||||
|
||||
Field* field;
|
||||
|
||||
const DynamicPrintConfig& print_config = m_preset_bundle->fff_prints.get_edited_preset().config;
|
||||
const DynamicPrintConfig& filament_config = m_preset_bundle->filaments.get_edited_preset().config;
|
||||
const DynamicPrintConfig& printer_config = m_preset_bundle->printers.get_edited_preset().config;
|
||||
|
||||
// Print config values
|
||||
DynamicPrintConfig full_print_config;
|
||||
full_print_config.apply(print_config);
|
||||
full_print_config.apply(filament_config);
|
||||
full_print_config.apply(printer_config);
|
||||
|
||||
bool have_multiple_extruders = m_extruders_count > 1;
|
||||
field = get_field("toolchange_gcode");
|
||||
if (field) field->toggle(have_multiple_extruders);
|
||||
@ -3004,7 +3016,7 @@ void TabPrinter::toggle_options()
|
||||
|
||||
// some options only apply when not using firmware retraction
|
||||
vec.resize(0);
|
||||
vec = { "retract_speed", "deretract_speed", "retract_before_wipe", "retract_restart_extra", "wipe", "wipe_speed" };
|
||||
vec = { "retract_speed", "deretract_speed", "retract_before_wipe", "retract_restart_extra", "wipe", "wipe_speed" , "wipe_only_crossing"};
|
||||
for (auto el : vec) {
|
||||
field = get_field(el, i);
|
||||
if (field)
|
||||
@ -3012,13 +3024,17 @@ void TabPrinter::toggle_options()
|
||||
}
|
||||
|
||||
bool wipe = m_config->opt_bool("wipe", i) && have_retract_length;
|
||||
vec = { "retract_before_wipe", "wipe_speed" };
|
||||
vec = { "retract_before_wipe", "wipe_only_crossing", "wipe_speed" };
|
||||
for (auto el : vec) {
|
||||
field = get_field(el, i);
|
||||
if (field)
|
||||
field->toggle(wipe);
|
||||
}
|
||||
|
||||
// wipe_only_crossing can only work if avoid_crossing_perimeters
|
||||
if (!full_print_config.opt_bool("avoid_crossing_perimeters"))
|
||||
get_field("wipe_only_crossing", i)->toggle(false);
|
||||
|
||||
if (use_firmware_retraction && wipe) {
|
||||
wxMessageDialog dialog(parent(),
|
||||
_(L("The Wipe option is not available when using the Firmware Retraction mode.\n"
|
||||
|
Loading…
x
Reference in New Issue
Block a user