diff options
author | Lukáš Hejl <hejl.lukas@gmail.com> | 2022-07-22 12:50:58 +0300 |
---|---|---|
committer | Lukas Matena <lukasmatena@seznam.cz> | 2022-08-18 18:00:28 +0300 |
commit | 952a6c882c7553644aec74563e7e2be3716a2bfb (patch) | |
tree | d0b112cce639e2e37c8897d0fc5306cf0b362337 | |
parent | 0c22ca3ece854d982faa6c5448f7320c85abcef6 (diff) |
Fixed an issue that the wipe was shorter when it was located where extrusion width was changing.
-rw-r--r-- | src/libslic3r/Arachne/utils/ExtrusionLine.cpp | 4 | ||||
-rw-r--r-- | src/libslic3r/Fill/Fill.cpp | 11 | ||||
-rw-r--r-- | src/libslic3r/GCode.cpp | 41 | ||||
-rw-r--r-- | src/libslic3r/PerimeterGenerator.cpp | 85 | ||||
-rw-r--r-- | src/libslic3r/PerimeterGenerator.hpp | 2 |
5 files changed, 100 insertions, 43 deletions
diff --git a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp index a5734f478..75e4d5338 100644 --- a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp +++ b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp @@ -268,13 +268,13 @@ void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extr { for (const ClipperLib_Z::Path &extrusion_path : extrusion_paths) { ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion_path); - Slic3r::append(dst, thick_polyline_to_extrusion_paths(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON))); + Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON)).paths); } } void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow) { ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion); - Slic3r::append(dst, thick_polyline_to_extrusion_paths(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON))); + Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON)).paths); } } // namespace Slic3r
\ No newline at end of file diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index d6eaff03a..9d25143fb 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -426,14 +426,13 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: for (const ThickPolyline &thick_polyline : thick_polylines) { Flow new_flow = surface_fill.params.flow.with_spacing(float(f->spacing)); - ExtrusionPaths paths = thick_polyline_to_extrusion_paths(thick_polyline, surface_fill.params.extrusion_role, new_flow, scaled<float>(0.05), 0); + ExtrusionMultiPath multi_path = thick_polyline_to_multi_path(thick_polyline, surface_fill.params.extrusion_role, new_flow, scaled<float>(0.05), float(SCALED_EPSILON)); // Append paths to collection. - if (!paths.empty()) { - if (paths.front().first_point() == paths.back().last_point()) - eec->entities.emplace_back(new ExtrusionLoop(std::move(paths))); + if (!multi_path.empty()) { + if (multi_path.paths.front().first_point() == multi_path.paths.back().last_point()) + eec->entities.emplace_back(new ExtrusionLoop(std::move(multi_path.paths))); else - for (ExtrusionPath &path : paths) - eec->entities.emplace_back(new ExtrusionPath(std::move(path))); + eec->entities.emplace_back(new ExtrusionMultiPath(std::move(multi_path))); } } diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index f2c435c4f..f8fc2e5a7 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2642,6 +2642,12 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou // thus empty path segments will not be produced by G-code export. loop.split_at(last_pos, false, scaled<double>(0.0015)); + for (auto it = std::next(loop.paths.begin()); it != loop.paths.end(); ++it) { + assert(it->polyline.points.size() >= 2); + assert(std::prev(it)->polyline.last_point() == it->polyline.first_point()); + } + assert(loop.paths.front().first_point() == loop.paths.back().last_point()); + // 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 @@ -2670,8 +2676,21 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou // reset acceleration gcode += m_writer.set_acceleration((unsigned int)(m_config.default_acceleration.value + 0.5)); - if (m_wipe.enable) - m_wipe.path = paths.front().polyline; // TODO: don't limit wipe to last path + if (m_wipe.enable) { + m_wipe.path = paths.front().polyline; + + for (auto it = std::next(paths.begin()); it != paths.end(); ++it) { + if (is_bridge(it->role())) + break; // Don't perform a wipe on bridges. + + assert(it->polyline.points.size() >= 2); + assert(m_wipe.path.points.back() == it->polyline.first_point()); + if (m_wipe.path.points.back() != it->polyline.first_point()) + break; // ExtrusionLoop is interrupted in some place. + + m_wipe.path.points.insert(m_wipe.path.points.end(), it->polyline.points.begin() + 1, it->polyline.points.end()); + } + } // 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) { @@ -2712,6 +2731,10 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string description, double speed) { + for (auto it = std::next(multipath.paths.begin()); it != multipath.paths.end(); ++it) { + assert(it->polyline.points.size() >= 2); + assert(std::prev(it)->polyline.last_point() == it->polyline.first_point()); + } // extrude along the path std::string gcode; for (ExtrusionPath path : multipath.paths) { @@ -2721,8 +2744,20 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string gcode += this->_extrude(path, description, speed); } if (m_wipe.enable) { - m_wipe.path = std::move(multipath.paths.back().polyline); // TODO: don't limit wipe to last path + m_wipe.path = std::move(multipath.paths.back().polyline); m_wipe.path.reverse(); + + for (auto it = std::next(multipath.paths.rbegin()); it != multipath.paths.rend(); ++it) { + if (is_bridge(it->role())) + break; // Do not perform a wipe on bridges. + + assert(it->polyline.points.size() >= 2); + assert(m_wipe.path.points.back() == it->polyline.last_point()); + if (m_wipe.path.points.back() != it->polyline.last_point()) + break; // ExtrusionMultiPath is interrupted in some place. + + m_wipe.path.points.insert(m_wipe.path.points.end(), it->polyline.points.rbegin() + 1, it->polyline.points.rend()); + } } // reset acceleration gcode += m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5)); diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 830d48571..e61f9097d 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -21,12 +21,12 @@ namespace Slic3r { -ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance) +ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance) { - ExtrusionPaths paths; - ExtrusionPath path(role); - ThickLines lines = thick_polyline.thicklines(); - + ExtrusionMultiPath multi_path; + ExtrusionPath path(role); + ThickLines lines = thick_polyline.thicklines(); + for (int i = 0; i < (int)lines.size(); ++i) { const ThickLine& line = lines[i]; assert(line.a_width >= SCALED_EPSILON && line.b_width >= SCALED_EPSILON); @@ -38,8 +38,8 @@ ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_poly path.polyline.points.back() = line.b; // If the variable path is non-empty, connect this tiny line to it. else if (i + 1 < (int)lines.size()) // If there is at least one following line, connect this tiny line to it. lines[i + 1].a = line.a; - else if (!paths.empty()) - paths.back().polyline.points.back() = line.b; // Connect this tiny line to the last finished path. + else if (!multi_path.paths.empty()) + multi_path.paths.back().polyline.points.back() = line.b; // Connect this tiny line to the last finished path. // If any of the above isn't satisfied, then remove this tiny line. continue; @@ -103,40 +103,38 @@ ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_poly path.polyline.append(line.b); } else { // we need to initialize a new line - paths.emplace_back(std::move(path)); + multi_path.paths.emplace_back(std::move(path)); path = ExtrusionPath(role); -- i; } } } if (path.polyline.is_valid()) - paths.emplace_back(std::move(path)); - return paths; + multi_path.paths.emplace_back(std::move(path)); + return multi_path; } -static void variable_width(const ThickPolylines& polylines, ExtrusionRole role, const Flow &flow, std::vector<ExtrusionEntity*> &out) +static void variable_width(const ThickPolylines &polylines, ExtrusionRole role, const Flow &flow, std::vector<ExtrusionEntity *> &out) { - // This value determines granularity of adaptive width, as G-code does not allow - // 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 auto tolerance = float(scale_(0.05)); - for (const ThickPolyline &p : polylines) { - ExtrusionPaths paths = thick_polyline_to_extrusion_paths(p, role, flow, tolerance, tolerance); - // Append paths to collection. - if (!paths.empty()) { - for (auto it = std::next(paths.begin()); it != paths.end(); ++it) { + // This value determines granularity of adaptive width, as G-code does not allow + // 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 auto tolerance = float(scale_(0.05)); + for (const ThickPolyline &p : polylines) { + ExtrusionMultiPath multi_path = thick_polyline_to_multi_path(p, role, flow, tolerance, tolerance); + // Append paths to collection. + if (!multi_path.paths.empty()) { + for (auto it = std::next(multi_path.paths.begin()); it != multi_path.paths.end(); ++it) { assert(it->polyline.points.size() >= 2); assert(std::prev(it)->polyline.last_point() == it->polyline.first_point()); } - if (paths.front().first_point() == paths.back().last_point()) { - out.emplace_back(new ExtrusionLoop(std::move(paths))); - } else { - for (ExtrusionPath &path : paths) - out.emplace_back(new ExtrusionPath(std::move(path))); - } - } - } + if (multi_path.paths.front().first_point() == multi_path.paths.back().last_point()) + out.emplace_back(new ExtrusionLoop(std::move(multi_path.paths))); + else + out.emplace_back(new ExtrusionMultiPath(std::move(multi_path))); + } + } } // Hierarchy of perimeters. @@ -534,10 +532,35 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &p else extrusion_loop.make_clockwise(); + for (auto it = std::next(extrusion_loop.paths.begin()); it != extrusion_loop.paths.end(); ++it) { + assert(it->polyline.points.size() >= 2); + assert(std::prev(it)->polyline.last_point() == it->polyline.first_point()); + } + assert(extrusion_loop.paths.front().first_point() == extrusion_loop.paths.back().last_point()); + extrusion_coll.append(std::move(extrusion_loop)); - } else - for (ExtrusionPath &path : paths) - extrusion_coll.append(ExtrusionPath(std::move(path))); + } else { + // Because we are processing one ExtrusionLine all ExtrusionPaths should form one connected path. + // But there is possibility that due to numerical issue there is poss + assert([&paths = std::as_const(paths)]() -> bool { + for (auto it = std::next(paths.begin()); it != paths.end(); ++it) + if (std::prev(it)->polyline.last_point() != it->polyline.first_point()) + return false; + return true; + }()); + ExtrusionMultiPath multi_path; + multi_path.paths.emplace_back(std::move(paths.front())); + + for (auto it_path = std::next(paths.begin()); it_path != paths.end(); ++it_path) { + if (multi_path.paths.back().last_point() != it_path->first_point()) { + extrusion_coll.append(ExtrusionMultiPath(std::move(multi_path))); + multi_path = ExtrusionMultiPath(); + } + multi_path.paths.emplace_back(std::move(*it_path)); + } + + extrusion_coll.append(ExtrusionMultiPath(std::move(multi_path))); + } } } diff --git a/src/libslic3r/PerimeterGenerator.hpp b/src/libslic3r/PerimeterGenerator.hpp index 2e478e107..ecf09c593 100644 --- a/src/libslic3r/PerimeterGenerator.hpp +++ b/src/libslic3r/PerimeterGenerator.hpp @@ -72,7 +72,7 @@ private: Polygons m_lower_slices_polygons; }; -ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, float tolerance, float merge_tolerance); +ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, float tolerance, float merge_tolerance); } |