mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-15 11:51:33 +00:00
Keep the G-code identical to main on Clipper2
Since main moved to Clipper2, parts of this branch no longer gave the same G-code as main: - bridge_over_infill dropped expand(limiting_area, 0.3 * flow.spacing()) as a no-op. The offset is below one unit, but Clipper2 still unites its result, which splits and merges touching polygons and so changes the anchor lines. Running it on the polygons next to the bridge gives main's anchors without the whole-layer pass. - tsp_remove_crossings stopped at the first repeated ordering, where main runs on to its pn * pn cap. The loop is periodic from that point, so it now takes only the steps to the ordering main stops on. - With a single tile, the tiled booleans now make the plain call instead of cutting the clip to the tile first. The tiled boolean test compared rings exactly. With the safety offset a tile unites only the clip polygons near it, and Clipper2 can then round a crossing 1 unit differently, so that case allows 1 unit. Comments that named ClipperLib now say Clipper, and docs/HLSD/polygon-clipping.md describes the tiled booleans. G-code of the five handy models in four configurations and of a baked texture relief is byte-identical to main. Colour-painted models still differ: segmenting each island on its own splits a colour's region into different pieces than one diagram over the layer, which on one model also changes the first layer's tool order.
This commit is contained in:
@@ -325,6 +325,15 @@ static std::vector<std::vector<coord_t>> canonical_rings(const ExPolygons &expol
|
||||
return rings;
|
||||
}
|
||||
|
||||
// The same rings, every coordinate within `tolerance`.
|
||||
static bool same_rings(const ExPolygons &a, const ExPolygons &b, coord_t tolerance)
|
||||
{
|
||||
const std::vector<std::vector<coord_t>> ra = canonical_rings(a), rb = canonical_rings(b);
|
||||
return std::equal(ra.begin(), ra.end(), rb.begin(), rb.end(), [tolerance](const std::vector<coord_t> &x, const std::vector<coord_t> &y) {
|
||||
return std::equal(x.begin(), x.end(), y.begin(), y.end(), [tolerance](coord_t u, coord_t v) { return std::abs(u - v) <= tolerance; });
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("Tiled diff and intersection return the same polygons as the plain calls", "[ClipperUtils]") {
|
||||
// A grid of disjoint framed squares, enough of them to be split into several tiles.
|
||||
const int n = 40;
|
||||
@@ -358,13 +367,16 @@ TEST_CASE("Tiled diff and intersection return the same polygons as the plain cal
|
||||
// path under test is never taken.
|
||||
REQUIRE(ClipperUtils::tile_expolygons(subject, 32).size() > 1);
|
||||
|
||||
// With the safety offset a tile unites fewer clip polygons, so Clipper2 can round a crossing 1 unit differently.
|
||||
const coord_t tolerance = safety == ApplySafetyOffset::Yes ? 1 : 0;
|
||||
|
||||
const ExPolygons diff_plain = diff_ex(subject, clip, safety);
|
||||
const ExPolygons diff_tiled = diff_ex_by_piece(subject, clip, safety);
|
||||
REQUIRE(area(diff_plain) > 0.);
|
||||
CHECK(canonical_rings(diff_tiled) == canonical_rings(diff_plain));
|
||||
CHECK(same_rings(diff_tiled, diff_plain, tolerance));
|
||||
|
||||
const ExPolygons intersection_plain = intersection_ex(subject, clip, safety);
|
||||
const ExPolygons intersection_tiled = intersection_ex_by_piece(subject, clip, safety);
|
||||
REQUIRE(area(intersection_plain) > 0.);
|
||||
CHECK(canonical_rings(intersection_tiled) == canonical_rings(intersection_plain));
|
||||
CHECK(same_rings(intersection_tiled, intersection_plain, tolerance));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user