diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 9b10d321ea..3b0d037a20 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -469,7 +469,7 @@ sub load_model_objects { $need_arrange = 1; # add a default instance and center object around origin - $o->center_around_origin; + $o->center_around_origin; # also aligns object to Z = 0 $o->add_instance(offset => $bed_centerf); } @@ -1074,15 +1074,7 @@ sub export_stl { return if !@{$self->{objects}}; my $output_file = $self->_get_export_file('STL') or return; - - # In order to allow for consistent positioning in the parts editor, - # we never alter the original Z position. Meshes are aligned to zero - # at slice time. So we do the same before exporting. - my $model = $self->{model}->clone; - foreach my $model_object (@{$model->objects}) { - $model_object->translate(0,0,-$model_object->bounding_box->z_min); - } - Slic3r::Format::STL->write_file($output_file, $model, binary => 1); + Slic3r::Format::STL->write_file($output_file, $self->{model}, binary => 1); $self->statusbar->SetStatusText("STL file exported to $output_file"); # this method gets executed in a separate thread by wxWidgets since it's a button handler @@ -1282,10 +1274,12 @@ sub object_settings_dialog { $self->pause_background_process; $dlg->ShowModal; - # update thumbnail since parts may have changed - if ($dlg->PartsChanged) { - $self->make_thumbnail($obj_idx); - } + # update thumbnail since parts may have changed + if ($dlg->PartsChanged) { + # recenter and re-align to Z = 0 + $model_object->center_around_origin; + $self->make_thumbnail($obj_idx); + } # update print if ($dlg->PartsChanged || $dlg->PartSettingsChanged) { diff --git a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm index d24aa8932c..bacc119d7d 100644 --- a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm +++ b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm @@ -214,7 +214,7 @@ sub on_btn_load { $new_volume->set_name(basename($input_file)); # apply the same translation we applied to the object - $new_volume->mesh->translate(@{$self->{model_object}->origin_translation}, 0); + $new_volume->mesh->translate(@{$self->{model_object}->origin_translation}); # set a default extruder value, since user can't add it manually $new_volume->config->set_ifndef('extruder', 0); @@ -226,7 +226,9 @@ sub on_btn_load { $self->reload_tree; if ($self->{canvas}) { + $self->{canvas}->reset_objects; $self->{canvas}->load_object($self->{model_object}); + $self->{canvas}->set_bounding_box($self->{model_object}->bounding_box); $self->{canvas}->Render; } } diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 677cae1942..4a5ec01feb 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -332,7 +332,7 @@ sub _slice_region { # consider the first one $self->model_object->instances->[0]->transform_mesh($mesh, 1); - # align mesh to Z = 0 and apply XY shift + # align mesh to Z = 0 (it should be already aligned actually) and apply XY shift $mesh->translate((map unscale(-$_), @{$self->_copies_shift}), -$self->model_object->bounding_box->z_min); # perform actual slicing diff --git a/lib/Slic3r/Print/Simple.pm b/lib/Slic3r/Print/Simple.pm index 7647bbfc42..5618484fa1 100644 --- a/lib/Slic3r/Print/Simple.pm +++ b/lib/Slic3r/Print/Simple.pm @@ -68,6 +68,7 @@ sub set_model { # if all input objects have defined position(s) apply duplication to the whole model $model->duplicate($self->duplicate, $self->_print->config->min_object_distance); } + $_->translate(0,0,-$_->bounding_box->z_min) for @{$model->objects}; $model->center_instances_around_point($self->print_center); foreach my $model_object (@{$model->objects}) { diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index d5e9aa6ee1..06919cedd3 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -480,26 +480,31 @@ ModelObject::center_around_origin() mesh.bounding_box(&bb); } - // first align to origin on XY - double shift_x = -bb.min.x; - double shift_y = -bb.min.y; + // first align to origin on XYZ + Vectorf3 vector(-bb.min.x, -bb.min.y, -bb.min.z); // then center it on XY Sizef3 size = bb.size(); - shift_x -= size.x/2; - shift_y -= size.y/2; + vector.x -= size.x/2; + vector.y -= size.y/2; - this->translate(shift_x, shift_y, 0); - this->origin_translation.translate(shift_x, shift_y); + this->translate(vector); + this->origin_translation.translate(vector); if (!this->instances.empty()) { for (ModelInstancePtrs::const_iterator i = this->instances.begin(); i != this->instances.end(); ++i) { - (*i)->offset.translate(-shift_x, -shift_y); + (*i)->offset.translate(-vector.x, -vector.y); } this->update_bounding_box(); } } +void +ModelObject::translate(const Vectorf3 &vector) +{ + this->translate(vector.x, vector.y, vector.z); +} + void ModelObject::translate(coordf_t x, coordf_t y, coordf_t z) { diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index 9cbe6be40b..62bb38bfc5 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -99,7 +99,7 @@ class ModelObject center_around_origin() method. Callers might want to apply the same translation to new volumes before adding them to this object in order to preset alignment when user expects that. */ - Pointf origin_translation; + Pointf3 origin_translation; // these should be private but we need to expose them via XS until all methods are ported BoundingBoxf3 _bounding_box; @@ -126,6 +126,7 @@ class ModelObject void raw_bounding_box(BoundingBoxf3* bb) const; void instance_bounding_box(size_t instance_idx, BoundingBoxf3* bb) const; void center_around_origin(); + void translate(const Vectorf3 &vector); void translate(coordf_t x, coordf_t y, coordf_t z); void scale(const Pointf3 &versor); size_t materials_count() const; diff --git a/xs/src/libslic3r/Point.cpp b/xs/src/libslic3r/Point.cpp index 76da85334f..5f3f1da01a 100644 --- a/xs/src/libslic3r/Point.cpp +++ b/xs/src/libslic3r/Point.cpp @@ -41,7 +41,7 @@ Point::translate(double x, double y) } void -Point::translate(const Point &vector) +Point::translate(const Vector &vector) { this->translate(vector.x, vector.y); } @@ -340,6 +340,12 @@ Pointf3::scale(double factor) this->z *= factor; } +void +Pointf3::translate(const Vectorf3 &vector) +{ + this->translate(vector.x, vector.y, vector.z); +} + void Pointf3::translate(double x, double y, double z) { diff --git a/xs/src/libslic3r/Point.hpp b/xs/src/libslic3r/Point.hpp index 60127b1b7a..271c9584ef 100644 --- a/xs/src/libslic3r/Point.hpp +++ b/xs/src/libslic3r/Point.hpp @@ -14,6 +14,7 @@ class Point; class Pointf; class Pointf3; typedef Point Vector; +typedef Pointf3 Vectorf3; typedef std::vector Points; typedef std::vector PointPtrs; typedef std::vector PointConstPtrs; @@ -36,7 +37,7 @@ class Point std::string wkt() const; void scale(double factor); void translate(double x, double y); - void translate(const Point &vector); + void translate(const Vector &vector); void rotate(double angle, const Point ¢er); bool coincides_with(const Point &point) const; bool coincides_with_epsilon(const Point &point) const; @@ -93,6 +94,7 @@ class Pointf3 : public Pointf coordf_t z; explicit Pointf3(coordf_t _x = 0, coordf_t _y = 0, coordf_t _z = 0): Pointf(_x, _y), z(_z) {}; void scale(double factor); + void translate(const Vectorf3 &vector); void translate(double x, double y, double z); }; diff --git a/xs/t/19_model.t b/xs/t/19_model.t index 56b3631af3..d6f6d97a18 100644 --- a/xs/t/19_model.t +++ b/xs/t/19_model.t @@ -10,9 +10,9 @@ use Test::More tests => 4; my $model = Slic3r::Model->new; my $object = $model->_add_object; isa_ok $object, 'Slic3r::Model::Object::Ref'; - isa_ok $object->origin_translation, 'Slic3r::Pointf::Ref'; - $object->origin_translation->translate(10,0); - is_deeply \@{$object->origin_translation}, [10,0], 'origin_translation is modified by ref'; + isa_ok $object->origin_translation, 'Slic3r::Pointf3::Ref'; + $object->origin_translation->translate(10,0,0); + is_deeply \@{$object->origin_translation}, [10,0,0], 'origin_translation is modified by ref'; my $lhr = [ [ 5, 10, 0.1 ] ]; $object->set_layer_height_ranges($lhr); diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index fd31a93d47..8d795f7d66 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -188,9 +188,9 @@ ModelMaterial::attributes() void set_layer_height_ranges(t_layer_height_ranges ranges) %code%{ THIS->layer_height_ranges = ranges; %}; - Ref origin_translation() + Ref origin_translation() %code%{ RETVAL = &THIS->origin_translation; %}; - void set_origin_translation(Pointf* point) + void set_origin_translation(Pointf3* point) %code%{ THIS->origin_translation = *point; %}; bool needed_repair() const;