From e53f60dc1aab829d86733a5590f4b43e6c0daff8 Mon Sep 17 00:00:00 2001 From: supermerill Date: Mon, 11 Oct 2021 16:51:16 +0200 Subject: [PATCH] Fix crash from perimeter_loop one-point loop supermerill/SuperSlicer#1623 Fixme: take the first object from this issue project and you can see some bad lines at layer 31. --- src/libslic3r/ExtrusionEntity.cpp | 22 ++++++++++++++++++++++ src/libslic3r/ExtrusionEntity.hpp | 8 ++++++++ src/libslic3r/PerimeterGenerator.cpp | 15 ++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index 3ec8800bb..6b0611cca 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -388,6 +388,28 @@ void ExtrusionLength::use(const ExtrusionEntityCollection& collection) { } } + +void ExtrusionVisitorRecursiveConst::use(const ExtrusionMultiPath& multipath) { + for (const ExtrusionPath& path: multipath.paths) { + path.visit(*this); + } +} +void ExtrusionVisitorRecursiveConst::use(const ExtrusionMultiPath3D& multipath3D) { + for (const ExtrusionPath3D& path3D : multipath3D.paths) { + path3D.visit(*this); + } +} +void ExtrusionVisitorRecursiveConst::use(const ExtrusionLoop& loop) { + for (const ExtrusionPath& path : loop.paths) { + path.visit(*this); + } +} +void ExtrusionVisitorRecursiveConst::use(const ExtrusionEntityCollection& collection) { + for (const ExtrusionEntity* entity : collection.entities) { + entity->visit(*this); + } +} + //class ExtrusionTreeVisitor : ExtrusionVisitor { //public: // //virtual void use(ExtrusionEntity &entity) { assert(false); }; diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 8ce95e910..5369998cf 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -606,6 +606,14 @@ public: } }; +class ExtrusionVisitorRecursiveConst : public ExtrusionVisitorConst { +public: + virtual void use(const ExtrusionMultiPath& multipath) override; + virtual void use(const ExtrusionMultiPath3D& multipath) override; + virtual void use(const ExtrusionLoop& loop) override; + virtual void use(const ExtrusionEntityCollection& collection) override; +}; + } #endif diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index a5bedcc33..ed6e34549 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -1852,6 +1852,8 @@ PerimeterGenerator::_extrude_and_cut_loop(const PerimeterGeneratorLoop &loop, co for (ExtrusionPath &path : paths) { direction_polyline.points.insert(direction_polyline.points.end(), path.polyline.points.begin(), path.polyline.points.end()); } + for (int i = 0; i < direction_polyline.points.size() - 1; i++) + assert(direction_polyline.points[i] != direction_polyline.points[i + 1]); direction_polyline.clip_start(SCALED_RESOLUTION); direction_polyline.clip_end(SCALED_RESOLUTION); coord_t dot = direction.dot(Line(direction_polyline.points.back(), direction_polyline.points.front())); @@ -1950,11 +1952,12 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop, //create new node with recursive ask for the inner perimeter & COPY of the points, ready to be cut my_loop.paths.insert(my_loop.paths.begin() + nearest.idx_polyline_outter + 1, my_loop.paths[nearest.idx_polyline_outter]); + // outer_start == outer_end ExtrusionPath *outer_start = &my_loop.paths[nearest.idx_polyline_outter]; ExtrusionPath *outer_end = &my_loop.paths[nearest.idx_polyline_outter + 1]; Line deletedSection; - //cut our polyline + //cut our polyline, so outer_start has no common point with outer_end //separate them size_t nearest_idx_outter = outer_start->polyline.closest_point_index(nearest.outter_best); if (outer_start->polyline.points[nearest_idx_outter].coincides_with_epsilon(nearest.outter_best)) { @@ -2195,6 +2198,16 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop, my_loop.paths.insert(my_loop.paths.begin() + nearest.idx_polyline_outter + 1, travel_path_begin[i]); } } + //remove one-point extrusion + //FIXME prevent this instead of patching here? + for (int i = 0; i < my_loop.paths.size(); i++) { + if (my_loop.paths[i].polyline.size() < 2) { + if (my_loop.paths[i].polyline.size() == 1) + std::cout << "erase one-point extrusion : layer " << this->layer->id() << " " << my_loop.paths[i].polyline.points.front().x() << ":" << my_loop.paths[i].polyline.points.front().y() << "\n"; + my_loop.paths.erase(my_loop.paths.begin() + i); + i--; + } + } //update for next loop childs.erase(childs.begin() + nearest.idx_children);