mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Manual control
This commit is contained in:
		
							parent
							
								
									cb8f8a24b0
								
							
						
					
					
						commit
						4295d65115
					
				
					 9 changed files with 369 additions and 135 deletions
				
			
		
							
								
								
									
										196
									
								
								lib/Slic3r/GUI/2DBed.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								lib/Slic3r/GUI/2DBed.pm
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,196 @@ | |||
| package Slic3r::GUI::2DBed; | ||||
| use strict; | ||||
| use warnings; | ||||
| 
 | ||||
| use List::Util qw(min max); | ||||
| use Slic3r::Geometry qw(PI X Y unscale deg2rad); | ||||
| use Slic3r::Geometry::Clipper qw(intersection_pl); | ||||
| use Wx qw(:misc :pen :brush :font wxTAB_TRAVERSAL); | ||||
| use Wx::Event qw(EVT_PAINT EVT_MOUSE_EVENTS); | ||||
| use base qw(Wx::Panel Class::Accessor); | ||||
| 
 | ||||
| __PACKAGE__->mk_accessors(qw(bed_shape interactive pos _scale_factor _shift on_move)); | ||||
| 
 | ||||
| sub new { | ||||
|     my ($class, $parent, $bed_shape) = @_; | ||||
|      | ||||
|     my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, [250,-1], wxTAB_TRAVERSAL); | ||||
|     $self->bed_shape($bed_shape // []); | ||||
|     EVT_PAINT($self, \&_repaint); | ||||
|     EVT_MOUSE_EVENTS($self, \&_mouse_event); | ||||
|      | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| sub _repaint { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|     my $dc = Wx::PaintDC->new($self); | ||||
|     my ($cw, $ch) = $self->GetSizeWH; | ||||
|     return if $cw == 0;  # when canvas is not rendered yet, size is 0,0 | ||||
|      | ||||
|     # turn $cw and $ch from sizes to max coordinates | ||||
|     $cw--; | ||||
|     $ch--; | ||||
|      | ||||
|     my $cbb = Slic3r::Geometry::BoundingBoxf->new_from_points([ | ||||
|         Slic3r::Pointf->new(0, 0), | ||||
|         Slic3r::Pointf->new($cw, $ch), | ||||
|     ]); | ||||
|      | ||||
|     # leave space for origin point | ||||
|     $cbb->set_x_min($cbb->x_min + 2); | ||||
|     $cbb->set_y_max($cbb->y_max - 2); | ||||
|      | ||||
|     # leave space for origin label | ||||
|     $cbb->set_y_max($cbb->y_max - 10); | ||||
|      | ||||
|     # read new size | ||||
|     ($cw, $ch) = @{$cbb->size}; | ||||
|     my $ccenter = $cbb->center; | ||||
|      | ||||
|     # get bounding box of bed shape in G-code coordinates | ||||
|     my $bed_shape = $self->bed_shape; | ||||
|     my $bed_polygon = Slic3r::Polygon->new_scale(@$bed_shape); | ||||
|     my $bb = Slic3r::Geometry::BoundingBoxf->new_from_points($bed_shape); | ||||
|     $bb->merge_point(Slic3r::Pointf->new(0,0));  # origin needs to be in the visible area | ||||
|     my ($bw, $bh) = @{$bb->size}; | ||||
|     my $bcenter = $bb->center; | ||||
|      | ||||
|     # calculate the scaling factor for fitting bed shape in canvas area | ||||
|     my $sfactor = min($cw/$bw, $ch/$bh); | ||||
|     my $shift = Slic3r::Pointf->new( | ||||
|         $ccenter->x - $bcenter->x * $sfactor, | ||||
|         $ccenter->y - $bcenter->y * $sfactor,  #- | ||||
|     ); | ||||
|     $self->_scale_factor($sfactor); | ||||
|     $self->_shift(Slic3r::Pointf->new( | ||||
|         $shift->x + $cbb->x_min, | ||||
|         $shift->y - ($cbb->y_max-$self->GetSize->GetHeight), #++ | ||||
|     )); | ||||
|      | ||||
|     # draw bed fill | ||||
|     { | ||||
|         $dc->SetPen(Wx::Pen->new(Wx::Colour->new(0,0,0), 1, wxSOLID)); | ||||
|         $dc->SetBrush(Wx::Brush->new(Wx::Colour->new(255,255,255), wxSOLID)); | ||||
|         $dc->DrawPolygon([ map $self->to_pixels($_), @$bed_shape ], 0, 0); | ||||
|     } | ||||
|      | ||||
|     # draw grid | ||||
|     { | ||||
|         my $step = 10;  # 1cm grid | ||||
|         my @polylines = (); | ||||
|         for (my $x = $bb->x_min - ($bb->x_min % $step) + $step; $x < $bb->x_max; $x += $step) { | ||||
|             push @polylines, Slic3r::Polyline->new_scale([$x, $bb->y_min], [$x, $bb->y_max]); | ||||
|         } | ||||
|         for (my $y = $bb->y_min - ($bb->y_min % $step) + $step; $y < $bb->y_max; $y += $step) { | ||||
|             push @polylines, Slic3r::Polyline->new_scale([$bb->x_min, $y], [$bb->x_max, $y]); | ||||
|         } | ||||
|         @polylines = @{intersection_pl(\@polylines, [$bed_polygon])}; | ||||
|          | ||||
|         $dc->SetPen(Wx::Pen->new(Wx::Colour->new(230,230,230), 1, wxSOLID)); | ||||
|         $dc->DrawLine(map @{$self->to_pixels([map unscale($_), @$_])}, @$_[0,-1]) for @polylines; | ||||
|     } | ||||
|      | ||||
|     # draw bed contour | ||||
|     { | ||||
|         $dc->SetPen(Wx::Pen->new(Wx::Colour->new(0,0,0), 1, wxSOLID)); | ||||
|         $dc->SetBrush(Wx::Brush->new(Wx::Colour->new(255,255,255), wxTRANSPARENT)); | ||||
|         $dc->DrawPolygon([ map $self->to_pixels($_), @$bed_shape ], 0, 0); | ||||
|     } | ||||
|      | ||||
|     my $origin_px = $self->to_pixels(Slic3r::Pointf->new(0,0)); | ||||
|      | ||||
|     # draw axes | ||||
|     { | ||||
|         my $axes_len = 50; | ||||
|         my $arrow_len = 6; | ||||
|         my $arrow_angle = deg2rad(45); | ||||
|         $dc->SetPen(Wx::Pen->new(Wx::Colour->new(255,0,0), 2, wxSOLID));  # red | ||||
|         my $x_end = Slic3r::Pointf->new($origin_px->[X] + $axes_len, $origin_px->[Y]); | ||||
|         $dc->DrawLine(@$origin_px, @$x_end); | ||||
|         foreach my $angle (-$arrow_angle, +$arrow_angle) { | ||||
|             my $end = $x_end->clone; | ||||
|             $end->translate(-$arrow_len, 0); | ||||
|             $end->rotate($angle, $x_end); | ||||
|             $dc->DrawLine(@$x_end, @$end); | ||||
|         } | ||||
|          | ||||
|         $dc->SetPen(Wx::Pen->new(Wx::Colour->new(0,255,0), 2, wxSOLID));  # green | ||||
|         my $y_end = Slic3r::Pointf->new($origin_px->[X], $origin_px->[Y] - $axes_len); | ||||
|         $dc->DrawLine(@$origin_px, @$y_end); | ||||
|         foreach my $angle (-$arrow_angle, +$arrow_angle) { | ||||
|             my $end = $y_end->clone; | ||||
|             $end->translate(0, +$arrow_len); | ||||
|             $end->rotate($angle, $y_end); | ||||
|             $dc->DrawLine(@$y_end, @$end); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     # draw origin | ||||
|     { | ||||
|         $dc->SetPen(Wx::Pen->new(Wx::Colour->new(0,0,0), 1, wxSOLID)); | ||||
|         $dc->SetBrush(Wx::Brush->new(Wx::Colour->new(0,0,0), wxSOLID)); | ||||
|         $dc->DrawCircle(@$origin_px, 3); | ||||
|          | ||||
|         $dc->SetTextForeground(Wx::Colour->new(0,0,0)); | ||||
|         $dc->SetFont(Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL)); | ||||
|         $dc->DrawText("(0,0)", $origin_px->[X] + 1, $origin_px->[Y] + 2); | ||||
|     } | ||||
|      | ||||
|     # draw current position | ||||
|     if (defined $self->pos) { | ||||
|         my $pos_px = $self->to_pixels($self->pos); | ||||
|         $dc->SetPen(Wx::Pen->new(Wx::Colour->new(200,0,0), 2, wxSOLID)); | ||||
|         $dc->SetBrush(Wx::Brush->new(Wx::Colour->new(200,0,0), wxTRANSPARENT)); | ||||
|         $dc->DrawCircle(@$pos_px, 5); | ||||
|          | ||||
|         $dc->DrawLine($pos_px->[X]-15, $pos_px->[Y], $pos_px->[X]+15, $pos_px->[Y]); | ||||
|         $dc->DrawLine($pos_px->[X], $pos_px->[Y]-15, $pos_px->[X], $pos_px->[Y]+15); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| sub _mouse_event { | ||||
|     my ($self, $event) = @_; | ||||
|      | ||||
|     return if !$self->interactive; | ||||
|      | ||||
|     my $pos = $event->GetPosition; | ||||
|     my $point = $self->to_units([ $pos->x, $pos->y ]);  #]] | ||||
|     if ($event->LeftDown || $event->Dragging) { | ||||
|         $self->on_move->($point) if $self->on_move; | ||||
|         $self->Refresh; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| # convert G-code coordinates into pixels | ||||
| sub to_pixels { | ||||
|     my ($self, $point) = @_; | ||||
|      | ||||
|     my $p = Slic3r::Pointf->new(@$point); | ||||
|     $p->scale($self->_scale_factor); | ||||
|     $p->translate(@{$self->_shift}); | ||||
|     return [$p->x, $self->GetSize->GetHeight - $p->y]; #]] | ||||
| } | ||||
| 
 | ||||
| # convert pixels into G-code coordinates | ||||
| sub to_units { | ||||
|     my ($self, $point) = @_; | ||||
|      | ||||
|     my $p = Slic3r::Pointf->new( | ||||
|         $point->[X], | ||||
|         $self->GetSize->GetHeight - $point->[Y], | ||||
|     ); | ||||
|     $p->translate(@{$self->_shift->negative}); | ||||
|     $p->scale(1/$self->_scale_factor); | ||||
|     return $p; | ||||
| } | ||||
| 
 | ||||
| sub set_pos { | ||||
|     my ($self, $pos) = @_; | ||||
|      | ||||
|     $self->pos($pos); | ||||
|     $self->Refresh; | ||||
| } | ||||
| 
 | ||||
| 1; | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci