From 7a20c4d52a1545378eba57e3f928240cbf9ec454 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 16 Jun 2014 14:05:22 +0200 Subject: [PATCH] More incomplete work for using bed_shape in plater --- lib/Slic3r/GUI/Plater.pm | 9 +-- lib/Slic3r/GUI/Plater/2D.pm | 126 +++++++++++++++++++++--------------- lib/Slic3r/Model.pm | 1 + xs/src/Print.cpp | 2 +- 4 files changed, 77 insertions(+), 61 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index edc0b5d10..8565e6668 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -50,7 +50,7 @@ sub new { my ($parent) = @_; my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); $self->{config} = Slic3r::Config->new_from_defaults(qw( - bed_size print_center complete_objects extruder_clearance_radius skirts skirt_distance + bed_size bed_shape print_center complete_objects extruder_clearance_radius skirts skirt_distance )); $self->{model} = Slic3r::Model->new; $self->{print} = Slic3r::Print->new; @@ -676,12 +676,7 @@ sub changescale { sub arrange { my $self = shift; - # get the bounding box of the model area shown in the viewport - my $bb = Slic3r::Geometry::BoundingBox->new_from_points([ - Slic3r::Point->new(@{ $self->{canvas}->point_to_model_units([0,0]) }), - Slic3r::Point->new(@{ $self->{canvas}->point_to_model_units([ map { $_->GetWidth, $_->GetHeight } $self->{canvas}->GetSize ]) }), - ]); - + my $bb = Slic3r::Polygon->new_scale(@{$self->{config}->bed_shape})->bounding_box; eval { $self->{model}->arrange_objects($self->GetFrame->config->min_object_distance, $bb); }; diff --git a/lib/Slic3r/GUI/Plater/2D.pm b/lib/Slic3r/GUI/Plater/2D.pm index b335ab876..e7e69d7eb 100644 --- a/lib/Slic3r/GUI/Plater/2D.pm +++ b/lib/Slic3r/GUI/Plater/2D.pm @@ -3,11 +3,11 @@ use strict; use warnings; use utf8; -use List::Util qw(max first); +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 Wx qw(:misc :pen :brush :sizer :font :cursor wxTAB_TRAVERSAL); -use Wx::Event qw(EVT_MOUSE_EVENTS EVT_PAINT); +use Wx::Event qw(EVT_MOUSE_EVENTS EVT_PAINT EVT_SIZE); use base 'Wx::Panel'; use constant CANVAS_TEXT => join('-', +(localtime)[3,4]) eq '13-8' @@ -40,6 +40,9 @@ sub new { EVT_PAINT($self, \&repaint); EVT_MOUSE_EVENTS($self, \&mouse_event); + EVT_SIZE($self, sub { + $self->update_bed_size; + }); return $self; } @@ -71,25 +74,27 @@ sub repaint { my $size = $self->GetSize; my @size = ($size->GetWidth, $size->GetHeight); - # draw grid - $dc->SetPen($self->{grid_pen}); - my $step = 10 * $self->{scaling_factor}; - for (my $x = $step; $x <= $size[X]; $x += $step) { - $dc->DrawLine($x, 0, $x, $size[Y]); - } - for (my $y = $step; $y <= $size[Y]; $y += $step) { - $dc->DrawLine(0, $y, $size[X], $y); + # draw bed + { + $dc->SetPen($self->{print_center_pen}); + $dc->SetBrush($self->{transparent_brush}); + $dc->DrawPolygon($self->scaled_points_to_pixel($self->{bed_polygon}, 1), 0, 0); } + # draw grid + $dc->SetPen($self->{grid_pen}); + $dc->DrawLine(map @$_, @$_) for @{$self->{grid}}; + # draw print center - if (@{$self->{objects}}) { + if (@{$self->{objects}} && $Slic3r::GUI::Settings->{_}{autocenter}) { + my $center = $self->unscaled_point_to_pixel($self->{config}->print_center); $dc->SetPen($self->{print_center_pen}); - $dc->DrawLine($size[X]/2, 0, $size[X]/2, $size[Y]); - $dc->DrawLine(0, $size[Y]/2, $size[X], $size[Y]/2); + $dc->DrawLine($center->[X], 0, $center->[X], $size[Y]); + $dc->DrawLine(0, $center->[Y], $size[X], $center->[Y]); $dc->SetTextForeground(Wx::Colour->new(0,0,0)); $dc->SetFont(Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL)); - $dc->DrawLabel("X = " . $self->{config}->print_center->[X], Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM); - $dc->DrawRotatedText("Y = " . $self->{config}->print_center->[Y], 0, $size[Y]/2+15, 90); + $dc->DrawLabel("X = " . $self->{config}->print_center->[X], Wx::Rect->new(0, 0, $center->[X]*2, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM); + $dc->DrawRotatedText("Y = " . $self->{config}->print_center->[Y], 0, $center->[Y]+15, 90); } # draw frame @@ -131,7 +136,7 @@ sub repaint { } foreach my $expolygon (@$thumbnail) { foreach my $points (@{$expolygon->pp}) { - $dc->DrawPolygon($self->points_to_pixel($points, 1), 0, 0); + $dc->DrawPolygon($self->scaled_points_to_pixel($points, 1), 0, 0); } } @@ -151,7 +156,7 @@ sub repaint { my ($clearance) = @{offset([$thumbnail->convex_hull], (scale($self->{config}->extruder_clearance_radius) / 2), 1, JT_ROUND, scale(0.1))}; $dc->SetPen($self->{clearance_pen}); $dc->SetBrush($self->{transparent_brush}); - $dc->DrawPolygon($self->points_to_pixel($clearance, 1), 0, 0); + $dc->DrawPolygon($self->scaled_points_to_pixel($clearance, 1), 0, 0); } } } @@ -163,7 +168,7 @@ sub repaint { my ($convex_hull) = @{offset([convex_hull(\@points)], scale($self->{config}->skirt_distance), 1, JT_ROUND, scale(0.1))}; $dc->SetPen($self->{skirt_pen}); $dc->SetBrush($self->{transparent_brush}); - $dc->DrawPolygon($self->points_to_pixel($convex_hull, 1), 0, 0); + $dc->DrawPolygon($self->scaled_points_to_pixel($convex_hull, 1), 0, 0); } } @@ -173,16 +178,15 @@ sub repaint { sub mouse_event { my ($self, $event) = @_; - my $point = $event->GetPosition; - my $pos = $self->point_to_model_units([ $point->x, $point->y ]); #]] - $pos = Slic3r::Point->new_scale(@$pos); + my $pos = $event->GetPosition; + my $point = $self->point_to_model_units([ $pos->x, $pos->y ]); #]] if ($event->ButtonDown) { $self->{on_select_object}->(undef); OBJECTS: for my $obj_idx (0 .. $#{$self->{objects}}) { my $object = $self->{objects}->[$obj_idx]; for my $instance_idx (0 .. $#{ $object->instance_thumbnails }) { my $thumbnail = $object->instance_thumbnails->[$instance_idx]; - if (defined first { $_->contour->contains_point($pos) } @$thumbnail) { + if (defined first { $_->contour->contains_point($point) } @$thumbnail) { $self->{on_select_object}->($obj_idx); if ($event->LeftDown) { @@ -190,12 +194,12 @@ sub mouse_event { my $instance = $self->{model}->objects->[$obj_idx]->instances->[$instance_idx]; my $instance_origin = [ map scale($_), @{$instance->offset} ]; $self->{drag_start_pos} = [ # displacement between the click and the instance origin in scaled model units - $pos->x - $instance_origin->[X], - $pos->y - $instance_origin->[Y], #- + $point->x - $instance_origin->[X], + $point->y - $instance_origin->[Y], #- ]; $self->{drag_object} = [ $obj_idx, $instance_idx ]; } elsif ($event->RightDown) { - $self->{on_right_click}->($point); + $self->{on_right_click}->($pos); } last OBJECTS; @@ -224,7 +228,7 @@ sub mouse_event { $self->Refresh; } elsif ($event->Moving) { my $cursor = wxSTANDARD_CURSOR; - if (defined first { $_->contour->contains_point($pos) } map @$_, map @{$_->instance_thumbnails}, @{ $self->{objects} }) { + if (defined first { $_->contour->contains_point($point) } map @$_, map @{$_->instance_thumbnails}, @{ $self->{objects} }) { $cursor = Wx::Cursor->new(wxCURSOR_HAND); } $self->SetCursor($cursor); @@ -234,13 +238,37 @@ sub mouse_event { sub update_bed_size { my $self = shift; - # supposing the preview canvas is square, calculate the scaling factor - # to constrain print bed area inside preview # when the canvas is not rendered yet, its GetSize() method returns 0,0 + my $canvas_size = $self->GetSize; + my ($canvas_w, $canvas_h) = ($canvas_size->GetWidth, $canvas_size->GetHeight); + return if $canvas_w == 0; + + # get bed shape polygon + $self->{bed_polygon} = my $polygon = Slic3r::Polygon->new_scale(@{$self->{config}->bed_shape}); + my $bb = $polygon->bounding_box; + my $size = $bb->size; + + # calculate the scaling factor needed for constraining print bed area inside preview # scaling_factor is expressed in pixel / mm - my $width = $self->GetSize->GetWidth; - $self->{scaling_factor} = $width / max(@{ $self->{config}->bed_size }) - if $width != 0; + $self->{scaling_factor} = min($canvas_w / unscale($size->x), $canvas_h / unscale($size->y)); #) + + # calculate the displacement needed to center bed + $self->{bed_origin} = [ + $self->GetSize->GetWidth/2 - (unscale($bb->x_max + $bb->x_min)/2 * $self->{scaling_factor}), + $canvas_h - ($self->GetSize->GetHeight/2 - (unscale($bb->y_max + $bb->y_min)/2 * $self->{scaling_factor})), + ]; + + # cache bed contours and grid + { + my $step = scale 10; # 1cm grid + $self->{grid} = my $grid = []; # arrayref of lines + 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); + } + 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); + } + } } sub clean_instance_thumbnails { @@ -251,35 +279,25 @@ sub clean_instance_thumbnails { } } -# coordinates of the model origin (0,0) in pixels -sub model_origin_to_pixel { - my ($self) = @_; - - return [ - $self->GetSize->GetWidth/2 - ($self->{config}->print_center->[X] * $self->{scaling_factor}), - $self->GetSize->GetHeight/2 - ($self->{config}->print_center->[Y] * $self->{scaling_factor}), - ]; -} - -# convert a model coordinate into a pixel coordinate, assuming preview has square shape -sub point_to_pixel { +# convert a model coordinate into a pixel coordinate +sub unscaled_point_to_pixel { my ($self, $point) = @_; my $canvas_height = $self->GetSize->GetHeight; - my $zero = $self->model_origin_to_pixel; + my $zero = $self->{bed_origin}; return [ - $point->[X] * $self->{scaling_factor} + $zero->[X], - $canvas_height - ($point->[Y] * $self->{scaling_factor} + $zero->[Y]), + $point->[X] * $self->{scaling_factor} + $zero->[X], + $canvas_height - $point->[Y] * $self->{scaling_factor} + ($zero->[Y] - $canvas_height), ]; } -sub points_to_pixel { +sub scaled_points_to_pixel { my ($self, $points, $unscale) = @_; my $result = []; foreach my $point (@$points) { $point = [ map unscale($_), @$point ] if $unscale; - push @$result, $self->point_to_pixel($point); + push @$result, $self->unscaled_point_to_pixel($point); } return $result; } @@ -288,11 +306,13 @@ sub point_to_model_units { my ($self, $point) = @_; my $canvas_height = $self->GetSize->GetHeight; - my $zero = $self->model_origin_to_pixel; - return [ - ($point->[X] - $zero->[X]) / $self->{scaling_factor}, - (($canvas_height - $point->[Y] - $zero->[Y]) / $self->{scaling_factor}), - ]; + my $zero = $self->{bed_origin}; + my $p = Slic3r::Point->new( + scale ($point->[X] - $zero->[X]) / $self->{scaling_factor}, + scale ($point->[Y] - $zero->[Y]) / $self->{scaling_factor}, + ); + use XXX; YYY $p->pp; + return $p; } 1; diff --git a/lib/Slic3r/Model.pm b/lib/Slic3r/Model.pm index 24f17016c..c4c80e1f9 100644 --- a/lib/Slic3r/Model.pm +++ b/lib/Slic3r/Model.pm @@ -146,6 +146,7 @@ sub duplicate { sub _arrange { my ($self, $sizes, $distance, $bb) = @_; + # we supply unscaled data to arrange() return Slic3r::Geometry::arrange( scalar(@$sizes), # number of parts max(map $_->x, @$sizes), # cell width diff --git a/xs/src/Print.cpp b/xs/src/Print.cpp index 3b38b8e94..67efad678 100644 --- a/xs/src/Print.cpp +++ b/xs/src/Print.cpp @@ -427,7 +427,7 @@ Print::invalidate_state_by_config_options(const std::vector } else if (*opt_key == "nozzle_diameter") { steps.insert(psInitExtruders); } else if (*opt_key == "avoid_crossing_perimeters" - || *opt_key == "bed_size" + || *opt_key == "bed_shape" || *opt_key == "bed_temperature" || *opt_key == "bridge_acceleration" || *opt_key == "bridge_fan_speed"