diff --git a/src/libslic3r/Arrange/Arrange.hpp b/src/libslic3r/Arrange/Arrange.hpp index 466de153ce..6bf1321e44 100644 --- a/src/libslic3r/Arrange/Arrange.hpp +++ b/src/libslic3r/Arrange/Arrange.hpp @@ -61,7 +61,7 @@ class DefaultArrangerCtl : public Arranger::Ctl { public: DefaultArrangerCtl() = default; - explicit DefaultArrangerCtl(ArrangeTaskBase::Ctl &ctl) : taskctl{&ctl} {} + explicit DefaultArrangerCtl(ArrangeTaskCtl &ctl) : taskctl{&ctl} {} void update_status(int st) override { diff --git a/src/libslic3r/Arrange/ArrangeImpl.hpp b/src/libslic3r/Arrange/ArrangeImpl.hpp index d3cda35e3e..c0e6be35f8 100644 --- a/src/libslic3r/Arrange/ArrangeImpl.hpp +++ b/src/libslic3r/Arrange/ArrangeImpl.hpp @@ -292,7 +292,7 @@ class DefaultArranger: public Arranger { firstfit::SelectionStrategy sel{cmpfn, on_arranged, stop_cond}; - constexpr auto ep = ex_tbb; + constexpr auto ep = ex_seq; VariantKernel basekernel; switch (m_settings.get_arrange_strategy()) { @@ -328,7 +328,7 @@ class DefaultArranger: public Arranger { // a pure RectangleBed with inner-fit polygon calculation. if (!with_wipe_tower && m_settings.get_arrange_strategy() == ArrangeSettingsView::asAuto && - std::is_convertible_v) { + IsRectangular) { PackStrategyNFP base_strategy{std::move(kernel), ep, Accuracy, stop_cond}; RectangleOverfitPackingStrategy final_strategy{std::move(base_strategy)}; diff --git a/src/libslic3r/Arrange/Core/Beds.hpp b/src/libslic3r/Arrange/Core/Beds.hpp index 4f4a41251c..56566a0b40 100644 --- a/src/libslic3r/Arrange/Core/Beds.hpp +++ b/src/libslic3r/Arrange/Core/Beds.hpp @@ -184,6 +184,12 @@ inline ExPolygons to_expolygons(const ArrangeBed &bed) ArrangeBed to_arrange_bed(const Points &bedpts); +template struct IsRectangular_ : public std::false_type {}; +template<> struct IsRectangular_: public std::true_type {}; +template<> struct IsRectangular_: public std::true_type {}; + +template static constexpr bool IsRectangular = IsRectangular_::value; + } // namespace arr2 inline BoundingBox &bounding_box(BoundingBox &bb) { return bb; } diff --git a/src/libslic3r/Arrange/Core/NFP/Kernels/TMArrangeKernel.hpp b/src/libslic3r/Arrange/Core/NFP/Kernels/TMArrangeKernel.hpp index b73327c522..9cab9d5936 100644 --- a/src/libslic3r/Arrange/Core/NFP/Kernels/TMArrangeKernel.hpp +++ b/src/libslic3r/Arrange/Core/NFP/Kernels/TMArrangeKernel.hpp @@ -54,9 +54,9 @@ protected: public: TMArrangeKernel() = default; TMArrangeKernel(Vec2crd gravity_center, size_t itm_cnt, double bedarea = NaNd) - : sink{gravity_center} - , m_bin_area(bedarea) + : m_bin_area(bedarea) , m_item_cnt{itm_cnt} + , sink{gravity_center} {} TMArrangeKernel(size_t itm_cnt, double bedarea = NaNd) @@ -90,18 +90,12 @@ public: // Will hold the resulting score double score = 0; - // Density is the pack density: how big is the arranged pile - double density = 0; - // Distinction of cases for the arrangement scene enum e_cases { // This branch is for big items in a mixed (big and small) scene // OR for all items in a small-only scene. BIG_ITEM, - // This branch is for the last big item in a mixed scene - LAST_BIG_ITEM, - // For small items in a mixed scene. SMALL_ITEM, @@ -112,10 +106,8 @@ public: bool bigitems = is_big(envelope_area(item)) || m_rtree.empty(); if (is_wt) compute_case = WIPE_TOWER; - else if (bigitems && m_rem_cnt > 0) + else if (bigitems) compute_case = BIG_ITEM; - else if (bigitems && m_rem_cnt == 0) - compute_case = LAST_BIG_ITEM; else compute_case = SMALL_ITEM; @@ -132,20 +124,8 @@ public: Point top_left{minc.x(), maxc.y()}; Point bottom_right{maxc.x(), minc.y()}; - // Now the distance of the gravity center will be calculated to the - // five anchor points and the smallest will be chosen. - std::array dists; - auto cc = fullbb.center(); // The gravity center - dists[0] = (minc - cc).cast().norm(); - dists[1] = (maxc - cc).cast().norm(); - dists[2] = (itmcntr - cc).template cast().norm(); - dists[3] = (top_left - cc).cast().norm(); - dists[4] = (bottom_right - cc).cast().norm(); - - // The smalles distance from the arranged pile center: - double dist = norm(*(std::min_element(dists.begin(), dists.end()))); - double bindist = norm((ibb.center() - active_sink).template cast().norm()); - dist = 0.8 * dist + 0.2 * bindist; + // The smallest distance from the arranged pile center: + double dist = norm((itmcntr - m_pilebb.center()).template cast().norm()); // Prepare a variable for the alignment score. // This will indicate: how well is the candidate item @@ -153,7 +133,7 @@ public: // with all neighbors and return the score for the best // alignment. So it is enough for the candidate to be // aligned with only one item. - auto alignment_score = 1.0; + auto alignment_score = 1.; auto query = bgi::intersects(ibb); auto& index = is_big(envelope_area(item)) ? m_rtree : m_smallsrtree; @@ -173,31 +153,23 @@ public: auto bb = p.bb; bb.merge(ibb); auto bbarea = area(bb); - auto ascore = 1.0 - (fixed_area(item) + parea) / bbarea; + auto ascore = 1.0 - (area(fixed_bounding_box(item)) + area(p.bb)) / bbarea; if(ascore < alignment_score) alignment_score = ascore; } } - auto fullbbsz = fullbb.size(); - density = std::sqrt(norm(fullbbsz.x()) * norm(fullbbsz.y())); double R = double(m_rem_cnt) / (m_item_cnt); + R = std::pow(R, 1./3.); // The final mix of the score is the balance between the // distance from the full pile center, the pack density and // the alignment with the neighbors - if (result.empty()) - score = 0.50 * dist + 0.50 * density; - else - // Let the density matter more when fewer objects remain - score = 0.50 * dist + (1.0 - R) * 0.20 * density + - 0.30 * alignment_score; - break; - } - case LAST_BIG_ITEM: { - score = norm((itmcntr - m_pilebb.center()).template cast().norm()); + // Let the density matter more when fewer objects remain + score = 0.6 * dist + 0.1 * alignment_score + (1.0 - R) * (0.3 * dist) + R * 0.3 * alignment_score; + break; } case SMALL_ITEM: { @@ -239,8 +211,11 @@ public: if (m_item_cnt == 0) m_item_cnt = m_rem_cnt + fixed.size() + 1; - if (std::isnan(m_bin_area)) - m_bin_area = area(bed); + if (std::isnan(m_bin_area)) { + auto sz = bounding_box(bed).size(); + + m_bin_area = scaled(unscaled(sz.x()) * unscaled(sz.y())); + } m_norm = std::sqrt(m_bin_area); @@ -248,7 +223,7 @@ public: m_itemstats.reserve(fixed.size()); m_rtree.clear(); m_smallsrtree.clear(); - m_pilebb = {}; + m_pilebb = {active_sink, active_sink}; unsigned idx = 0; for (auto &fixitem : fixed) { auto fixitmbb = fixed_bounding_box(fixitem); diff --git a/src/libslic3r/Arrange/SegmentedRectangleBed.hpp b/src/libslic3r/Arrange/SegmentedRectangleBed.hpp index cc8594ddc7..08778911af 100644 --- a/src/libslic3r/Arrange/SegmentedRectangleBed.hpp +++ b/src/libslic3r/Arrange/SegmentedRectangleBed.hpp @@ -104,6 +104,10 @@ ExPolygons to_expolygons(const SegmentedRectangleBed &bed) return to_expolygons(RectangleBed{bed.bb}); } +template +struct IsRectangular_, void>> : public std::true_type +{}; + }} // namespace Slic3r::arr2 #endif // SEGMENTEDRECTANGLEBED_HPP diff --git a/tests/arrange/test_arrange.cpp b/tests/arrange/test_arrange.cpp index a2eda8c480..b36eac7065 100644 --- a/tests/arrange/test_arrange.cpp +++ b/tests/arrange/test_arrange.cpp @@ -207,7 +207,7 @@ static void check_nfp(const std::string & outfile_prefix, auto orb_ex_offs_pos_r_ch = offset_ex(orb_ex_r_ch, scaled(EPSILON)); auto orb_ex_offs_neg_r_ch = offset_ex(orb_ex_r_ch, -scaled(EPSILON)); - auto bedpoly_offs = offset_ex(bedpoly, SCALED_EPSILON); + auto bedpoly_offs = offset_ex(bedpoly, static_cast(SCALED_EPSILON)); auto check_at_nfppos = [&](const Point &pos) { ExPolygons orb_ex = orb_ex_r;