diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 40ee73672..34ee42304 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -92,6 +92,8 @@ public: virtual bool is_collection() const { return false; } virtual bool is_loop() const { return false; } virtual bool can_reverse() const { return true; } + virtual bool can_sort() const { return true; }//BBS: only used in ExtrusionEntityCollection + virtual void set_reverse() {} virtual ExtrusionEntity* clone() const = 0; // Create a new object, initialize it with this object using the move semantics. virtual ExtrusionEntity* clone_move() = 0; @@ -142,12 +144,53 @@ public: ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), m_role(role), m_no_extrusion(false) {} ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height, bool no_extrusion = false) : mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role), m_no_extrusion(no_extrusion) {} ExtrusionPath(int overhang_degree, int curve_degree, ExtrusionRole role, double mm3_per_mm, float width, float height) : overhang_degree(overhang_degree), curve_degree(curve_degree), mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role) {} - ExtrusionPath(const ExtrusionPath& rhs) : polyline(rhs.polyline), overhang_degree(rhs.overhang_degree), curve_degree(rhs.curve_degree), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), m_role(rhs.m_role), m_no_extrusion(rhs.m_no_extrusion) {} - ExtrusionPath(ExtrusionPath&& rhs) : polyline(std::move(rhs.polyline)), overhang_degree(rhs.overhang_degree), curve_degree(rhs.curve_degree), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), m_role(rhs.m_role), m_no_extrusion(rhs.m_no_extrusion) {} - ExtrusionPath(const Polyline &polyline, const ExtrusionPath &rhs) : polyline(polyline), overhang_degree(rhs.overhang_degree), curve_degree(rhs.curve_degree), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), m_role(rhs.m_role), m_no_extrusion(rhs.m_no_extrusion) {} - ExtrusionPath(Polyline &&polyline, const ExtrusionPath &rhs) : polyline(std::move(polyline)), overhang_degree(rhs.overhang_degree), curve_degree(rhs.curve_degree), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), m_role(rhs.m_role), m_no_extrusion(rhs.m_no_extrusion) {} + ExtrusionPath(const ExtrusionPath &rhs) + : polyline(rhs.polyline) + , overhang_degree(rhs.overhang_degree) + , curve_degree(rhs.curve_degree) + , mm3_per_mm(rhs.mm3_per_mm) + , width(rhs.width) + , height(rhs.height) + , m_can_reverse(rhs.m_can_reverse) + , m_role(rhs.m_role) + , m_no_extrusion(rhs.m_no_extrusion) + {} + ExtrusionPath(ExtrusionPath &&rhs) + : polyline(std::move(rhs.polyline)) + , overhang_degree(rhs.overhang_degree) + , curve_degree(rhs.curve_degree) + , mm3_per_mm(rhs.mm3_per_mm) + , width(rhs.width) + , height(rhs.height) + , m_can_reverse(rhs.m_can_reverse) + , m_role(rhs.m_role) + , m_no_extrusion(rhs.m_no_extrusion) + {} + ExtrusionPath(const Polyline &polyline, const ExtrusionPath &rhs) + : polyline(polyline) + , overhang_degree(rhs.overhang_degree) + , curve_degree(rhs.curve_degree) + , mm3_per_mm(rhs.mm3_per_mm) + , width(rhs.width) + , height(rhs.height) + , m_can_reverse(rhs.m_can_reverse) + , m_role(rhs.m_role) + , m_no_extrusion(rhs.m_no_extrusion) + {} + ExtrusionPath(Polyline &&polyline, const ExtrusionPath &rhs) + : polyline(std::move(polyline)) + , overhang_degree(rhs.overhang_degree) + , curve_degree(rhs.curve_degree) + , mm3_per_mm(rhs.mm3_per_mm) + , width(rhs.width) + , height(rhs.height) + , m_can_reverse(rhs.m_can_reverse) + , m_role(rhs.m_role) + , m_no_extrusion(rhs.m_no_extrusion) + {} ExtrusionPath& operator=(const ExtrusionPath& rhs) { + m_can_reverse = rhs.m_can_reverse; m_role = rhs.m_role; m_no_extrusion = rhs.m_no_extrusion; this->mm3_per_mm = rhs.mm3_per_mm; @@ -159,6 +202,7 @@ public: return *this; } ExtrusionPath& operator=(ExtrusionPath&& rhs) { + m_can_reverse = rhs.m_can_reverse; m_role = rhs.m_role; m_no_extrusion = rhs.m_no_extrusion; this->mm3_per_mm = rhs.mm3_per_mm; @@ -229,10 +273,12 @@ public: bool is_force_no_extrusion() const { return m_no_extrusion; } void set_force_no_extrusion(bool no_extrusion) { m_no_extrusion = no_extrusion; } void set_extrusion_role(ExtrusionRole extrusion_role) { m_role = extrusion_role; } + void set_reverse() override { m_can_reverse = false; } + bool can_reverse() const override { return m_can_reverse; } private: void _inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const; - + bool m_can_reverse = true; ExtrusionRole m_role; //BBS bool m_no_extrusion = false; @@ -247,16 +293,27 @@ public: ExtrusionPaths paths; ExtrusionMultiPath() {} - ExtrusionMultiPath(const ExtrusionMultiPath &rhs) : paths(rhs.paths) {} - ExtrusionMultiPath(ExtrusionMultiPath &&rhs) : paths(std::move(rhs.paths)) {} + ExtrusionMultiPath(const ExtrusionMultiPath &rhs) : paths(rhs.paths), m_can_reverse(rhs.m_can_reverse) {} + ExtrusionMultiPath(ExtrusionMultiPath &&rhs) : paths(std::move(rhs.paths)), m_can_reverse(rhs.m_can_reverse) {} ExtrusionMultiPath(const ExtrusionPaths &paths) : paths(paths) {} - ExtrusionMultiPath(const ExtrusionPath &path) { this->paths.push_back(path); } + ExtrusionMultiPath(const ExtrusionPath &path) {this->paths.push_back(path); m_can_reverse = path.can_reverse(); } - ExtrusionMultiPath& operator=(const ExtrusionMultiPath &rhs) { this->paths = rhs.paths; return *this; } - ExtrusionMultiPath& operator=(ExtrusionMultiPath &&rhs) { this->paths = std::move(rhs.paths); return *this; } + ExtrusionMultiPath &operator=(const ExtrusionMultiPath &rhs) + { + this->paths = rhs.paths; + m_can_reverse = rhs.m_can_reverse; + return *this; + } + ExtrusionMultiPath &operator=(ExtrusionMultiPath &&rhs) + { + this->paths = std::move(rhs.paths); + m_can_reverse = rhs.m_can_reverse; + return *this; + } bool is_loop() const override { return false; } - bool can_reverse() const override { return true; } + bool can_reverse() const override { return m_can_reverse; } + void set_reverse() override { m_can_reverse = false; } ExtrusionEntity* clone() const override { return new ExtrusionMultiPath(*this); } // Create a new object, initialize it with this object using the move semantics. ExtrusionEntity* clone_move() override { return new ExtrusionMultiPath(std::move(*this)); } @@ -289,6 +346,9 @@ public: append(dst, p.polyline.points); } double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; } + +private: + bool m_can_reverse = true; }; // Single continuous extrusion loop, possibly with varying extrusion thickness, extrusion height or bridging / non bridging. diff --git a/src/libslic3r/ExtrusionEntityCollection.hpp b/src/libslic3r/ExtrusionEntityCollection.hpp index 6e62a45fd..413834db2 100644 --- a/src/libslic3r/ExtrusionEntityCollection.hpp +++ b/src/libslic3r/ExtrusionEntityCollection.hpp @@ -32,12 +32,17 @@ public: ExtrusionEntitiesPtr entities; // we own these entities bool no_sort; ExtrusionEntityCollection(): no_sort(false) {} - ExtrusionEntityCollection(const ExtrusionEntityCollection &other) : no_sort(other.no_sort) { this->append(other.entities); } - ExtrusionEntityCollection(ExtrusionEntityCollection &&other) : entities(std::move(other.entities)), no_sort(other.no_sort) {} + ExtrusionEntityCollection(const ExtrusionEntityCollection &other) : no_sort(other.no_sort), is_reverse(other.is_reverse) { this->append(other.entities); } + ExtrusionEntityCollection(ExtrusionEntityCollection &&other) : entities(std::move(other.entities)), no_sort(other.no_sort), is_reverse(other.is_reverse) {} explicit ExtrusionEntityCollection(const ExtrusionPaths &paths); ExtrusionEntityCollection& operator=(const ExtrusionEntityCollection &other); ExtrusionEntityCollection& operator=(ExtrusionEntityCollection &&other) - { this->entities = std::move(other.entities); this->no_sort = other.no_sort; return *this; } + { + this->entities = std::move(other.entities); + this->no_sort = other.no_sort; + is_reverse = other.is_reverse; + return *this; + } ~ExtrusionEntityCollection() { clear(); } explicit operator ExtrusionPaths() const; @@ -50,7 +55,15 @@ public: } return out; } - bool can_reverse() const override { return !this->no_sort; } + bool can_sort() const override { return !this->no_sort; } + bool can_reverse() const override + { + if (this->no_sort) + return false; + else + return is_reverse; + } + void set_reverse() override { is_reverse = false; } bool empty() const { return this->entities.empty(); } void clear(); void swap (ExtrusionEntityCollection &c); @@ -126,6 +139,9 @@ public: throw Slic3r::RuntimeError("Calling length() on a ExtrusionEntityCollection"); return 0.; } + +private: + bool is_reverse{true}; }; } // namespace Slic3r diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index f1af208ea..6650c4cb2 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -476,7 +476,8 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: params.using_internal_flow = using_internal_flow; params.no_extrusion_overlap = surface_fill.params.overlap; params.with_loop = surface_fill.params.with_loop; - + if (surface_fill.params.pattern == ipGrid) + params.can_reverse = false; LayerRegion* layerm = this->m_regions[surface_fill.region_id]; for (ExPolygon& expoly : surface_fill.expolygons) { f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly}, ApplySafetyOffset::Yes); diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index acbf8f028..baa426c49 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -187,6 +187,7 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para out.push_back(eec = new ExtrusionEntityCollection()); // Only concentric fills are not sorted. eec->no_sort = this->no_sort(); + size_t idx = eec->entities.size(); if (params.use_arachne) { Flow new_flow = params.flow.with_spacing(float(this->spacing)); variable_width(thick_polylines, params.extrusion_role, new_flow, eec->entities); @@ -198,6 +199,10 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para params.extrusion_role, flow_mm3_per_mm, float(flow_width), params.flow.height()); } + if (!params.can_reverse) { + for (size_t i = idx; i < eec->entities.size(); i++) + eec->entities[i]->set_reverse(); + } } } diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp index 5d0cbc2ad..4ddfbaf5e 100644 --- a/src/libslic3r/Fill/FillBase.hpp +++ b/src/libslic3r/Fill/FillBase.hpp @@ -77,6 +77,7 @@ struct FillParams //BBS: only used for new top surface pattern float no_extrusion_overlap{ 0.0 }; bool dont_sort{ false }; // do not sort the lines, just simply connect them + bool can_reverse{true}; }; static_assert(IsTriviallyCopyable::value, "FillParams class is not POD (and it should be - see constructor)."); diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp index e0ac77e47..1b5132481 100644 --- a/src/libslic3r/Fill/FillRectilinear.cpp +++ b/src/libslic3r/Fill/FillRectilinear.cpp @@ -2994,6 +2994,10 @@ Polylines FillGrid::fill_surface(const Surface *surface, const FillParams ¶m { { 0.f, 0.f }, { float(M_PI / 2.), 0.f } }, polylines_out)) BOOST_LOG_TRIVIAL(error) << "FillGrid::fill_surface() failed to fill a region."; + + if (this->layer_id % 2 == 1) + for (int i = 0; i < polylines_out.size(); i++) + std::reverse(polylines_out[i].begin(), polylines_out[i].end()); return polylines_out; } diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 7b6deb7ab..26303e4a3 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -4436,9 +4436,9 @@ void GCode::ObjectByExtruder::Island::Region::append(const Type type, const Extr // First we append the entities, there are eec->entities.size() of them: size_t old_size = perimeters_or_infills->size(); - size_t new_size = old_size + (eec->can_reverse() ? eec->entities.size() : 1); + size_t new_size = old_size + (eec->can_sort() ? eec->entities.size() : 1); perimeters_or_infills->reserve(new_size); - if (eec->can_reverse()) { + if (eec->can_sort()) { for (auto* ee : eec->entities) perimeters_or_infills->emplace_back(ee); } else