diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 8d0de99cd7..a0a95b68e1 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -144,7 +144,6 @@ sub thread_cleanup { *Slic3r::Config::Static::DESTROY = sub {}; *Slic3r::ExPolygon::DESTROY = sub {}; *Slic3r::ExPolygon::Collection::DESTROY = sub {}; - *Slic3r::Extruder::DESTROY = sub {}; *Slic3r::ExtrusionLoop::DESTROY = sub {}; *Slic3r::ExtrusionMultiPath::DESTROY = sub {}; *Slic3r::ExtrusionPath::DESTROY = sub {}; @@ -154,7 +153,6 @@ sub thread_cleanup { *Slic3r::GCode::DESTROY = sub {}; *Slic3r::GCode::PlaceholderParser::DESTROY = sub {}; *Slic3r::GCode::Sender::DESTROY = sub {}; - *Slic3r::GCode::Writer::DESTROY = sub {}; *Slic3r::Geometry::BoundingBox::DESTROY = sub {}; *Slic3r::Geometry::BoundingBoxf::DESTROY = sub {}; *Slic3r::Geometry::BoundingBoxf3::DESTROY = sub {}; diff --git a/t/cooling.t b/t/cooling.t index 560af1beb9..29996c7892 100644 --- a/t/cooling.t +++ b/t/cooling.t @@ -2,14 +2,14 @@ use Test::More; use strict; use warnings; -plan tests => 12; +plan tests => 13; BEGIN { use FindBin; use lib "$FindBin::Bin/../lib"; } -use List::Util qw(first); +use List::Util qw(none all); use Slic3r; use Slic3r::Test; @@ -139,21 +139,33 @@ $config->set('disable_fan_first_layers', [ 0 ]); $config->set('slowdown_below_layer_time', [ 10 ]); $config->set('min_print_speed', [ 0 ]); $config->set('start_gcode', ''); + $config->set('first_layer_speed', '100%'); + $config->set('external_perimeter_speed', 99); my $print = Slic3r::Test::init_print('20mm_cube', config => $config); my @layer_times = (0); # in seconds + my %layer_external = (); # z => 1 Slic3r::GCode::Reader->new->parse(my $gcode = Slic3r::Test::gcode($print), sub { my ($self, $cmd, $args, $info) = @_; if ($cmd eq 'G1') { if ($info->{dist_Z}) { push @layer_times, 0; + $layer_external{ $args->{Z} } = 0; } $layer_times[-1] += abs($info->{dist_XY} || $info->{dist_E} || $info->{dist_Z} || 0) / ($args->{F} // $self->F) * 60; + if ($args->{F} && $args->{F} == $config->external_perimeter_speed*60) { + $layer_external{ $self->Z }++; + } } }); - my $all_below = !defined first { $_ > 0 && $_ < $config->slowdown_below_layer_time->[0] } @layer_times; + @layer_times = grep $_, @layer_times; + my $all_below = none { $_ < $config->slowdown_below_layer_time->[0] } @layer_times; ok $all_below, 'slowdown_below_layer_time is honored'; + + # check that all layers have at least one unaltered external perimeter speed + my $external = all { $_ > 0 } values %layer_external; + ok $external, 'slowdown_below_layer_time does not alter external perimeters'; } __END__ diff --git a/xs/MANIFEST b/xs/MANIFEST index 182a0814ac..0285569065 100644 --- a/xs/MANIFEST +++ b/xs/MANIFEST @@ -524,7 +524,6 @@ xsp/Clipper.xsp xsp/Config.xsp xsp/ExPolygon.xsp xsp/ExPolygonCollection.xsp -xsp/Extruder.xsp xsp/ExtrusionEntityCollection.xsp xsp/ExtrusionLoop.xsp xsp/ExtrusionMultiPath.xsp @@ -534,7 +533,6 @@ xsp/Filler.xsp xsp/Flow.xsp xsp/GCode.xsp xsp/GCodeSender.xsp -xsp/GCodeWriter.xsp xsp/Geometry.xsp xsp/GUI.xsp xsp/GUI_3DScene.xsp diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm index c2af3fd73f..e72890e991 100644 --- a/xs/lib/Slic3r/XS.pm +++ b/xs/lib/Slic3r/XS.pm @@ -269,7 +269,6 @@ for my $class (qw( Slic3r::Config::Static Slic3r::ExPolygon Slic3r::ExPolygon::Collection - Slic3r::Extruder Slic3r::ExtrusionLoop Slic3r::ExtrusionMultiPath Slic3r::ExtrusionPath @@ -279,7 +278,6 @@ for my $class (qw( Slic3r::Flow Slic3r::GCode Slic3r::GCode::PlaceholderParser - Slic3r::GCode::Writer Slic3r::Geometry::BoundingBox Slic3r::Geometry::BoundingBoxf Slic3r::Geometry::BoundingBoxf3 diff --git a/xs/src/libslic3r/Extruder.cpp b/xs/src/libslic3r/Extruder.cpp index 19f08d9077..206f9c11ec 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 8569a54c0a..5de1a68173 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 2383c243ca..88966e0446 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(extruder.id, used_filament)); + print.filament_stats.insert(std::pair(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 baf37e9c6a..9509cf6ab1 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 9040a86a97..dcc06b12de 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 ac4ba8a882..da8677e1e9 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 m_object_ids_visited; }; diff --git a/xs/src/libslic3r/GCodeWriter.cpp b/xs/src/libslic3r/GCodeWriter.cpp index 6612ead35a..4d92410ee6 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 &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(&*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(&*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 2fa1a899de..02fca4129f 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 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 &extruder_ids); + const std::vector& extruders() const { return m_extruders; } std::vector extruder_ids() const { std::vector 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 m_extruders; std::string m_extrusion_axis; bool m_single_extruder_multi_material; Extruder* m_extruder; diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index 59fb0f3905..17c3435892 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -5,7 +5,6 @@ namespace Slic3r { REGISTER_CLASS(ExPolygon, "ExPolygon"); REGISTER_CLASS(ExPolygonCollection, "ExPolygon::Collection"); -REGISTER_CLASS(Extruder, "Extruder"); REGISTER_CLASS(ExtrusionMultiPath, "ExtrusionMultiPath"); REGISTER_CLASS(ExtrusionPath, "ExtrusionPath"); REGISTER_CLASS(ExtrusionLoop, "ExtrusionLoop"); @@ -17,7 +16,6 @@ REGISTER_CLASS(Flow, "Flow"); REGISTER_CLASS(CoolingBuffer, "GCode::CoolingBuffer"); REGISTER_CLASS(GCode, "GCode"); REGISTER_CLASS(GCodeSender, "GCode::Sender"); -REGISTER_CLASS(GCodeWriter, "GCode::Writer"); REGISTER_CLASS(Layer, "Layer"); REGISTER_CLASS(SupportLayer, "Layer::Support"); REGISTER_CLASS(LayerRegion, "Layer::Region"); diff --git a/xs/xsp/Extruder.xsp b/xs/xsp/Extruder.xsp deleted file mode 100644 index 2031b01459..0000000000 --- a/xs/xsp/Extruder.xsp +++ /dev/null @@ -1,52 +0,0 @@ -%module{Slic3r::XS}; - -%{ -#include -#include "libslic3r/Extruder.hpp" -%} - -%name{Slic3r::Extruder} class Extruder { - Extruder(unsigned int id, StaticPrintConfig* config) - %code%{ RETVAL = new Extruder (id, dynamic_cast(config)); %}; - ~Extruder(); - void reset(); - double extrude(double dE); - double retract(double length, double restart_extra); - double unretract(); - double e_per_mm(double mm3_per_mm); - double extruded_volume(); - double used_filament(); - - unsigned int id() - %code%{ RETVAL = THIS->id; %}; - - double E() - %code%{ RETVAL = THIS->E; %}; - double set_E(double val) - %code%{ RETVAL = THIS->E = val; %}; - double absolute_E() - %code%{ RETVAL = THIS->absolute_E; %}; - double set_absolute_E(double val) - %code%{ RETVAL = THIS->absolute_E = val; %}; - double retracted() - %code%{ RETVAL = THIS->retracted; %}; - double set_retracted(double val) - %code%{ RETVAL = THIS->retracted = val; %}; - double restart_extra() - %code%{ RETVAL = THIS->restart_extra; %}; - double set_restart_extra(double val) - %code%{ RETVAL = THIS->restart_extra = val; %}; - double e_per_mm3() - %code%{ RETVAL = THIS->e_per_mm3; %}; - - double filament_diameter(); - double filament_density(); - double filament_cost(); - double extrusion_multiplier(); - double retract_length(); - double retract_lift(); - int retract_speed(); - double retract_restart_extra(); - double retract_length_toolchange(); - double retract_restart_extra_toolchange(); -}; diff --git a/xs/xsp/GCodeWriter.xsp b/xs/xsp/GCodeWriter.xsp deleted file mode 100644 index 094dcf7659..0000000000 --- a/xs/xsp/GCodeWriter.xsp +++ /dev/null @@ -1,64 +0,0 @@ -%module{Slic3r::XS}; - -%{ -#include -#include "libslic3r/GCodeWriter.hpp" -%} - -%name{Slic3r::GCode::Writer} class GCodeWriter { - GCodeWriter(); - ~GCodeWriter(); - - Ref config() - %code%{ RETVAL = &THIS->config; %}; - bool multiple_extruders() - %code{% RETVAL = THIS->multiple_extruders; %}; - Ref extruder(); - std::string extrusion_axis(); - void apply_print_config(PrintConfig* print_config) - %code{% THIS->apply_print_config(*print_config); %}; - void set_extruders(std::vector extruder_ids); - std::string preamble(); - std::string postamble(); - std::string set_temperature(unsigned int temperature, bool wait = false, int tool = -1); - std::string set_bed_temperature(unsigned int temperature, bool wait = false); - std::string set_fan(unsigned int speed, bool dont_save = false); - std::string set_acceleration(unsigned int acceleration); - std::string reset_e(bool force = false); - std::string update_progress(unsigned int num, unsigned int tot, bool allow_100 = false); - bool need_toolchange(unsigned int extruder_id); - std::string set_extruder(unsigned int extruder_id); - std::string toolchange(unsigned int extruder_id); - std::string set_speed(double F, std::string comment = std::string()); - std::string travel_to_xy(Pointf* point, std::string comment = std::string()) - %code{% RETVAL = THIS->travel_to_xy(*point, comment); %}; - std::string travel_to_xyz(Pointf3* point, std::string comment = std::string()) - %code{% RETVAL = THIS->travel_to_xyz(*point, comment); %}; - std::string travel_to_z(double z, std::string comment = std::string()); - bool will_move_z(double z); - std::string extrude_to_xy(Pointf* point, double dE, std::string comment = std::string()) - %code{% RETVAL = THIS->extrude_to_xy(*point, dE, comment); %}; - std::string extrude_to_xyz(Pointf3* point, double dE, std::string comment = std::string()) - %code{% RETVAL = THIS->extrude_to_xyz(*point, dE, comment); %}; - std::string retract(); - std::string retract_for_toolchange(); - std::string unretract(); - std::string lift(); - std::string unlift(); - Clone get_position() const; -%{ - -SV* -GCodeWriter::extruders() - CODE: - AV* av = newAV(); - av_fill(av, THIS->extruders.size()-1); - int i = 0; - for (const Extruder &extruder : THIS->extruders) - av_store(av, i++, perl_to_SV_ref(const_cast(extruder))); - RETVAL = newRV_noinc((SV*)av); - OUTPUT: - RETVAL - -%} -}; diff --git a/xs/xsp/my.map b/xs/xsp/my.map index 8fd011c7d2..31d6c3eea5 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -138,10 +138,6 @@ Clone O_OBJECT_SLIC3R_T SurfaceCollection* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T -Extruder* O_OBJECT_SLIC3R -Ref O_OBJECT_SLIC3R_T -Clone O_OBJECT_SLIC3R_T - Model* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T Clone O_OBJECT_SLIC3R_T @@ -201,10 +197,6 @@ GCodeSender* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T Clone O_OBJECT_SLIC3R_T -GCodeWriter* O_OBJECT_SLIC3R -Ref O_OBJECT_SLIC3R_T -Clone O_OBJECT_SLIC3R_T - BridgeDetector* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T Clone O_OBJECT_SLIC3R_T diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index 129ca8eb98..d536210bb3 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -99,9 +99,6 @@ %typemap{MotionPlanner*}; %typemap{Ref}{simple}; %typemap{Clone}{simple}; -%typemap{GCodeWriter*}; -%typemap{Ref}{simple}; -%typemap{Clone}{simple}; %typemap{GCodeSender*}; %typemap{Ref}{simple}; %typemap{Clone}{simple}; @@ -169,9 +166,6 @@ %typemap{Polygons*}; %typemap{TriangleMesh*}; %typemap{TriangleMeshPtrs}; -%typemap{Extruder*}; -%typemap{Ref}{simple}; -%typemap{Clone}{simple}; %typemap{Model*}; %typemap{Ref}{simple}; %typemap{Clone}{simple};