VibrationLimit.pm 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. package Slic3r::GCode::VibrationLimit;
  2. use Moo;
  3. extends 'Slic3r::GCode::Reader';
  4. has '_min_time' => (is => 'lazy');
  5. has '_last_dir' => (is => 'ro', default => sub { [0,0] });
  6. has '_dir_time' => (is => 'ro', default => sub { [0,0] });
  7. # inspired by http://hydraraptor.blogspot.it/2010/12/frequency-limit.html
  8. use List::Util qw(max);
  9. sub _build__min_time {
  10. my ($self) = @_;
  11. return 1 / ($self->config->vibration_limit * 60); # in minutes
  12. }
  13. sub process {
  14. my $self = shift;
  15. my ($gcode) = @_;
  16. my $new_gcode = "";
  17. $self->parse($gcode, sub {
  18. my ($reader, $cmd, $args, $info) = @_;
  19. if ($cmd eq 'G1' && $info->{dist_XY} > 0) {
  20. my $point = Slic3r::Pointf->new($args->{X} // $reader->X, $args->{Y} // $reader->Y);
  21. my @dir = (
  22. ($point->x <=> $reader->X),
  23. ($point->y <=> $reader->Y), #$
  24. );
  25. my $time = $info->{dist_XY} / ($args->{F} // $reader->F); # in minutes
  26. if ($time > 0) {
  27. my @pause = ();
  28. foreach my $axis (0..$#dir) {
  29. if ($dir[$axis] != 0 && $self->_last_dir->[$axis] != $dir[$axis]) {
  30. if ($self->_last_dir->[$axis] != 0) {
  31. # this axis is changing direction: check whether we need to pause
  32. if ($self->_dir_time->[$axis] < $self->_min_time) {
  33. push @pause, ($self->_min_time - $self->_dir_time->[$axis]);
  34. }
  35. }
  36. $self->_last_dir->[$axis] = $dir[$axis];
  37. $self->_dir_time->[$axis] = 0;
  38. }
  39. $self->_dir_time->[$axis] += $time;
  40. }
  41. if (@pause) {
  42. $new_gcode .= sprintf "G4 P%d\n", max(@pause) * 60 * 1000;
  43. }
  44. }
  45. }
  46. $new_gcode .= $info->{raw} . "\n";
  47. });
  48. return $new_gcode;
  49. }
  50. 1;