Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/xs
diff options
context:
space:
mode:
authorAlessandro Ranellucci <aar@cpan.org>2016-12-22 01:09:58 +0300
committerbubnikv <bubnikv@gmail.com>2017-02-21 16:02:47 +0300
commita65c9ba0839bcfc4363e369294bdcc3ceeb949d2 (patch)
tree6eeccd31a50a62e1a1279d67926e80a4c19e8890 /xs
parentc517b0d8f17ced2b93c63f47aa4cc12eed268801 (diff)
Ported CoolingBuffer to C++/XS
Diffstat (limited to 'xs')
-rw-r--r--xs/MANIFEST2
-rw-r--r--xs/src/libslic3r/GCode/CoolingBuffer.cpp132
-rw-r--r--xs/src/libslic3r/GCode/CoolingBuffer.hpp39
-rw-r--r--xs/src/perlglue.cpp1
-rw-r--r--xs/xsp/GCode.xsp11
-rw-r--r--xs/xsp/my.map4
-rw-r--r--xs/xsp/typemap.xspt4
7 files changed, 193 insertions, 0 deletions
diff --git a/xs/MANIFEST b/xs/MANIFEST
index db101d689..03e52ae50 100644
--- a/xs/MANIFEST
+++ b/xs/MANIFEST
@@ -52,6 +52,8 @@ src/libslic3r/Flow.cpp
src/libslic3r/Flow.hpp
src/libslic3r/GCode.cpp
src/libslic3r/GCode.hpp
+src/libslic3r/GCode/CoolingBuffer.cpp
+src/libslic3r/GCode/CoolingBuffer.hpp
src/libslic3r/GCodeSender.cpp
src/libslic3r/GCodeSender.hpp
src/libslic3r/GCodeWriter.cpp
diff --git a/xs/src/libslic3r/GCode/CoolingBuffer.cpp b/xs/src/libslic3r/GCode/CoolingBuffer.cpp
new file mode 100644
index 000000000..84df9cfd3
--- /dev/null
+++ b/xs/src/libslic3r/GCode/CoolingBuffer.cpp
@@ -0,0 +1,132 @@
+#include "CoolingBuffer.hpp"
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include <iostream>
+
+namespace Slic3r {
+
+std::string
+CoolingBuffer::append(const std::string &gcode, std::string obj_id, size_t layer_id, float print_z)
+{
+ std::string out;
+ if (this->_last_z.find(obj_id) != this->_last_z.end()) {
+ // A layer was finished, Z of the object's layer changed. Process the layer.
+ out = this->flush();
+ }
+
+ this->_layer_id = layer_id;
+ this->_last_z[obj_id] = print_z;
+ this->_gcode += gcode;
+ // This is a very rough estimate of the print time,
+ // not taking into account the acceleration curves generated by the printer firmware.
+ this->_elapsed_time += this->_gcodegen->elapsed_time;
+ this->_gcodegen->elapsed_time = 0;
+
+ return out;
+}
+
+void
+apply_speed_factor(std::string &line, float speed_factor, float min_print_speed)
+{
+ // find pos of F
+ size_t pos = line.find_first_of('F');
+ size_t last_pos = line.find_first_of(' ', pos+1);
+
+ // extract current speed
+ float speed;
+ {
+ std::istringstream iss(line.substr(pos+1, last_pos));
+ iss >> speed;
+ }
+
+ // change speed
+ speed *= speed_factor;
+ speed = std::max(speed, min_print_speed);
+
+ // replace speed in string
+ {
+ std::ostringstream oss;
+ oss << speed;
+ line.replace(pos+1, (last_pos-pos), oss.str());
+ }
+}
+
+std::string
+CoolingBuffer::flush()
+{
+ GCode &gg = *this->_gcodegen;
+
+ std::string gcode = this->_gcode;
+ float elapsed = this->_elapsed_time;
+ this->_gcode = "";
+ this->_elapsed_time = 0;
+ this->_last_z.clear(); // reset the whole table otherwise we would compute overlapping times
+
+ int fan_speed = gg.config.fan_always_on ? gg.config.min_fan_speed.value : 0;
+
+ float speed_factor = 1.0;
+
+ if (gg.config.cooling) {
+ #ifdef SLIC3R_DEBUG
+ printf("Layer %zu estimated printing time: %f seconds\n", layer_id, elapsed);
+ #endif
+
+ if (elapsed < (float)gg.config.slowdown_below_layer_time) {
+ // Layer time very short. Enable the fan to a full throttle and slow down the print
+ // (stretch the layer print time to slowdown_below_layer_time).
+ fan_speed = gg.config.max_fan_speed;
+ speed_factor = elapsed / (float)gg.config.slowdown_below_layer_time;
+ } else if (elapsed < (float)gg.config.fan_below_layer_time) {
+ // Layer time quite short. Enable the fan proportionally according to the current layer time.
+ fan_speed = gg.config.max_fan_speed
+ - (gg.config.max_fan_speed - gg.config.min_fan_speed)
+ * (elapsed - (float)gg.config.slowdown_below_layer_time)
+ / (gg.config.fan_below_layer_time - gg.config.slowdown_below_layer_time);
+ }
+
+ #ifdef SLIC3R_DEBUG
+ printf(" fan = %d%%, speed = %f%%\n", fan_speed, speed_factor * 100);
+ #endif
+
+ if (speed_factor < 1.0) {
+ // Adjust feed rate of G1 commands marked with an _EXTRUDE_SET_SPEED
+ // as long as they are not _WIPE moves (they cannot if they are _EXTRUDE_SET_SPEED)
+ // and they are not preceded directly by _BRIDGE_FAN_START (do not adjust bridging speed).
+ std::string new_gcode;
+ std::istringstream ss(gcode);
+ std::string line;
+ bool bridge_fan_start = false;
+ while (std::getline(ss, line)) {
+ if (boost::starts_with(line, "G1")
+ && boost::contains(line, ";_EXTRUDE_SET_SPEED")
+ && !boost::contains(line, ";_WIPE")
+ && !bridge_fan_start) {
+ apply_speed_factor(line, speed_factor, this->_min_print_speed);
+ boost::replace_first(line, ";_EXTRUDE_SET_SPEED", "");
+ }
+ bridge_fan_start = boost::contains(line, ";_BRIDGE_FAN_START");
+ new_gcode += line + '\n';
+ }
+ gcode = new_gcode;
+ }
+ }
+ if (this->_layer_id < gg.config.disable_fan_first_layers)
+ fan_speed = 0;
+
+ gcode = gg.writer.set_fan(fan_speed) + gcode;
+
+ // bridge fan speed
+ if (!gg.config.cooling || gg.config.bridge_fan_speed == 0 || this->_layer_id < gg.config.disable_fan_first_layers) {
+ boost::replace_all(gcode, ";_BRIDGE_FAN_START", "");
+ boost::replace_all(gcode, ";_BRIDGE_FAN_END", "");
+ } else {
+ boost::replace_all(gcode, ";_BRIDGE_FAN_START", gg.writer.set_fan(gg.config.bridge_fan_speed, true));
+ boost::replace_all(gcode, ";_BRIDGE_FAN_END", gg.writer.set_fan(fan_speed, true));
+ }
+ boost::replace_all(gcode, ";_WIPE", "");
+ boost::replace_all(gcode, ";_EXTRUDE_SET_SPEED", "");
+
+ return gcode;
+}
+
+}
diff --git a/xs/src/libslic3r/GCode/CoolingBuffer.hpp b/xs/src/libslic3r/GCode/CoolingBuffer.hpp
new file mode 100644
index 000000000..01770a58d
--- /dev/null
+++ b/xs/src/libslic3r/GCode/CoolingBuffer.hpp
@@ -0,0 +1,39 @@
+#ifndef slic3r_CoolingBuffer_hpp_
+#define slic3r_CoolingBuffer_hpp_
+
+#include "libslic3r.h"
+#include "GCode.hpp"
+#include <map>
+#include <string>
+
+namespace Slic3r {
+
+/*
+A standalone G-code filter, to control cooling of the print.
+The G-code is processed per layer. Once a layer is collected, fan start / stop commands are edited
+and the print is modified to stretch over a minimum layer time.
+*/
+
+class CoolingBuffer {
+ public:
+ CoolingBuffer(GCode &gcodegen)
+ : _gcodegen(&gcodegen), _elapsed_time(0.), _layer_id(0)
+ {
+ this->_min_print_speed = this->_gcodegen->config.min_print_speed * 60;
+ };
+ std::string append(const std::string &gcode, std::string obj_id, size_t layer_id, float print_z);
+ std::string flush();
+ GCode* gcodegen() { return this->_gcodegen; };
+
+ private:
+ GCode* _gcodegen;
+ std::string _gcode;
+ float _elapsed_time;
+ size_t _layer_id;
+ std::map<std::string,float> _last_z;
+ float _min_print_speed;
+};
+
+}
+
+#endif
diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp
index 523d3fe06..552524eaa 100644
--- a/xs/src/perlglue.cpp
+++ b/xs/src/perlglue.cpp
@@ -15,6 +15,7 @@ REGISTER_CLASS(ExtrusionSimulator, "ExtrusionSimulator");
REGISTER_CLASS(Filler, "Filler");
REGISTER_CLASS(Flow, "Flow");
REGISTER_CLASS(AvoidCrossingPerimeters, "GCode::AvoidCrossingPerimeters");
+REGISTER_CLASS(CoolingBuffer, "GCode::CoolingBuffer");
REGISTER_CLASS(OozePrevention, "GCode::OozePrevention");
REGISTER_CLASS(Wipe, "GCode::Wipe");
REGISTER_CLASS(GCode, "GCode");
diff --git a/xs/xsp/GCode.xsp b/xs/xsp/GCode.xsp
index 507132dcf..78f1f9d1f 100644
--- a/xs/xsp/GCode.xsp
+++ b/xs/xsp/GCode.xsp
@@ -3,6 +3,7 @@
%{
#include <xsinit.h>
#include "libslic3r/GCode.hpp"
+#include "libslic3r/GCode/CoolingBuffer.hpp"
%}
%name{Slic3r::GCode::AvoidCrossingPerimeters} class AvoidCrossingPerimeters {
@@ -70,6 +71,16 @@
%code{% THIS->path = *value; %};
};
+%name{Slic3r::GCode::CoolingBuffer} class CoolingBuffer {
+ CoolingBuffer(GCode* gcode)
+ %code{% RETVAL = new CoolingBuffer(*gcode); %};
+ ~CoolingBuffer();
+ Ref<GCode> gcodegen();
+
+ std::string append(std::string gcode, std::string obj_id, size_t layer_id, float print_z);
+ std::string flush();
+};
+
%name{Slic3r::GCode} class GCode {
GCode();
~GCode();
diff --git a/xs/xsp/my.map b/xs/xsp/my.map
index c6308aca7..8f5f67d4e 100644
--- a/xs/xsp/my.map
+++ b/xs/xsp/my.map
@@ -197,6 +197,10 @@ OozePrevention* O_OBJECT_SLIC3R
Ref<OozePrevention> O_OBJECT_SLIC3R_T
Clone<OozePrevention> O_OBJECT_SLIC3R_T
+CoolingBuffer* O_OBJECT_SLIC3R
+Ref<CoolingBuffer> O_OBJECT_SLIC3R_T
+Clone<CoolingBuffer> O_OBJECT_SLIC3R_T
+
GCode* O_OBJECT_SLIC3R
Ref<GCode> O_OBJECT_SLIC3R_T
Clone<GCode> O_OBJECT_SLIC3R_T
diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt
index e32271ac9..57109055a 100644
--- a/xs/xsp/typemap.xspt
+++ b/xs/xsp/typemap.xspt
@@ -164,6 +164,10 @@
%typemap{Ref<OozePrevention>}{simple};
%typemap{Clone<OozePrevention>}{simple};
+%typemap{CoolingBuffer*};
+%typemap{Ref<CoolingBuffer>}{simple};
+%typemap{Clone<CoolingBuffer>}{simple};
+
%typemap{GCode*};
%typemap{Ref<GCode>}{simple};
%typemap{Clone<GCode>}{simple};