diff --git a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm index 411c49549..454ba5d11 100644 --- a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm +++ b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm @@ -3,6 +3,7 @@ use strict; use warnings; use utf8; +use Slic3r::Geometry qw(PI); use Wx qw(:dialog :id :misc :sizer wxTAB_TRAVERSAL); use Wx::Event qw(EVT_CLOSE EVT_BUTTON); use base 'Wx::Dialog'; @@ -17,9 +18,10 @@ sub new { # cut options $self->{cut_options} = { - z => 0, - keep_upper => 1, - keep_lower => 1, + z => 0, + keep_upper => 1, + keep_lower => 1, + rotate_lower => 1, }; my $cut_button_sizer = Wx::BoxSizer->new(wxVERTICAL); { @@ -48,6 +50,13 @@ sub new { label => 'Lower part', default => $self->{cut_options}{keep_lower}, }, + { + opt_key => 'rotate_lower', + type => 'bool', + label => '', + tooltip => 'If enabled, the lower part will be rotated by 180° so that the flat cut surface lies on the print bed.', + default => $self->{cut_options}{rotate_lower}, + }, ], lines => [ { @@ -58,6 +67,10 @@ sub new { label => 'Keep', options => [qw(keep_upper keep_lower)], }, + { + label => 'Rotate lower part', + options => [qw(rotate_lower)], + }, { sizer => $cut_button_sizer, }, @@ -73,7 +86,7 @@ sub new { } } }, - label_width => 50, + label_width => 120, ); # left pane with tree @@ -112,10 +125,15 @@ sub perform_cut { my ($upper_object, $lower_object) = $self->{model_object}->cut($self->{cut_options}{z}); $self->{new_model_objects} = []; - push @{$self->{new_model_objects}}, $upper_object - if $self->{cut_options}{keep_upper} && defined $upper_object; - push @{$self->{new_model_objects}}, $lower_object - if $self->{cut_options}{keep_lower} && defined $lower_object; + if ($self->{cut_options}{keep_upper} && defined $upper_object) { + push @{$self->{new_model_objects}}, $upper_object; + } + if ($self->{cut_options}{keep_lower} && defined $lower_object) { + push @{$self->{new_model_objects}}, $lower_object; + if ($self->{cut_options}{rotate_lower}) { + $lower_object->rotate_x(PI); + } + } $self->Close; } diff --git a/lib/Slic3r/Model.pm b/lib/Slic3r/Model.pm index 1efe3c9f3..11f784658 100644 --- a/lib/Slic3r/Model.pm +++ b/lib/Slic3r/Model.pm @@ -2,7 +2,7 @@ package Slic3r::Model; use Moo; use List::Util qw(first max); -use Slic3r::Geometry qw(X Y Z MIN move_points); +use Slic3r::Geometry qw(X Y Z move_points); has 'materials' => (is => 'ro', default => sub { {} }); has 'objects' => (is => 'ro', default => sub { [] }); @@ -331,7 +331,7 @@ use Moo; use File::Basename qw(basename); use List::Util qw(first sum); -use Slic3r::Geometry qw(X Y Z MIN MAX); +use Slic3r::Geometry qw(X Y Z rad2deg); has 'input_file' => (is => 'rw'); has 'model' => (is => 'ro', weak_ref => 1, required => 1); @@ -504,6 +504,16 @@ sub translate { $self->_bounding_box->translate(@shift) if defined $self->_bounding_box; } +sub rotate_x { + my ($self, $angle) = @_; + + # we accept angle in radians but mesh currently uses degrees + $angle = rad2deg($angle); + + $_->mesh->rotate_x($angle) for @{$self->volumes}; + $self->_bounding_box(undef); +} + sub materials_count { my $self = shift; diff --git a/xs/src/TriangleMesh.cpp b/xs/src/TriangleMesh.cpp index 29fdf13c2..1641319ea 100644 --- a/xs/src/TriangleMesh.cpp +++ b/xs/src/TriangleMesh.cpp @@ -161,6 +161,21 @@ void TriangleMesh::translate(float x, float y, float z) stl_translate_relative(&(this->stl), x, y, z); } +void TriangleMesh::rotate_x(float angle) +{ + stl_rotate_x(&(this->stl), angle); +} + +void TriangleMesh::rotate_y(float angle) +{ + stl_rotate_y(&(this->stl), angle); +} + +void TriangleMesh::rotate_z(float angle) +{ + stl_rotate_z(&(this->stl), angle); +} + void TriangleMesh::align_to_origin() { this->translate( diff --git a/xs/src/TriangleMesh.hpp b/xs/src/TriangleMesh.hpp index 3b7519126..2f79832c9 100644 --- a/xs/src/TriangleMesh.hpp +++ b/xs/src/TriangleMesh.hpp @@ -29,6 +29,9 @@ class TriangleMesh void scale(float factor); void scale(std::vector versor); void translate(float x, float y, float z); + void rotate_x(float angle); + void rotate_y(float angle); + void rotate_z(float angle); void align_to_origin(); void rotate(double angle, Point* center); TriangleMeshPtrs split() const; diff --git a/xs/xsp/TriangleMesh.xsp b/xs/xsp/TriangleMesh.xsp index a124f8dac..5f92874b1 100644 --- a/xs/xsp/TriangleMesh.xsp +++ b/xs/xsp/TriangleMesh.xsp @@ -20,6 +20,9 @@ void scale_xyz(std::vector versor) %code{% THIS->scale(versor); %}; void translate(float x, float y, float z); + void rotate_x(float angle); + void rotate_y(float angle); + void rotate_z(float angle); void align_to_origin(); void rotate(double angle, Point* center); TriangleMeshPtrs split();