Flow.pm 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package Slic3r::Flow;
  2. use Moo;
  3. use Slic3r::Geometry qw(PI scale);
  4. has 'nozzle_diameter' => (is => 'ro', required => 1);
  5. has 'layer_height' => (is => 'ro', required => 1);
  6. has 'role' => (is => 'ro', default => sub { '' });
  7. has 'width' => (is => 'rwp', builder => 1);
  8. has 'spacing' => (is => 'lazy');
  9. has 'scaled_width' => (is => 'lazy');
  10. has 'scaled_spacing' => (is => 'lazy');
  11. sub BUILD {
  12. my $self = shift;
  13. if ($self->width =~ /^(\d+(?:\.\d+)?)%$/) {
  14. $self->_set_width($self->layer_height * $1 / 100);
  15. }
  16. $self->_set_width($self->_build_width) if $self->width == 0; # auto
  17. }
  18. sub _build_width {
  19. my $self = shift;
  20. # here we calculate a sane default by matching the flow speed (at the nozzle) and the feed rate
  21. my $volume = ($self->nozzle_diameter**2) * PI/4;
  22. my $shape_threshold = $self->nozzle_diameter * $self->layer_height + ($self->layer_height**2) * PI/4;
  23. my $width;
  24. if ($volume >= $shape_threshold) {
  25. # rectangle with semicircles at the ends
  26. $width = (($self->nozzle_diameter**2) * PI + ($self->layer_height**2) * (4 - PI)) / (4 * $self->layer_height);
  27. } else {
  28. # rectangle with squished semicircles at the ends
  29. $width = $self->nozzle_diameter * ($self->nozzle_diameter/$self->layer_height - 4/PI + 1);
  30. }
  31. my $min = $self->nozzle_diameter * 1.05;
  32. my $max;
  33. if ($self->role eq 'perimeter' || $self->role eq 'support_material') {
  34. $min = $max = $self->nozzle_diameter;
  35. } elsif ($self->role ne 'infill') {
  36. # do not limit width for sparse infill so that we use full native flow for it
  37. $max = $self->nozzle_diameter * 1.7;
  38. }
  39. $width = $max if defined($max) && $width > $max;
  40. $width = $min if $width < $min;
  41. return $width;
  42. }
  43. sub _build_spacing {
  44. my $self = shift;
  45. my $min_flow_spacing;
  46. if ($self->width >= ($self->nozzle_diameter + $self->layer_height)) {
  47. # rectangle with semicircles at the ends
  48. $min_flow_spacing = $self->width - $self->layer_height * (1 - PI/4);
  49. } else {
  50. # rectangle with shrunk semicircles at the ends
  51. $min_flow_spacing = $self->nozzle_diameter * (1 - PI/4) + $self->width * PI/4;
  52. }
  53. return $self->width - &Slic3r::OVERLAP_FACTOR * ($self->width - $min_flow_spacing);
  54. }
  55. sub clone {
  56. my $self = shift;
  57. return (ref $self)->new(
  58. nozzle_diameter => $self->nozzle_diameter,
  59. layer_height => $self->layer_height,
  60. @_,
  61. );
  62. }
  63. sub _build_scaled_width {
  64. my $self = shift;
  65. return scale $self->width;
  66. }
  67. sub _build_scaled_spacing {
  68. my $self = shift;
  69. return scale $self->spacing;
  70. }
  71. package Slic3r::Flow::Bridge;
  72. use Moo;
  73. extends 'Slic3r::Flow';
  74. # layer_height is not required in this case
  75. has '+layer_height' => (is => 'ro', required => 0);
  76. use Slic3r::Geometry qw(PI);
  77. sub _build_width {
  78. my $self = shift;
  79. return sqrt($Slic3r::Config->bridge_flow_ratio * ($self->nozzle_diameter**2));
  80. }
  81. sub _build_spacing {
  82. my $self = shift;
  83. return $self->width + 0.05;
  84. }
  85. 1;