diff --git a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp index 2ca4f5d50..06afbd187 100644 --- a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp +++ b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp @@ -71,7 +71,8 @@ template<> inline ClipperLib::cInt& y(PointImpl& p) namespace shapelike { -template<> inline void offset(PolygonImpl& sh, TCoord distance) +template<> +inline void offset(PolygonImpl& sh, TCoord distance, const PolygonTag&) { #define DISABLE_BOOST_OFFSET @@ -123,6 +124,14 @@ template<> inline void offset(PolygonImpl& sh, TCoord distance) } } +template<> +inline void offset(PathImpl& sh, TCoord distance, const PathTag&) +{ + PolygonImpl p(std::move(sh)); + offset(p, distance, PolygonTag()); + sh = p.Contour; +} + // Tell libnest2d how to make string out of a ClipperPolygon object template<> inline std::string toString(const PolygonImpl& sh) { diff --git a/src/libnest2d/include/libnest2d/geometry_traits.hpp b/src/libnest2d/include/libnest2d/geometry_traits.hpp index c4f2fcaca..827e2d8ba 100644 --- a/src/libnest2d/include/libnest2d/geometry_traits.hpp +++ b/src/libnest2d/include/libnest2d/geometry_traits.hpp @@ -507,15 +507,13 @@ enum class Formats { namespace shapelike { template -inline S create(const TContour& contour, - const THolesContainer& holes) +inline S create(const TContour& contour, const THolesContainer& holes) { return S(contour, holes); } template -inline S create(TContour&& contour, - THolesContainer&& holes) +inline S create(TContour&& contour, THolesContainer&& holes) { return S(contour, holes); } @@ -727,11 +725,18 @@ inline void translate(S& /*sh*/, const P& /*offs*/) } template -inline void offset(S& /*sh*/, TCoord> /*distance*/) +inline void offset(S& /*sh*/, TCoord /*distance*/, const PathTag&) { dout() << "The current geometry backend does not support offsetting!\n"; } +template +inline void offset(S& sh, TCoord distance, const PolygonTag&) +{ + offset(contour(sh), distance); + for(auto &h : holes(sh)) offset(h, -distance); +} + template inline std::pair isValid(const S& /*sh*/) { @@ -1228,6 +1233,23 @@ template inline bool isConvex(const S& sh) // dispatch return isConvex(sh, Tag()); } +template inline void offset(Box& bb, TCoord d, const BoxTag&) +{ + TPoint md{d, d}; + bb.minCorner() -= md; + bb.maxCorner() += md; +} + +template inline void offset(C& circ, TCoord d, const CircleTag&) +{ + circ.radius(circ.radius() + double(d)); +} + +// Dispatch function +template inline void offset(S& sh, TCoord d) { + offset(sh, d, Tag()); +} + } #define DECLARE_MAIN_TYPES(T) \ diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index b02efa55c..f692f91c7 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -514,19 +514,30 @@ void _arrange( coord_t minobjd, std::function prind, std::function stopfn) -{ - AutoArranger arranger{bin, minobjd, prind, stopfn}; +{ + // Integer ceiling the min distance from the bed perimeters + coord_t md = minobjd - 2 * scaled(0.1 + EPSILON); + md = (md % 2) ? md / 2 + 1 : md / 2; + + auto corrected_bin = bin; + sl::offset(corrected_bin, md); + + AutoArranger arranger{corrected_bin, 0, prind, stopfn}; + + auto infl = coord_t(std::ceil(minobjd / 2.0)); + for (Item& itm : shapes) itm.inflate(infl); + for (Item& itm : excludes) itm.inflate(infl); auto it = excludes.begin(); while (it != excludes.end()) - sl::isInside(it->transformedShape(), bin) ? + sl::isInside(it->transformedShape(), corrected_bin) ? ++it : it = excludes.erase(it); // If there is something on the plate if(!excludes.empty()) { arranger.preload(excludes); - auto binbb = sl::boundingBox(bin); + auto binbb = sl::boundingBox(corrected_bin); // Try to put the first item to the center, as the arranger // will not do this for us. @@ -548,6 +559,7 @@ void _arrange( for (auto &itm : excludes) inp.emplace_back(itm); arranger(inp.begin(), inp.end()); + for (Item &itm : inp) itm.inflate(-infl); } // The final client function for arrangement. A progress indicator and @@ -594,10 +606,6 @@ void arrange(ArrangePolygons & arrangables, for (Item &itm : fixeditems) itm.inflate(scaled(-2. * EPSILON)); - // Integer ceiling the min distance from the bed perimeters - coord_t md = min_obj_dist - 2 * scaled(0.1 + EPSILON); - md = (md % 2) ? md / 2 + 1 : md / 2; - auto &cfn = stopcondition; auto &pri = progressind; @@ -605,7 +613,6 @@ void arrange(ArrangePolygons & arrangables, case bsBox: { // Create the arranger for the box shaped bed BoundingBox bbb = bedhint.get_box(); - bbb.min -= Point{md, md}, bbb.max += Point{md, md}; Box binbb{{bbb.min(X), bbb.min(Y)}, {bbb.max(X), bbb.max(Y)}}; _arrange(items, fixeditems, binbb, min_obj_dist, pri, cfn);