diff options
author | tamasmeszaros <meszaros.q@gmail.com> | 2018-08-06 21:13:04 +0300 |
---|---|---|
committer | tamasmeszaros <meszaros.q@gmail.com> | 2018-08-06 21:13:04 +0300 |
commit | e1edb05bbbd95bf0f15d3540545d9bf1cf63356e (patch) | |
tree | 08d4599056595b9297c2517b09039e50134dd120 /xs/src/libslic3r | |
parent | 3c32a7c3db52df072d205b6b464b4867e2e5cd97 (diff) |
Better support for circular bed.
Diffstat (limited to 'xs/src/libslic3r')
-rw-r--r-- | xs/src/libslic3r/ModelArrange.hpp | 52 |
1 files changed, 31 insertions, 21 deletions
diff --git a/xs/src/libslic3r/ModelArrange.hpp b/xs/src/libslic3r/ModelArrange.hpp index 53b99b781..57a169205 100644 --- a/xs/src/libslic3r/ModelArrange.hpp +++ b/xs/src/libslic3r/ModelArrange.hpp @@ -102,9 +102,9 @@ using SpatIndex = bgi::rtree< SpatElement, bgi::rstar<16, 4> >; std::tuple<double /*score*/, Box /*farthest point from bin center*/> objfunc(const PointImpl& bincenter, - double /*bin_area*/, + double bin_area, ShapeLike::Shapes<PolygonImpl>& pile, // The currently arranged pile - double /*pile_area*/, + double pile_area, const Item &item, double norm, // A norming factor for physical dimensions std::vector<double>& areacache, // pile item areas will be cached @@ -115,12 +115,16 @@ objfunc(const PointImpl& bincenter, using pl = PointLike; using sl = ShapeLike; - static const double BIG_ITEM_TRESHOLD = 0.2; + static const double BIG_ITEM_TRESHOLD = 0.04; static const double ROUNDNESS_RATIO = 0.5; static const double DENSITY_RATIO = 1.0 - ROUNDNESS_RATIO; // We will treat big items (compared to the print bed) differently - auto normarea = [norm](double area) { return std::sqrt(area)/norm; }; + + auto isBig = [&areacache, bin_area](double a) { + bool t = areacache.empty() ? true : a > 0.5*areacache.front(); + return a/bin_area > BIG_ITEM_TRESHOLD || t; + }; // If a new bin has been created: if(pile.size() < areacache.size()) { @@ -133,7 +137,7 @@ objfunc(const PointImpl& bincenter, for(auto& p : pile) { if(idx == areacache.size()) { areacache.emplace_back(sl::area(p)); - if(normarea(areacache[idx]) > BIG_ITEM_TRESHOLD) + if(isBig(areacache[idx])) spatindex.insert({sl::boundingBox(p), idx}); } @@ -157,14 +161,10 @@ objfunc(const PointImpl& bincenter, boost::geometry::convert(boostbb, bigbb); } - // The size indicator of the candidate item. This is not the area, - // but almost... - double item_normarea = normarea(item.area()); - // Will hold the resulting score double score = 0; - if(item_normarea > BIG_ITEM_TRESHOLD) { + if(isBig(item.area())) { // This branch is for the bigger items.. // Here we will use the closest point of the item bounding box to // the already arranged pile. So not the bb center nor the a choosen @@ -223,10 +223,9 @@ objfunc(const PointImpl& bincenter, // 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 neigbours - auto C = 0.33; - score = C * dist + C * density + C * alignment_score; + score = 0.4 * dist + 0.4 * density + 0.2 * alignment_score; - } else if( item_normarea < BIG_ITEM_TRESHOLD && spatindex.empty()) { + } else if( !isBig(item.area()) && spatindex.empty()) { // If there are no big items, only small, we should consider the // density here as well to not get silly results auto bindist = pl::distance(ibb.center(), bincenter) / norm; @@ -349,17 +348,26 @@ public: auto result = objfunc(bin.center(), bin_area_, pile, pile_area, item, norm, areacache_, rtree_); double score = std::get<0>(result); - - // Circle fitting detection is very rough at the moment but - // we still need something that tells how badly the arrangement - // misses the print bed. auto& fullbb = std::get<1>(result); - auto bbr = 0.5*PointLike::distance(fullbb.minCorner(), - fullbb.maxCorner()); - auto diff = bbr - bin.radius(); - if(diff > 0) score += std::pow(diff, 2) / norm; + auto d = PointLike::distance(fullbb.minCorner(), + fullbb.maxCorner()); + auto diff = d - 2*bin.radius(); + + if(diff > 0) { + if( item.area() > 0.01*bin_area_ && item.vertexCount() < 20) { + pile.emplace_back(item.transformedShape()); + auto chull = ShapeLike::convexHull(pile); + pile.pop_back(); + auto C = strategies::boundingCircle(chull); + auto rdiff = C.radius() - bin.radius(); + + if(rdiff > 0) { + score += std::pow(rdiff, 3) / norm; + } + } + } return score; }; @@ -695,6 +703,8 @@ bool arrange(Model &model, coordf_t min_obj_distance, } }; + if(result.empty()) return false; + if(first_bin_only) { applyResult(result.front(), 0, shapemap); } else { |