diff options
author | supermerill <merill@free.fr> | 2021-12-29 18:03:23 +0300 |
---|---|---|
committer | supermerill <merill@free.fr> | 2021-12-29 18:03:23 +0300 |
commit | b0a79d9ce5c9a5d8b792549b22e2477520c8aff1 (patch) | |
tree | 24b3a4d42fa97322847e3d88f06b5176c4802483 /src | |
parent | de7bfabae8677914aab6bb047e5fcaf24f7b7d6d (diff) | |
parent | fee585a0ae5833d3a782cde63afafe950d08ed9a (diff) |
merge more fixes
Diffstat (limited to 'src')
-rw-r--r-- | src/libslic3r/GCode.cpp | 159 | ||||
-rw-r--r-- | src/libslic3r/MedialAxis.cpp | 55 | ||||
-rw-r--r-- | src/slic3r/GUI/Tab.cpp | 4 |
3 files changed, 138 insertions, 80 deletions
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 6a4b0a97a..8c034318b 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2916,7 +2916,7 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s speed = -1; // get a copy; don't modify the orientation of the original loop object otherwise // next copies (if any) would not detect the correct orientation - ExtrusionLoop loop = original_loop; + ExtrusionLoop loop_to_seam = original_loop; if (m_layer->lower_layer != nullptr && lower_layer_edge_grid != nullptr) { if (!*lower_layer_edge_grid) { @@ -2941,31 +2941,31 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s // extrude all loops ccw //no! this was decided in perimeter_generator - bool is_hole_loop = (loop.loop_role() & ExtrusionLoopRole::elrHole) != 0;// loop.make_counter_clockwise(); - bool reverse_turn = loop.polygon().is_clockwise() ^ is_hole_loop; + bool is_hole_loop = (loop_to_seam.loop_role() & ExtrusionLoopRole::elrHole) != 0;// loop.make_counter_clockwise(); + bool reverse_turn = loop_to_seam.polygon().is_clockwise() ^ is_hole_loop; - split_at_seam_pos(loop, lower_layer_edge_grid, reverse_turn); + split_at_seam_pos(loop_to_seam, lower_layer_edge_grid, reverse_turn); + const coordf_t full_loop_length = loop_to_seam.length(); - // 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 - // we discard it in that case - coordf_t clip_length = 0; + // don't clip the path ? + ExtrusionPaths &paths = loop_to_seam.paths; + if (false && m_enable_loop_clipping && m_writer.tool_is_extruder()) { + coordf_t clip_length = scale_(m_config.seam_gap.get_abs_value(m_writer.tool()->id(), EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0))); coordf_t min_clip_length = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)) * 0.15; - if (m_enable_loop_clipping && m_writer.tool_is_extruder()) - clip_length = scale_(m_config.seam_gap.get_abs_value(m_writer.tool()->id(), EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0))); - - // get paths - ExtrusionPaths paths = loop.paths; - ExtrusionPaths clipped; - if (clip_length > min_clip_length) { - clipped = clip_end(paths, clip_length); - clip_end(clipped, min_clip_length); - for (ExtrusionPath& ep : clipped) - ep.mm3_per_mm = 0; - append(paths, clipped); - } else { - clip_end(paths, clip_length); + + // get paths + ExtrusionPaths clipped; + if (clip_length > min_clip_length) { + clipped = clip_end(paths, clip_length); + clip_end(clipped, min_clip_length); + for (ExtrusionPath& ep : clipped) + ep.mm3_per_mm = 0; + append(paths, clipped); + } else { + clip_end(paths, clip_length); + } } + if (paths.empty()) return ""; // apply the small/external? perimeter speed @@ -2973,12 +2973,12 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s coordf_t min_length = scale_d(this->m_config.small_perimeter_min_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0))); coordf_t max_length = scale_d(this->m_config.small_perimeter_max_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0))); max_length = std::max(min_length, max_length); - if (loop.length() < max_length) { - if (loop.length() <= min_length) { + if (full_loop_length < max_length) { + if (full_loop_length <= min_length) { speed = SMALL_PERIMETER_SPEED_RATIO_OFFSET; } else if (max_length > min_length) { //use a negative speed: it will be use as a ratio when computing the real speed - speed = SMALL_PERIMETER_SPEED_RATIO_OFFSET - (loop.length() - min_length) / (max_length - min_length); + speed = SMALL_PERIMETER_SPEED_RATIO_OFFSET - (full_loop_length - min_length) / (max_length - min_length); } } } @@ -3244,7 +3244,7 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s // get a copy; don't modify the orientation of the original loop object otherwise // next copies (if any) would not detect the correct orientation - ExtrusionLoop loop = original_loop; + ExtrusionLoop loop_to_seam = original_loop; if (m_layer->lower_layer != nullptr && lower_layer_edge_grid != nullptr) { if (! *lower_layer_edge_grid) { @@ -3270,35 +3270,42 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s // extrude all loops ccw //no! this was decided in perimeter_generator //but we need to know where is "inside", so we will use is_hole_loop. if is_hole_loop, then we need toconsider that the right direction is clockwise, else counter clockwise. - bool is_hole_loop = (loop.loop_role() & ExtrusionLoopRole::elrHole) != 0;// loop.make_counter_clockwise(); + bool is_hole_loop = (loop_to_seam.loop_role() & ExtrusionLoopRole::elrHole) != 0;// loop.make_counter_clockwise(); //if spiral vase, we have to ensure that all loops are in the same orientation. if (this->m_config.spiral_vase) { - loop.make_counter_clockwise(); + loop_to_seam.make_counter_clockwise(); is_hole_loop = false; } - split_at_seam_pos(loop, lower_layer_edge_grid, is_hole_loop); + split_at_seam_pos(loop_to_seam, lower_layer_edge_grid, is_hole_loop); + const coordf_t full_loop_length = loop_to_seam.length(); + const bool is_full_loop_ccw = loop_to_seam.polygon().is_counter_clockwise(); + //after that point, loop_to_seam can be modified by 'paths', so don't use it anymore // 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 // we discard it in that case - coordf_t clip_length = 0; - coordf_t min_clip_length = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)) * 0.15; - if (m_enable_loop_clipping && m_writer.tool_is_extruder()) - clip_length = scale_(m_config.seam_gap.get_abs_value(m_writer.tool()->id(), EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0))); - - // get paths - ExtrusionPaths paths = loop.paths; - ExtrusionPaths clipped; - if (clip_length > min_clip_length) { - clipped = clip_end(paths, clip_length); - clip_end(clipped, min_clip_length); - for (ExtrusionPath& ep : clipped) - ep.mm3_per_mm = 0; - append(paths, clipped); - } else { - clip_end(paths, clip_length); + ExtrusionPaths& paths = loop_to_seam.paths; + if (m_enable_loop_clipping && m_writer.tool_is_extruder()) { + coordf_t clip_length = scale_(m_config.seam_gap.get_abs_value(m_writer.tool()->id(), EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0))); + coordf_t min_clip_length = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0)) * 0.15; + + // get paths + ExtrusionPaths clipped; + if (clip_length > min_clip_length) { + // remove clip_length, like normally, but keep the removed part + clipped = clip_end(paths, clip_length); + // remove min_clip_length from the removed paths + clip_end(clipped, min_clip_length); + // ensure that the removed paths are travels + for (ExtrusionPath& ep : clipped) + ep.mm3_per_mm = 0; + // re-add removed paths as travels. + append(paths, clipped); + } else { + clip_end(paths, clip_length); + } } if (paths.empty()) return ""; @@ -3306,12 +3313,12 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s if (speed == -1 && is_perimeter(paths.front().role()) && paths.front().role() != erThinWall) { double min_length = scale_d(this->m_config.small_perimeter_min_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0))); double max_length = scale_d(this->m_config.small_perimeter_max_length.get_abs_value(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0))); - if (loop.length() < max_length) { - if (loop.length() <= min_length) { + if (full_loop_length < max_length) { + if (full_loop_length <= min_length) { speed = SMALL_PERIMETER_SPEED_RATIO_OFFSET; } else if (max_length > min_length) { //use a negative speed: it will be use as a ratio when computing the real speed - speed = SMALL_PERIMETER_SPEED_RATIO_OFFSET - (loop.length() - min_length) / (max_length - min_length); + speed = SMALL_PERIMETER_SPEED_RATIO_OFFSET - (full_loop_length - min_length) / (max_length - min_length); } } } @@ -3331,8 +3338,9 @@ 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 - //wipe for External Perimeter - if (paths.back().role() == erExternalPerimeter && m_layer != NULL && m_config.perimeters.value > 0 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 2) { + //wipe for External Perimeter (and not vase) + if (paths.back().role() == erExternalPerimeter && m_layer != NULL && m_config.perimeters.value > 0 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 2 + && (m_enable_loop_clipping && m_writer.tool_is_extruder()) ) { //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(); @@ -3349,32 +3357,32 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s ExtrusionPath& path = paths[i]; if (wipe_dist > 0) { //first, we use the polyline for wipe_extra_perimeter - 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(); + if (path.length() < wipe_dist) { + wipe_dist -= path.length(); + paths_wipe.push_back(path); } else { - next_point = paths[0].first_point(); + 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(); + } + m_wipe.path.append(path.polyline); + m_wipe.path.clip_start(wipe_dist); + wipe_dist -= path.length(); } - m_wipe.path.append(path.polyline); - m_wipe.path.clip_start(wipe_dist); - wipe_dist -= path.length(); - } } else { //then, it's stored for the wipe on retract m_wipe.path.append(path.polyline); - } + } } //move for (ExtrusionPath& path : paths_wipe) { @@ -3395,14 +3403,14 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s //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()) { + if (is_hole_loop ? is_full_loop_ccw : (!is_full_loop_ccw)) { // swap points Point c = a; a = b; b = c; } 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; + if (is_hole_loop ? is_full_loop_ccw : (!is_full_loop_ccw)) angle *= -1; // 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 @@ -4438,13 +4446,18 @@ Polyline GCode::travel_to(std::string &gcode, const Point &point, ExtrusionRole 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. + bool updated_first_pos = false; 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); + updated_first_pos = true; } } + if (!updated_first_pos) { + travel.points.front() = this->last_pos(); + } } else { // Reset the wipe path when traveling, so one would not wipe along an old path. m_wipe.reset_path(); diff --git a/src/libslic3r/MedialAxis.cpp b/src/libslic3r/MedialAxis.cpp index 02b4816e2..e9fc6ee4f 100644 --- a/src/libslic3r/MedialAxis.cpp +++ b/src/libslic3r/MedialAxis.cpp @@ -651,6 +651,8 @@ MedialAxis::remove_bits(ThickPolylines &pp) ///reorder, in case of change std::sort(pp.begin(), pp.end(), [](const ThickPolyline & a, const ThickPolyline & b) { return a.length() < b.length(); }); } + + //TODO: check if there is a U-turn (almost 180° direction change) : remove it. } void @@ -1492,6 +1494,40 @@ MedialAxis::remove_too_short_polylines(ThickPolylines& pp, const coord_t min_siz } if (changes) concatThickPolylines(pp); } + + //remove points too near each other + changes = true; + while (changes) { + changes = false; + + coordf_t shortest_size = (coordf_t)min_size; + size_t shortest_idx = -1; + for (size_t polyidx = 0; polyidx < pp.size(); ++polyidx) { + ThickPolyline& tp = pp[polyidx]; + for (size_t pt_idx = 1; pt_idx < tp.points.size() - 1; pt_idx++) { + if (tp.points[pt_idx - 1].coincides_with_epsilon(tp.points[pt_idx])) { + tp.points.erase(tp.points.begin() + pt_idx); + tp.width.erase(tp.width.begin() + pt_idx); + pt_idx--; + changes = true; + } + } + //check last segment + if (tp.points.size() > 2 && tp.points[tp.points.size() - 2].coincides_with_epsilon(tp.points.back())) { + tp.points.erase(tp.points.end() - 2); + tp.width.erase(tp.width.end() - 2); + changes = true; + } + //delete null-length polylines + if (tp.length() < SCALED_EPSILON && tp.first_point().coincides_with_epsilon(tp.last_point())) { + pp.erase(pp.begin() + polyidx); + --polyidx; + changes = true; + } + } + if (changes) concatThickPolylines(pp); + } + } void @@ -2037,7 +2073,7 @@ thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow fl // variable extrusion within a single move; this value shall only affect the amount // of segments, and any pruning shall be performed before we apply this tolerance const coord_t tolerance = flow.scaled_width() / 10;//scale_(0.05); - + ExtrusionEntityCollection coll; for (const ThickPolyline &p : polylines) { ExtrusionPaths paths; @@ -2052,8 +2088,8 @@ thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow fl const coordf_t prev_line_len = saved_line_len; saved_line_len = line_len; - assert(line.a_width >= 0); - assert(line.b_width >= 0); + assert(line.a_width >= 0 && !std::isnan(line.a_width)); + assert(line.b_width >= 0 && !std::isnan(line.b_width)); coord_t thickness_delta = std::abs(line.a_width - line.b_width); // split lines ? @@ -2108,7 +2144,16 @@ thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow fl coordf_t width = prev_line_len * (prev_line.a_width + prev_line.b_width) / 2; width += line_len * (line.a_width + line.b_width) / 2; prev_line.b = line.b; - coordf_t new_length = prev_line.length(); + const coordf_t new_length = prev_line.length(); + if (new_length < SCALED_EPSILON) { + // too short, remove it and restart + if (i > 1) { + line.a = lines[i - 2].b; + } + lines.erase(lines.begin() + i-1); + i-=2; + continue; + } width /= new_length; prev_line.a_width = width; prev_line.b_width = width; @@ -2131,7 +2176,7 @@ thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow fl // but we can't extrude with a negative spacing, so we have to gradually fall back to spacing if the width is too small. // default: extrude a thin wall that doesn't go outside of the specified width. - double wanted_width = unscaled(line.a_width); + coordf_t wanted_width = unscaled(line.a_width); if (role == erGapFill) { // Convert from spacing to extrusion width based on the extrusion model // of a square extrusion ended with semi circles. diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 38ec11954..2e7ccf7c3 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2348,7 +2348,7 @@ void TabFilament::add_filament_overrides_page() "filament_retract_layer_change", "filament_seam_gap", "filament_wipe", - "filament_wipe_extra_perimeter", + "filament_wipe_only_crossing", "filament_wipe_speed", "filament_wipe_extra_perimeter" }) @@ -2378,7 +2378,7 @@ void TabFilament::update_filament_overrides_page() "filament_retract_layer_change", "filament_seam_gap", "filament_wipe", - "filament_wipe_extra_perimeter", + "filament_wipe_only_crossing", "filament_wipe_speed", "filament_wipe_extra_perimeter" }; |