diff --git a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp index c51e0f5c94..2ca4f5d50e 100644 --- a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp +++ b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp @@ -259,10 +259,12 @@ inline TMultiShape clipper_execute( poly.Contour.swap(pptr->Contour); assert(!pptr->IsHole()); - - if(pptr->IsOpen()) { + + if(!poly.Contour.empty() ) { auto front_p = poly.Contour.front(); - poly.Contour.emplace_back(front_p); + auto &back_p = poly.Contour.back(); + if(front_p.X != back_p.X || front_p.Y != back_p.X) + poly.Contour.emplace_back(front_p); } for(auto h : pptr->Childs) { processHole(h, poly); } @@ -274,10 +276,12 @@ inline TMultiShape clipper_execute( poly.Holes.emplace_back(std::move(pptr->Contour)); assert(pptr->IsHole()); - - if(pptr->IsOpen()) { - auto front_p = poly.Holes.back().front(); - poly.Holes.back().emplace_back(front_p); + + if(!poly.Contour.empty() ) { + auto front_p = poly.Contour.front(); + auto &back_p = poly.Contour.back(); + if(front_p.X != back_p.X || front_p.Y != back_p.X) + poly.Contour.emplace_back(front_p); } for(auto c : pptr->Childs) processPoly(c); diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index cf0f7c8556..abe8af16ae 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -402,9 +402,11 @@ bool Model::arrange_objects(coordf_t dist, const BoundingBoxf* bb) for(size_t i = 0; i < input.size(); ++i) { if (input[i].bed_idx != 0) ret = false; - if (input[i].bed_idx >= 0) - instances[i]->apply_arrange_result(input[i], - {input[i].bed_idx * stride, 0}); + if (input[i].bed_idx >= 0) { + input[i].translation += Vec2crd{input[i].bed_idx * stride, 0}; + instances[i]->apply_arrange_result(input[i].translation, + input[i].rotation); + } } return ret; @@ -1826,23 +1828,20 @@ arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const // this may happen for malformed models, see: // https://github.com/prusa3d/PrusaSlicer/issues/2209 - if (p.points.empty()) return {}; - - Polygons pp{p}; - pp = p.simplify(scaled(SIMPLIFY_TOLERANCE_MM)); - if (!pp.empty()) p = pp.front(); + if (!p.points.empty()) { + Polygons pp{p}; + pp = p.simplify(scaled(SIMPLIFY_TOLERANCE_MM)); + if (!pp.empty()) p = pp.front(); + } + m_arrange_cache.poly.contour = std::move(p); - m_arrange_cache.bed_origin = {0, 0}; - m_arrange_cache.bed_idx = arrangement::UNARRANGED; m_arrange_cache.valid = true; } arrangement::ArrangePolygon ret; ret.poly = m_arrange_cache.poly; - ret.translation = Vec2crd{scaled(get_offset(X)), scaled(get_offset(Y))} - - m_arrange_cache.bed_origin; + ret.translation = Vec2crd{scaled(get_offset(X)), scaled(get_offset(Y))}; ret.rotation = get_rotation(Z); - ret.bed_idx = m_arrange_cache.bed_idx; return ret; } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 548e0f015d..5a0dc98635 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -516,7 +516,7 @@ public: const Vec3d& get_offset() const { return m_transformation.get_offset(); } double get_offset(Axis axis) const { return m_transformation.get_offset(axis); } - + void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); } void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); } @@ -558,15 +558,12 @@ public: arrangement::ArrangePolygon get_arrange_polygon() const; // Apply the arrange result on the ModelInstance - void apply_arrange_result(const arrangement::ArrangePolygon& ap, - const Vec2crd& bed_origin = {0, 0}) + void apply_arrange_result(const Vec2crd& offs, double rotation) { // write the transformation data into the model instance - set_rotation(Z, ap.rotation); - set_offset(X, unscale(ap.translation(X) + bed_origin.x())); - set_offset(Y, unscale(ap.translation(Y) + bed_origin.y())); - m_arrange_cache.bed_origin = bed_origin; - m_arrange_cache.bed_idx = ap.bed_idx; + set_rotation(Z, rotation); + set_offset(X, unscale(offs(X))); + set_offset(Y, unscale(offs(Y))); } protected: @@ -601,9 +598,7 @@ private: // Warning! This object is not guarded against concurrency. mutable struct ArrangeCache { bool valid = false; - Vec2crd bed_origin {0, 0}; ExPolygon poly; - int bed_idx = arrangement::UNARRANGED; } m_arrange_cache; }; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 6c5e6475c5..36d16035e6 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -4,7 +4,6 @@ #include #include -#include "libslic3r/Arrange.hpp" #include "3DScene.hpp" #include "GLToolbar.hpp" #include "Event.hpp" diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index a6360a0205..1516426139 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1264,21 +1264,18 @@ struct Plater::priv // Cache the wti info class WipeTower: public GLCanvas3D::WipeTowerInfo { - Vec2d m_bed_origin = {0., 0.}; - int m_bed_idx = arrangement::UNARRANGED; + using ArrangePolygon = arrangement::ArrangePolygon; + static const constexpr auto UNARRANGED = arrangement::UNARRANGED; friend priv; public: - void apply_arrange_result(const arrangement::ArrangePolygon& ap, - const Vec2crd& bedc) { - m_bed_origin = unscaled(bedc); - m_pos = unscaled(ap.translation) + m_bed_origin; - m_rotation = ap.rotation; - m_bed_idx = ap.bed_idx; + void apply_arrange_result(const Vec2crd& tr, double rotation) + { + m_pos = unscaled(tr); m_rotation = rotation; apply_wipe_tower(); } - arrangement::ArrangePolygon get_arrange_polygon() const + ArrangePolygon get_arrange_polygon() const { Polygon p({ {coord_t(0), coord_t(0)}, @@ -1288,28 +1285,20 @@ struct Plater::priv {coord_t(0), coord_t(0)}, }); - arrangement::ArrangePolygon ret; + ArrangePolygon ret; ret.poly.contour = std::move(p); - ret.translation = scaled(m_pos) - scaled(m_bed_origin); + ret.translation = scaled(m_pos); ret.rotation = m_rotation; - ret.bed_idx = m_bed_idx; return ret; } - - // For future use - int bed_index() const { return m_bed_idx; } - }; + } wipetower; -private: - WipeTower m_wipetower; - -public: - WipeTower& wipe_tower() { + WipeTower& updated_wipe_tower() { auto wti = view3D->get_canvas3d()->get_wipe_tower_info(); - m_wipetower.m_pos = wti.pos(); - m_wipetower.m_rotation = wti.rotation(); - m_wipetower.m_bb_size = wti.bb_size(); - return m_wipetower; + wipetower.m_pos = wti.pos(); + wipetower.m_rotation = wti.rotation(); + wipetower.m_bb_size = wti.bb_size(); + return wipetower; } // A class to handle UI jobs like arranging and optimizing rotation. @@ -1506,26 +1495,31 @@ public: ModelInstance *mi = mo->instances[i]; ArrangePolygon ap = mi->get_arrange_polygon(); ap.priority = 0; - ap.setter = [mi, stride](const ArrangePolygon &p) { - if (p.bed_idx != UNARRANGED) - mi->apply_arrange_result(p, {p.bed_idx * stride, 0}); - }; + ap.bed_idx = ap.translation.x() / stride; + ap.setter = [mi, stride](const ArrangePolygon &p) { + if (p.bed_idx != UNARRANGED) { + auto t = p.translation; t.x() += p.bed_idx * stride; + mi->apply_arrange_result(t, p.rotation); + } + }; + inst_sel[i] ? m_selected.emplace_back(std::move(ap)) : m_unselected.emplace_back(std::move(ap)); } } - auto& wti = plater().wipe_tower(); + auto& wti = plater().updated_wipe_tower(); if (wti) { ArrangePolygon ap = wti.get_arrange_polygon(); + ap.bed_idx = ap.translation.x() / stride; + ap.priority = 1; // Wipe tower should be on physical bed ap.setter = [&wti, stride](const ArrangePolygon &p) { - if (p.bed_idx != UNARRANGED) - wti.apply_arrange_result(p, {p.bed_idx * stride, 0}); + auto t = p.translation; t.x() += p.bed_idx * stride; + wti.apply_arrange_result(t, p.rotation); }; - ap.priority = 1; sel.is_wipe_tower() ? m_selected.emplace_back(std::move(ap)) : m_unselected.emplace_back(std::move(ap)); @@ -1533,6 +1527,11 @@ public: // If the selection was empty arrange everything if (m_selected.empty()) m_selected.swap(m_unselected); + + // The strides have to be removed from the fixed items. For the + // arrangeable (selected) items it bed_idx is ignored and the + // translation is irrelevant. + for (auto &p : m_unselected) p.translation(X) -= p.bed_idx * stride; } public: @@ -2553,14 +2552,15 @@ void Plater::priv::find_new_position(const ModelInstancePtrs &instances, movable.emplace_back(std::move(arrpoly)); } - if (wipe_tower()) - fixed.emplace_back(m_wipetower.get_arrange_polygon()); + if (updated_wipe_tower()) + fixed.emplace_back(wipetower.get_arrange_polygon()); arrangement::arrange(movable, fixed, min_d, get_bed_shape_hint()); for (size_t i = 0; i < instances.size(); ++i) if (movable[i].bed_idx == 0) - instances[i]->apply_arrange_result(movable[i]); + instances[i]->apply_arrange_result(movable[i].translation, + movable[i].rotation); } void Plater::priv::ArrangeJob::process() {