Keep model objects aligned to Z = 0 in plater
This commit is contained in:
parent
050f9ff61a
commit
360dee862b
10 changed files with 43 additions and 32 deletions
|
@ -469,7 +469,7 @@ sub load_model_objects {
|
||||||
$need_arrange = 1;
|
$need_arrange = 1;
|
||||||
|
|
||||||
# add a default instance and center object around origin
|
# 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);
|
$o->add_instance(offset => $bed_centerf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1074,15 +1074,7 @@ sub export_stl {
|
||||||
return if !@{$self->{objects}};
|
return if !@{$self->{objects}};
|
||||||
|
|
||||||
my $output_file = $self->_get_export_file('STL') or return;
|
my $output_file = $self->_get_export_file('STL') or return;
|
||||||
|
Slic3r::Format::STL->write_file($output_file, $self->{model}, binary => 1);
|
||||||
# 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);
|
|
||||||
$self->statusbar->SetStatusText("STL file exported to $output_file");
|
$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
|
# 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;
|
$self->pause_background_process;
|
||||||
$dlg->ShowModal;
|
$dlg->ShowModal;
|
||||||
|
|
||||||
# update thumbnail since parts may have changed
|
# update thumbnail since parts may have changed
|
||||||
if ($dlg->PartsChanged) {
|
if ($dlg->PartsChanged) {
|
||||||
$self->make_thumbnail($obj_idx);
|
# recenter and re-align to Z = 0
|
||||||
}
|
$model_object->center_around_origin;
|
||||||
|
$self->make_thumbnail($obj_idx);
|
||||||
|
}
|
||||||
|
|
||||||
# update print
|
# update print
|
||||||
if ($dlg->PartsChanged || $dlg->PartSettingsChanged) {
|
if ($dlg->PartsChanged || $dlg->PartSettingsChanged) {
|
||||||
|
|
|
@ -214,7 +214,7 @@ sub on_btn_load {
|
||||||
$new_volume->set_name(basename($input_file));
|
$new_volume->set_name(basename($input_file));
|
||||||
|
|
||||||
# apply the same translation we applied to the object
|
# 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
|
# set a default extruder value, since user can't add it manually
|
||||||
$new_volume->config->set_ifndef('extruder', 0);
|
$new_volume->config->set_ifndef('extruder', 0);
|
||||||
|
@ -226,7 +226,9 @@ sub on_btn_load {
|
||||||
|
|
||||||
$self->reload_tree;
|
$self->reload_tree;
|
||||||
if ($self->{canvas}) {
|
if ($self->{canvas}) {
|
||||||
|
$self->{canvas}->reset_objects;
|
||||||
$self->{canvas}->load_object($self->{model_object});
|
$self->{canvas}->load_object($self->{model_object});
|
||||||
|
$self->{canvas}->set_bounding_box($self->{model_object}->bounding_box);
|
||||||
$self->{canvas}->Render;
|
$self->{canvas}->Render;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -332,7 +332,7 @@ sub _slice_region {
|
||||||
# consider the first one
|
# consider the first one
|
||||||
$self->model_object->instances->[0]->transform_mesh($mesh, 1);
|
$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);
|
$mesh->translate((map unscale(-$_), @{$self->_copies_shift}), -$self->model_object->bounding_box->z_min);
|
||||||
|
|
||||||
# perform actual slicing
|
# perform actual slicing
|
||||||
|
|
|
@ -68,6 +68,7 @@ sub set_model {
|
||||||
# if all input objects have defined position(s) apply duplication to the whole 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);
|
$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);
|
$model->center_instances_around_point($self->print_center);
|
||||||
|
|
||||||
foreach my $model_object (@{$model->objects}) {
|
foreach my $model_object (@{$model->objects}) {
|
||||||
|
|
|
@ -480,26 +480,31 @@ ModelObject::center_around_origin()
|
||||||
mesh.bounding_box(&bb);
|
mesh.bounding_box(&bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
// first align to origin on XY
|
// first align to origin on XYZ
|
||||||
double shift_x = -bb.min.x;
|
Vectorf3 vector(-bb.min.x, -bb.min.y, -bb.min.z);
|
||||||
double shift_y = -bb.min.y;
|
|
||||||
|
|
||||||
// then center it on XY
|
// then center it on XY
|
||||||
Sizef3 size = bb.size();
|
Sizef3 size = bb.size();
|
||||||
shift_x -= size.x/2;
|
vector.x -= size.x/2;
|
||||||
shift_y -= size.y/2;
|
vector.y -= size.y/2;
|
||||||
|
|
||||||
this->translate(shift_x, shift_y, 0);
|
this->translate(vector);
|
||||||
this->origin_translation.translate(shift_x, shift_y);
|
this->origin_translation.translate(vector);
|
||||||
|
|
||||||
if (!this->instances.empty()) {
|
if (!this->instances.empty()) {
|
||||||
for (ModelInstancePtrs::const_iterator i = this->instances.begin(); i != this->instances.end(); ++i) {
|
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();
|
this->update_bounding_box();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ModelObject::translate(const Vectorf3 &vector)
|
||||||
|
{
|
||||||
|
this->translate(vector.x, vector.y, vector.z);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ModelObject::translate(coordf_t x, coordf_t y, coordf_t z)
|
ModelObject::translate(coordf_t x, coordf_t y, coordf_t z)
|
||||||
{
|
{
|
||||||
|
|
|
@ -99,7 +99,7 @@ class ModelObject
|
||||||
center_around_origin() method. Callers might want to apply the same translation
|
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
|
to new volumes before adding them to this object in order to preset alignment
|
||||||
when user expects that. */
|
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
|
// these should be private but we need to expose them via XS until all methods are ported
|
||||||
BoundingBoxf3 _bounding_box;
|
BoundingBoxf3 _bounding_box;
|
||||||
|
@ -126,6 +126,7 @@ class ModelObject
|
||||||
void raw_bounding_box(BoundingBoxf3* bb) const;
|
void raw_bounding_box(BoundingBoxf3* bb) const;
|
||||||
void instance_bounding_box(size_t instance_idx, BoundingBoxf3* bb) const;
|
void instance_bounding_box(size_t instance_idx, BoundingBoxf3* bb) const;
|
||||||
void center_around_origin();
|
void center_around_origin();
|
||||||
|
void translate(const Vectorf3 &vector);
|
||||||
void translate(coordf_t x, coordf_t y, coordf_t z);
|
void translate(coordf_t x, coordf_t y, coordf_t z);
|
||||||
void scale(const Pointf3 &versor);
|
void scale(const Pointf3 &versor);
|
||||||
size_t materials_count() const;
|
size_t materials_count() const;
|
||||||
|
|
|
@ -41,7 +41,7 @@ Point::translate(double x, double y)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Point::translate(const Point &vector)
|
Point::translate(const Vector &vector)
|
||||||
{
|
{
|
||||||
this->translate(vector.x, vector.y);
|
this->translate(vector.x, vector.y);
|
||||||
}
|
}
|
||||||
|
@ -340,6 +340,12 @@ Pointf3::scale(double factor)
|
||||||
this->z *= factor;
|
this->z *= factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Pointf3::translate(const Vectorf3 &vector)
|
||||||
|
{
|
||||||
|
this->translate(vector.x, vector.y, vector.z);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Pointf3::translate(double x, double y, double z)
|
Pointf3::translate(double x, double y, double z)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,6 +14,7 @@ class Point;
|
||||||
class Pointf;
|
class Pointf;
|
||||||
class Pointf3;
|
class Pointf3;
|
||||||
typedef Point Vector;
|
typedef Point Vector;
|
||||||
|
typedef Pointf3 Vectorf3;
|
||||||
typedef std::vector<Point> Points;
|
typedef std::vector<Point> Points;
|
||||||
typedef std::vector<Point*> PointPtrs;
|
typedef std::vector<Point*> PointPtrs;
|
||||||
typedef std::vector<const Point*> PointConstPtrs;
|
typedef std::vector<const Point*> PointConstPtrs;
|
||||||
|
@ -36,7 +37,7 @@ class Point
|
||||||
std::string wkt() const;
|
std::string wkt() const;
|
||||||
void scale(double factor);
|
void scale(double factor);
|
||||||
void translate(double x, double y);
|
void translate(double x, double y);
|
||||||
void translate(const Point &vector);
|
void translate(const Vector &vector);
|
||||||
void rotate(double angle, const Point ¢er);
|
void rotate(double angle, const Point ¢er);
|
||||||
bool coincides_with(const Point &point) const;
|
bool coincides_with(const Point &point) const;
|
||||||
bool coincides_with_epsilon(const Point &point) const;
|
bool coincides_with_epsilon(const Point &point) const;
|
||||||
|
@ -93,6 +94,7 @@ class Pointf3 : public Pointf
|
||||||
coordf_t z;
|
coordf_t z;
|
||||||
explicit Pointf3(coordf_t _x = 0, coordf_t _y = 0, coordf_t _z = 0): Pointf(_x, _y), z(_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 scale(double factor);
|
||||||
|
void translate(const Vectorf3 &vector);
|
||||||
void translate(double x, double y, double z);
|
void translate(double x, double y, double z);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,9 @@ use Test::More tests => 4;
|
||||||
my $model = Slic3r::Model->new;
|
my $model = Slic3r::Model->new;
|
||||||
my $object = $model->_add_object;
|
my $object = $model->_add_object;
|
||||||
isa_ok $object, 'Slic3r::Model::Object::Ref';
|
isa_ok $object, 'Slic3r::Model::Object::Ref';
|
||||||
isa_ok $object->origin_translation, 'Slic3r::Pointf::Ref';
|
isa_ok $object->origin_translation, 'Slic3r::Pointf3::Ref';
|
||||||
$object->origin_translation->translate(10,0);
|
$object->origin_translation->translate(10,0,0);
|
||||||
is_deeply \@{$object->origin_translation}, [10,0], 'origin_translation is modified by ref';
|
is_deeply \@{$object->origin_translation}, [10,0,0], 'origin_translation is modified by ref';
|
||||||
|
|
||||||
my $lhr = [ [ 5, 10, 0.1 ] ];
|
my $lhr = [ [ 5, 10, 0.1 ] ];
|
||||||
$object->set_layer_height_ranges($lhr);
|
$object->set_layer_height_ranges($lhr);
|
||||||
|
|
|
@ -188,9 +188,9 @@ ModelMaterial::attributes()
|
||||||
void set_layer_height_ranges(t_layer_height_ranges ranges)
|
void set_layer_height_ranges(t_layer_height_ranges ranges)
|
||||||
%code%{ THIS->layer_height_ranges = ranges; %};
|
%code%{ THIS->layer_height_ranges = ranges; %};
|
||||||
|
|
||||||
Ref<Pointf> origin_translation()
|
Ref<Pointf3> origin_translation()
|
||||||
%code%{ RETVAL = &THIS->origin_translation; %};
|
%code%{ RETVAL = &THIS->origin_translation; %};
|
||||||
void set_origin_translation(Pointf* point)
|
void set_origin_translation(Pointf3* point)
|
||||||
%code%{ THIS->origin_translation = *point; %};
|
%code%{ THIS->origin_translation = *point; %};
|
||||||
|
|
||||||
bool needed_repair() const;
|
bool needed_repair() const;
|
||||||
|
|
Loading…
Reference in a new issue