6
6
#include < memory.h>
7
7
#include < cstring>
8
8
#include < cfloat>
9
- #include < algorithm>
10
9
11
10
#include " ../libslic3r.h"
12
11
#include " ../PrintConfig.hpp"
@@ -29,12 +28,6 @@ static const std::string EXTERNAL_PERIMETER_TAG = ";_EXTERNAL_PERIMETER";
29
28
// affect how distant will be propagated a flow rate adjustment.
30
29
static constexpr int max_look_back_limit = 128 ;
31
30
32
- // Max non-extruding XY distance (travel move) in mm between two continous extrusions where we pretend
33
- // its all one continous extruded line. Above this distance we assume extruder pressure hits 0
34
- // This exists because often there's tiny travel moves between stuff like infill
35
- // lines where some extruder pressure will remain (so we should equalize between these small travels)
36
- static constexpr long max_ignored_gap_between_extruding_segments = 3 ;
37
-
38
31
PressureEqualizer::PressureEqualizer (const Slic3r::GCodeConfig &config) : m_use_relative_e_distances(config.use_relative_e_distances.value)
39
32
{
40
33
// Preallocate some data, so that output_buffer.data() will return an empty string.
@@ -48,8 +41,10 @@ PressureEqualizer::PressureEqualizer(const Slic3r::GCodeConfig &config) : m_use_
48
41
m_current_extrusion_role = GCodeExtrusionRole::None;
49
42
// Expect the first command to fill the nozzle (deretract).
50
43
m_retracted = true ;
51
-
52
- m_max_segment_length = 2 .f ;
44
+
45
+ // Maximum segment length to split a long segment if the initial and the final flow rate differ.
46
+ // Smaller value means a smoother transition between two different flow rates.
47
+ m_max_segment_length = 5 .f ;
53
48
54
49
// Calculate filamet crossections for the multiple extruders.
55
50
m_filament_crossections.clear ();
@@ -64,17 +59,17 @@ PressureEqualizer::PressureEqualizer(const Slic3r::GCodeConfig &config) : m_use_
64
59
65
60
if (config.max_volumetric_extrusion_rate_slope .value > 0 ){
66
61
m_max_volumetric_extrusion_rate_slope_positive = float (config.max_volumetric_extrusion_rate_slope .value ) * 60 .f * 60 .f ;
67
- m_max_volumetric_extrusion_rate_slope_negative = float (config.max_volumetric_extrusion_rate_slope .value ) * 60 .f * 60 .f ;
68
- m_max_segment_length = float (config.max_volumetric_extrusion_rate_slope_segment_length .value );
62
+ m_max_volumetric_extrusion_rate_slope_negative = float (config.max_volumetric_extrusion_rate_slope .value ) * 60 .f * 60 .f ;
63
+ m_max_segment_length = float (config.max_volumetric_extrusion_rate_slope_segment_length .value );
69
64
}
70
65
71
66
for (ExtrusionRateSlope &extrusion_rate_slope : m_max_volumetric_extrusion_rate_slopes) {
72
67
extrusion_rate_slope.negative = m_max_volumetric_extrusion_rate_slope_negative;
73
68
extrusion_rate_slope.positive = m_max_volumetric_extrusion_rate_slope_positive;
74
69
}
75
-
76
- // Don't regulate the pressure before and after ironing.
77
- for (const GCodeExtrusionRole er : {GCodeExtrusionRole::Ironing}) {
70
+
71
+ // Don't regulate the pressure before and after gap-fill and ironing.
72
+ for (const GCodeExtrusionRole er : {GCodeExtrusionRole::GapFill, GCodeExtrusionRole:: Ironing}) {
78
73
m_max_volumetric_extrusion_rate_slopes[size_t (er)].negative = 0 ;
79
74
m_max_volumetric_extrusion_rate_slopes[size_t (er)].positive = 0 ;
80
75
}
@@ -111,67 +106,6 @@ void PressureEqualizer::process_layer(const std::string &gcode)
111
106
}
112
107
assert (!this ->opened_extrude_set_speed_block );
113
108
}
114
-
115
- // at this point, we have an entire layer of gcode lines loaded into m_gcode_lines
116
- // now we will split the mix of travels and extrudes into segments of continous extrusion and process those
117
- // We skip over large travels, and pretend small ones are part of a continous extrusion segment
118
- long idx_end_current_extrusion = 0 ;
119
- while (idx_end_current_extrusion < m_gcode_lines.size ()) {
120
- // find beginning of next extrusion segment from current pos
121
- const long idx_begin_current_extrusion = find_if (m_gcode_lines.begin () + idx_end_current_extrusion, m_gcode_lines.end (),
122
- [](GCodeLine line) { return line.extruding (); }) - m_gcode_lines.begin ();
123
- // (extrusion begin idx = extrusion end idx) here because we start with extrusion length of zero
124
- idx_end_current_extrusion = idx_begin_current_extrusion;
125
-
126
- // inner loop extends the extrusion segment over small travel moves
127
- while (idx_end_current_extrusion < m_gcode_lines.size ()) {
128
- // find end of the current extrusion segment
129
- const auto just_after_end_extrusion = find_if (m_gcode_lines.begin () + idx_end_current_extrusion, m_gcode_lines.end (),
130
- [](GCodeLine line) { return !line.extruding (); });
131
- idx_end_current_extrusion = std::max<long >(0 ,(just_after_end_extrusion - m_gcode_lines.begin ()) - 1 );
132
- const long idx_begin_segment_continuation = advance_segment_beyond_small_gap (idx_end_current_extrusion);
133
- if (idx_begin_segment_continuation > idx_end_current_extrusion) {
134
- // extend the continous line over the small gap
135
- idx_end_current_extrusion = idx_begin_segment_continuation;
136
- continue ; // keep going, loop again to find new end of extrusion segment
137
- } else {
138
- // gap to next extrude is too big, stop looking forward. We've found end of this segment
139
- break ;
140
- }
141
- }
142
-
143
- // now run the pressure equalizer across the segment like a streamroller
144
- // it operates on a sliding window that moves forward across gcode line by line
145
- for (int i = idx_begin_current_extrusion; i < idx_end_current_extrusion; ++i) {
146
- // feed pressure equalizer past lines, going back to max_look_back_limit (or start of segment)
147
- const auto start_idx = std::max<long >(idx_begin_current_extrusion, i - max_look_back_limit);
148
- adjust_volumetric_rate (start_idx, i);
149
- }
150
- // current extrusion is all done processing so advance beyond it for next loop
151
- idx_end_current_extrusion++;
152
- }
153
- }
154
-
155
- long PressureEqualizer::advance_segment_beyond_small_gap (const long idx_orig)
156
- {
157
- // this should only be run on the last extruding line before a gap
158
- assert (m_gcode_lines[idx_cur_pos].extruding ());
159
- double distance_traveled = 0.0 ;
160
- // start at beginning of gap, advance till extrusion found or gap too big
161
- for (auto idx_cur_pos = idx_orig + 1 ; idx_cur_pos < m_gcode_lines.size (); idx_cur_pos++) {
162
- // started extruding again! return segment extension
163
- if (m_gcode_lines[idx_cur_pos].extruding ()) {
164
- return idx_cur_pos;
165
- }
166
-
167
- distance_traveled += m_gcode_lines[idx_cur_pos].dist_xy ();
168
- // gap too big, dont extend segment
169
- if (distance_traveled > max_ignored_gap_between_extruding_segments) {
170
- return idx_orig;
171
- }
172
- }
173
- // looped until end of layer and couldn't extend extrusion
174
- return idx_orig;
175
109
}
176
110
177
111
LayerResult PressureEqualizer::process_layer (LayerResult &&input)
@@ -465,6 +399,8 @@ bool PressureEqualizer::process_line(const char *line, const char *line_end, GCo
465
399
466
400
buf.extruder_id = m_current_extruder;
467
401
memcpy (buf.pos_end , m_current_pos, sizeof (float )*5 );
402
+
403
+ adjust_volumetric_rate ();
468
404
#ifdef PRESSURE_EQUALIZER_DEBUG
469
405
++line_idx;
470
406
#endif
@@ -579,12 +515,14 @@ void PressureEqualizer::output_gcode_line(const size_t line_idx)
579
515
}
580
516
}
581
517
582
- void PressureEqualizer::adjust_volumetric_rate (const size_t fist_line_idx, const size_t last_line_idx )
518
+ void PressureEqualizer::adjust_volumetric_rate ()
583
519
{
584
- // don't bother adjusting volumetric rate if there's no gcode to adjust
585
- if (last_line_idx-fist_line_idx < 2 )
520
+ if (m_gcode_lines.size () < 2 )
586
521
return ;
587
522
523
+ // Go back from the current circular_buffer_pos and lower the feedtrate to decrease the slope of the extrusion rate changes.
524
+ size_t fist_line_idx = size_t (std::max<int >(0 , int (m_gcode_lines.size ()) - max_look_back_limit));
525
+ const size_t last_line_idx = m_gcode_lines.size () - 1 ;
588
526
size_t line_idx = last_line_idx;
589
527
if (line_idx == fist_line_idx || !m_gcode_lines[line_idx].extruding ())
590
528
// Nothing to do, the last move is not extruding.
@@ -599,8 +537,9 @@ void PressureEqualizer::adjust_volumetric_rate(const size_t fist_line_idx, const
599
537
for (; !m_gcode_lines[idx_prev].extruding () && idx_prev != fist_line_idx; --idx_prev);
600
538
if (!m_gcode_lines[idx_prev].extruding ())
601
539
break ;
602
- // Don't decelerate before ironing.
603
- if (m_gcode_lines[line_idx].extrusion_role == GCodeExtrusionRole::Ironing) { line_idx = idx_prev;
540
+ // Don't decelerate before ironing and gap-fill.
541
+ if (m_gcode_lines[line_idx].extrusion_role == GCodeExtrusionRole::Ironing || m_gcode_lines[line_idx].extrusion_role == GCodeExtrusionRole::GapFill) {
542
+ line_idx = idx_prev;
604
543
continue ;
605
544
}
606
545
// Volumetric extrusion rate at the start of the succeding segment.
@@ -619,8 +558,7 @@ void PressureEqualizer::adjust_volumetric_rate(const size_t fist_line_idx, const
619
558
// Limit by the succeeding volumetric flow rate.
620
559
rate_end = rate_succ;
621
560
622
- // don't alter the flow rate for these extrusion types
623
- if (!line.adjustable_flow || line.extrusion_role == GCodeExtrusionRole::BridgeInfill || line.extrusion_role == GCodeExtrusionRole::Ironing) {
561
+ if (!line.adjustable_flow || line.extrusion_role == GCodeExtrusionRole::ExternalPerimeter || line.extrusion_role == GCodeExtrusionRole::GapFill || line.extrusion_role == GCodeExtrusionRole::BridgeInfill || line.extrusion_role == GCodeExtrusionRole::Ironing) {
624
562
rate_end = line.volumetric_extrusion_rate_end ;
625
563
} else if (line.volumetric_extrusion_rate_end > rate_end) {
626
564
line.volumetric_extrusion_rate_end = rate_end;
@@ -643,8 +581,8 @@ void PressureEqualizer::adjust_volumetric_rate(const size_t fist_line_idx, const
643
581
}
644
582
}
645
583
// feedrate_per_extrusion_role[iRole] = (iRole == line.extrusion_role) ? line.volumetric_extrusion_rate_start : rate_start;
646
- // Don't store feed rate for ironing
647
- if (line.extrusion_role != GCodeExtrusionRole::Ironing)
584
+ // Don't store feed rate for ironing and gap-fill.
585
+ if (line.extrusion_role != GCodeExtrusionRole::Ironing && line. extrusion_role != GCodeExtrusionRole::GapFill )
648
586
feedrate_per_extrusion_role[iRole] = line.volumetric_extrusion_rate_start ;
649
587
}
650
588
}
@@ -658,8 +596,8 @@ void PressureEqualizer::adjust_volumetric_rate(const size_t fist_line_idx, const
658
596
for (; !m_gcode_lines[idx_next].extruding () && idx_next != last_line_idx; ++idx_next);
659
597
if (!m_gcode_lines[idx_next].extruding ())
660
598
break ;
661
- // Don't accelerate after ironing.
662
- if (m_gcode_lines[line_idx].extrusion_role == GCodeExtrusionRole::Ironing) {
599
+ // Don't accelerate after ironing and gap-fill .
600
+ if (m_gcode_lines[line_idx].extrusion_role == GCodeExtrusionRole::Ironing || m_gcode_lines[line_idx]. extrusion_role == GCodeExtrusionRole::GapFill ) {
663
601
line_idx = idx_next;
664
602
continue ;
665
603
}
@@ -674,8 +612,7 @@ void PressureEqualizer::adjust_volumetric_rate(const size_t fist_line_idx, const
674
612
continue ; // The positive rate is unlimited or the rate for GCodeExtrusionRole iRole is unlimited.
675
613
676
614
float rate_start = feedrate_per_extrusion_role[iRole];
677
- // don't alter the flow rate for these extrusion types
678
- if (!line.adjustable_flow || line.extrusion_role == GCodeExtrusionRole::BridgeInfill || line.extrusion_role == GCodeExtrusionRole::Ironing) {
615
+ if (!line.adjustable_flow || line.extrusion_role == GCodeExtrusionRole::ExternalPerimeter || line.extrusion_role == GCodeExtrusionRole::GapFill || line.extrusion_role == GCodeExtrusionRole::BridgeInfill || line.extrusion_role == GCodeExtrusionRole::Ironing) {
679
616
rate_start = line.volumetric_extrusion_rate_start ;
680
617
} else if (iRole == size_t (line.extrusion_role ) && rate_prec < rate_start)
681
618
rate_start = rate_prec;
@@ -700,8 +637,8 @@ void PressureEqualizer::adjust_volumetric_rate(const size_t fist_line_idx, const
700
637
}
701
638
}
702
639
// feedrate_per_extrusion_role[iRole] = (iRole == line.extrusion_role) ? line.volumetric_extrusion_rate_end : rate_end;
703
- // Don't store feed rate for ironing
704
- if (line.extrusion_role != GCodeExtrusionRole::Ironing)
640
+ // Don't store feed rate for ironing and gap-fill.
641
+ if (line.extrusion_role != GCodeExtrusionRole::Ironing && line. extrusion_role != GCodeExtrusionRole::GapFill )
705
642
feedrate_per_extrusion_role[iRole] = line.volumetric_extrusion_rate_end ;
706
643
}
707
644
}
0 commit comments