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

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2017-06-22 13:59:23 +0300
committerbubnikv <bubnikv@gmail.com>2017-06-22 13:59:23 +0300
commit0454cc95f949f1d7818566c466b313f56c352ca4 (patch)
treeec8c4694908a0ab0a2e7b06cb19c25c0505f9418 /xs/src/libslic3r
parentc1146e298b8ff96bd029bad494627c5a6b547f56 (diff)
Ported the cooling changes from @alexrj: Don't slow down the external
perimeters if not necessary, don't take the bridging time into account when slowing down the print. Removed Extruder & GCodeWriter Perl bindings. Improved Extruder for constness. Refactored GCode::m_elapsed_time to struct ElapsedTime.
Diffstat (limited to 'xs/src/libslic3r')
-rw-r--r--xs/src/libslic3r/Extruder.cpp32
-rw-r--r--xs/src/libslic3r/Extruder.hpp18
-rw-r--r--xs/src/libslic3r/GCode.cpp50
-rw-r--r--xs/src/libslic3r/GCode.hpp30
-rw-r--r--xs/src/libslic3r/GCode/CoolingBuffer.cpp56
-rw-r--r--xs/src/libslic3r/GCode/CoolingBuffer.hpp6
-rw-r--r--xs/src/libslic3r/GCodeWriter.cpp16
-rw-r--r--xs/src/libslic3r/GCodeWriter.hpp12
8 files changed, 141 insertions, 79 deletions
diff --git a/xs/src/libslic3r/Extruder.cpp b/xs/src/libslic3r/Extruder.cpp
index 19f08d907..206f9c11e 100644
--- a/xs/src/libslic3r/Extruder.cpp
+++ b/xs/src/libslic3r/Extruder.cpp
@@ -3,16 +3,16 @@
namespace Slic3r {
Extruder::Extruder(unsigned int id, GCodeConfig *config)
-: id(id),
+: m_id(id),
m_config(config)
{
reset();
// cache values that are going to be called often
if (m_config->use_volumetric_e) {
- this->e_per_mm3 = this->extrusion_multiplier();
+ m_e_per_mm3 = this->extrusion_multiplier();
} else {
- this->e_per_mm3 = this->extrusion_multiplier()
+ m_e_per_mm3 = this->extrusion_multiplier()
* (4 / ((this->filament_diameter() * this->filament_diameter()) * PI));
}
}
@@ -64,7 +64,7 @@ double Extruder::unretract()
double Extruder::e_per_mm(double mm3_per_mm) const
{
- return mm3_per_mm * this->e_per_mm3;
+ return mm3_per_mm * m_e_per_mm3;
}
double Extruder::extruded_volume() const
@@ -91,64 +91,64 @@ double Extruder::used_filament() const
double Extruder::filament_diameter() const
{
- return m_config->filament_diameter.get_at(this->id);
+ return m_config->filament_diameter.get_at(m_id);
}
double Extruder::filament_density() const
{
- return m_config->filament_density.get_at(this->id);
+ return m_config->filament_density.get_at(m_id);
}
double Extruder::filament_cost() const
{
- return m_config->filament_cost.get_at(this->id);
+ return m_config->filament_cost.get_at(m_id);
}
double Extruder::extrusion_multiplier() const
{
- return m_config->extrusion_multiplier.get_at(this->id);
+ return m_config->extrusion_multiplier.get_at(m_id);
}
// Return a "retract_before_wipe" percentage as a factor clamped to <0, 1>
double Extruder::retract_before_wipe() const
{
- return std::min(1., std::max(0., m_config->retract_before_wipe.get_at(this->id) * 0.01));
+ return std::min(1., std::max(0., m_config->retract_before_wipe.get_at(m_id) * 0.01));
}
double Extruder::retract_length() const
{
- return m_config->retract_length.get_at(this->id);
+ return m_config->retract_length.get_at(m_id);
}
double Extruder::retract_lift() const
{
- return m_config->retract_lift.get_at(this->id);
+ return m_config->retract_lift.get_at(m_id);
}
int Extruder::retract_speed() const
{
- return m_config->retract_speed.get_at(this->id);
+ return m_config->retract_speed.get_at(m_id);
}
int Extruder::deretract_speed() const
{
- int speed = m_config->deretract_speed.get_at(this->id);
+ int speed = m_config->deretract_speed.get_at(m_id);
return (speed > 0) ? speed : this->retract_speed();
}
double Extruder::retract_restart_extra() const
{
- return m_config->retract_restart_extra.get_at(this->id);
+ return m_config->retract_restart_extra.get_at(m_id);
}
double Extruder::retract_length_toolchange() const
{
- return m_config->retract_length_toolchange.get_at(this->id);
+ return m_config->retract_length_toolchange.get_at(m_id);
}
double Extruder::retract_restart_extra_toolchange() const
{
- return m_config->retract_restart_extra_toolchange.get_at(this->id);
+ return m_config->retract_restart_extra_toolchange.get_at(m_id);
}
}
diff --git a/xs/src/libslic3r/Extruder.hpp b/xs/src/libslic3r/Extruder.hpp
index 8569a54c0..5de1a6817 100644
--- a/xs/src/libslic3r/Extruder.hpp
+++ b/xs/src/libslic3r/Extruder.hpp
@@ -10,12 +10,10 @@ namespace Slic3r {
class Extruder
{
public:
- unsigned int id;
double E;
double absolute_E;
double retracted;
double restart_extra;
- double e_per_mm3;
Extruder(unsigned int id, GCodeConfig *config);
virtual ~Extruder() {}
@@ -27,10 +25,13 @@ public:
this->restart_extra = 0;
}
+ unsigned int id() const { return m_id; }
+
double extrude(double dE);
double retract(double length, double restart_extra);
double unretract();
double e_per_mm(double mm3_per_mm) const;
+ double e_per_mm3() const { return m_e_per_mm3; }
double extruded_volume() const;
double used_filament() const;
@@ -47,20 +48,23 @@ public:
double retract_length_toolchange() const;
double retract_restart_extra_toolchange() const;
+ // Constructor for a key object, to be used by the stdlib search functions.
static Extruder key(unsigned int id) { return Extruder(id); }
private:
// Private constructor to create a key for a search in std::set.
- Extruder(unsigned int id) : id(id) {}
+ Extruder(unsigned int id) : m_id(id) {}
GCodeConfig *m_config;
+ unsigned int m_id;
+ double m_e_per_mm3;
};
// Sort Extruder objects by the extruder id by default.
-inline bool operator==(const Extruder &e1, const Extruder &e2) { return e1.id == e2.id; }
-inline bool operator!=(const Extruder &e1, const Extruder &e2) { return e1.id != e2.id; }
-inline bool operator< (const Extruder &e1, const Extruder &e2) { return e1.id < e2.id; }
-inline bool operator> (const Extruder &e1, const Extruder &e2) { return e1.id > e2.id; }
+inline bool operator==(const Extruder &e1, const Extruder &e2) { return e1.id() == e2.id(); }
+inline bool operator!=(const Extruder &e1, const Extruder &e2) { return e1.id() != e2.id(); }
+inline bool operator< (const Extruder &e1, const Extruder &e2) { return e1.id() < e2.id(); }
+inline bool operator> (const Extruder &e1, const Extruder &e2) { return e1.id() > e2.id(); }
}
diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp
index 2383c243c..88966e044 100644
--- a/xs/src/libslic3r/GCode.cpp
+++ b/xs/src/libslic3r/GCode.cpp
@@ -83,8 +83,8 @@ int
OozePrevention::_get_temp(GCode &gcodegen)
{
return (gcodegen.layer() != NULL && gcodegen.layer()->id() == 0)
- ? gcodegen.config().first_layer_temperature.get_at(gcodegen.writer().extruder()->id)
- : gcodegen.config().temperature.get_at(gcodegen.writer().extruder()->id);
+ ? gcodegen.config().first_layer_temperature.get_at(gcodegen.writer().extruder()->id())
+ : gcodegen.config().temperature.get_at(gcodegen.writer().extruder()->id());
}
std::string
@@ -172,7 +172,7 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
// Accumulate the elapsed time for the correct calculation of layer cooling.
//FIXME currently disabled as Slic3r PE needs to be updated to differentiate the moves it could slow down
// from the moves it could not.
-// gcodegen.m_elapsed_time += tcr.elapsed_time;
+ gcodegen.m_elapsed_time.other += tcr.elapsed_time;
// Let the m_writer know the current extruder_id, but ignore the generated G-code.
if (new_extruder_id >= 0 && gcodegen.writer().need_toolchange(new_extruder_id))
gcodegen.writer().toolchange(new_extruder_id);
@@ -220,7 +220,7 @@ std::string WipeTowerIntegration::finalize(GCode &gcodegen)
return gcode;
}
-#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_writer.extruder()->id)
+#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_writer.extruder()->id())
inline void write(FILE *file, const std::string &what)
{
@@ -648,12 +648,12 @@ bool GCode::do_export(FILE *file, Print &print)
print.total_extruded_volume = 0.;
print.total_weight = 0.;
print.total_cost = 0.;
- for (const Extruder &extruder : m_writer.extruders) {
+ for (const Extruder &extruder : m_writer.extruders()) {
double used_filament = extruder.used_filament();
double extruded_volume = extruder.extruded_volume();
double filament_weight = extruded_volume * extruder.filament_density() * 0.001;
double filament_cost = filament_weight * extruder.filament_cost() * 0.001;
- print.filament_stats.insert(std::pair<size_t,float>(extruder.id, used_filament));
+ print.filament_stats.insert(std::pair<size_t,float>(extruder.id(), used_filament));
fprintf(file, "; filament used = %.1lfmm (%.1lfcm3)\n", used_filament, extruded_volume * 0.001);
if (filament_weight > 0.) {
print.total_weight = print.total_weight + filament_weight;
@@ -815,13 +815,13 @@ void GCode::process_layer(
if (! first_layer && ! m_second_layer_things_done) {
// Transition from 1st to 2nd layer. Adjust nozzle temperatures as prescribed by the nozzle dependent
// first_layer_temperature vs. temperature settings.
- for (const Extruder &extruder : m_writer.extruders) {
- if (print.config.single_extruder_multi_material.value && extruder.id != m_writer.extruder()->id)
+ for (const Extruder &extruder : m_writer.extruders()) {
+ if (print.config.single_extruder_multi_material.value && extruder.id() != m_writer.extruder()->id())
// In single extruder multi material mode, set the temperature for the current extruder only.
continue;
- int temperature = print.config.temperature.get_at(extruder.id);
- if (temperature > 0 && temperature != print.config.first_layer_temperature.get_at(extruder.id))
- gcode += m_writer.set_temperature(temperature, false, extruder.id);
+ int temperature = print.config.temperature.get_at(extruder.id());
+ if (temperature > 0 && temperature != print.config.first_layer_temperature.get_at(extruder.id()))
+ gcode += m_writer.set_temperature(temperature, false, extruder.id());
}
gcode += m_writer.set_bed_temperature(print.config.bed_temperature.get_at(first_extruder_id));
// Mark the temperature transition from 1st to 2nd layer to be finished.
@@ -1792,7 +1792,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
}
// calculate extrusion length per distance unit
- double e_per_mm = m_writer.extruder()->e_per_mm3 * path.mm3_per_mm;
+ double e_per_mm = m_writer.extruder()->e_per_mm3() * path.mm3_per_mm;
if (m_writer.extrusion_axis().empty()) e_per_mm = 0;
// set speed
@@ -1846,8 +1846,11 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
}
if (is_bridge(path.role()) && m_enable_cooling_markers)
gcode += ";_BRIDGE_FAN_START\n";
- gcode += m_writer.set_speed(F, "", m_enable_cooling_markers ? ";_EXTRUDE_SET_SPEED" : "");
- double path_length = 0;
+ std::string comment = ";_EXTRUDE_SET_SPEED";
+ if (path.role() == erExternalPerimeter)
+ comment += ";_EXTERNAL_PERIMETER";
+ gcode += m_writer.set_speed(F, "", m_enable_cooling_markers ? comment : "");
+ double path_length = 0.;
{
std::string comment = m_config.gcode_comments ? description : "";
for (const Line &line : path.polyline.lines()) {
@@ -1864,8 +1867,14 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
this->set_last_pos(path.last_point());
- if (m_config.cooling.values.front())
- m_elapsed_time += path_length / F * 60.f;
+ if (m_config.cooling.values.front()) {
+ float t = path_length / F * 60.f;
+ m_elapsed_time.total += t;
+ if (is_bridge(path.role()))
+ m_elapsed_time.bridges += t;
+ if (path.role() == erExternalPerimeter)
+ m_elapsed_time.external_perimeters += t;
+ }
return gcode;
}
@@ -1912,13 +1921,8 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string
for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line)
gcode += m_writer.travel_to_xy(this->point_to_gcode(line->b), comment);
- /* While this makes the estimate more accurate, CoolingBuffer calculates the slowdown
- factor on the whole elapsed time but only alters non-travel moves, thus the resulting
- time is still shorter than the configured threshold. We could create a new
- elapsed_travel_time but we would still need to account for bridges, retractions, wipe etc.
if (m_config.cooling.values.front())
- m_elapsed_time += unscale(travel.length()) / m_config.get_abs_value("travel_speed");
- */
+ m_elapsed_time.travel += unscale(travel.length()) / m_config.get_abs_value("travel_speed");
return gcode;
}
@@ -2000,7 +2004,7 @@ std::string GCode::set_extruder(unsigned int extruder_id)
// append custom toolchange G-code
if (m_writer.extruder() != nullptr && !m_config.toolchange_gcode.value.empty()) {
PlaceholderParser pp = m_placeholder_parser;
- pp.set("previous_extruder", m_writer.extruder()->id);
+ pp.set("previous_extruder", m_writer.extruder()->id());
pp.set("next_extruder", extruder_id);
gcode += pp.process(m_config.toolchange_gcode.value) + '\n';
}
diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp
index baf37e9c6..9509cf6ab 100644
--- a/xs/src/libslic3r/GCode.hpp
+++ b/xs/src/libslic3r/GCode.hpp
@@ -107,6 +107,27 @@ private:
bool m_brim_done;
};
+struct ElapsedTime
+{
+ ElapsedTime() { this->reset(); }
+ void reset() { total = bridges = external_perimeters = travel = other = 0.f; }
+
+ ElapsedTime& operator+=(const ElapsedTime &rhs) {
+ this->total += rhs.total;
+ this->bridges += rhs.bridges;
+ this->external_perimeters += rhs.external_perimeters;
+ this->travel += rhs.travel;
+ this->other += rhs.other;
+ return *this;
+ }
+
+ float total;
+ float bridges;
+ float external_perimeters;
+ float travel;
+ float other;
+};
+
class GCode {
public:
GCode() :
@@ -117,7 +138,6 @@ public:
m_layer_count(0),
m_layer_index(-1),
m_layer(nullptr),
- m_elapsed_time(0.0),
m_volumetric_speed(0),
m_last_pos_defined(false),
m_last_extrusion_role(erNone),
@@ -140,13 +160,13 @@ public:
const Layer* layer() const { return m_layer; }
GCodeWriter& writer() { return m_writer; }
bool enable_cooling_markers() const { return m_enable_cooling_markers; }
- float get_reset_elapsed_time() { float t = m_elapsed_time; m_elapsed_time = 0.f; return t; }
+ ElapsedTime get_reset_elapsed_time() { ElapsedTime et = this->m_elapsed_time; this->m_elapsed_time.reset(); return et; }
// For Perl bindings, to be used exclusively by unit tests.
unsigned int layer_count() const { return m_layer_count; }
void set_layer_count(unsigned int value) { m_layer_count = value; }
- float elapsed_time() const { return m_elapsed_time; }
- void set_elapsed_time(float value) { m_elapsed_time = value; }
+ float elapsed_time() const { return m_elapsed_time.total; }
+ void set_elapsed_time(float value) { m_elapsed_time.total = value; }
void apply_print_config(const PrintConfig &print_config);
protected:
@@ -247,7 +267,7 @@ protected:
// This value is not quite precise. First it only accouts for extrusion moves and travel moves,
// it does not account for wipe, retract / unretract moves.
// second it does not account for the velocity profiles of the printer.
- float m_elapsed_time; // seconds
+ ElapsedTime m_elapsed_time;
double m_volumetric_speed;
// Support for the extrusion role markers. Which marker is active?
ExtrusionRole m_last_extrusion_role;
diff --git a/xs/src/libslic3r/GCode/CoolingBuffer.cpp b/xs/src/libslic3r/GCode/CoolingBuffer.cpp
index 9040a86a9..dcc06b12d 100644
--- a/xs/src/libslic3r/GCode/CoolingBuffer.cpp
+++ b/xs/src/libslic3r/GCode/CoolingBuffer.cpp
@@ -6,6 +6,17 @@
namespace Slic3r {
+CoolingBuffer::CoolingBuffer(GCode &gcodegen) :
+ m_gcodegen(gcodegen), m_layer_id(0),
+ m_elapsed_time(new ElapsedTime)
+{
+}
+
+CoolingBuffer::~CoolingBuffer()
+{
+ delete m_elapsed_time;
+}
+
std::string CoolingBuffer::append(const std::string &gcode, size_t object_id, size_t layer_id, bool is_support)
{
std::string out;
@@ -21,7 +32,7 @@ std::string CoolingBuffer::append(const std::string &gcode, size_t object_id, si
m_gcode += gcode;
// This is a very rough estimate of the print time,
// not taking into account the acceleration curves generated by the printer firmware.
- m_elapsed_time += m_gcodegen.get_reset_elapsed_time();
+ *m_elapsed_time += m_gcodegen.get_reset_elapsed_time();
return out;
}
@@ -46,37 +57,49 @@ void apply_speed_factor(std::string &line, float speed_factor, float min_print_s
{
std::ostringstream oss;
oss << speed;
- line.replace(pos+1, (last_pos-pos), oss.str());
+ line.replace(pos+1, last_pos-pos, oss.str());
}
}
std::string CoolingBuffer::flush()
{
const FullPrintConfig &config = m_gcodegen.config();
-
- std::string gcode = m_gcode;
- float elapsed = m_elapsed_time;
+
+ std::string gcode = std::move(m_gcode);
m_gcode.clear();
- m_elapsed_time = 0.;
int fan_speed = config.fan_always_on.values.front() ? config.min_fan_speed.values.front() : 0;
float speed_factor = 1.0;
-
+ bool slowdown_external = true;
+
if (config.cooling.values.front()) {
#ifdef SLIC3R_DEBUG
- printf("Layer %zu estimated printing time: %f seconds\n", m_layer_id, elapsed);
- #endif
- if (elapsed < (float)config.slowdown_below_layer_time.values.front()) {
+ printf("Layer %zu estimated printing time: %f seconds\n", m_layer_id, m_elapsed_time->total);
+ #endif
+ if (m_elapsed_time->total < (float)config.slowdown_below_layer_time.values.front()) {
// 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 = config.max_fan_speed.values.front();
- speed_factor = elapsed / (float)config.slowdown_below_layer_time.values.front();
- } else if (elapsed < (float)config.fan_below_layer_time.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;
+
+ // If we spend most of our time on external perimeters include them in the slowdown,
+ // otherwise only alter other extrusions.
+ if (m_elapsed_time->external_perimeters < 0.5f * time_to_stretch) {
+ time_to_stretch -= m_elapsed_time->external_perimeters;
+ target_time -= m_elapsed_time->external_perimeters;
+ slowdown_external = false;
+ }
+
+ speed_factor = time_to_stretch / target_time;
+ } else if (m_elapsed_time->total < (float)config.fan_below_layer_time.values.front()) {
// Layer time quite short. Enable the fan proportionally according to the current layer time.
fan_speed = config.max_fan_speed.values.front()
- (config.max_fan_speed.values.front() - config.min_fan_speed.values.front())
- * (elapsed - (float)config.slowdown_below_layer_time.values.front())
+ * (m_elapsed_time->total - (float)config.slowdown_below_layer_time.values.front())
/ (config.fan_below_layer_time.values.front() - config.slowdown_below_layer_time.values.front());
}
@@ -97,11 +120,12 @@ std::string CoolingBuffer::flush()
if (boost::starts_with(line, "G1")
&& boost::contains(line, ";_EXTRUDE_SET_SPEED")
&& !boost::contains(line, ";_WIPE")
- && !bridge_fan_start) {
+ && !bridge_fan_start
+ && (slowdown_external || !boost::contains(line, ";_EXTERNAL_PERIMETER"))) {
apply_speed_factor(line, speed_factor, min_print_speed);
boost::replace_first(line, ";_EXTRUDE_SET_SPEED", "");
}
- bridge_fan_start = boost::contains(line, ";_BRIDGE_FAN_START");
+ bridge_fan_start = boost::starts_with(line, ";_BRIDGE_FAN_START");
new_gcode += line + '\n';
}
gcode = new_gcode;
@@ -122,8 +146,10 @@ std::string CoolingBuffer::flush()
}
boost::replace_all(gcode, ";_WIPE", "");
boost::replace_all(gcode, ";_EXTRUDE_SET_SPEED", "");
+ boost::replace_all(gcode, ";_EXTERNAL_PERIMETER", "");
m_object_ids_visited.clear();
+ m_elapsed_time->reset();
return gcode;
}
diff --git a/xs/src/libslic3r/GCode/CoolingBuffer.hpp b/xs/src/libslic3r/GCode/CoolingBuffer.hpp
index ac4ba8a88..da8677e1e 100644
--- a/xs/src/libslic3r/GCode/CoolingBuffer.hpp
+++ b/xs/src/libslic3r/GCode/CoolingBuffer.hpp
@@ -7,6 +7,7 @@
namespace Slic3r {
+struct ElapsedTime;
class GCode;
class Layer;
@@ -18,7 +19,8 @@ and the print is modified to stretch over a minimum layer time.
class CoolingBuffer {
public:
- CoolingBuffer(GCode &gcodegen) : m_gcodegen(gcodegen), m_elapsed_time(0.), m_layer_id(0) {}
+ CoolingBuffer(GCode &gcodegen);
+ ~CoolingBuffer();
std::string append(const std::string &gcode, size_t object_id, size_t layer_id, bool is_support);
std::string flush();
GCode* gcodegen() { return &m_gcodegen; };
@@ -28,7 +30,7 @@ private:
GCode& m_gcodegen;
std::string m_gcode;
- float m_elapsed_time;
+ ElapsedTime *m_elapsed_time;
size_t m_layer_id;
std::set<size_t> m_object_ids_visited;
};
diff --git a/xs/src/libslic3r/GCodeWriter.cpp b/xs/src/libslic3r/GCodeWriter.cpp
index 6612ead35..4d92410ee 100644
--- a/xs/src/libslic3r/GCodeWriter.cpp
+++ b/xs/src/libslic3r/GCodeWriter.cpp
@@ -22,8 +22,10 @@ void GCodeWriter::apply_print_config(const PrintConfig &print_config)
void GCodeWriter::set_extruders(const std::vector<unsigned int> &extruder_ids)
{
+ m_extruders.clear();
+ m_extruders.reserve(extruder_ids.size());
for (unsigned int extruder_id : extruder_ids)
- this->extruders.insert(Extruder(extruder_id, &this->config));
+ m_extruders.emplace_back(Extruder(extruder_id, &this->config));
/* we enable support for multiple extruder if any extruder greater than 0 is used
(even if prints only uses that one) since we need to output Tx commands
@@ -229,8 +231,10 @@ std::string GCodeWriter::update_progress(unsigned int num, unsigned int tot, boo
std::string GCodeWriter::toolchange(unsigned int extruder_id)
{
// set the new extruder
- m_extruder = const_cast<Extruder*>(&*this->extruders.find(Extruder::key(extruder_id)));
-
+ auto it_extruder = std::lower_bound(m_extruders.begin(), m_extruders.end(), Extruder::key(extruder_id));
+ assert(it_extruder != m_extruders.end());
+ m_extruder = const_cast<Extruder*>(&*it_extruder);
+
// return the toolchange command
// if we are running a single-extruder setup, just set the extruder and return nothing
std::ostringstream gcode;
@@ -469,10 +473,10 @@ std::string GCodeWriter::lift()
// check whether the above/below conditions are met
double target_lift = 0;
{
- double above = this->config.retract_lift_above.get_at(m_extruder->id);
- double below = this->config.retract_lift_below.get_at(m_extruder->id);
+ double above = this->config.retract_lift_above.get_at(m_extruder->id());
+ double below = this->config.retract_lift_below.get_at(m_extruder->id());
if (m_pos.z >= above && (below == 0 || m_pos.z <= below))
- target_lift = this->config.retract_lift.get_at(m_extruder->id);
+ target_lift = this->config.retract_lift.get_at(m_extruder->id());
}
if (m_lifted == 0 && target_lift > 0) {
m_lifted = target_lift;
diff --git a/xs/src/libslic3r/GCodeWriter.hpp b/xs/src/libslic3r/GCodeWriter.hpp
index 2fa1a899d..02fca4129 100644
--- a/xs/src/libslic3r/GCodeWriter.hpp
+++ b/xs/src/libslic3r/GCodeWriter.hpp
@@ -12,7 +12,6 @@ namespace Slic3r {
class GCodeWriter {
public:
GCodeConfig config;
- std::set<Extruder> extruders;
bool multiple_extruders;
GCodeWriter() :
@@ -26,12 +25,14 @@ public:
const Extruder* extruder() const { return m_extruder; }
std::string extrusion_axis() const { return m_extrusion_axis; }
void apply_print_config(const PrintConfig &print_config);
+ // Extruders are expected to be sorted in an increasing order.
void set_extruders(const std::vector<unsigned int> &extruder_ids);
+ const std::vector<Extruder>& extruders() const { return m_extruders; }
std::vector<unsigned int> extruder_ids() const {
std::vector<unsigned int> out;
- out.reserve(extruders.size());
- for (const auto e : extruders)
- out.push_back(e.id);
+ out.reserve(m_extruders.size());
+ for (const Extruder &e : m_extruders)
+ out.push_back(e.id());
return out;
}
std::string preamble();
@@ -44,7 +45,7 @@ public:
std::string update_progress(unsigned int num, unsigned int tot, bool allow_100 = false) const;
// return false if this extruder was already selected
bool need_toolchange(unsigned int extruder_id) const
- { return m_extruder == nullptr || m_extruder->id != extruder_id; }
+ { return m_extruder == nullptr || m_extruder->id() != extruder_id; }
std::string set_extruder(unsigned int extruder_id)
{ return this->need_toolchange(extruder_id) ? this->toolchange(extruder_id) : ""; }
std::string toolchange(unsigned int extruder_id);
@@ -63,6 +64,7 @@ public:
Pointf3 get_position() const { return m_pos; }
private:
+ std::vector<Extruder> m_extruders;
std::string m_extrusion_axis;
bool m_single_extruder_multi_material;
Extruder* m_extruder;