diff options
author | tamasmeszaros <meszaros.q@gmail.com> | 2018-08-07 20:48:00 +0300 |
---|---|---|
committer | tamasmeszaros <meszaros.q@gmail.com> | 2018-08-07 20:51:23 +0300 |
commit | 20b7aad6d1cbb4b282586a3844fb66843c81f10d (patch) | |
tree | 649241d67c41b813764ae6ee5eeb87e0cdcec246 /xs/src/libslic3r | |
parent | 08fb677583518382f3ff4a42fadc431d0a9870f0 (diff) |
Bug fixes for the neighborhood detection
Diffstat (limited to 'xs/src/libslic3r')
-rw-r--r-- | xs/src/libslic3r/ModelArrange.hpp | 126 |
1 files changed, 82 insertions, 44 deletions
diff --git a/xs/src/libslic3r/ModelArrange.hpp b/xs/src/libslic3r/ModelArrange.hpp index f4ce0daca..952a9e3a6 100644 --- a/xs/src/libslic3r/ModelArrange.hpp +++ b/xs/src/libslic3r/ModelArrange.hpp @@ -99,6 +99,7 @@ namespace bgi = boost::geometry::index; using SpatElement = std::pair<Box, unsigned>; using SpatIndex = bgi::rtree< SpatElement, bgi::rstar<16, 4> >; +using ItemGroup = std::vector<std::reference_wrapper<Item>>; std::tuple<double /*score*/, Box /*farthest point from bin center*/> objfunc(const PointImpl& bincenter, @@ -109,24 +110,21 @@ objfunc(const PointImpl& bincenter, double norm, // A norming factor for physical dimensions std::vector<double>& areacache, // pile item areas will be cached // a spatial index to quickly get neighbors of the candidate item - SpatIndex& spatindex + SpatIndex& spatindex, + const ItemGroup& remaining ) { using pl = PointLike; using sl = ShapeLike; + using Coord = TCoord<PointImpl>; static const double BIG_ITEM_TRESHOLD = 0.02; 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 isBig = [&areacache, bin_area](double a) { - double farea = areacache.empty() ? 0 : areacache.front(); - bool fbig = farea / bin_area > BIG_ITEM_TRESHOLD; - bool abig = a/bin_area > BIG_ITEM_TRESHOLD; - bool rbig = fbig && a > 0.5*farea; - return abig || rbig; + return a/bin_area > BIG_ITEM_TRESHOLD ; }; // If a new bin has been created: @@ -195,39 +193,74 @@ objfunc(const PointImpl& bincenter, auto dist = *(std::min_element(dists.begin(), dists.end())) / norm; // Density is the pack density: how big is the arranged pile - auto density = std::sqrt(fullbb.width()*fullbb.height()) / norm; - - // Prepare a variable for the alignment score. - // This will indicate: how well is the candidate item aligned with - // its neighbors. We will check the aligment 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 = std::numeric_limits<double>::max(); - - auto& trsh = item.transformedShape(); - - auto querybb = item.boundingBox(); - - // Query the spatial index for the neigbours - std::vector<SpatElement> result; - spatindex.query(bgi::intersects(querybb), std::back_inserter(result)); + double density = 0; + + if(remaining.empty()) { + pile.emplace_back(item.transformedShape()); + auto chull = sl::convexHull(pile); + pile.pop_back(); + strategies::EdgeCache<PolygonImpl> ec(chull); + + double circ = ec.circumference() / norm; + double bcirc = 2.0*(fullbb.width() + fullbb.height()) / norm; + score = 0.5*circ + 0.5*bcirc; + + } else { + // Prepare a variable for the alignment score. + // This will indicate: how well is the candidate item aligned with + // its neighbors. We will check the aligment 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 = std::numeric_limits<double>::max(); + + density = (fullbb.width()*fullbb.height()) / (norm*norm); + auto& trsh = item.transformedShape(); + auto querybb = item.boundingBox(); + auto wp = querybb.width()*0.2; + auto hp = querybb.height()*0.2; + auto pad = PointImpl( Coord(wp), Coord(hp)); + querybb = Box({ querybb.minCorner() - pad, + querybb.maxCorner() + pad + }); + + // Query the spatial index for the neigbours + std::vector<SpatElement> result; + result.reserve(spatindex.size()); + spatindex.query(bgi::intersects(querybb), + std::back_inserter(result)); + +// if(result.empty()) { +// std::cout << "Error while arranging!" << std::endl; +// std::cout << spatindex.size() << " " << pile.size() << std::endl; + +// auto ib = spatindex.bounds(); +// Box ibb; +// boost::geometry::convert(ib, ibb); +// std::cout << "Inside: " << (sl::isInside<PolygonImpl>(querybb, ibb) || +// boost::geometry::intersects(querybb, ibb)) << std::endl; +// } + + for(auto& e : result) { // now get the score for the best alignment + auto idx = e.second; + auto& p = pile[idx]; + auto parea = areacache[idx]; + auto bb = sl::boundingBox(sl::Shapes<PolygonImpl>{p, trsh}); + auto bbarea = bb.area(); + auto ascore = 1.0 - (item.area() + parea)/bbarea; + + if(ascore < alignment_score) alignment_score = ascore; + } - for(auto& e : result) { // now get the score for the best alignment - auto idx = e.second; - auto& p = pile[idx]; - auto parea = areacache[idx]; - auto bb = sl::boundingBox(sl::Shapes<PolygonImpl>{p, trsh}); - auto bbarea = bb.area(); - auto ascore = 1.0 - (item.area() + parea)/bbarea; + // 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 + if(result.empty()) + score = 0.5 * dist + 0.5 * density; + else + score = 0.45 * dist + 0.45 * density + 0.1 * alignment_score; - if(ascore < alignment_score) alignment_score = ascore; } - // 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 - score = 0.45 * dist + 0.45 * density + 0.1 * alignment_score; - } 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 @@ -312,10 +345,12 @@ public: const Item &item, double pile_area, double norm, - double /*penality*/) { + const ItemGroup& rem) { auto result = objfunc(bin.center(), bin_area_, pile, - pile_area, item, norm, areacache_, rtree_); + pile_area, item, norm, areacache_, + rtree_, + rem); double score = std::get<0>(result); auto& fullbb = std::get<1>(result); @@ -346,10 +381,11 @@ public: const Item &item, double pile_area, double norm, - double /*penality*/) { + const ItemGroup& rem) { auto result = objfunc(bin.center(), bin_area_, pile, - pile_area, item, norm, areacache_, rtree_); + pile_area, item, norm, areacache_, + rtree_, rem); double score = std::get<0>(result); auto& fullbb = std::get<1>(result); @@ -391,11 +427,12 @@ public: const Item &item, double pile_area, double norm, - double /*penality*/) { + const ItemGroup& rem) { auto binbb = ShapeLike::boundingBox(bin); auto result = objfunc(binbb.center(), bin_area_, pile, - pile_area, item, norm, areacache_, rtree_); + pile_area, item, norm, areacache_, + rtree_, rem); double score = std::get<0>(result); return score; @@ -417,10 +454,11 @@ public: const Item &item, double pile_area, double norm, - double /*penality*/) { + const ItemGroup& rem) { auto result = objfunc({0, 0}, 0, pile, pile_area, - item, norm, areacache_, rtree_); + item, norm, areacache_, + rtree_, rem); return std::get<0>(result); }; |