diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 84c4e6c1a..f152c4154 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -114,7 +114,7 @@ sub OnInit { } if (!defined $last_version || $last_version =~ /^(?:0|1\.[01])\./) { show_info($self->{mainframe}, "Hello! In this version a new Bed Shape option was " - . "added. If the bed placement in the plater preview screen looks wrong, go " + . "added. If the bed coordinates in the plater preview screen look wrong, go " . "to Print Settings and click the \"Set\" button next to \"Bed Shape\".", "Bed Shape"); } } diff --git a/lib/Slic3r/GUI/BedShapeDialog.pm b/lib/Slic3r/GUI/BedShapeDialog.pm index 7295d027d..bfc5a844e 100644 --- a/lib/Slic3r/GUI/BedShapeDialog.pm +++ b/lib/Slic3r/GUI/BedShapeDialog.pm @@ -6,7 +6,7 @@ use utf8; use List::Util qw(min max); use Slic3r::Geometry qw(PI X Y unscale); use Wx qw(:dialog :id :misc :sizer :choicebook wxTAB_TRAVERSAL); -use Wx::Event qw(EVT_CLOSE EVT_BUTTON EVT_CHOICE); +use Wx::Event qw(EVT_CLOSE); use base 'Wx::Dialog'; sub new { @@ -40,10 +40,10 @@ sub GetValue { package Slic3r::GUI::BedShapePanel; -use List::Util qw(min max); -use Slic3r::Geometry qw(PI X Y unscale); +use List::Util qw(min max sum first); +use Slic3r::Geometry qw(PI X Y unscale scaled_epsilon); use Wx qw(:dialog :id :misc :sizer :choicebook wxTAB_TRAVERSAL); -use Wx::Event qw(EVT_CLOSE EVT_BUTTON EVT_CHOICE); +use Wx::Event qw(EVT_CLOSE EVT_CHOICEBOOK_PAGE_CHANGED); use base 'Wx::Panel'; use constant SHAPE_RECTANGULAR => 0; @@ -83,6 +83,20 @@ sub new { default => 'corner', }, ]); + $self->_init_shape_options_page('Circular', [ + { + opt_key => 'diameter', + type => 'f', + label => 'Diameter', + tooltip => 'Diameter of the print bed. It is assumed that origin (0,0) is located in the center.', + sidetext => 'mm', + default => 200, + }, + ]); + + EVT_CHOICEBOOK_PAGE_CHANGED($self, -1, sub { + $self->_update_shape; + }); # right pane with preview canvas my $canvas; @@ -137,6 +151,21 @@ sub _set_shape { } } + # is this a circle? + { + my $polygon = Slic3r::Polygon->new_scale(@$points); + my $center = $polygon->bounding_box->center; + my @vertex_distances = map $center->distance_to($_), @$polygon; + my $avg_dist = sum(@vertex_distances)/@vertex_distances; + if (!defined first { abs($_ - $avg_dist) > scaled_epsilon } @vertex_distances) { + # all vertices are equidistant to center + $self->{shape_options_book}->SetSelection(SHAPE_CIRCULAR); + my $optgroup = $self->{optgroups}[SHAPE_CIRCULAR]; + $optgroup->set_value('diameter', sprintf("%.0f", unscale($avg_dist*2))); + return; + } + } + $self->{shape_options_book}->SetSelection(SHAPE_CUSTOM); } @@ -161,6 +190,18 @@ sub _update_shape { [$x1,$y1], [$x0,$y1], ]; + } elsif ($page_idx == SHAPE_CIRCULAR) { + return if grep !defined($self->{"_$_"}), qw(diameter); # not loaded yet + my $r = $self->{_diameter}/2; + my $twopi = 2*PI; + my $edges = 60; + my $polygon = Slic3r::Polygon->new_scale( + map [ $r * cos $_, $r * sin $_ ], + map { $twopi/$edges*$_ } 1..$edges + ); + $self->{bed_shape} = [ + map [ unscale($_->x), unscale($_->y) ], @$polygon #)) + ]; } $self->{on_change}->(); @@ -176,18 +217,21 @@ sub _update_preview { sub _init_shape_options_page { my ($self, $title, $options) = @_; + my $on_change = sub { + my ($opt_key, $value) = @_; + $self->{"_$opt_key"} = $value; + $self->_update_shape; + }; + my $panel = Wx::Panel->new($self->{shape_options_book}); push @{$self->{optgroups}}, my $optgroup = Slic3r::GUI::OptionsGroup->new( parent => $panel, title => 'Settings', options => $options, - on_change => sub { - my ($opt_key, $value) = @_; - $self->{"_$opt_key"} = $value; - $self->_update_shape; - }, + on_change => $on_change, label_width => 100, ); + $on_change->($_->{opt_key}, $_->{default}) for @$options; # populate with defaults $panel->SetSizerAndFit($optgroup->sizer); $self->{shape_options_book}->AddPage($panel, $title); } diff --git a/lib/Slic3r/GUI/Plater/2D.pm b/lib/Slic3r/GUI/Plater/2D.pm index 97ef5fb36..43c5ef976 100644 --- a/lib/Slic3r/GUI/Plater/2D.pm +++ b/lib/Slic3r/GUI/Plater/2D.pm @@ -5,7 +5,7 @@ use utf8; use List::Util qw(min max first); use Slic3r::Geometry qw(X Y scale unscale convex_hull); -use Slic3r::Geometry::Clipper qw(offset JT_ROUND); +use Slic3r::Geometry::Clipper qw(offset JT_ROUND intersection_pl); use Wx qw(:misc :pen :brush :sizer :font :cursor wxTAB_TRAVERSAL); use Wx::Event qw(EVT_MOUSE_EVENTS EVT_PAINT EVT_SIZE); use base 'Wx::Panel'; @@ -261,13 +261,15 @@ sub update_bed_size { # cache bed contours and grid { my $step = scale 10; # 1cm grid - $self->{grid} = my $grid = []; # arrayref of lines + my @polylines = (); for (my $x = $bb->x_min + $step; $x < $bb->x_max; $x += $step) { - push @$grid, $self->scaled_points_to_pixel([[$x, $bb->y_min], [$x, $bb->y_max]], 1); + push @polylines, Slic3r::Polyline->new([$x, $bb->y_min], [$x, $bb->y_max]); } for (my $y = $bb->y_min + $step; $y < $bb->y_max; $y += $step) { - push @$grid, $self->scaled_points_to_pixel([[$bb->x_min, $y], [$bb->x_max, $y]], 1); + push @polylines, Slic3r::Polyline->new([$bb->x_min, $y], [$bb->x_max, $y]); } + @polylines = @{intersection_pl(\@polylines, [$polygon])}; + $self->{grid} = [ map $self->scaled_points_to_pixel(\@$_, 1), @polylines ]; } }