From bfbf5ad1c28b4f2a3cadfac802dd814f907263d3 Mon Sep 17 00:00:00 2001 From: harrierpigeon Date: Fri, 2 Oct 2026 12:09:59 -0500 Subject: [PATCH] Arrange: keep a pile aligned to an off-centre point on the bed With best_object_pos away from the bed centre the placer packs the pile inside the bin and then translates it so its centre lands on that point, without checking that it still fits there. A belt printer aims at the leading end of the belt (BabyBelt Pro: 0.5, 0.05), so any pile longer than the 50 mm around that point was pushed past the edge: four 90 mm parts on the 95 x 500 mm belt ended with one across the edge and one outside while 290 mm of belt stayed free. The final alignment now stops the pile at the edge of the bin; the items' inflated boxes leave the object spacing as the margin. A pile that does not fit along an axis is centred on it, as before. --- .../include/libnest2d/placers/nfpplacer.hpp | 22 +++++++++++++++- tests/libslic3r/test_arrange.cpp | 26 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/deps_src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/deps_src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index dc7733ebd6..cf66c4c97e 100644 --- a/deps_src/libnest2d/include/libnest2d/placers/nfpplacer.hpp +++ b/deps_src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -1111,7 +1111,27 @@ private: default: ; // DONT_ALIGN } - auto d = cb - ci; + auto d = cb - ci; + + // Keep the pile on the bin. A target near an edge (a belt printer starts its parts + // at the leading end of the belt) would otherwise centre a pile that is larger than + // the room around that point on it and push part of the pile off the bed. The pile + // stops at the edge instead; the items' boxes carry their inflation, which is the + // margin left there. A pile that does not fit along an axis is centred on it. + { + auto on_bin = [](Coord lo, Coord hi, Coord bin_lo, Coord bin_hi, Coord shift) { + if (hi - lo >= bin_hi - bin_lo) + return (bin_lo + bin_hi) / 2 - (lo + hi) / 2; + if (lo + shift < bin_lo) + shift = bin_lo - lo; + if (hi + shift > bin_hi) + shift = bin_hi - hi; + return shift; + }; + setX(d, on_bin(getX(bb.minCorner()), getX(bb.maxCorner()), getX(bbin.minCorner()), getX(bbin.maxCorner()), getX(d))); + setY(d, on_bin(getY(bb.minCorner()), getY(bb.maxCorner()), getY(bbin.minCorner()), getY(bbin.maxCorner()), getY(d))); + cb = ci + d; + } // BBS make sure the item won't clash with excluded regions // do we have wipe tower after arranging? diff --git a/tests/libslic3r/test_arrange.cpp b/tests/libslic3r/test_arrange.cpp index 3906cba8ba..a8bc56d2d5 100644 --- a/tests/libslic3r/test_arrange.cpp +++ b/tests/libslic3r/test_arrange.cpp @@ -1,3 +1,4 @@ +#include #include #include "libslic3r/Arrange.hpp" @@ -259,6 +260,31 @@ TEST_CASE("Arrange aligns the pile to a custom center", "[Arrange]") require_no_overlap(items); } +// A belt printer starts its parts at the leading end of the belt (best_object_pos 0.5, 0.05). +// Centring a pile on a point that close to the edge pushed everything longer than the room +// around it off the bed: four 90 mm parts on a 95 x 500 mm belt ended with one across the +// edge and one outside, with 290 mm of belt free behind them. The pile stops at the edge. +TEST_CASE("Arrange keeps a pile aligned near an edge on the bed", "[Arrange]") +{ + const BoundingBox belt = bed(95, 500); + ArrangePolygons items = squares(4, 90.); + ArrangeParams params = quiet_params(scaled(2.)); + params.align_center = Vec2d(0.5, 0.05); + + arrange(items, belt, params); + + coord_t lowest = std::numeric_limits::max(); + for (const ArrangePolygon &ap : items) { + REQUIRE(ap.bed_idx == 0); + const BoundingBox bb = ap.transformed_poly().contour.bounding_box(); + CHECK(belt.contains(bb)); + lowest = std::min(lowest, bb.min.y()); + } + // Snapped to the edge it was aimed at, less the spacing margin, not re-centred. + CHECK(lowest < scaled(10.)); + require_no_overlap(items); +} + TEST_CASE("Sequential print floors the object distance by object height", "[Arrange]") { // The only place sequential-print clearance is enforced. The arrange menu offers