From c8370b5408cd367026faf976149967cd589f00c8 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 2 Aug 2018 17:51:11 +0200 Subject: [PATCH] New approach to big items with calculating the best alignment with other big items. --- .../libnest2d/libnest2d/geometry_traits.hpp | 4 +- .../libnest2d/libnest2d/placers/nfpplacer.hpp | 3 +- xs/src/libslic3r/ModelArrange.hpp | 72 +++++++++++++------ 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/xs/src/libnest2d/libnest2d/geometry_traits.hpp b/xs/src/libnest2d/libnest2d/geometry_traits.hpp index 00740f30c..058c47cd4 100644 --- a/xs/src/libnest2d/libnest2d/geometry_traits.hpp +++ b/xs/src/libnest2d/libnest2d/geometry_traits.hpp @@ -314,8 +314,8 @@ inline RawPoint _Box::center() const BP2D_NOEXCEPT { using Coord = TCoord; RawPoint ret = { - static_cast( (getX(minc) + getX(maxc))/2.0 ), - static_cast( (getY(minc) + getY(maxc))/2.0 ) + static_cast( std::round((getX(minc) + getX(maxc))/2.0) ), + static_cast( std::round((getY(minc) + getY(maxc))/2.0) ) }; return ret; diff --git a/xs/src/libnest2d/libnest2d/placers/nfpplacer.hpp b/xs/src/libnest2d/libnest2d/placers/nfpplacer.hpp index 0c5776400..5d09a61fc 100644 --- a/xs/src/libnest2d/libnest2d/placers/nfpplacer.hpp +++ b/xs/src/libnest2d/libnest2d/placers/nfpplacer.hpp @@ -590,7 +590,8 @@ public: [this, &merged_pile]( Nfp::Shapes& /*pile*/, const Item& item, - double occupied_area, double norm, + double occupied_area, + double norm, double /*penality*/) { merged_pile.emplace_back(item.transformedShape()); diff --git a/xs/src/libslic3r/ModelArrange.hpp b/xs/src/libslic3r/ModelArrange.hpp index 73dc83c57..5f1717f71 100644 --- a/xs/src/libslic3r/ModelArrange.hpp +++ b/xs/src/libslic3r/ModelArrange.hpp @@ -95,12 +95,16 @@ void toSVG(SVG& svg, const Model& model) { std::tuple objfunc(const PointImpl& bincenter, + double bin_area, ShapeLike::Shapes& pile, // The currently arranged pile + double pile_area, const Item &item, - double norm // A norming factor for physical dimensions + double norm, // A norming factor for physical dimensions + std::vector& areacache ) { using pl = PointLike; + using sl = ShapeLike; static const double BIG_ITEM_TRESHOLD = 0.2; static const double ROUNDNESS_RATIO = 0.5; @@ -109,10 +113,14 @@ objfunc(const PointImpl& bincenter, // We will treat big items (compared to the print bed) differently NfpPlacer::Pile bigs; bigs.reserve(pile.size()); + + int idx = 0; + if(pile.size() < areacache.size()) areacache.clear(); for(auto& p : pile) { - auto pbb = ShapeLike::boundingBox(p); - auto na = std::sqrt(pbb.width()*pbb.height())/norm; - if(na > BIG_ITEM_TRESHOLD) bigs.emplace_back(p); + if(idx == areacache.size()) areacache.emplace_back(sl::area(p)); + if(std::sqrt(areacache[idx])/norm > BIG_ITEM_TRESHOLD) + bigs.emplace_back(p); + idx++; } // Candidate item bounding box @@ -166,9 +174,28 @@ objfunc(const PointImpl& bincenter, // Density is the pack density: how big is the arranged pile auto density = std::sqrt(fullbb.width()*fullbb.height()) / norm; - // The score is a weighted sum of the distance from pile center - // and the pile size - score = ROUNDNESS_RATIO * dist + DENSITY_RATIO * density; + auto alignment_score = std::numeric_limits::max(); + + auto& trsh = item.transformedShape(); + + idx = 0; + for(auto& p : pile) { + + auto parea = areacache[idx]; + if(std::sqrt(parea)/norm > BIG_ITEM_TRESHOLD) { + auto chull = sl::convexHull(sl::Shapes{p, trsh}); + auto carea = sl::area(chull); + + auto ascore = carea - (item.area() + parea); + ascore = std::sqrt(ascore) / norm; + + if(ascore < alignment_score) alignment_score = ascore; + } + idx++; + } + + auto C = 0.33; + score = C * dist + C * density + C * alignment_score; } else if(itemnormarea < BIG_ITEM_TRESHOLD && bigs.empty()) { // If there are no big items, only small, we should consider the @@ -203,7 +230,7 @@ void fillConfig(PConf& pcfg) { // The accuracy of optimization. // Goes from 0.0 to 1.0 and scales performance as well - pcfg.accuracy = 0.35f; + pcfg.accuracy = 0.4f; } template @@ -221,18 +248,20 @@ protected: Packer pck_; PConfig pconf_; // Placement configuration - + double bin_area_; + std::vector areacache_; public: _ArrBase(const TBin& bin, Distance dist, std::function progressind): - pck_(bin, dist) + pck_(bin, dist), bin_area_(ShapeLike::area(bin)) { fillConfig(pconf_); pck_.progressIndicator(progressind); } template inline IndexedPackGroup operator()(Args&&...args) { + areacache_.clear(); return pck_.arrangeIndexed(std::forward(args)...); } }; @@ -245,14 +274,15 @@ public: std::function progressind): _ArrBase(bin, dist, progressind) { - pconf_.object_function = [bin] ( + pconf_.object_function = [this, bin] ( Pile& pile, const Item &item, - double /*occupied_area*/, + double pile_area, double norm, - double penality) { + double /*penality*/) { - auto result = objfunc(bin.center(), pile, item, norm); + auto result = objfunc(bin.center(), bin_area_, pile, + pile_area, item, norm, areacache_); double score = std::get<0>(result); auto& fullbb = std::get<1>(result); @@ -275,15 +305,16 @@ public: std::function progressind): _ArrBase(bin, dist, progressind) { - pconf_.object_function = [&bin] ( + pconf_.object_function = [this, &bin] ( Pile& pile, const Item &item, - double /*area*/, + double pile_area, double norm, double /*penality*/) { auto binbb = ShapeLike::boundingBox(bin); - auto result = objfunc(binbb.center(), pile, item, norm); + auto result = objfunc(binbb.center(), bin_area_, pile, + pile_area, item, norm, areacache_); double score = std::get<0>(result); pile.emplace_back(item.transformedShape()); @@ -309,14 +340,15 @@ public: AutoArranger(Distance dist, std::function progressind): _ArrBase(Box(0, 0), dist, progressind) { - this->pconf_.object_function = [] ( + this->pconf_.object_function = [this] ( Pile& pile, const Item &item, - double /*area*/, + double pile_area, double norm, double /*penality*/) { - auto result = objfunc({0, 0}, pile, item, norm); + auto result = objfunc({0, 0}, 0, pile, pile_area, + item, norm, areacache_); return std::get<0>(result); };