From 38cd7fea6540ecf41cd0773f859861ef7924757e Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 25 Aug 2021 12:39:46 +0200 Subject: [PATCH] Fixed update of backend after the changes introduced with b3010a817bdc8e63b2ad2f9d281be3ba89216ba7 (Do not allow objects to be placed fully below bed) and pop object on the bed when only one part is left --- src/libslic3r/Model.cpp | 53 +++++++++++++++++++++++++++++-- src/libslic3r/Model.hpp | 2 ++ src/slic3r/GUI/GUI_ObjectList.cpp | 11 +++---- src/slic3r/GUI/Plater.cpp | 3 +- 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 235c35797..8eb5bb389 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -956,9 +956,22 @@ void ModelObject::center_around_origin(bool include_modifiers) void ModelObject::ensure_on_bed(bool allow_negative_z) { - const double min_z = get_min_z(); - if (!allow_negative_z || min_z > SINKING_Z_THRESHOLD) - translate_instances({ 0.0, 0.0, -min_z }); + double z_offset = 0.0; + + if (allow_negative_z) { + if (volumes.size() == 1) + z_offset = -get_min_z(); + else { + const double max_z = get_max_z(); + if (max_z < SINKING_MIN_Z_THRESHOLD) + z_offset = SINKING_MIN_Z_THRESHOLD - max_z; + } + } + else + z_offset = -get_min_z(); + + if (z_offset != 0.0) + translate_instances(z_offset * Vec3d::UnitZ()); } void ModelObject::translate_instances(const Vec3d& vector) @@ -1429,6 +1442,19 @@ double ModelObject::get_min_z() const } } +double ModelObject::get_max_z() const +{ + if (instances.empty()) + return 0.0; + else { + double max_z = -DBL_MAX; + for (size_t i = 0; i < instances.size(); ++i) { + max_z = std::max(max_z, get_instance_max_z(i)); + } + return max_z; + } +} + double ModelObject::get_instance_min_z(size_t instance_idx) const { double min_z = DBL_MAX; @@ -1450,6 +1476,27 @@ double ModelObject::get_instance_min_z(size_t instance_idx) const return min_z + inst->get_offset(Z); } +double ModelObject::get_instance_max_z(size_t instance_idx) const +{ + double max_z = -DBL_MAX; + + const ModelInstance* inst = instances[instance_idx]; + const Transform3d& mi = inst->get_matrix(true); + + for (const ModelVolume* v : volumes) { + if (!v->is_model_part()) + continue; + + const Transform3d mv = mi * v->get_matrix(); + const TriangleMesh& hull = v->get_convex_hull(); + for (const stl_facet& facet : hull.stl.facet_start) + for (int i = 0; i < 3; ++i) + max_z = std::max(max_z, (mv * facet.vertex[i].cast()).z()); + } + + return max_z + inst->get_offset(Z); +} + unsigned int ModelObject::check_instances_print_volume_state(const BoundingBoxf3& print_volume) { unsigned int num_printable = 0; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 1dd16ee91..25f19e792 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -358,7 +358,9 @@ public: void bake_xy_rotation_into_meshes(size_t instance_idx); double get_min_z() const; + double get_max_z() const; double get_instance_min_z(size_t instance_idx) const; + double get_instance_max_z(size_t instance_idx) const; // Called by Print::validate() from the UI thread. unsigned int check_instances_print_volume_state(const BoundingBoxf3& print_volume); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 1e290beae..23ce819dd 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1920,16 +1920,15 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con if (vol->is_model_part()) ++solid_cnt; if (volume->is_model_part() && solid_cnt == 1) { - Slic3r::GUI::show_error(nullptr, _(L("From Object List You can't delete the last solid part from object."))); + Slic3r::GUI::show_error(nullptr, _L("From Object List You can't delete the last solid part from object.")); return false; } - take_snapshot(_(L("Delete Subobject"))); + take_snapshot(_L("Delete Subobject")); object->delete_volume(idx); - if (object->volumes.size() == 1) - { + if (object->volumes.size() == 1) { const auto last_volume = object->volumes[0]; if (!last_volume->config.empty()) { object->config.apply(last_volume->config); @@ -1948,11 +1947,11 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con } else if (type == itInstance) { if (object->instances.size() == 1) { - Slic3r::GUI::show_error(nullptr, _(L("Last instance of an object cannot be deleted."))); + Slic3r::GUI::show_error(nullptr, _L("Last instance of an object cannot be deleted.")); return false; } - take_snapshot(_(L("Delete Instance"))); + take_snapshot(_L("Delete Instance")); object->delete_instance(idx); } else diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 60215484b..72b2c5909 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6200,8 +6200,7 @@ void Plater::changed_object(int obj_idx) if (obj_idx < 0) return; // recenter and re - align to Z = 0 - auto model_object = p->model.objects[obj_idx]; - model_object->ensure_on_bed(this->p->printer_technology != ptSLA); + p->model.objects[obj_idx]->ensure_on_bed(p->printer_technology != ptSLA); if (this->p->printer_technology == ptSLA) { // Update the SLAPrint from the current Model, so that the reload_scene() // pulls the correct data, update the 3D scene.