diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 1e229a78..0213f6c4 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -719,11 +719,11 @@ sub make_model { $new_model_object->scale($plater_object->scale); $new_model_object->add_instance( rotation => $plater_object->rotate, # around center point - offset => [ @$_ ], + offset => Slic3r::Point->new($_), ) for @{$plater_object->instances}; - $new_model_object->align_to_origin; } + $model->align_to_origin; return $model; } diff --git a/lib/Slic3r/Model.pm b/lib/Slic3r/Model.pm index 70824726..b7ff6f7a 100644 --- a/lib/Slic3r/Model.pm +++ b/lib/Slic3r/Model.pm @@ -164,14 +164,19 @@ sub vertices { return [ map @{$_->vertices}, @{$self->objects} ]; } +sub used_vertices { + my $self = shift; + return [ map @{$_->used_vertices}, @{$self->objects} ]; +} + sub size { my $self = shift; - return [ Slic3r::Geometry::size_3D($self->vertices) ]; + return [ Slic3r::Geometry::size_3D($self->used_vertices) ]; } sub extents { my $self = shift; - return Slic3r::Geometry::bounding_box_3D($self->vertices); + return Slic3r::Geometry::bounding_box_3D($self->used_vertices); } sub align_to_origin { @@ -179,8 +184,17 @@ sub align_to_origin { # 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 @extents = $self->extents; + $self->move(map -$extents[$_][MIN], X,Y,Z); + } + + # align all instances to 0,0 as well + { + my @instances = map @{$_->instances}, @{$self->objects}; + my @extents = Slic3r::Geometry::bounding_box_3D([ map $_->offset, @instances ]); + $_->offset->translate(-$extents[X][MIN], -$extents[Y][MIN]) for @instances; + } } sub move { @@ -260,7 +274,7 @@ package Slic3r::Model::Object; use Moo; use List::Util qw(first); -use Slic3r::Geometry qw(X Y Z MIN move_points_3D); +use Slic3r::Geometry qw(X Y Z MIN move_points move_points_3D); use Storable qw(dclone); has 'input_file' => (is => 'rw'); @@ -309,14 +323,19 @@ sub mesh { ); } +sub used_vertices { + my $self = shift; + return [ map $self->vertices->[$_], map @$_, map @{$_->facets}, @{$self->volumes} ]; +} + sub size { my $self = shift; - return [ Slic3r::Geometry::size_3D($self->vertices) ]; + return [ Slic3r::Geometry::size_3D($self->used_vertices) ]; } sub extents { my $self = shift; - return Slic3r::Geometry::bounding_box_3D($self->vertices); + return Slic3r::Geometry::bounding_box_3D($self->used_vertices); } sub align_to_origin { @@ -391,6 +410,6 @@ use Moo; has 'object' => (is => 'ro', weak_ref => 1, required => 1); has 'rotation' => (is => 'rw', default => sub { 0 }); # around mesh center point -has 'offset' => (is => 'rw'); +has 'offset' => (is => 'rw'); # must be Slic3r::Point object 1; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index ae299248..84a208ea 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -6,7 +6,7 @@ use File::Spec; use List::Util qw(max first); use Math::ConvexHull::MonotoneChain qw(convex_hull); use Slic3r::ExtrusionPath ':roles'; -use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 MIN PI scale unscale move_points nearest_point); +use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 MIN MAX PI scale unscale move_points nearest_point); use Slic3r::Geometry::Clipper qw(diff_ex union_ex union_pt intersection_ex offset offset2 traverse_pt JT_ROUND JT_SQUARE PFT_EVENODD); use Time::HiRes qw(gettimeofday tv_interval); @@ -116,8 +116,7 @@ sub add_model { : $mesh; } - foreach my $mesh (@meshes) { - next unless $mesh; + foreach my $mesh (grep $_, @meshes) { $mesh->check_manifoldness; # we ignore the per-instance rotation currently and only @@ -127,12 +126,22 @@ sub add_model { $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); + } + # initialize print object push @{$self->objects}, Slic3r::Print::Object->new( print => $self, meshes => [ @meshes ], - copies => [ map [ scale $_->offset->[X], scale $_->offset->[Y] ], @{$object->instances} ], - size => [ map scale $_, @{ $object->size } ], + copies => [ + map [ (scale $_->offset->[X]) + $extents[X][MIN], (scale $_->offset->[Y]) + $extents[Y][MIN] ], @{$object->instances}, + ], + size => [ map $extents[$_][MAX] - $extents[$_][MIN], (X,Y,Z) ], input_file => $object->input_file, layer_height_ranges => $object->layer_height_ranges, ); diff --git a/lib/Slic3r/TriangleMesh.pm b/lib/Slic3r/TriangleMesh.pm index f6146d54..3506d893 100644 --- a/lib/Slic3r/TriangleMesh.pm +++ b/lib/Slic3r/TriangleMesh.pm @@ -398,14 +398,19 @@ sub duplicate { $self->BUILD; } +sub used_vertices { + my $self = shift; + return [ map $self->vertices->[$_], map @$_, @{$self->facets} ]; +} + sub extents { my $self = shift; - return Slic3r::Geometry::bounding_box_3D($self->vertices); + return Slic3r::Geometry::bounding_box_3D($self->used_vertices); } sub size { my $self = shift; - return Slic3r::Geometry::size_3D($self->vertices); + return Slic3r::Geometry::size_3D($self->used_vertices); } sub slice_facet {