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.