From c71e456b95a3f3229f6f68181b1aa11d9392f8bb Mon Sep 17 00:00:00 2001 From: Lam Wei Lun Date: Tue, 20 Oct 2026 19:09:01 +0800 Subject: [PATCH] Scale to Fit Print Volume: fit the area every nozzle reaches Each nozzle reaches only part of the bed on a multi-nozzle printer (H2D: left 0-325, right 25-350 in X), but the command fitted the whole 350 mm bed. A model that filled the bed in X therefore landed outside both nozzles' printable range, and right after the user asked to fit it the plater warned "The position or size of the model exceeds the right nozzle's printable range". Fit the volume every nozzle shares instead -- the same region Arrange already places items in -- and centre on it rather than on the bed. --- src/slic3r/GUI/Plater.cpp | 6 +++++- src/slic3r/GUI/Selection.cpp | 9 ++++----- src/slic3r/GUI/Selection.hpp | 5 +++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 7b96d39eef..13f522d2df 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -11040,7 +11040,11 @@ void Plater::priv::scale_selection_to_fit_print_volume() PartPlate* plate = this->partplate_list.get_curr_plate(); const Vec3d bed_center = plate != nullptr ? plate->get_center_origin() : Vec3d(volume.bed_center().x(), volume.bed_center().y(), 0.); - this->view3D->get_canvas3d()->get_selection().scale_to_fit_print_volume(volume, Vec2d(bed_center.x(), bed_center.y())); + // On a multi-nozzle printer each nozzle reaches only part of the bed, so a model fitted + // to the bed can still exceed a nozzle's printable range. Fit into the volume every + // nozzle shares, which is also the area Arrange places items in. + const BoundingBoxf3 print_volume = plate != nullptr ? plate->get_build_volume(true) : volume.bounding_volume(); + this->view3D->get_canvas3d()->get_selection().scale_to_fit_print_volume(volume, Vec2d(bed_center.x(), bed_center.y()), print_volume); #else this->view3D->get_canvas3d()->get_selection().scale_to_fit_print_volume(*config); #endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 12d6d2abb0..62ec56cf64 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1495,7 +1495,7 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type } #if ENABLE_ENHANCED_PRINT_VOLUME_FIT -void Selection::scale_to_fit_print_volume(const BuildVolume& volume, const Vec2d& bed_center) +void Selection::scale_to_fit_print_volume(const BuildVolume& volume, const Vec2d& bed_center, const BoundingBoxf3& print_volume) { auto fit = [this](double s, Vec3d offset) { if (s <= 0.0 || s == 1.0) @@ -1525,8 +1525,7 @@ void Selection::scale_to_fit_print_volume(const BuildVolume& volume, const Vec2d //wxGetApp().obj_manipul()->set_dirty(); }; - auto fit_rectangle = [this, fit, &bed_center](const BuildVolume& volume) { - const BoundingBoxf3 print_volume = volume.bounding_volume(); + auto fit_rectangle = [this, fit, &print_volume]() { const Vec3d print_volume_size = print_volume.size(); // adds 1/100th of a mm on all sides to avoid false out of print volume detections due to floating-point roundings @@ -1537,7 +1536,7 @@ void Selection::scale_to_fit_print_volume(const BuildVolume& volume, const Vec2d const double sz = (box_size.z() != 0.0) ? print_volume_size.z() / box_size.z() : 0.0; if (sx != 0.0 && sy != 0.0 && sz != 0.0) - fit(std::min(sx, std::min(sy, sz)), Vec3d(bed_center.x(), bed_center.y(), print_volume.center().z()) - get_bounding_box().center()); + fit(std::min(sx, std::min(sy, sz)), print_volume.center() - get_bounding_box().center()); }; auto fit_circle = [this, fit, &bed_center](const BuildVolume& volume) { @@ -1582,7 +1581,7 @@ void Selection::scale_to_fit_print_volume(const BuildVolume& volume, const Vec2d switch (volume.type()) { - case BuildVolume_Type::Rectangle: { fit_rectangle(volume); break; } + case BuildVolume_Type::Rectangle: { fit_rectangle(); break; } case BuildVolume_Type::Circle: { fit_circle(volume); break; } default: { break; } } diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index cb5e7c4728..5b03690ac8 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -355,8 +355,9 @@ public: void scale(const Vec3d& scale, TransformationType transformation_type); #if ENABLE_ENHANCED_PRINT_VOLUME_FIT // bed_center is the centre of the plate the selection is on: every plate shares the - // bed size, but each sits at its own origin. - void scale_to_fit_print_volume(const BuildVolume& volume, const Vec2d& bed_center); + // bed size, but each sits at its own origin. print_volume is the box the selection must + // fit in, which is the area every nozzle reaches rather than the whole bed. + void scale_to_fit_print_volume(const BuildVolume& volume, const Vec2d& bed_center, const BoundingBoxf3& print_volume); #else void scale_to_fit_print_volume(const DynamicPrintConfig& config); #endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT