From bd3976ff9450214c32f517a2a2cdbaa335da3896 Mon Sep 17 00:00:00 2001 From: rongith Date: Fri, 20 Mar 2020 03:14:52 +0100 Subject: [PATCH] Layer time preview merged commit: - One decimal for time less than 1minutes. - Geometric scale for layer time - Handle 0.0 min value special case for geometric scale. --- src/libslic3r/GCode.cpp | 15 ++--- src/libslic3r/GCode/Analyzer.cpp | 45 +++++++++++--- src/libslic3r/GCode/Analyzer.hpp | 13 +++-- src/libslic3r/GCode/PreviewData.cpp | 87 +++++++++++++++++++++++++--- src/libslic3r/GCode/PreviewData.hpp | 14 ++++- src/libslic3r/GCodeTimeEstimator.cpp | 44 ++++++++++++++ src/libslic3r/GCodeTimeEstimator.hpp | 15 +++++ src/slic3r/GUI/GLCanvas3D.cpp | 8 +++ src/slic3r/GUI/GUI_Preview.cpp | 1 + 9 files changed, 213 insertions(+), 29 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 98576f965..8bb921406 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -800,6 +800,14 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_ GCodeTimeEstimator::post_process(path_tmp, 60.0f, remaining_times_enabled ? &normal_data : nullptr, (remaining_times_enabled && m_silent_time_estimator_enabled) ? &silent_data : nullptr); + // starts analyzer calculations + if (m_enable_analyzer) { + BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data" << log_memory_info(); + GCodeTimeEstimator* time_estimator = &m_normal_time_estimator; + m_analyzer.calc_gcode_preview_data(*preview_data, *time_estimator, [print]() { print->throw_if_canceled(); }); + m_analyzer.reset(); + } + if (remaining_times_enabled) { m_normal_time_estimator.reset(); @@ -807,13 +815,6 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_ m_silent_time_estimator.reset(); } - // starts analyzer calculations - if (m_enable_analyzer) { - BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data" << log_memory_info(); - m_analyzer.calc_gcode_preview_data(*preview_data, [print]() { print->throw_if_canceled(); }); - m_analyzer.reset(); - } - if (rename_file(path_tmp, path)) throw std::runtime_error( std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + path + '\n' + diff --git a/src/libslic3r/GCode/Analyzer.cpp b/src/libslic3r/GCode/Analyzer.cpp index 9e05fa00f..c7e33e82c 100644 --- a/src/libslic3r/GCode/Analyzer.cpp +++ b/src/libslic3r/GCode/Analyzer.cpp @@ -11,6 +11,7 @@ #include "Analyzer.hpp" #include "PreviewData.hpp" +#include "GCodeTimeEstimator.hpp" static const std::string AXIS_STR = "XYZE"; static const float MMMIN_TO_MMSEC = 1.0f / 60.0f; @@ -21,6 +22,7 @@ static const unsigned int DEFAULT_COLOR_PRINT_ID = 0; static const Slic3r::Vec3d DEFAULT_START_POSITION = Slic3r::Vec3d(0.0f, 0.0f, 0.0f); static const float DEFAULT_START_EXTRUSION = 0.0f; static const float DEFAULT_FAN_SPEED = 0.0f; +static const float DEFAULT_LAYER_TIME = 0.0f; namespace Slic3r { @@ -45,11 +47,12 @@ GCodeAnalyzer::Metadata::Metadata() , height(GCodeAnalyzer::Default_Height) , feedrate(DEFAULT_FEEDRATE) , fan_speed(DEFAULT_FAN_SPEED) + , layer_time(DEFAULT_LAYER_TIME) , cp_color_id(DEFAULT_COLOR_PRINT_ID) { } -GCodeAnalyzer::Metadata::Metadata(ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, float fan_speed, unsigned int cp_color_id/* = 0*/) +GCodeAnalyzer::Metadata::Metadata(ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, float fan_speed, float layer_time, unsigned int cp_color_id/* = 0*/) : extrusion_role(extrusion_role) , extruder_id(extruder_id) , mm3_per_mm(mm3_per_mm) @@ -57,6 +60,7 @@ GCodeAnalyzer::Metadata::Metadata(ExtrusionRole extrusion_role, unsigned int ext , height(height) , feedrate(feedrate) , fan_speed(fan_speed) + , layer_time(layer_time) , cp_color_id(cp_color_id) { } @@ -84,15 +88,18 @@ bool GCodeAnalyzer::Metadata::operator != (const GCodeAnalyzer::Metadata& other) if (fan_speed != other.fan_speed) return true; + if (layer_time != other.layer_time) + return true; + if (cp_color_id != other.cp_color_id) return true; return false; } -GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder, float fan_speed, unsigned int cp_color_id/* = 0*/) +GCodeAnalyzer::GCodeMove::GCodeMove(GCodeMove::EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder, float fan_speed, float layer_time, unsigned int cp_color_id/* = 0*/) : type(type) - , data(extrusion_role, extruder_id, mm3_per_mm, width, height, feedrate, fan_speed, cp_color_id) + , data(extrusion_role, extruder_id, mm3_per_mm, width, height, feedrate, fan_speed, layer_time, cp_color_id) , start_position(start_position) , end_position(end_position) , delta_extruder(delta_extruder) @@ -130,6 +137,7 @@ void GCodeAnalyzer::reset() _set_start_position(DEFAULT_START_POSITION); _set_start_extrusion(DEFAULT_START_EXTRUSION); _set_fan_speed(DEFAULT_FAN_SPEED); + _set_layer_time(DEFAULT_LAYER_TIME); _reset_axes_position(); _reset_axes_origin(); _reset_cached_position(); @@ -151,13 +159,13 @@ const std::string& GCodeAnalyzer::process_gcode(const std::string& gcode) return m_process_output; } -void GCodeAnalyzer::calc_gcode_preview_data(GCodePreviewData& preview_data, std::function cancel_callback) +void GCodeAnalyzer::calc_gcode_preview_data(GCodePreviewData& preview_data, GCodeTimeEstimator& time_estimator, std::function cancel_callback) { // resets preview data preview_data.reset(); // calculates extrusion layers - _calc_gcode_preview_extrusion_layers(preview_data, cancel_callback); + _calc_gcode_preview_extrusion_layers(preview_data, time_estimator, cancel_callback); // calculates travel _calc_gcode_preview_travel(preview_data, cancel_callback); @@ -847,6 +855,16 @@ float GCodeAnalyzer::_get_fan_speed() const return m_state.data.fan_speed; } +void GCodeAnalyzer::_set_layer_time(float layer_time_sec) +{ + m_state.data.layer_time = layer_time_sec; +} + +float GCodeAnalyzer::_get_layer_time() const +{ + return m_state.data.layer_time; +} + void GCodeAnalyzer::_set_axis_position(EAxis axis, float position) { m_state.position[axis] = position; @@ -934,7 +952,7 @@ void GCodeAnalyzer::_store_move(GCodeAnalyzer::GCodeMove::EType type) Vec3d start_position = _get_start_position() + extruder_offset; Vec3d end_position = _get_end_position() + extruder_offset; - it->second.emplace_back(type, _get_extrusion_role(), extruder_id, _get_mm3_per_mm(), _get_width(), _get_height(), _get_feedrate(), start_position, end_position, _get_delta_extrusion(), _get_fan_speed(), _get_cp_color_id()); + it->second.emplace_back(type, _get_extrusion_role(), extruder_id, _get_mm3_per_mm(), _get_width(), _get_height(), _get_feedrate(), start_position, end_position, _get_delta_extrusion(), _get_fan_speed(), _get_layer_time(), _get_cp_color_id()); } bool GCodeAnalyzer::_is_valid_extrusion_role(int value) const @@ -942,7 +960,7 @@ bool GCodeAnalyzer::_is_valid_extrusion_role(int value) const return ((int)erNone <= value) && (value <= (int)erMixed); } -void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, std::function cancel_callback) +void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, GCodeTimeEstimator& time_estimator, std::function cancel_callback) { struct Helper { @@ -978,6 +996,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ path.extruder_id = data.extruder_id; path.cp_color_id = data.cp_color_id; path.fan_speed = data.fan_speed; + path.layer_time = data.layer_time; } } }; @@ -996,11 +1015,21 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ GCodePreviewData::MultiRange feedrate_range; GCodePreviewData::Range volumetric_rate_range; GCodePreviewData::Range fan_speed_range; + GCodePreviewData::Range layer_time_range; // to avoid to call the callback too often unsigned int cancel_callback_threshold = (unsigned int)std::max((int)extrude_moves->second.size() / 25, 1); unsigned int cancel_callback_curr = 0; + time_estimator.calculate_layer_time(); + for (GCodeMove& move : extrude_moves->second) + { + z = (float)move.start_position.z(); + float layer_timet = time_estimator.get_layer_time(z); + move.data.layer_time = layer_timet; + } + time_estimator.reset_layers(); + // constructs the polylines while traversing the moves for (const GCodeMove& move : extrude_moves->second) { @@ -1031,6 +1060,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ feedrate_range.update_from(move.data.feedrate, GCodePreviewData::FeedrateKind::EXTRUSION); volumetric_rate_range.update_from(volumetric_rate); fan_speed_range.update_from(move.data.fan_speed); + layer_time_range.update_from(move.data.layer_time); } else // append end vertex of the move to current polyline @@ -1050,6 +1080,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ preview_data.ranges.feedrate.update_from(feedrate_range); preview_data.ranges.volumetric_rate.update_from(volumetric_rate_range); preview_data.ranges.fan_speed.update_from(fan_speed_range); + preview_data.ranges.layer_time.update_from(layer_time_range); // we need to sort the layers by their z as they can be shuffled in case of sequential prints std::sort(preview_data.extrusion.layers.begin(), preview_data.extrusion.layers.end(), [](const GCodePreviewData::Extrusion::Layer& l1, const GCodePreviewData::Extrusion::Layer& l2)->bool { return l1.z < l2.z; }); diff --git a/src/libslic3r/GCode/Analyzer.hpp b/src/libslic3r/GCode/Analyzer.hpp index 88421d08e..08cf312cc 100644 --- a/src/libslic3r/GCode/Analyzer.hpp +++ b/src/libslic3r/GCode/Analyzer.hpp @@ -12,6 +12,7 @@ namespace Slic3r { class GCodePreviewData; +class GCodeTimeEstimator; class GCodeAnalyzer { @@ -59,10 +60,11 @@ public: float height; // mm float feedrate; // mm/s float fan_speed; // percentage + float layer_time; //s unsigned int cp_color_id; Metadata(); - Metadata(ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, float fan_speed, unsigned int cp_color_id = 0); + Metadata(ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, float fan_speed, float layer_time, unsigned int cp_color_id = 0); bool operator != (const Metadata& other) const; }; @@ -86,7 +88,7 @@ public: Vec3d end_position; float delta_extruder; - GCodeMove(EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder, float fan_speed, unsigned int cp_color_id = 0); + GCodeMove(EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder, float fan_speed, float layer_time, unsigned int cp_color_id = 0); GCodeMove(EType type, const Metadata& data, const Vec3d& start_position, const Vec3d& end_position, float delta_extruder); }; @@ -141,7 +143,7 @@ public: // Calculates all data needed for gcode visualization // throws CanceledException through print->throw_if_canceled() (sent by the caller as callback). - void calc_gcode_preview_data(GCodePreviewData& preview_data, std::function cancel_callback = std::function()); + void calc_gcode_preview_data(GCodePreviewData& preview_data, GCodeTimeEstimator& time_estimator, std::function cancel_callback = std::function()); // Return an estimate of the memory consumed by the time estimator. size_t memory_used() const; @@ -262,6 +264,9 @@ private: void _set_fan_speed(float fan_speed_percentage); float _get_fan_speed() const; + void _set_layer_time(float layer_time_sec); + float _get_layer_time() const; + void _set_axis_position(EAxis axis, float position); float _get_axis_position(EAxis axis) const; @@ -295,7 +300,7 @@ private: bool _is_valid_extrusion_role(int value) const; // All the following methods throw CanceledException through print->throw_if_canceled() (sent by the caller as callback). - void _calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, std::function cancel_callback); + void _calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, GCodeTimeEstimator& time_estimator, std::function cancel_callback); void _calc_gcode_preview_travel(GCodePreviewData& preview_data, std::function cancel_callback); void _calc_gcode_preview_retractions(GCodePreviewData& preview_data, std::function cancel_callback); void _calc_gcode_preview_unretractions(GCodePreviewData& preview_data, std::function cancel_callback); diff --git a/src/libslic3r/GCode/PreviewData.cpp b/src/libslic3r/GCode/PreviewData.cpp index 014efd39d..678fe03a1 100644 --- a/src/libslic3r/GCode/PreviewData.cpp +++ b/src/libslic3r/GCode/PreviewData.cpp @@ -63,16 +63,33 @@ void GCodePreviewData::Range::update_from(const RangeBase& other) max_val = std::max(max_val, other.max()); } -float GCodePreviewData::RangeBase::step_size() const +float GCodePreviewData::RangeBase::step_size(bool geometric_scale) const { - return (max() - min()) / static_cast(range_rainbow_colors.size() - 1); + if (geometric_scale) + { + float min_range = min(); + if (min_range == 0) + min_range = 0.001f; + return (log(max() / min_range) / static_cast(range_rainbow_colors.size() - 1)); + } + else + return (max() - min()) / static_cast(range_rainbow_colors.size() - 1); } -Color GCodePreviewData::RangeBase::get_color_at(float value) const +Color GCodePreviewData::RangeBase::get_color_at(float value, bool geometric_scale) const { // Input value scaled to the color range - float step = step_size(); - const float global_t = (step != 0.0f) ? std::max(0.0f, value - min()) / step_size() : 0.0f; // lower limit of 0.0f + float step = step_size(geometric_scale); + float global_t; + if (geometric_scale) + { + float min_range = min(); + if (min_range == 0) + min_range = 0.001f; + global_t = (step != 0.0f) ? std::max(0.0f, log(value / min_range)) / step : 0.0f; // lower limit of 0.0f + } + else + global_t = (step != 0.0f) ? std::max(0.0f, value - min()) / step : 0.0f; // lower limit of 0.0f constexpr std::size_t color_max_idx = range_rainbow_colors.size() - 1; @@ -245,6 +262,8 @@ void GCodePreviewData::reset() ranges.feedrate.reset(); ranges.fan_speed.reset(); ranges.volumetric_rate.reset(); + ranges.fan_speed.reset(); + ranges.layer_time.reset(); extrusion.layers.clear(); travel.polylines.clear(); retraction.positions.clear(); @@ -281,6 +300,16 @@ Color GCodePreviewData::get_fan_speed_color(float fan_speed) const return ranges.fan_speed.get_color_at(fan_speed); } +Color GCodePreviewData::get_layer_time_color(float layer_time) const +{ + return ranges.layer_time.get_color_at(layer_time); +} + +Color GCodePreviewData::get_layer_time_log_color(float layer_time) const +{ + return ranges.layer_time.get_color_at(layer_time, true); +} + Color GCodePreviewData::get_volumetric_rate_color(float rate) const { return ranges.volumetric_rate.get_color_at(rate); @@ -354,6 +383,10 @@ std::string GCodePreviewData::get_legend_title() const return L("Speed (mm/s)"); case Extrusion::FanSpeed: return L("Fan Speed (%)"); + case Extrusion::LayerTime: + return L("Layer Time"); + case Extrusion::LayerTimeLog: + return L("Layer Time (log)"); case Extrusion::VolumetricRate: return L("Volumetric flow rate (mm³/s)"); case Extrusion::Tool: @@ -374,11 +407,23 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std:: { struct Helper { - static void FillListFromRange(LegendItemsList& list, const RangeBase& range, unsigned int decimals, float scale_factor) + static std::string _get_time_ms(float time_in_secs) + { + int minutes = (int)(time_in_secs / 60.0f); + time_in_secs -= (float)minutes * 60.0f; + char buffer[64]; + if (minutes > 0) + ::sprintf(buffer, "%dm %ds", minutes, (int)time_in_secs); + else + ::sprintf(buffer, "%.*fs", 1, time_in_secs); + return buffer; + } + + static void FillListFromRange(LegendItemsList& list, const RangeBase& range, unsigned int decimals, float scale_factor, bool istime = false, bool geometric_scale = false) { list.reserve(range_rainbow_colors.size()); - float step = range.step_size(); + float step = range.step_size(geometric_scale); if (step == 0.0f) { char buf[1024]; @@ -390,7 +435,23 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std:: for (int i = static_cast(range_rainbow_colors.size()) - 1; i >= 0; --i) { char buf[1024]; - sprintf(buf, "%.*f", decimals, scale_factor * (range.min() + (float)i * step)); + if (geometric_scale) + { + float min_range = range.min(); + if (min_range == 0) + min_range = 0.001f; + if (istime) + sprintf(buf, "%s", _get_time_ms(scale_factor * exp(log(min_range) + (float)i * step)).c_str()); + else + sprintf(buf, "%.*f", decimals, scale_factor * exp(log(min_range) + (float)i * step)); + } + else + { + if (istime) + sprintf(buf, "%s", _get_time_ms(scale_factor * (range.min() + (float)i * step)).c_str()); + else + sprintf(buf, "%.*f", decimals, scale_factor * (range.min() + (float)i * step)); + } list.emplace_back(buf, range_rainbow_colors[i]); } } @@ -434,6 +495,16 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std:: Helper::FillListFromRange(items, ranges.fan_speed, 0, 1.0f); break; } + case Extrusion::LayerTime: + { + Helper::FillListFromRange(items, ranges.layer_time, 1, 1.0f, true); + break; + } + case Extrusion::LayerTimeLog: + { + Helper::FillListFromRange(items, ranges.layer_time, 1, 1.0f, true, true); + break; + } case Extrusion::VolumetricRate: { Helper::FillListFromRange(items, ranges.volumetric_rate, 3, 1.0f); diff --git a/src/libslic3r/GCode/PreviewData.hpp b/src/libslic3r/GCode/PreviewData.hpp index 0dc6b83fc..f2f8f3a36 100644 --- a/src/libslic3r/GCode/PreviewData.hpp +++ b/src/libslic3r/GCode/PreviewData.hpp @@ -64,10 +64,10 @@ public: virtual float max() const = 0; // Gets the step size using min(), max() and colors - float step_size() const; + float step_size(bool geometric_scale = false) const; // Gets the color at a value using colors, min(), and max() - Color get_color_at(float value) const; + Color get_color_at(float value, bool geometric_scale = false) const; }; // Color mapping converting a float in a range between a min and a max into a smooth rainbow of 10 colors. @@ -201,6 +201,8 @@ public: MultiRange feedrate; // Color mapping by fan speed. Range fan_speed; + // Color mapping by layer time. + Range layer_time; // Color mapping by volumetric extrusion rate. Range volumetric_rate; }; @@ -224,6 +226,8 @@ public: Width, Feedrate, FanSpeed, + LayerTime, + LayerTimeLog, VolumetricRate, Tool, Filament, @@ -254,7 +258,9 @@ public: uint32_t cp_color_id; // Fan speed for the extrusion, used for visualization purposes. float fan_speed; - }; + // Layer time for the extrusion, used for visualization purposes. + float layer_time; + }; using Paths = std::vector; struct Layer @@ -379,6 +385,8 @@ public: Color get_width_color(float width) const; Color get_feedrate_color(float feedrate) const; Color get_fan_speed_color(float fan_speed) const; + Color get_layer_time_color(float layer_time) const; + Color get_layer_time_log_color(float layer_time) const; Color get_volumetric_rate_color(float rate) const; void set_extrusion_role_color(const std::string& role_name, float red, float green, float blue, float alpha); diff --git a/src/libslic3r/GCodeTimeEstimator.cpp b/src/libslic3r/GCodeTimeEstimator.cpp index 14265222e..17ba4abc1 100644 --- a/src/libslic3r/GCodeTimeEstimator.cpp +++ b/src/libslic3r/GCodeTimeEstimator.cpp @@ -854,6 +854,7 @@ namespace Slic3r { block_time += block.deceleration_time(); m_time += block_time; block.elapsed_time = m_time; + block.time = block_time; #if ENABLE_MOVE_STATS MovesStatsMap::iterator it = _moves_stats.find(block.move_type); @@ -1031,6 +1032,7 @@ namespace Slic3r { // updates axes positions from line float new_pos[Num_Axis]; + long raw_axis_absolute_position; for (unsigned char a = X; a < Num_Axis; ++a) { new_pos[a] = axis_absolute_position((EAxis)a, line); @@ -1050,6 +1052,7 @@ namespace Slic3r { block.delta_pos[a] = new_pos[a] - get_axis_position((EAxis)a); max_abs_delta = std::max(max_abs_delta, std::abs(block.delta_pos[a])); } + block.z = new_pos[Z]; // is it a move ? if (max_abs_delta == 0.0f) @@ -1688,6 +1691,47 @@ namespace Slic3r { return std::to_string((int)(::roundf(time_in_secs / 60.0f))); } + void GCodeTimeEstimator::reset_layers() + { + m_layers.clear(); + } + + void GCodeTimeEstimator::calculate_layer_time() + { + for (int i = 0; i < (int)m_blocks.size(); ++i) + { + if (m_blocks[i].delta_pos[Z] == 0) + { + int j = 0; + bool layer_found = false; + while (j < (int)m_layers.size()) + { + if (m_blocks[i].z == m_layers[j].z) { + m_layers[j].time += m_blocks[i].time; + layer_found = true; + } + j++; + } + if (!layer_found) { + m_layers.push_back({ m_blocks[i].z, m_blocks[i].time }); + } + } + } + } + + float GCodeTimeEstimator::get_layer_time(float z) + { + int j = 0; + while (j < (int)m_layers.size()) + { + if (z == m_layers[j].z) { + return m_layers[j].time; + } + j++; + } + return 0; + } + #if ENABLE_MOVE_STATS void GCodeTimeEstimator::_log_moves_stats() const { diff --git a/src/libslic3r/GCodeTimeEstimator.hpp b/src/libslic3r/GCodeTimeEstimator.hpp index 3909eabb3..feaf3fbee 100644 --- a/src/libslic3r/GCodeTimeEstimator.hpp +++ b/src/libslic3r/GCodeTimeEstimator.hpp @@ -154,6 +154,7 @@ namespace Slic3r { Flags flags; float delta_pos[Num_Axis]; // mm + float z; float acceleration; // mm/s^2 float max_entry_speed; // mm/s float safe_feedrate; // mm/s @@ -161,6 +162,7 @@ namespace Slic3r { FeedrateProfile feedrate; Trapezoid trapezoid; float elapsed_time; + float time; Block(); @@ -204,6 +206,14 @@ namespace Slic3r { typedef std::vector BlocksList; + struct Layer + { + float z; + float time; + }; + + typedef std::vector LayersList; + #if ENABLE_MOVE_STATS struct MoveStats { @@ -236,6 +246,7 @@ namespace Slic3r { Feedrates m_curr; Feedrates m_prev; BlocksList m_blocks; + LayersList m_layers; // Map between g1 line id and blocks id, used to speed up export of remaining times G1LineIdToBlockIdMap m_g1_line_ids; // Index of the last block already st_synchronized @@ -354,6 +365,10 @@ namespace Slic3r { void set_additional_time(float timeSec); float get_additional_time() const; + void calculate_layer_time(); + float get_layer_time(float z); + void reset_layers(); + void set_default(); // Call this method before to start adding lines using add_gcode_line() when reusing an instance of GCodeTimeEstimator diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 2e9599213..9985577cc 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -6205,6 +6205,10 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat return path.feedrate; case GCodePreviewData::Extrusion::FanSpeed: return path.fan_speed; + case GCodePreviewData::Extrusion::LayerTime: + return path.layer_time; + case GCodePreviewData::Extrusion::LayerTimeLog: + return path.layer_time; case GCodePreviewData::Extrusion::VolumetricRate: return path.feedrate * (float)path.mm3_per_mm; case GCodePreviewData::Extrusion::Tool: @@ -6233,6 +6237,10 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat return data.get_feedrate_color(value); case GCodePreviewData::Extrusion::FanSpeed: return data.get_fan_speed_color(value); + case GCodePreviewData::Extrusion::LayerTime: + return data.get_layer_time_color(value); + case GCodePreviewData::Extrusion::LayerTimeLog: + return data.get_layer_time_log_color(value); case GCodePreviewData::Extrusion::VolumetricRate: return data.get_volumetric_rate_color(value); case GCodePreviewData::Extrusion::Tool: diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 4491cb755..0054a5959 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -242,6 +242,7 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view m_choice_view_type->Append(_(L("Width"))); m_choice_view_type->Append(_(L("Speed"))); m_choice_view_type->Append(_(L(width_screen == tiny ? "Fan" : "Fan speed"))); + m_choice_view_type->Append(_(L(width_screen == tiny ?"time":"Layer time"))); m_choice_view_type->Append(_(L(width_screen == tiny ? "Vol. flow" :"Volumetric flow rate"))); m_choice_view_type->Append(_(L("Tool"))); m_choice_view_type->Append(_(L("Filament")));