Keep model objects aligned to Z = 0 in plater

This commit is contained in:
Alessandro Ranellucci 2014-12-12 22:43:04 +01:00
parent 050f9ff61a
commit 360dee862b
10 changed files with 43 additions and 32 deletions

View file

@ -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) {

View file

@ -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;
} }
} }

View file

@ -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

View file

@ -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}) {

View file

@ -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)
{ {

View file

@ -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;

View file

@ -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)
{ {

View file

@ -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 &center); void rotate(double angle, const Point &center);
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);
}; };

View file

@ -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);

View file

@ -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;