From 4e90df1ea50729bef5fdb40b40f9ab47e4618be1 Mon Sep 17 00:00:00 2001 From: tamasmeszaros <meszaros.q@gmail.com> Date: Wed, 2 Dec 2020 17:50:12 +0100 Subject: [PATCH 1/3] Fix status indication glitch for bed filling --- src/slic3r/GUI/Jobs/FillBedJob.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/Jobs/FillBedJob.cpp b/src/slic3r/GUI/Jobs/FillBedJob.cpp index 5bc9cbb36..69aa7c5a6 100644 --- a/src/slic3r/GUI/Jobs/FillBedJob.cpp +++ b/src/slic3r/GUI/Jobs/FillBedJob.cpp @@ -55,18 +55,17 @@ void FillBedJob::prepare() double unsel_area = std::accumulate(m_unselected.begin(), m_unselected.end(), 0., [](double s, const auto &ap) { - return s + ap.poly.area(); + return s + (ap.bed_idx == 0) * ap.poly.area(); }) / sc; double fixed_area = unsel_area + m_selected.size() * poly_area; + double bed_area = Polygon{m_bedpts}.area() / sc; - // This is the maximum range, the real number will always be close but less. - double bed_area = Polygon{m_bedpts}.area() / sc; - - m_status_range = (bed_area - fixed_area) / poly_area; + // This is the maximum number of items, the real number will always be close but less. + int needed_items = (bed_area - fixed_area) / poly_area; ModelInstance *mi = model_object->instances[0]; - for (int i = 0; i < m_status_range; ++i) { + for (int i = 0; i < needed_items; ++i) { ArrangePolygon ap; ap.poly = m_selected.front().poly; ap.bed_idx = arrangement::UNARRANGED; @@ -77,6 +76,8 @@ void FillBedJob::prepare() }; m_selected.emplace_back(ap); } + + m_status_range = m_selected.size(); } void FillBedJob::process() From 2813db890600703663f489ea1679e3562b4de460 Mon Sep 17 00:00:00 2001 From: tamasmeszaros <meszaros.q@gmail.com> Date: Wed, 2 Dec 2020 17:52:40 +0100 Subject: [PATCH 2/3] Fix for bed filling with some existing items out of bed. --- src/libslic3r/Arrange.hpp | 9 +++++++++ src/libslic3r/BoundingBox.hpp | 3 +++ src/slic3r/GUI/Jobs/FillBedJob.cpp | 21 ++++++++++++++++++--- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/Arrange.hpp b/src/libslic3r/Arrange.hpp index ec46da8d3..0ff87c88d 100644 --- a/src/libslic3r/Arrange.hpp +++ b/src/libslic3r/Arrange.hpp @@ -62,6 +62,15 @@ struct ArrangePolygon { /// Test if arrange() was called previously and gave a successful result. bool is_arranged() const { return bed_idx != UNARRANGED; } + + inline ExPolygon transformed_poly() const + { + ExPolygon ret = poly; + ret.rotate(rotation); + ret.translate(translation.x(), translation.y()); + + return ret; + } }; using ArrangePolygons = std::vector<ArrangePolygon>; diff --git a/src/libslic3r/BoundingBox.hpp b/src/libslic3r/BoundingBox.hpp index 819162ec9..8de28af5c 100644 --- a/src/libslic3r/BoundingBox.hpp +++ b/src/libslic3r/BoundingBox.hpp @@ -53,6 +53,9 @@ public: return point(0) >= this->min(0) && point(0) <= this->max(0) && point(1) >= this->min(1) && point(1) <= this->max(1); } + bool contains(const BoundingBoxBase<PointClass> &other) const { + return contains(other.min) && contains(other.max); + } bool overlap(const BoundingBoxBase<PointClass> &other) const { return ! (this->max(0) < other.min(0) || this->min(0) > other.max(0) || this->max(1) < other.min(1) || this->min(1) > other.max(1)); diff --git a/src/slic3r/GUI/Jobs/FillBedJob.cpp b/src/slic3r/GUI/Jobs/FillBedJob.cpp index 69aa7c5a6..d2ff5252a 100644 --- a/src/slic3r/GUI/Jobs/FillBedJob.cpp +++ b/src/slic3r/GUI/Jobs/FillBedJob.cpp @@ -29,7 +29,9 @@ void FillBedJob::prepare() for (ModelInstance *inst : model_object->instances) if (inst->printable) { ArrangePolygon ap = get_arrange_poly(PtrWrapper{inst}, m_plater); - ++ap.priority; // need to be included in the result + // Existing objects need to be included in the result. Only + // the needed amount of object will be added, no more. + ++ap.priority; m_selected.emplace_back(ap); } @@ -38,11 +40,18 @@ void FillBedJob::prepare() m_bedpts = get_bed_shape(*m_plater->config()); auto &objects = m_plater->model().objects; + BoundingBox bedbb = get_extents(m_bedpts); + for (size_t idx = 0; idx < objects.size(); ++idx) if (int(idx) != m_object_idx) for (ModelInstance *mi : objects[idx]->instances) { - m_unselected.emplace_back(get_arrange_poly(PtrWrapper{mi}, m_plater)); - m_unselected.back().bed_idx = 0; + ArrangePolygon ap = get_arrange_poly(PtrWrapper{mi}, m_plater); + auto ap_bb = ap.transformed_poly().contour.bounding_box(); + + if (ap.bed_idx == 0 && !bedbb.contains(ap_bb)) + ap.bed_idx = arrangement::UNARRANGED; + + m_unselected.emplace_back(ap); } if (auto wt = get_wipe_tower_arrangepoly(*m_plater)) @@ -78,6 +87,12 @@ void FillBedJob::prepare() } m_status_range = m_selected.size(); + + // The strides have to be removed from the fixed items. For the + // arrangeable (selected) items bed_idx is ignored and the + // translation is irrelevant. + double stride = bed_stride(m_plater); + for (auto &p : m_unselected) p.translation(X) -= p.bed_idx * stride; } void FillBedJob::process() From 869ae0247ebe69e51df4a794825f286fea42a9ae Mon Sep 17 00:00:00 2001 From: tamasmeszaros <meszaros.q@gmail.com> Date: Wed, 2 Dec 2020 17:53:22 +0100 Subject: [PATCH 3/3] Use smarter object function in partial arrangement with empty bed. --- .../include/libnest2d/placers/nfpplacer.hpp | 8 ++++++++ src/libslic3r/Arrange.cpp | 20 +++++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index 35e7e160d..83f7bd246 100644 --- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -167,6 +167,8 @@ struct NfpPConfig { const ItemGroup& // remaining items )> before_packing; + std::function<void(const ItemGroup &, NfpPConfig &config)> on_preload; + NfpPConfig(): rotations({0.0, Pi/2.0, Pi, 3*Pi/2}), alignment(Alignment::CENTER), starting_point(Alignment::CENTER) {} }; @@ -577,6 +579,12 @@ public: Base::clearItems(); } + void preload(const ItemGroup& packeditems) { + Base::preload(packeditems); + if (config_.on_preload) + config_.on_preload(packeditems, config_); + } + private: using Shapes = TMultiShape<RawShape>; diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index 705e213e3..eaa9726dd 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -109,6 +109,7 @@ void fill_config(PConf& pcfg, const ArrangeParams ¶ms) { // Apply penalty to object function result. This is used only when alignment // after arrange is explicitly disabled (PConfig::Alignment::DONT_ALIGN) +// Also, this will only work well for Box shaped beds. static double fixed_overfit(const std::tuple<double, Box>& result, const Box &binbb) { double score = std::get<0>(result); @@ -348,6 +349,17 @@ public: m_pconf.object_function = get_objfn(); + m_pconf.on_preload = [this](const ItemGroup &items, PConfig &cfg) { + if (items.empty()) return; + + cfg.alignment = PConfig::Alignment::DONT_ALIGN; + auto bb = sl::boundingBox(m_bin); + auto bbcenter = bb.center(); + cfg.object_function = [this, bb, bbcenter](const Item &item) { + return fixed_overfit(objfunc(item, bbcenter), bb); + }; + }; + auto on_packed = params.on_packed; if (progressind || on_packed) @@ -384,13 +396,6 @@ public: const PConfig& config() const { return m_pconf; } inline void preload(std::vector<Item>& fixeditems) { - m_pconf.alignment = PConfig::Alignment::DONT_ALIGN; - auto bb = sl::boundingBox(m_bin); - auto bbcenter = bb.center(); - m_pconf.object_function = [this, bb, bbcenter](const Item &item) { - return fixed_overfit(objfunc(item, bbcenter), bb); - }; - // Build the rtree for queries to work for(unsigned idx = 0; idx < fixeditems.size(); ++idx) { @@ -398,7 +403,6 @@ public: itm.markAsFixedInBin(itm.binId()); } - m_pck.configure(m_pconf); m_item_count += fixeditems.size(); } };