Merge branch 'master' of https://github.com/Prusa-Development/PrusaSlicerPrivate into et_transformations
This commit is contained in:
commit
7b08170077
@ -382,7 +382,7 @@ int CLI::run(int argc, char **argv)
|
||||
} else if (opt_key == "align_xy") {
|
||||
const Vec2d &p = m_config.option<ConfigOptionPoint>("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());
|
||||
}
|
||||
@ -423,7 +423,7 @@ int CLI::run(int argc, char **argv)
|
||||
} else if (opt_key == "cut" || opt_key == "cut_x" || opt_key == "cut_y") {
|
||||
std::vector<Model> new_models;
|
||||
for (auto &model : m_models) {
|
||||
model.translate(0, 0, -model.bounding_box().min.z()); // align to z = 0
|
||||
model.translate(0, 0, -model.bounding_box_exact().min.z()); // align to z = 0
|
||||
size_t num_objects = model.objects.size();
|
||||
for (size_t i = 0; i < num_objects; ++ i) {
|
||||
|
||||
|
@ -323,14 +323,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;
|
||||
@ -377,7 +393,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) {
|
||||
@ -548,13 +564,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));
|
||||
}
|
||||
@ -627,8 +643,11 @@ 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_bounding_box_approx = rhs.m_bounding_box_approx;
|
||||
m_bounding_box_approx_valid = rhs.m_bounding_box_approx_valid;
|
||||
m_bounding_box_exact = rhs.m_bounding_box_exact;
|
||||
m_bounding_box_exact_valid = rhs.m_bounding_box_exact_valid;
|
||||
m_min_max_z_valid = rhs.m_min_max_z_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;
|
||||
@ -668,8 +687,11 @@ 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_bounding_box_approx = std::move(rhs.m_bounding_box_approx);
|
||||
m_bounding_box_approx_valid = std::move(rhs.m_bounding_box_approx_valid);
|
||||
m_bounding_box_exact = std::move(rhs.m_bounding_box_exact);
|
||||
m_bounding_box_exact_valid = std::move(rhs.m_bounding_box_exact_valid);
|
||||
m_min_max_z_valid = rhs.m_min_max_z_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;
|
||||
@ -864,16 +886,73 @@ 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;
|
||||
BoundingBoxf3 raw_bbox = this->raw_mesh_bounding_box();
|
||||
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<ModelObject*>(this)->update_min_max_z();
|
||||
return m_bounding_box_exact.min.z();
|
||||
}
|
||||
|
||||
double ModelObject::max_z() const
|
||||
{
|
||||
const_cast<ModelObject*>(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<double>::max();
|
||||
double global_max_z = - std::numeric_limits<double>::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<double>();
|
||||
const double shift_z = m.translation().z();
|
||||
double this_min_z = std::numeric_limits<double>::max();
|
||||
double this_max_z = - std::numeric_limits<double>::max();
|
||||
for (const Vec3f &p : v->mesh().its.vertices) {
|
||||
double z = row_z.dot(p.cast<double>());
|
||||
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.
|
||||
@ -1031,19 +1110,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());
|
||||
@ -1070,8 +1149,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)
|
||||
@ -1866,32 +1947,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;
|
||||
@ -2268,7 +2323,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(
|
||||
@ -2373,37 +2428,6 @@ void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) cons
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
|
||||
BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh& mesh, bool dont_translate) const
|
||||
{
|
||||
// Rotate around mesh origin.
|
||||
TriangleMesh copy(mesh);
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
copy.transform(get_transformation().get_rotation_matrix());
|
||||
#else
|
||||
copy.transform(get_matrix(true, false, true, true));
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
BoundingBoxf3 bbox = copy.bounding_box();
|
||||
|
||||
if (!empty(bbox)) {
|
||||
// Scale the bounding box along the three axes.
|
||||
for (unsigned int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (std::abs(get_scaling_factor((Axis)i)-1.0) > EPSILON)
|
||||
{
|
||||
bbox.min(i) *= get_scaling_factor((Axis)i);
|
||||
bbox.max(i) *= get_scaling_factor((Axis)i);
|
||||
}
|
||||
}
|
||||
|
||||
// Translate the bounding box.
|
||||
if (! dont_translate) {
|
||||
bbox.min += get_offset();
|
||||
bbox.max += get_offset();
|
||||
}
|
||||
}
|
||||
return bbox;
|
||||
}
|
||||
|
||||
BoundingBoxf3 ModelInstance::transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate) const
|
||||
{
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
|
@ -168,7 +168,7 @@ private:
|
||||
friend class cereal::access;
|
||||
friend class UndoRedo::StackImpl;
|
||||
// Create an object for deserialization, don't allocate IDs for ModelMaterial and its config.
|
||||
ModelMaterial() : ObjectBase(-1), config(-1), m_model(nullptr) { assert(this->id().invalid()); assert(this->config.id().invalid()); }
|
||||
ModelMaterial() : ObjectBase(-1), config(-1) { assert(this->id().invalid()); assert(this->config.id().invalid()); }
|
||||
template<class Archive> void serialize(Archive &ar) {
|
||||
assert(this->id().invalid()); assert(this->config.id().invalid());
|
||||
Internal::StaticSerializationWrapper<ModelConfigObject> config_wrapper(config);
|
||||
@ -343,7 +343,7 @@ public:
|
||||
// The pairs of <z, layer_height> 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.
|
||||
@ -397,11 +397,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;
|
||||
@ -477,8 +488,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;
|
||||
|
||||
@ -500,14 +509,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());
|
||||
@ -585,15 +593,18 @@ 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 };
|
||||
|
||||
// Called by Print::apply() to set the model pointer after making a copy.
|
||||
friend class Print;
|
||||
@ -605,8 +616,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());
|
||||
@ -617,12 +627,17 @@ private:
|
||||
Internal::StaticSerializationWrapper<LayerHeightProfile> layer_heigth_profile_wrapper(layer_height_profile);
|
||||
ar(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);
|
||||
}
|
||||
|
||||
// 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 {
|
||||
@ -1106,7 +1121,7 @@ public:
|
||||
// flag showing the position of this instance with respect to the print volume (set by Print::validate() using ModelObject::check_instances_print_volume_state())
|
||||
ModelInstanceEPrintVolumeState print_volume_state;
|
||||
// Whether or not this instance is printable
|
||||
bool printable;
|
||||
bool printable { true };
|
||||
|
||||
ModelObject* get_object() const { return this->object; }
|
||||
|
||||
@ -1156,9 +1171,7 @@ public:
|
||||
|
||||
// To be called on an external mesh
|
||||
void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const;
|
||||
// Calculate a bounding box of a transformed mesh. To be called on an external mesh.
|
||||
BoundingBoxf3 transform_mesh_bounding_box(const TriangleMesh& mesh, bool dont_translate = false) const;
|
||||
// Transform an external bounding box.
|
||||
// Transform an external bounding box, thus the resulting bounding box is no more snug.
|
||||
BoundingBoxf3 transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate = false) const;
|
||||
// Transform an external vector.
|
||||
Vec3d transform_vector(const Vec3d& v, bool dont_translate = false) const;
|
||||
@ -1201,7 +1214,7 @@ private:
|
||||
ModelObject* object;
|
||||
|
||||
// Constructor, which assigns a new unique ID.
|
||||
explicit ModelInstance(ModelObject* object) : print_volume_state(ModelInstancePVS_Inside), printable(true), object(object) { assert(this->id().valid()); }
|
||||
explicit ModelInstance(ModelObject* object) : print_volume_state(ModelInstancePVS_Inside), object(object) { assert(this->id().valid()); }
|
||||
// Constructor, which assigns a new unique ID.
|
||||
explicit ModelInstance(ModelObject *object, const ModelInstance &other) :
|
||||
m_transformation(other.m_transformation), print_volume_state(ModelInstancePVS_Inside), printable(other.printable), object(object) { assert(this->id().valid() && this->id() != other.id()); }
|
||||
@ -1316,8 +1329,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);
|
||||
|
@ -77,7 +77,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Transfor
|
||||
Vec3d bbox_center = bbox.center();
|
||||
// We may need to rotate the bbox / bbox_center from the original instance to the current instance.
|
||||
double z_diff = Geometry::rotation_diff_z(model_object->instances.front()->get_matrix(), instances.front().model_instance->get_matrix());
|
||||
if (std::abs(z_diff) > EPSILON) {
|
||||
if (std::abs(z_diff) > EPSILON) {
|
||||
auto z_rot = Eigen::AngleAxisd(z_diff, Vec3d::UnitZ());
|
||||
bbox = bbox.transformed(Transform3d(z_rot));
|
||||
bbox_center = (z_rot * bbox_center).eval();
|
||||
@ -87,6 +87,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<coord_t>();
|
||||
m_size.z() = model_object->max_z();
|
||||
|
||||
this->set_instances(std::move(instances));
|
||||
}
|
||||
@ -1736,7 +1737,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)
|
||||
|
@ -1440,7 +1440,7 @@ static void generate_initial_areas(
|
||||
top_contacts[i] = nullptr;
|
||||
move_bounds[i].clear();
|
||||
}
|
||||
if (raft_contact_layer_idx != std::numeric_limits<coord_t>::max() && print_object.config().raft_expansion.value > 0) {
|
||||
if (raft_contact_layer_idx != std::numeric_limits<size_t>::max() && print_object.config().raft_expansion.value > 0) {
|
||||
// If any tips at first_tree_layer now are completely inside the expanded raft layer, remove them as well before they are propagated to the ground.
|
||||
Polygons &raft_polygons = top_contacts[raft_contact_layer_idx]->polygons;
|
||||
EdgeGrid::Grid grid(get_extents(raft_polygons).inflated(SCALED_EPSILON));
|
||||
|
@ -2246,7 +2246,7 @@ void GCodeViewer::load_shells(const Print& print)
|
||||
|
||||
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptFFF) {
|
||||
// adds wipe tower's volume
|
||||
const double max_z = print.objects()[0]->model_object()->get_model()->bounding_box().max(2);
|
||||
const double max_z = print.objects()[0]->model_object()->get_model()->max_z();
|
||||
const PrintConfig& config = print.config();
|
||||
const size_t extruders_count = config.nozzle_diameter.size();
|
||||
if (extruders_count > 1 && config.wipe_tower && !config.complete_objects) {
|
||||
|
@ -140,7 +140,7 @@ 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<float>(model_object_new->bounding_box().max.z());
|
||||
const float new_max_z = (model_object_new == nullptr) ? 0.0f : static_cast<float>(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();
|
||||
@ -1977,7 +1977,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
|
||||
if (extruders_count > 1 && wt && !co) {
|
||||
// Height of a print (Show at least a slab)
|
||||
const double height = std::max(m_model->bounding_box().max.z(), 10.0);
|
||||
const double height = std::max(m_model->max_z(), 10.0);
|
||||
|
||||
const float x = dynamic_cast<const ConfigOptionFloat*>(m_config->option("wipe_tower_x"))->value;
|
||||
const float y = dynamic_cast<const ConfigOptionFloat*>(m_config->option("wipe_tower_y"))->value;
|
||||
|
@ -3520,7 +3520,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());
|
||||
@ -3835,7 +3835,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());
|
||||
bool has_name = !old_volume->name.empty() && boost::algorithm::iequals(old_volume->name, fs::path(path).filename().string());
|
||||
@ -4816,7 +4816,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 &&
|
||||
return 0 <= obj_idx && obj_idx < (int)model.objects.size() && model.objects[obj_idx]->max_z() > SINKING_Z_THRESHOLD &&
|
||||
config->opt_bool("variable_layer_height") && view3D->is_layers_editing_allowed();
|
||||
}
|
||||
|
||||
@ -7435,7 +7435,7 @@ void Plater::changed_objects(const std::vector<size_t>& 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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user