Reader.pm 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #/|/ Copyright (c) Prusa Research 2016 - 2017 Vojtěch Bubník @bubnikv
  2. #/|/ Copyright (c) Slic3r 2013 - 2015 Alessandro Ranellucci @alranel
  3. #/|/
  4. #/|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
  5. #/|/
  6. # Helper module to parse and interpret a G-code file,
  7. # invoking a callback for each move extracted from the G-code.
  8. # Currently used by the automatic tests only.
  9. package Slic3r::GCode::Reader;
  10. use Moo;
  11. has 'config' => (is => 'ro', default => sub { Slic3r::Config::GCode->new });
  12. has 'X' => (is => 'rw', default => sub {0});
  13. has 'Y' => (is => 'rw', default => sub {0});
  14. has 'Z' => (is => 'rw', default => sub {0});
  15. has 'E' => (is => 'rw', default => sub {0});
  16. has 'F' => (is => 'rw', default => sub {0});
  17. has '_extrusion_axis' => (is => 'rw', default => sub {"E"});
  18. our $Verbose = 0;
  19. my @AXES = qw(X Y Z E);
  20. sub apply_print_config {
  21. my ($self, $print_config) = @_;
  22. $self->config->apply_static($print_config);
  23. $self->_extrusion_axis($self->config->get_extrusion_axis);
  24. }
  25. sub clone {
  26. my $self = shift;
  27. return (ref $self)->new(
  28. map { $_ => $self->$_ } (@AXES, 'F', '_extrusion_axis', 'config'),
  29. );
  30. }
  31. sub parse {
  32. my $self = shift;
  33. my ($gcode, $cb) = @_;
  34. foreach my $raw_line (split /\R+/, $gcode) {
  35. print "$raw_line\n" if $Verbose || $ENV{SLIC3R_TESTS_GCODE};
  36. my $line = $raw_line;
  37. $line =~ s/\s*;(.*)//; # strip comment
  38. my %info = (comment => $1, raw => $raw_line);
  39. # parse command
  40. my ($command, @args) = split /\s+/, $line;
  41. $command //= '';
  42. my %args = map { /([A-Z])(.*)/; ($1 => $2) } @args;
  43. # convert extrusion axis
  44. if (exists $args{ $self->_extrusion_axis }) {
  45. $args{E} = $args{ $self->_extrusion_axis };
  46. }
  47. # check motion
  48. if ($command =~ /^G[01]$/) {
  49. foreach my $axis (@AXES) {
  50. if (exists $args{$axis}) {
  51. $self->$axis(0) if $axis eq 'E' && $self->config->use_relative_e_distances;
  52. $info{"dist_$axis"} = $args{$axis} - $self->$axis;
  53. $info{"new_$axis"} = $args{$axis};
  54. } else {
  55. $info{"dist_$axis"} = 0;
  56. $info{"new_$axis"} = $self->$axis;
  57. }
  58. }
  59. $info{dist_XY} = sqrt(($info{dist_X}**2) + ($info{dist_Y}**2));
  60. if (exists $args{E}) {
  61. if ($info{dist_E} > 0) {
  62. $info{extruding} = 1;
  63. } elsif ($info{dist_E} < 0) {
  64. $info{retracting} = 1
  65. }
  66. } else {
  67. $info{travel} = 1;
  68. }
  69. }
  70. # run callback
  71. $cb->($self, $command, \%args, \%info);
  72. # update coordinates
  73. if ($command =~ /^(?:G[01]|G92)$/) {
  74. for my $axis (@AXES, 'F') {
  75. $self->$axis($args{$axis}) if exists $args{$axis};
  76. }
  77. }
  78. # TODO: update temperatures
  79. }
  80. }
  81. 1;