From 2aa4122aae3bf1b045400053c92454ad7c80c407 Mon Sep 17 00:00:00 2001 From: harrierpigeon Date: Fri, 2 Oct 2026 01:07:42 -0500 Subject: [PATCH] Belt: check object height against the gantry clearance again validate() skipped the build-volume height check whenever the machine-frame transform was active, which is every shipped belt profile, so a 400 mm object passed on a 300 mm printable_height. The transform only changes how the height is written to G-code; the clearance check from f682ab5cd3 applies regardless. Raised in Hanif Koh's review of #14394. --- src/libslic3r/Print.cpp | 13 +++---------- tests/fff_print/test_print.cpp | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index dc018388b2..8f70405307 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -20,7 +20,6 @@ #include "GCode.hpp" #include "BeltGCode.hpp" #include "BeltTransform.hpp" -#include "GCode/MachineFrameTransform.hpp" #include "GCode/WipeTower.hpp" #include "GCode/WipeTower2.hpp" #include "GCode/WipeTowerEstimate.hpp" @@ -1621,17 +1620,11 @@ StringObjectException Print::validate(std::vector *warnin // is not comparable to printable_height (which is gantry clearance in the // build-volume frame). Compare against the model's pre-shear Z instead, // mirroring the bbox computed in PrintObject::update_slicing_parameters. - // When the post-gcode MachineFrameTransform is active the printer's - // physical Z mapping is non-trivial — skip the check entirely. + // The machine-frame transform only changes how that height is written to + // G-code, not how much room there is under the gantry. const bool belt_printer = this->config().belt_printer.value; - bool skip_max_height_check = false; - if (belt_printer) { - MachineFrameTransform machine_frame; - machine_frame.init_from_config(this->config()); - skip_max_height_check = machine_frame.is_active(); - } const double shrinkage_compensation_z = this->shrinkage_compensation().z(); - for (size_t print_object_idx = 0; !skip_max_height_check && print_object_idx < m_objects.size(); ++ print_object_idx) { + for (size_t print_object_idx = 0; print_object_idx < m_objects.size(); ++ print_object_idx) { const PrintObject &print_object = *m_objects[print_object_idx]; double effective_max_z = 0; diff --git a/tests/fff_print/test_print.cpp b/tests/fff_print/test_print.cpp index 8b342fde68..6f0eb7b00e 100644 --- a/tests/fff_print/test_print.cpp +++ b/tests/fff_print/test_print.cpp @@ -562,3 +562,37 @@ TEST_CASE("Belt printers never start a scarf seam below the layer", "[Print][bel }); CHECK(worst_backstep < 0.2); } + +// printable_height on a belt printer is the clearance under the gantry, so an object taller +// than that is refused whatever the machine-frame transform does to the emitted coordinates. +TEST_CASE("Belt printers refuse an object taller than the gantry clearance", "[Print][belt]") +{ + auto belt_config = [](double printable_height) { + DynamicPrintConfig config = DynamicPrintConfig::full_print_config(); + config.set_deserialize_strict({ + { "belt_printer", 1 }, + { "belt_slice_rotation", "x" }, + { "belt_slice_rotation_angle", 45 }, + { "belt_slice_rotation_global", 1 }, + { "gcode_remap_x", "rev_x" }, + { "gcode_remap_y", "pos_z" }, + { "gcode_remap_z", "pos_y" }, + { "printable_height", printable_height }, + { "skirt_loops", 0 }, + }); + return config; + }; + + SECTION("a 20 mm cube fits under 50 mm of clearance") { + Print print; + Model model; + init_print({ cube(20) }, print, model, belt_config(50)); + CHECK(print.validate().string.empty()); + } + SECTION("a 60 mm cube does not") { + Print print; + Model model; + init_print({ cube(60) }, print, model, belt_config(50)); + CHECK_FALSE(print.validate().string.empty()); + } +}