From 962a51cc800d8912739b25ab8248b087d3131289 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Thu, 13 Jun 2013 14:33:10 +0200 Subject: [PATCH] Some cleanup for the plater code --- lib/Slic3r/GUI/Plater.pm | 28 ++++++++++++---------------- lib/Slic3r/Model.pm | 22 ++++++++++++++++++++-- lib/Slic3r/Print.pm | 23 +++++++++++------------ 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 8c0020e84..3adf65f71 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -704,11 +704,6 @@ sub make_model { foreach my $plater_object (@{$self->{objects}}) { my $model_object = $plater_object->get_model_object; - # if we need to alter the mesh, clone it first - if ($plater_object->scale != 1) { - $model_object = $model_object->clone; - } - my $new_model_object = $model->add_object( vertices => $model_object->vertices, input_file => $plater_object->input_file, @@ -721,10 +716,10 @@ sub make_model { ); $model->set_material($volume->material_id || 0, {}); } - $new_model_object->scale($plater_object->scale); $new_model_object->align_to_origin; $new_model_object->add_instance( rotation => $plater_object->rotate, # around center point + scaling_factor => $plater_object->scale, offset => Slic3r::Point->new($_), ) for @{$plater_object->instances}; } @@ -778,9 +773,12 @@ sub recenter { map Slic3r::Geometry::move_points($_, @points), @{$obj->instances}; } @{$self->{objects}}, ]); + + # $self->{shift} contains the offset in pixels to add to object instances in order to center them + # it is expressed in upwards Y $self->{shift} = [ - ($self->{canvas}->GetSize->GetWidth - $self->to_pixel($print_bb[X2] + $print_bb[X1])) / 2, - ($self->{canvas}->GetSize->GetHeight - $self->to_pixel($print_bb[Y2] + $print_bb[Y1])) / 2, + $self->to_pixel(-$print_bb[X1]) + ($self->{canvas}->GetSize->GetWidth - $self->to_pixel($print_bb[X2] - $print_bb[X1])) / 2, + $self->to_pixel(-$print_bb[Y1]) + ($self->{canvas}->GetSize->GetHeight - $self->to_pixel($print_bb[Y2] - $print_bb[Y1])) / 2, ]; } @@ -814,10 +812,8 @@ sub _update_bed_size { # supposing the preview canvas is square, calculate the scaling factor # to constrain print bed area inside preview - my $bed_size = $self->{config}->bed_size; - my $canvas_side = CANVAS_SIZE->[X]; # when the canvas is not rendered yet, its GetSize() method returns 0,0 - my $bed_largest_side = $bed_size->[X] > $bed_size->[Y] ? $bed_size->[X] : $bed_size->[Y]; - $self->{scaling_factor} = $canvas_side / $bed_largest_side; + # when the canvas is not rendered yet, its GetSize() method returns 0,0 + $self->{scaling_factor} = CANVAS_SIZE->[X] / max(@{ $self->{config}->bed_size }); $_->change_thumbnail_scaling_factor($self->{scaling_factor}) for @{ $self->{objects} }; $self->recenter; } @@ -949,7 +945,6 @@ sub mouse_event { my ($obj_idx, $instance_idx, $thumbnail) = @$preview; my $instance = $parent->{objects}[$obj_idx]->instances->[$instance_idx]; $instance->[$_] = $parent->to_units($pos->[$_] - $self->{drag_start_pos}[$_] - $parent->{shift}[$_]) for X,Y; - $instance = $parent->_y([$instance])->[0]; $parent->Refresh; } } elsif ($event->Moving) { @@ -1098,10 +1093,12 @@ sub _trigger_model_object { my $self = shift; if ($self->model_object) { $self->model_object->align_to_origin; + $self->bounding_box($self->model_object->bounding_box); + my $mesh = $self->model_object->mesh; - $self->bounding_box($mesh->bounding_box); $self->facets(scalar @{$mesh->facets}); $self->vertices(scalar @{$mesh->vertices}); + $self->materials($self->model_object->materials_count); } } @@ -1140,8 +1137,7 @@ sub instances_count { sub make_thumbnail { my $self = shift; - my $mesh = $self->model_object->mesh; - $mesh->align_to_origin; + my $mesh = $self->model_object->mesh; # $self->model_object is already aligned to origin my $thumbnail = Slic3r::ExPolygon::Collection->new( expolygons => (@{$mesh->facets} <= 5000) ? $mesh->horizontal_projection diff --git a/lib/Slic3r/Model.pm b/lib/Slic3r/Model.pm index b7ff6f7ae..b0f422ea1 100644 --- a/lib/Slic3r/Model.pm +++ b/lib/Slic3r/Model.pm @@ -119,6 +119,7 @@ sub arrange_objects { $object->add_instance( offset => $_, rotation => $instance->rotation, + scaling_factor => $instance->scaling_factor, ) for move_points($instance->offset, @positions); } } @@ -213,6 +214,7 @@ sub mesh { my $mesh = $object->mesh->clone; if ($instance) { $mesh->rotate($instance->rotation); + $mesh->scale($instance->scaling_factor); $mesh->align_to_origin; $mesh->move(@{$instance->offset}); } @@ -259,6 +261,7 @@ sub split_meshes { $new_object->add_instance( offset => [ $_->offset->[X] + $extents[X][MIN], $_->offset->[Y] + $extents[Y][MIN] ], rotation => $_->rotation, + scaling_factor => $_->scaling_factor, ) for @{ $object->instances // [] }; } } @@ -274,7 +277,7 @@ package Slic3r::Model::Object; use Moo; use List::Util qw(first); -use Slic3r::Geometry qw(X Y Z MIN move_points move_points_3D); +use Slic3r::Geometry qw(X Y Z MIN MAX move_points move_points_3D); use Storable qw(dclone); has 'input_file' => (is => 'rw'); @@ -338,13 +341,27 @@ sub extents { return Slic3r::Geometry::bounding_box_3D($self->used_vertices); } +sub center { + my $self = shift; + + my @extents = $self->extents; + return [ map +($extents[$_][MAX] + $extents[$_][MIN])/2, X,Y,Z ]; +} + +sub bounding_box { + my $self = shift; + return Slic3r::Geometry::BoundingBox->new(extents => [ $self->extents ]); +} + sub align_to_origin { my $self = shift; # calculate the displacements needed to # have lowest value for each axis at coordinate 0 my @extents = $self->extents; - $self->move(map -$extents[$_][MIN], X,Y,Z); + my @shift = map -$extents[$_][MIN], X,Y,Z; + $self->move(@shift); + return @shift; } sub move { @@ -410,6 +427,7 @@ use Moo; has 'object' => (is => 'ro', weak_ref => 1, required => 1); has 'rotation' => (is => 'rw', default => sub { 0 }); # around mesh center point +has 'scaling_factor' => (is => 'rw', default => sub { 1 }); has 'offset' => (is => 'rw'); # must be Slic3r::Point object 1; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index e20d4acaa..638ce8d3a 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -106,6 +106,8 @@ sub add_model { $model->split_meshes if $Slic3r::Config->avoid_crossing_perimeters && !$Slic3r::Config->complete_objects; foreach my $object (@{ $model->objects }) { + my @align = $object->align_to_origin; + # extract meshes by material my @meshes = (); # by region_id foreach my $volume (@{$object->volumes}) { @@ -123,21 +125,18 @@ sub add_model { # the order of these transformations must be the same as the one used in plater # to make the object positioning consistent with the visual preview - # we ignore the per-instance rotation currently and only + # we ignore the per-instance transformations currently and only # consider the first one - $mesh->rotate($object->instances->[0]->rotation, $mesh->center) - if @{ $object->instances // [] }; + if ($object->instances && @{$object->instances}) { + $mesh->rotate($object->instances->[0]->rotation, $object->center); + $mesh->scale($object->instances->[0]->scaling_factor); + } $mesh->scale(1 / &Slic3r::SCALING_FACTOR); } - # align the object to origin; not sure this is required by the toolpath generation - # algorithms, but it's good practice to avoid negative coordinates; it probably - # provides also some better performance in infill generation - my @extents = Slic3r::Geometry::bounding_box_3D([ map @{$_->used_vertices}, grep $_, @meshes ]); - foreach my $mesh (grep $_, @meshes) { - $mesh->move(map -$extents[$_][MIN], X,Y,Z); - } + # calculate transformed size + my $size = [ Slic3r::Geometry::size_3D([ map @{$_->used_vertices}, grep $_, @meshes ]) ]; # initialize print object push @{$self->objects}, Slic3r::Print::Object->new( @@ -145,10 +144,10 @@ sub add_model { meshes => [ @meshes ], copies => [ $object->instances - ? (map [ (scale $_->offset->[X]) + $extents[X][MIN], (scale $_->offset->[Y]) + $extents[Y][MIN] ], @{$object->instances}) + ? (map [ scale($_->offset->[X] - $align[X]), scale($_->offset->[Y] - $align[Y]) ], @{$object->instances}) : [0,0], ], - size => [ map $extents[$_][MAX] - $extents[$_][MIN], (X,Y,Z) ], + size => $size, input_file => $object->input_file, layer_height_ranges => $object->layer_height_ranges, );