diff --git a/xs/src/libslic3r/Extruder.cpp b/xs/src/libslic3r/Extruder.cpp index 206f9c11ec..74d900825d 100644 --- a/xs/src/libslic3r/Extruder.cpp +++ b/xs/src/libslic3r/Extruder.cpp @@ -2,29 +2,27 @@ namespace Slic3r { -Extruder::Extruder(unsigned int id, GCodeConfig *config) -: m_id(id), +Extruder::Extruder(unsigned int id, GCodeConfig *config) : + m_id(id), m_config(config) { reset(); // cache values that are going to be called often - if (m_config->use_volumetric_e) { - m_e_per_mm3 = this->extrusion_multiplier(); - } else { - m_e_per_mm3 = this->extrusion_multiplier() - * (4 / ((this->filament_diameter() * this->filament_diameter()) * PI)); - } + m_e_per_mm3 = this->extrusion_multiplier(); + if (! m_config->use_volumetric_e) + m_e_per_mm3 /= this->filament_crossection(); } double Extruder::extrude(double dE) { // in case of relative E distances we always reset to 0 before any output if (m_config->use_relative_e_distances) - this->E = 0; - - this->E += dE; - this->absolute_E += dE; + m_E = 0.; + m_E += dE; + m_absolute_E += dE; + if (dE < 0.) + m_retracted -= dE; return dE; } @@ -39,54 +37,40 @@ double Extruder::retract(double length, double restart_extra) { // in case of relative E distances we always reset to 0 before any output if (m_config->use_relative_e_distances) - this->E = 0; - - double to_retract = length - this->retracted; - if (to_retract > 0) { - this->E -= to_retract; - this->absolute_E -= to_retract; - this->retracted += to_retract; - this->restart_extra = restart_extra; - return to_retract; - } else { - return 0; + m_E = 0.; + double to_retract = std::max(0., length - m_retracted); + if (to_retract > 0.) { + m_E -= to_retract; + m_absolute_E -= to_retract; + m_retracted += to_retract; + m_restart_extra = restart_extra; } + return to_retract; } double Extruder::unretract() { - double dE = this->retracted + this->restart_extra; + double dE = m_retracted + m_restart_extra; this->extrude(dE); - this->retracted = 0; - this->restart_extra = 0; + m_retracted = 0.; + m_restart_extra = 0.; return dE; } -double Extruder::e_per_mm(double mm3_per_mm) const -{ - return mm3_per_mm * m_e_per_mm3; -} - +// Used filament volume in mm^3. double Extruder::extruded_volume() const { - if (m_config->use_volumetric_e) { - // Any current amount of retraction should not affect used filament, since - // it represents empty volume in the nozzle. We add it back to E. - return this->absolute_E + this->retracted; - } - - return this->used_filament() * (this->filament_diameter() * this->filament_diameter()) * PI/4; + return m_config->use_volumetric_e ? + m_absolute_E + m_retracted : + this->used_filament() * this->filament_crossection(); } +// Used filament length in mm. double Extruder::used_filament() const { - if (m_config->use_volumetric_e) { - return this->extruded_volume() / (this->filament_diameter() * this->filament_diameter() * PI/4); - } - - // Any current amount of retraction should not affect used filament, since - // it represents empty volume in the nozzle. We add it back to E. - return this->absolute_E + this->retracted; + return m_config->use_volumetric_e ? + this->extruded_volume() / this->filament_crossection() : + m_absolute_E + m_retracted; } double Extruder::filament_diameter() const @@ -127,12 +111,12 @@ double Extruder::retract_lift() const int Extruder::retract_speed() const { - return m_config->retract_speed.get_at(m_id); + return int(floor(m_config->retract_speed.get_at(m_id)+0.5)); } int Extruder::deretract_speed() const { - int speed = m_config->deretract_speed.get_at(m_id); + int speed = int(floor(m_config->deretract_speed.get_at(m_id)+0.5)); return (speed > 0) ? speed : this->retract_speed(); } diff --git a/xs/src/libslic3r/Extruder.hpp b/xs/src/libslic3r/Extruder.hpp index 5de1a68173..df92bf84b3 100644 --- a/xs/src/libslic3r/Extruder.hpp +++ b/xs/src/libslic3r/Extruder.hpp @@ -10,19 +10,14 @@ namespace Slic3r { class Extruder { public: - double E; - double absolute_E; - double retracted; - double restart_extra; - Extruder(unsigned int id, GCodeConfig *config); virtual ~Extruder() {} void reset() { - this->E = 0; - this->absolute_E = 0; - this->retracted = 0; - this->restart_extra = 0; + m_E = 0; + m_absolute_E = 0; + m_retracted = 0; + m_restart_extra = 0; } unsigned int id() const { return m_id; } @@ -30,12 +25,17 @@ public: double extrude(double dE); double retract(double length, double restart_extra); double unretract(); - double e_per_mm(double mm3_per_mm) const; + double E() const { return m_E; } + void reset_E() { m_E = 0.; } + double e_per_mm(double mm3_per_mm) const { return mm3_per_mm * m_e_per_mm3; } double e_per_mm3() const { return m_e_per_mm3; } + // Used filament volume in mm^3. double extruded_volume() const; + // Used filament length in mm. double used_filament() const; double filament_diameter() const; + double filament_crossection() const { return this->filament_diameter() * this->filament_diameter() * 0.25 * PI; } double filament_density() const; double filament_cost() const; double extrusion_multiplier() const; @@ -55,8 +55,18 @@ private: // Private constructor to create a key for a search in std::set. Extruder(unsigned int id) : m_id(id) {} + // Reference to GCodeWriter instance owned by GCodeWriter. GCodeConfig *m_config; + // Print-wide global ID of this extruder. unsigned int m_id; + // Current state of the extruder axis, may be resetted if use_relative_e_distances. + double m_E; + // Current state of the extruder tachometer, used to output the extruded_volume() and used_filament() statistics. + double m_absolute_E; + // Current positive amount of retraction. + double m_retracted; + // When retracted, this value stores the extra amount of priming on deretraction. + double m_restart_extra; double m_e_per_mm3; }; diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 88966e0446..a1678ec682 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -121,10 +121,8 @@ Wipe::wipe(GCode &gcodegen, bool toolchange) wipe_path.clip_end(wipe_path.length() - wipe_dist); // subdivide the retraction in segments - double retracted = 0; - Lines lines = wipe_path.lines(); - for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) { - double segment_length = line->length(); + for (const Line &line : wipe_path.lines()) { + double segment_length = line.length(); /* Reduce retraction length a bit to avoid effective retraction speed to be greater than the configured one due to rounding (TODO: test and/or better math for this) */ double dE = length * (segment_length / wipe_dist) * 0.95; @@ -132,13 +130,11 @@ Wipe::wipe(GCode &gcodegen, bool toolchange) // Is it here for the cooling markers? Or should it be outside of the cycle? gcode += gcodegen.writer().set_speed(wipe_speed*60, "", gcodegen.enable_cooling_markers() ? ";_WIPE" : ""); gcode += gcodegen.writer().extrude_to_xy( - gcodegen.point_to_gcode(line->b), + gcodegen.point_to_gcode(line.b), -dE, "wipe and retract" ); - retracted += dE; } - gcodegen.writer().extruder()->retracted += retracted; // prevent wiping again on same path this->reset_path(); diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp index 9509cf6ab1..3760aae849 100644 --- a/xs/src/libslic3r/GCode.hpp +++ b/xs/src/libslic3r/GCode.hpp @@ -121,6 +121,11 @@ struct ElapsedTime return *this; } + // Potion of the total time, which cannot be stretched to heed the minimum layer print time. + float non_stretchable() const { return this->bridges + this->travel + this->other; } + // Potion of the total time, which could be stretched to heed the minimum layer print time. + float stretchable() const { return this->total - this->non_stretchable(); } + float total; float bridges; float external_perimeters; diff --git a/xs/src/libslic3r/GCode/CoolingBuffer.cpp b/xs/src/libslic3r/GCode/CoolingBuffer.cpp index dcc06b12de..632bdb6daa 100644 --- a/xs/src/libslic3r/GCode/CoolingBuffer.cpp +++ b/xs/src/libslic3r/GCode/CoolingBuffer.cpp @@ -83,8 +83,8 @@ std::string CoolingBuffer::flush() fan_speed = config.max_fan_speed.values.front(); // We are not altering speed of bridges. - float time_to_stretch = m_elapsed_time->total - m_elapsed_time->bridges; - float target_time = (float)config.slowdown_below_layer_time.values.front() - m_elapsed_time->bridges; + float time_to_stretch = m_elapsed_time->stretchable(); + float target_time = (float)config.slowdown_below_layer_time.values.front() - m_elapsed_time->non_stretchable(); // If we spend most of our time on external perimeters include them in the slowdown, // otherwise only alter other extrusions. diff --git a/xs/src/libslic3r/GCodeWriter.cpp b/xs/src/libslic3r/GCodeWriter.cpp index 4d92410ee6..06ec5d1afd 100644 --- a/xs/src/libslic3r/GCodeWriter.cpp +++ b/xs/src/libslic3r/GCodeWriter.cpp @@ -197,9 +197,9 @@ std::string GCodeWriter::reset_e(bool force) return ""; if (m_extruder != nullptr) { - if (m_extruder->E == 0. && ! force) + if (m_extruder->E() == 0. && ! force) return ""; - m_extruder->E = 0.; + m_extruder->reset_E(); } if (! m_extrusion_axis.empty() && ! this->config.use_relative_e_distances) { @@ -356,7 +356,7 @@ std::string GCodeWriter::extrude_to_xy(const Pointf &point, double dE, const std std::ostringstream gcode; gcode << "G1 X" << XYZF_NUM(point.x) << " Y" << XYZF_NUM(point.y) - << " " << m_extrusion_axis << E_NUM(m_extruder->E); + << " " << m_extrusion_axis << E_NUM(m_extruder->E()); COMMENT(comment); gcode << "\n"; return gcode.str(); @@ -372,7 +372,7 @@ std::string GCodeWriter::extrude_to_xyz(const Pointf3 &point, double dE, const s gcode << "G1 X" << XYZF_NUM(point.x) << " Y" << XYZF_NUM(point.y) << " Z" << XYZF_NUM(point.z) - << " " << m_extrusion_axis << E_NUM(m_extruder->E); + << " " << m_extrusion_axis << E_NUM(m_extruder->E()); COMMENT(comment); gcode << "\n"; return gcode.str(); @@ -425,7 +425,7 @@ std::string GCodeWriter::_retract(double length, double restart_extra, const std else gcode << "G10 ; retract\n"; } else { - gcode << "G1 " << m_extrusion_axis << E_NUM(m_extruder->E) + gcode << "G1 " << m_extrusion_axis << E_NUM(m_extruder->E()) << " F" << float(m_extruder->retract_speed() * 60.); COMMENT(comment); gcode << "\n"; @@ -455,7 +455,7 @@ std::string GCodeWriter::unretract() gcode << this->reset_e(); } else { // use G1 instead of G0 because G0 will blend the restart with the previous travel move - gcode << "G1 " << m_extrusion_axis << E_NUM(m_extruder->E) + gcode << "G1 " << m_extrusion_axis << E_NUM(m_extruder->E()) << " F" << float(m_extruder->deretract_speed() * 60.); if (this->config.gcode_comments) gcode << " ; unretract"; gcode << "\n";