diff --git a/src/OrcaSlicer.cpp b/src/OrcaSlicer.cpp index a39c35cfa2..09e6b3b574 100644 --- a/src/OrcaSlicer.cpp +++ b/src/OrcaSlicer.cpp @@ -3074,7 +3074,7 @@ int CLI::run(int argc, char **argv) } else if (opt_key == "align_xy") { const Vec2d &p = m_config.option("align_xy")->value; for (auto &model : m_models) { - BoundingBoxf3 bb = model.bounding_box(); + BoundingBoxf3 bb = model.bounding_box_exact(); // this affects volumes: model.translate(-(bb.min.x() - p.x()), -(bb.min.y() - p.y()), -bb.min.z()); } diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 2cf36a69a4..e68ff0a8ed 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -127,7 +127,7 @@ static std::vector get_path_of_change_filament(const Print& print) std::vector> object_intervals; for (PrintObject *print_object : print.objects()) { const PrintInstances &print_instances = print_object->instances(); - BoundingBoxf3 bounding_box = print_instances[0].model_instance->get_object()->bounding_box(); + BoundingBoxf3 bounding_box = print_instances[0].model_instance->get_object()->bounding_box_exact(); if (bounding_box.min.x() < start_x_position && bounding_box.min.y() < cutter_area_y) can_travel_form_left = false; diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index b19445b79f..630adcfb32 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -418,36 +418,12 @@ Vec3d extract_euler_angles(const Transform3d& transform) void rotation_from_two_vectors(Vec3d from, Vec3d to, Vec3d& rotation_axis, double& phi, Matrix3d* rotation_matrix) { - double epsilon = 1e-5; - // note: a.isMuchSmallerThan(b,prec) compares a.abs().sum()(0, 0); + const Eigen::AngleAxisd aa(m); + rotation_axis = aa.axis(); + phi = aa.angle(); + if (rotation_matrix) + *rotation_matrix = m; } Transform3d Transformation::get_offset_matrix() const diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 5cfc5c79ad..8d475cefbb 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -570,14 +570,30 @@ bool Model::add_default_instances() } // this returns the bounding box of the *transformed* instances -BoundingBoxf3 Model::bounding_box() const +BoundingBoxf3 Model::bounding_box_approx() const { BoundingBoxf3 bb; for (ModelObject *o : this->objects) - bb.merge(o->bounding_box()); + bb.merge(o->bounding_box_approx()); return bb; } +BoundingBoxf3 Model::bounding_box_exact() const +{ + BoundingBoxf3 bb; + for (ModelObject *o : this->objects) + bb.merge(o->bounding_box_exact()); + return bb; +} + +double Model::max_z() const +{ + double z = 0; + for (ModelObject *o : this->objects) + z = std::max(z, o->max_z()); + return z; +} + unsigned int Model::update_print_volume_state(const BuildVolume &build_volume) { unsigned int num_printable = 0; @@ -628,7 +644,7 @@ void Model::duplicate_objects_grid(size_t x, size_t y, coordf_t dist) ModelObject* object = this->objects.front(); object->clear_instances(); - Vec3d ext_size = object->bounding_box().size() + dist * Vec3d::Ones(); + Vec3d ext_size = object->bounding_box_exact().size() + dist * Vec3d::Ones(); for (size_t x_copy = 1; x_copy <= x; ++x_copy) { for (size_t y_copy = 1; y_copy <= y; ++y_copy) { @@ -647,7 +663,7 @@ bool Model::looks_like_multipart_object() const if (obj->volumes.size() > 1 || obj->config.keys().size() > 1) return false; - double zmin_this = obj->get_min_z(); + double zmin_this = obj->min_z(); if (zmin == std::numeric_limits::max()) zmin = zmin_this; else if (std::abs(zmin - zmin_this) > EPSILON) @@ -804,13 +820,13 @@ void Model::adjust_min_z() if (objects.empty()) return; - if (bounding_box().min(2) < 0.0) + if (this->bounding_box_exact().min.z() < 0.0) { for (ModelObject* obj : objects) { if (obj != nullptr) { - coordf_t obj_min_z = obj->bounding_box().min(2); + coordf_t obj_min_z = obj->min_z(); if (obj_min_z < 0.0) obj->translate_instances(Vec3d(0.0, 0.0, -obj_min_z)); } @@ -1021,12 +1037,7 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs) this->printable = rhs.printable; this->origin_translation = rhs.origin_translation; this->cut_id.copy(rhs.cut_id); - m_bounding_box = rhs.m_bounding_box; - m_bounding_box_valid = rhs.m_bounding_box_valid; - m_raw_bounding_box = rhs.m_raw_bounding_box; - m_raw_bounding_box_valid = rhs.m_raw_bounding_box_valid; - m_raw_mesh_bounding_box = rhs.m_raw_mesh_bounding_box; - m_raw_mesh_bounding_box_valid = rhs.m_raw_mesh_bounding_box_valid; + this->copy_transformation_caches(rhs); this->clear_volumes(); this->volumes.reserve(rhs.volumes.size()); @@ -1064,12 +1075,7 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs) this->layer_height_profile = std::move(rhs.layer_height_profile); this->printable = std::move(rhs.printable); this->origin_translation = std::move(rhs.origin_translation); - m_bounding_box = std::move(rhs.m_bounding_box); - m_bounding_box_valid = std::move(rhs.m_bounding_box_valid); - m_raw_bounding_box = rhs.m_raw_bounding_box; - m_raw_bounding_box_valid = rhs.m_raw_bounding_box_valid; - m_raw_mesh_bounding_box = rhs.m_raw_mesh_bounding_box; - m_raw_mesh_bounding_box_valid = rhs.m_raw_mesh_bounding_box_valid; + this->copy_transformation_caches(rhs); this->clear_volumes(); this->volumes = std::move(rhs.volumes); @@ -1312,16 +1318,72 @@ void ModelObject::clear_instances() // Returns the bounding box of the transformed instances. // This bounding box is approximate and not snug. -const BoundingBoxf3& ModelObject::bounding_box() const +const BoundingBoxf3& ModelObject::bounding_box_approx() const { - if (! m_bounding_box_valid) { - m_bounding_box_valid = true; + if (! m_bounding_box_approx_valid) { + m_bounding_box_approx_valid = true; BoundingBoxf3 raw_bbox = this->raw_mesh_bounding_box(); - m_bounding_box.reset(); + m_bounding_box_approx.reset(); for (const ModelInstance *i : this->instances) - m_bounding_box.merge(i->transform_bounding_box(raw_bbox)); + m_bounding_box_approx.merge(i->transform_bounding_box(raw_bbox)); + } + return m_bounding_box_approx; +} + +// Returns the bounding box of the transformed instances. +// This bounding box is approximate and not snug. +const BoundingBoxf3& ModelObject::bounding_box_exact() const +{ + if (! m_bounding_box_exact_valid) { + m_bounding_box_exact_valid = true; + m_min_max_z_valid = true; + m_bounding_box_exact.reset(); + for (size_t i = 0; i < this->instances.size(); ++ i) + m_bounding_box_exact.merge(this->instance_bounding_box(i)); + } + return m_bounding_box_exact; +} + +double ModelObject::min_z() const +{ + const_cast(this)->update_min_max_z(); + return m_bounding_box_exact.min.z(); +} + +double ModelObject::max_z() const +{ + const_cast(this)->update_min_max_z(); + return m_bounding_box_exact.max.z(); +} + +void ModelObject::update_min_max_z() +{ + assert(! this->instances.empty()); + if (! m_min_max_z_valid && ! this->instances.empty()) { + m_min_max_z_valid = true; + const Transform3d mat_instance = this->instances.front()->get_transformation().get_matrix(); + double global_min_z = std::numeric_limits::max(); + double global_max_z = - std::numeric_limits::max(); + for (const ModelVolume *v : this->volumes) + if (v->is_model_part()) { + const Transform3d m = mat_instance * v->get_matrix(); + const Vec3d row_z = m.linear().row(2).cast(); + const double shift_z = m.translation().z(); + double this_min_z = std::numeric_limits::max(); + double this_max_z = - std::numeric_limits::max(); + for (const Vec3f &p : v->mesh().its.vertices) { + double z = row_z.dot(p.cast()); + this_min_z = std::min(this_min_z, z); + this_max_z = std::max(this_max_z, z); + } + this_min_z += shift_z; + this_max_z += shift_z; + global_min_z = std::min(global_min_z, this_min_z); + global_max_z = std::max(global_max_z, this_max_z); + } + m_bounding_box_exact.min.z() = global_min_z; + m_bounding_box_exact.max.z() = global_max_z; } - return m_bounding_box; } // A mesh containing all transformed instances of this object. @@ -1532,19 +1594,19 @@ void ModelObject::ensure_on_bed(bool allow_negative_z) if (allow_negative_z) { if (parts_count() == 1) { - const double min_z = get_min_z(); - const double max_z = get_max_z(); + const double min_z = this->min_z(); + const double max_z = this->max_z(); if (min_z >= SINKING_Z_THRESHOLD || max_z < 0.0) z_offset = -min_z; } else { - const double max_z = get_max_z(); + const double max_z = this->max_z(); if (max_z < SINKING_MIN_Z_THRESHOLD) z_offset = SINKING_MIN_Z_THRESHOLD - max_z; } } else - z_offset = -get_min_z(); + z_offset = -this->min_z(); if (z_offset != 0.0) translate_instances(z_offset * Vec3d::UnitZ()); @@ -1571,8 +1633,10 @@ void ModelObject::translate(double x, double y, double z) v->translate(x, y, z); } - if (m_bounding_box_valid) - m_bounding_box.translate(x, y, z); + if (m_bounding_box_approx_valid) + m_bounding_box_approx.translate(x, y, z); + if (m_bounding_box_exact_valid) + m_bounding_box_exact.translate(x, y, z); } void ModelObject::scale(const Vec3d &versor) @@ -2049,32 +2113,6 @@ void ModelObject::bake_xy_rotation_into_meshes(size_t instance_idx) this->invalidate_bounding_box(); } -double ModelObject::get_min_z() const -{ - if (instances.empty()) - return 0.0; - else { - double min_z = DBL_MAX; - for (size_t i = 0; i < instances.size(); ++i) { - min_z = std::min(min_z, get_instance_min_z(i)); - } - return min_z; - } -} - -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; @@ -2611,7 +2649,7 @@ void ModelVolume::scale(const Vec3d& scaling_factors) void ModelObject::scale_to_fit(const Vec3d &size) { - Vec3d orig_size = this->bounding_box().size(); + Vec3d orig_size = this->bounding_box_exact().size(); double factor = std::min( size.x() / orig_size.x(), std::min( diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 5ef1c938fb..f30fca281a 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -380,7 +380,7 @@ public: // The pairs of are packed into a 1D array. LayerHeightProfile layer_height_profile; // Whether or not this object is printable - bool printable; + bool printable { true }; // This vector holds position of selected support points for SLA. The data are // saved in mesh coordinates to allow using them for several instances. @@ -444,11 +444,22 @@ public: void delete_last_instance(); void clear_instances(); - // Returns the bounding box of the transformed instances. - // This bounding box is approximate and not snug. - // This bounding box is being cached. - const BoundingBoxf3& bounding_box() const; - void invalidate_bounding_box() { m_bounding_box_valid = false; m_raw_bounding_box_valid = false; m_raw_mesh_bounding_box_valid = false; } + // Returns the bounding box of the transformed instances. This bounding box is approximate and not snug, it is being cached. + const BoundingBoxf3& bounding_box_approx() const; + // Returns an exact bounding box of the transformed instances. The result it is being cached. + const BoundingBoxf3& bounding_box_exact() const; + // Return minimum / maximum of a printable object transformed into the world coordinate system. + // All instances share the same min / max Z. + double min_z() const; + double max_z() const; + + void invalidate_bounding_box() { + m_bounding_box_approx_valid = false; + m_bounding_box_exact_valid = false; + m_min_max_z_valid = false; + m_raw_bounding_box_valid = false; + m_raw_mesh_bounding_box_valid = false; + } // A mesh containing all transformed instances of this object. TriangleMesh mesh() const; @@ -521,8 +532,6 @@ public: // Rotation and mirroring is being baked in. In case the instance scaling was non-uniform, it is baked in as well. 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; @@ -543,14 +552,13 @@ public: private: friend class Model; // This constructor assigns new ID to this ModelObject and its config. - explicit ModelObject(Model* model) : m_model(model), printable(true), origin_translation(Vec3d::Zero()), - m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) + explicit ModelObject(Model* model) : m_model(model), origin_translation(Vec3d::Zero()) { assert(this->id().valid()); assert(this->config.id().valid()); assert(this->layer_height_profile.id().valid()); } - explicit ModelObject(int) : ObjectBase(-1), config(-1), layer_height_profile(-1), m_model(nullptr), printable(true), origin_translation(Vec3d::Zero()), m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) + explicit ModelObject(int) : ObjectBase(-1), config(-1), layer_height_profile(-1), origin_translation(Vec3d::Zero()) { assert(this->id().invalid()); assert(this->config.id().invalid()); @@ -628,15 +636,31 @@ private: OBJECTBASE_DERIVED_COPY_MOVE_CLONE(ModelObject) // Parent object, owning this ModelObject. Set to nullptr here, so the macros above will have it initialized. - Model *m_model = nullptr; + Model *m_model { nullptr }; // Bounding box, cached. - mutable BoundingBoxf3 m_bounding_box; - mutable bool m_bounding_box_valid; + mutable BoundingBoxf3 m_bounding_box_approx; + mutable bool m_bounding_box_approx_valid { false }; + mutable BoundingBoxf3 m_bounding_box_exact; + mutable bool m_bounding_box_exact_valid { false }; + mutable bool m_min_max_z_valid { false }; mutable BoundingBoxf3 m_raw_bounding_box; - mutable bool m_raw_bounding_box_valid; + mutable bool m_raw_bounding_box_valid { false }; mutable BoundingBoxf3 m_raw_mesh_bounding_box; - mutable bool m_raw_mesh_bounding_box_valid; + mutable bool m_raw_mesh_bounding_box_valid { false }; + + // Only use this method if now the source and dest ModelObjects are equal, for example they were synchronized by Print::apply(). + void copy_transformation_caches(const ModelObject &src) { + m_bounding_box_approx = src.m_bounding_box_approx; + m_bounding_box_approx_valid = src.m_bounding_box_approx_valid; + m_bounding_box_exact = src.m_bounding_box_exact; + m_bounding_box_exact_valid = src.m_bounding_box_exact_valid; + m_min_max_z_valid = src.m_min_max_z_valid; + m_raw_bounding_box = src.m_raw_bounding_box; + m_raw_bounding_box_valid = src.m_raw_bounding_box_valid; + m_raw_mesh_bounding_box = src.m_raw_mesh_bounding_box; + m_raw_mesh_bounding_box_valid = src.m_raw_mesh_bounding_box_valid; + } // Called by Print::apply() to set the model pointer after making a copy. friend class Print; @@ -648,8 +672,7 @@ private: friend class UndoRedo::StackImpl; // Used for deserialization -> Don't allocate any IDs for the ModelObject or its config. ModelObject() : - ObjectBase(-1), config(-1), layer_height_profile(-1), - m_model(nullptr), m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) { + ObjectBase(-1), config(-1), layer_height_profile(-1) { assert(this->id().invalid()); assert(this->config.id().invalid()); assert(this->layer_height_profile.id().invalid()); @@ -660,7 +683,9 @@ private: Internal::StaticSerializationWrapper layer_heigth_profile_wrapper(layer_height_profile); ar(name, module_name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_heigth_profile_wrapper, sla_support_points, sla_points_status, sla_drain_holes, printable, origin_translation, - m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid, + m_bounding_box_approx, m_bounding_box_approx_valid, + m_bounding_box_exact, m_bounding_box_exact_valid, m_min_max_z_valid, + m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid, cut_connectors, cut_id); } template void load(Archive& ar) { @@ -671,7 +696,9 @@ private: SaveObjectGaurd gaurd(*this); ar(name, module_name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_heigth_profile_wrapper, sla_support_points, sla_points_status, sla_drain_holes, printable, origin_translation, - m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid, + m_bounding_box_approx, m_bounding_box_approx_valid, + m_bounding_box_exact, m_bounding_box_exact_valid, m_min_max_z_valid, + m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid, cut_connectors, cut_id); std::vector volume_ids2; std::transform(volumes.begin(), volumes.end(), std::back_inserter(volume_ids2), std::mem_fn(&ObjectBase::id)); @@ -682,6 +709,9 @@ private: // Called by Print::validate() from the UI thread. unsigned int update_instances_print_volume_state(const BuildVolume &build_volume); + + // Called by min_z(), max_z() + void update_min_max_z(); }; enum class EnforcerBlockerType : int8_t { @@ -1268,10 +1298,8 @@ public: // BBS void rotate(Matrix3d rotation_matrix) { - auto R = m_transformation.get_rotation_matrix().matrix().block<3, 3>(0, 0); - auto R_new = rotation_matrix * R; - auto euler_angles = Geometry::extract_euler_angles(R_new); - set_rotation(euler_angles); + const Geometry::Transformation& old_inst_trafo = get_transformation(); + set_transformation(Geometry::Transformation{old_inst_trafo.get_offset_matrix() * rotation_matrix * old_inst_trafo.get_matrix_no_offset()}); } Vec3d get_scaling_factor() const { return m_transformation.get_scaling_factor(); } @@ -1574,8 +1602,12 @@ public: void delete_material(t_model_material_id material_id); void clear_materials(); bool add_default_instances(); - // Returns approximate axis aligned bounding box of this model - BoundingBoxf3 bounding_box() const; + // Returns approximate axis aligned bounding box of this model. + BoundingBoxf3 bounding_box_approx() const; + // Returns exact axis aligned bounding box of this model. + BoundingBoxf3 bounding_box_exact() const; + // Return maximum height of all printable objects. + double max_z() const; // Set the print_volume_state of PrintObject::instances, // return total number of printable objects. unsigned int update_print_volume_state(const BuildVolume &build_volume); diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp index 50622a3b54..92ac77b191 100644 --- a/src/libslic3r/ModelArrange.cpp +++ b/src/libslic3r/ModelArrange.cpp @@ -176,7 +176,7 @@ ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r:: ap.has_tree_support = true; } - ap.height = obj->bounding_box().size().z(); + ap.height = obj->bounding_box_exact().size().z(); ap.name = obj->name; return ap; } diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 4812579f02..0dabd5ea09 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -108,6 +108,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Transfor m_center_offset = Point::new_scale(bbox_center.x(), bbox_center.y()); // Size of the transformed mesh. This bounding may not be snug in XY plane, but it is snug in Z. m_size = (bbox.size() * (1. / SCALING_FACTOR)).cast(); + m_size.z() = coord_t(model_object->max_z() * (1. / SCALING_FACTOR)); this->set_instances(std::move(instances)); } @@ -2932,7 +2933,7 @@ void PrintObject::update_slicing_parameters() { if (!m_slicing_params.valid) m_slicing_params = SlicingParameters::create_from_config( - this->print()->config(), m_config, this->model_object()->bounding_box().max.z(), this->object_extruders()); + this->print()->config(), m_config, this->model_object()->max_z(), this->object_extruders()); } SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig& full_config, const ModelObject& model_object, float object_max_z) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 05670cb472..e452aaabb3 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -160,7 +160,8 @@ void GLCanvas3D::LayersEditing::select_object(const Model& model, int object_id) // Maximum height of an object changes when the object gets rotated or scaled. // Changing maximum height of an object will invalidate the layer heigth editing profile. // m_model_object->bounding_box() is cached, therefore it is cheap even if this method is called frequently. - const float new_max_z = (model_object_new == nullptr) ? 0.0f : static_cast(model_object_new->bounding_box().max.z()); + const float new_max_z = (model_object_new == nullptr) ? 0.0f : static_cast(model_object_new->max_z()); + if (m_model_object != model_object_new || this->last_object_id != object_id || m_object_max_z != new_max_z || (model_object_new != nullptr && m_model_object->id() != model_object_new->id())) { m_layer_height_profile.clear(); diff --git a/src/slic3r/GUI/Jobs/OrientJob.cpp b/src/slic3r/GUI/Jobs/OrientJob.cpp index 1dcc510eea..be59225d8d 100644 --- a/src/slic3r/GUI/Jobs/OrientJob.cpp +++ b/src/slic3r/GUI/Jobs/OrientJob.cpp @@ -238,6 +238,7 @@ orientation::OrientMesh OrientJob::get_orient_mesh(ModelInstance* instance) om.setter = [instance](const OrientMesh& p) { instance->rotate(p.rotation_matrix); + instance->get_object()->invalidate_bounding_box(); instance->get_object()->ensure_on_bed(); }; return om; diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 6b0d8c6406..940028bd77 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -1601,7 +1601,7 @@ Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, con if (!use_global_objects && !contain_instance_totally(obj_idx, 0)) continue; - BoundingBoxf3 bbox = m_model->objects[obj_idx]->bounding_box(); + BoundingBoxf3 bbox = m_model->objects[obj_idx]->bounding_box_exact(); max_height = std::max(bbox.size().z(), max_height); } wipe_tower_size(2) = max_height; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 28b34b1559..fac25e091c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5295,7 +5295,7 @@ bool Plater::priv::replace_volume_with_stl(int object_idx, int volume_idx, const ModelObject* old_model_object = model.objects[object_idx]; ModelVolume* old_volume = old_model_object->volumes[volume_idx]; - bool sinking = old_model_object->bounding_box().min.z() < SINKING_Z_THRESHOLD; + bool sinking = old_model_object->min_z() < SINKING_Z_THRESHOLD; ModelObject* new_model_object = new_model.objects.front(); old_model_object->add_volume(*new_model_object->volumes.front()); @@ -5616,7 +5616,7 @@ void Plater::priv::reload_from_disk() ModelObject *old_model_object = model.objects[obj_idx]; ModelVolume *old_volume = old_model_object->volumes[vol_idx]; - bool sinking = old_model_object->bounding_box().min.z() < SINKING_Z_THRESHOLD; + bool sinking = old_model_object->min_z() < SINKING_Z_THRESHOLD; bool has_source = !old_volume->source.input_file.empty() && boost::algorithm::iequals(fs::path(old_volume->source.input_file).filename().string(), fs::path(path).filename().string()); @@ -7846,7 +7846,7 @@ bool Plater::priv::layers_height_allowed() const return false; int obj_idx = get_selected_object_idx(); - return 0 <= obj_idx && obj_idx < (int)model.objects.size() && model.objects[obj_idx]->bounding_box().max.z() > SINKING_Z_THRESHOLD && view3D->is_layers_editing_allowed(); + return 0 <= obj_idx && obj_idx < (int)model.objects.size() && model.objects[obj_idx]->max_z() > SINKING_Z_THRESHOLD && view3D->is_layers_editing_allowed(); } bool Plater::priv::can_layers_editing() const @@ -9104,7 +9104,7 @@ void Plater::_calib_pa_tower(const Calib_Params& params) { wxGetApp().get_tab(Preset::TYPE_PRINTER)->reload_config(); auto new_height = std::ceil((params.end - params.start) / params.step) + 1; - auto obj_bb = model().objects[0]->bounding_box(); + auto obj_bb = model().objects[0]->bounding_box_exact(); if (new_height < obj_bb.size().z()) { cut_horizontal(0, 0, new_height, ModelObjectCutAttribute::KeepLower); } @@ -9245,7 +9245,7 @@ void Plater::calib_temp(const Calib_Params& params) { wxGetApp().get_tab(Preset::TYPE_FILAMENT)->reload_config(); // cut upper - auto obj_bb = model().objects[0]->bounding_box(); + auto obj_bb = model().objects[0]->bounding_box_exact(); auto block_count = lround((350 - params.end) / 5 + 1); if(block_count > 0){ // add EPSILON offset to avoid cutting at the exact location where the flat surface is @@ -9256,7 +9256,7 @@ void Plater::calib_temp(const Calib_Params& params) { } // cut bottom - obj_bb = model().objects[0]->bounding_box(); + obj_bb = model().objects[0]->bounding_box_exact(); block_count = lround((350 - params.start) / 5); if(block_count > 0){ auto new_height = block_count * 10.0 + EPSILON; @@ -9285,7 +9285,7 @@ void Plater::calib_max_vol_speed(const Calib_Params& params) auto bed_shape = printer_config->option("printable_area")->values; BoundingBoxf bed_ext = get_extents(bed_shape); - auto scale_obj = (bed_ext.size().x() - 10) / obj->bounding_box().size().x(); + auto scale_obj = (bed_ext.size().x() - 10) / obj->bounding_box_exact().size().x(); if (scale_obj < 1.0) obj->scale(scale_obj, 1, 1); @@ -9327,7 +9327,7 @@ void Plater::calib_max_vol_speed(const Calib_Params& params) wxGetApp().get_tab(Preset::TYPE_PRINTER)->reload_config(); // cut upper - auto obj_bb = obj->bounding_box(); + auto obj_bb = obj->bounding_box_exact(); auto height = (params.end - params.start + 1) / params.step; if (height < obj_bb.size().z()) { cut_horizontal(0, 0, height, ModelObjectCutAttribute::KeepLower); @@ -9376,7 +9376,7 @@ void Plater::calib_retraction(const Calib_Params& params) changed_objects({ 0 }); // cut upper - auto obj_bb = obj->bounding_box(); + auto obj_bb = obj->bounding_box_exact(); auto height = 1.0 + 0.4 + ((params.end - params.start)) / params.step; if (height < obj_bb.size().z()) { cut_horizontal(0, 0, height, ModelObjectCutAttribute::KeepLower); @@ -9419,7 +9419,7 @@ void Plater::calib_VFA(const Calib_Params& params) wxGetApp().get_tab(Preset::TYPE_FILAMENT)->update_ui_from_settings(); // cut upper - auto obj_bb = model().objects[0]->bounding_box(); + auto obj_bb = model().objects[0]->bounding_box_exact(); auto height = 5 * ((params.end - params.start) / params.step + 1); if (height < obj_bb.size().z()) { cut_horizontal(0, 0, height, ModelObjectCutAttribute::KeepLower); @@ -12432,7 +12432,7 @@ void Plater::changed_objects(const std::vector& object_idxs) for (size_t obj_idx : object_idxs) { if (obj_idx < p->model.objects.size()) { - if (p->model.objects[obj_idx]->bounding_box().min.z() >= SINKING_Z_THRESHOLD) + if (p->model.objects[obj_idx]->min_z() >= SINKING_Z_THRESHOLD) // re - align to Z = 0 p->model.objects[obj_idx]->ensure_on_bed(); } diff --git a/src/slic3r/Utils/CalibUtils.cpp b/src/slic3r/Utils/CalibUtils.cpp index 9c61742bc8..e7455e6fa3 100644 --- a/src/slic3r/Utils/CalibUtils.cpp +++ b/src/slic3r/Utils/CalibUtils.cpp @@ -662,7 +662,7 @@ void CalibUtils::calib_temptue(const CalibInfo &calib_info, wxString &error_mess read_model_from_file(input_file, model); // cut upper - auto obj_bb = model.objects[0]->bounding_box(); + auto obj_bb = model.objects[0]->bounding_box_exact(); auto block_count = lround((350 - params.start) / 5 + 1); if (block_count > 0) { // add EPSILON offset to avoid cutting at the exact location where the flat surface is @@ -673,7 +673,7 @@ void CalibUtils::calib_temptue(const CalibInfo &calib_info, wxString &error_mess } // cut bottom - obj_bb = model.objects[0]->bounding_box(); + obj_bb = model.objects[0]->bounding_box_exact(); block_count = lround((350 - params.end) / 5); if (block_count > 0) { auto new_height = block_count * 10.0 + EPSILON; @@ -728,7 +728,7 @@ void CalibUtils::calib_max_vol_speed(const CalibInfo &calib_info, wxString &erro auto obj = model.objects[0]; auto bed_shape = printer_config.option("printable_area")->values; BoundingBoxf bed_ext = get_extents(bed_shape); - auto scale_obj = (bed_ext.size().x() - 10) / obj->bounding_box().size().x(); + auto scale_obj = (bed_ext.size().x() - 10) / obj->bounding_box_exact().size().x(); if (scale_obj < 1.0) obj->scale(scale_obj, 1, 1); @@ -762,7 +762,7 @@ void CalibUtils::calib_max_vol_speed(const CalibInfo &calib_info, wxString &erro obj->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0)); // cut upper - auto obj_bb = obj->bounding_box(); + auto obj_bb = obj->bounding_box_exact(); double height = (params.end - params.start + 1) / params.step; if (height < obj_bb.size().z()) { cut_model(model, height, ModelObjectCutAttribute::KeepLower); @@ -820,7 +820,7 @@ void CalibUtils::calib_VFA(const CalibInfo &calib_info, wxString &error_message) model.objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0)); // cut upper - auto obj_bb = model.objects[0]->bounding_box(); + auto obj_bb = model.objects[0]->bounding_box_exact(); auto height = 5 * ((params.end - params.start) / params.step + 1); if (height < obj_bb.size().z()) { cut_model(model, height, ModelObjectCutAttribute::KeepLower); @@ -875,7 +875,7 @@ void CalibUtils::calib_retraction(const CalibInfo &calib_info, wxString &error_m obj->config.set_key_value("layer_height", new ConfigOptionFloat(layer_height)); // cut upper - auto obj_bb = obj->bounding_box(); + auto obj_bb = obj->bounding_box_exact(); auto height = 1.0 + 0.4 + ((params.end - params.start)) / params.step; if (height < obj_bb.size().z()) { cut_model(model, height, ModelObjectCutAttribute::KeepLower); @@ -947,7 +947,7 @@ void CalibUtils::process_and_store_3mf(Model *model, const DynamicPrintConfig &f ModelInstance *instance = model->objects[0]->instances[0]; instance->set_offset(instance->get_offset() + Vec3d(current_width / 2, current_depth / 2, 0)); } else { - BoundingBoxf3 bbox = model->bounding_box(); + BoundingBoxf3 bbox = model->bounding_box_exact(); Vec3d bbox_center = bbox.center(); for (auto object : model->objects) { ModelInstance *instance = object->instances[0];