Flow.pm 2.8 KB

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