mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-18 02:35:57 +08:00
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.
This commit is contained in:
parent
319d0552ed
commit
bd3976ff94
@ -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,
|
GCodeTimeEstimator::post_process(path_tmp, 60.0f, remaining_times_enabled ? &normal_data : nullptr,
|
||||||
(remaining_times_enabled && m_silent_time_estimator_enabled) ? &silent_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)
|
if (remaining_times_enabled)
|
||||||
{
|
{
|
||||||
m_normal_time_estimator.reset();
|
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();
|
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))
|
if (rename_file(path_tmp, path))
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + path + '\n' +
|
std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + path + '\n' +
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "Analyzer.hpp"
|
#include "Analyzer.hpp"
|
||||||
#include "PreviewData.hpp"
|
#include "PreviewData.hpp"
|
||||||
|
#include "GCodeTimeEstimator.hpp"
|
||||||
|
|
||||||
static const std::string AXIS_STR = "XYZE";
|
static const std::string AXIS_STR = "XYZE";
|
||||||
static const float MMMIN_TO_MMSEC = 1.0f / 60.0f;
|
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 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_START_EXTRUSION = 0.0f;
|
||||||
static const float DEFAULT_FAN_SPEED = 0.0f;
|
static const float DEFAULT_FAN_SPEED = 0.0f;
|
||||||
|
static const float DEFAULT_LAYER_TIME = 0.0f;
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
@ -45,11 +47,12 @@ GCodeAnalyzer::Metadata::Metadata()
|
|||||||
, height(GCodeAnalyzer::Default_Height)
|
, height(GCodeAnalyzer::Default_Height)
|
||||||
, feedrate(DEFAULT_FEEDRATE)
|
, feedrate(DEFAULT_FEEDRATE)
|
||||||
, fan_speed(DEFAULT_FAN_SPEED)
|
, fan_speed(DEFAULT_FAN_SPEED)
|
||||||
|
, layer_time(DEFAULT_LAYER_TIME)
|
||||||
, cp_color_id(DEFAULT_COLOR_PRINT_ID)
|
, 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)
|
: extrusion_role(extrusion_role)
|
||||||
, extruder_id(extruder_id)
|
, extruder_id(extruder_id)
|
||||||
, mm3_per_mm(mm3_per_mm)
|
, mm3_per_mm(mm3_per_mm)
|
||||||
@ -57,6 +60,7 @@ GCodeAnalyzer::Metadata::Metadata(ExtrusionRole extrusion_role, unsigned int ext
|
|||||||
, height(height)
|
, height(height)
|
||||||
, feedrate(feedrate)
|
, feedrate(feedrate)
|
||||||
, fan_speed(fan_speed)
|
, fan_speed(fan_speed)
|
||||||
|
, layer_time(layer_time)
|
||||||
, cp_color_id(cp_color_id)
|
, cp_color_id(cp_color_id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -84,15 +88,18 @@ bool GCodeAnalyzer::Metadata::operator != (const GCodeAnalyzer::Metadata& other)
|
|||||||
if (fan_speed != other.fan_speed)
|
if (fan_speed != other.fan_speed)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (layer_time != other.layer_time)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (cp_color_id != other.cp_color_id)
|
if (cp_color_id != other.cp_color_id)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
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)
|
: 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)
|
, start_position(start_position)
|
||||||
, end_position(end_position)
|
, end_position(end_position)
|
||||||
, delta_extruder(delta_extruder)
|
, delta_extruder(delta_extruder)
|
||||||
@ -130,6 +137,7 @@ void GCodeAnalyzer::reset()
|
|||||||
_set_start_position(DEFAULT_START_POSITION);
|
_set_start_position(DEFAULT_START_POSITION);
|
||||||
_set_start_extrusion(DEFAULT_START_EXTRUSION);
|
_set_start_extrusion(DEFAULT_START_EXTRUSION);
|
||||||
_set_fan_speed(DEFAULT_FAN_SPEED);
|
_set_fan_speed(DEFAULT_FAN_SPEED);
|
||||||
|
_set_layer_time(DEFAULT_LAYER_TIME);
|
||||||
_reset_axes_position();
|
_reset_axes_position();
|
||||||
_reset_axes_origin();
|
_reset_axes_origin();
|
||||||
_reset_cached_position();
|
_reset_cached_position();
|
||||||
@ -151,13 +159,13 @@ const std::string& GCodeAnalyzer::process_gcode(const std::string& gcode)
|
|||||||
return m_process_output;
|
return m_process_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeAnalyzer::calc_gcode_preview_data(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
void GCodeAnalyzer::calc_gcode_preview_data(GCodePreviewData& preview_data, GCodeTimeEstimator& time_estimator, std::function<void()> cancel_callback)
|
||||||
{
|
{
|
||||||
// resets preview data
|
// resets preview data
|
||||||
preview_data.reset();
|
preview_data.reset();
|
||||||
|
|
||||||
// calculates extrusion layers
|
// 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
|
// calculates travel
|
||||||
_calc_gcode_preview_travel(preview_data, cancel_callback);
|
_calc_gcode_preview_travel(preview_data, cancel_callback);
|
||||||
@ -847,6 +855,16 @@ float GCodeAnalyzer::_get_fan_speed() const
|
|||||||
return m_state.data.fan_speed;
|
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)
|
void GCodeAnalyzer::_set_axis_position(EAxis axis, float position)
|
||||||
{
|
{
|
||||||
m_state.position[axis] = 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 start_position = _get_start_position() + extruder_offset;
|
||||||
Vec3d end_position = _get_end_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
|
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);
|
return ((int)erNone <= value) && (value <= (int)erMixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, GCodeTimeEstimator& time_estimator, std::function<void()> cancel_callback)
|
||||||
{
|
{
|
||||||
struct Helper
|
struct Helper
|
||||||
{
|
{
|
||||||
@ -978,6 +996,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
|
|||||||
path.extruder_id = data.extruder_id;
|
path.extruder_id = data.extruder_id;
|
||||||
path.cp_color_id = data.cp_color_id;
|
path.cp_color_id = data.cp_color_id;
|
||||||
path.fan_speed = data.fan_speed;
|
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<GCodePreviewData::FeedrateKind> feedrate_range;
|
GCodePreviewData::MultiRange<GCodePreviewData::FeedrateKind> feedrate_range;
|
||||||
GCodePreviewData::Range volumetric_rate_range;
|
GCodePreviewData::Range volumetric_rate_range;
|
||||||
GCodePreviewData::Range fan_speed_range;
|
GCodePreviewData::Range fan_speed_range;
|
||||||
|
GCodePreviewData::Range layer_time_range;
|
||||||
|
|
||||||
// to avoid to call the callback too often
|
// 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_threshold = (unsigned int)std::max((int)extrude_moves->second.size() / 25, 1);
|
||||||
unsigned int cancel_callback_curr = 0;
|
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
|
// constructs the polylines while traversing the moves
|
||||||
for (const GCodeMove& move : extrude_moves->second)
|
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);
|
feedrate_range.update_from(move.data.feedrate, GCodePreviewData::FeedrateKind::EXTRUSION);
|
||||||
volumetric_rate_range.update_from(volumetric_rate);
|
volumetric_rate_range.update_from(volumetric_rate);
|
||||||
fan_speed_range.update_from(move.data.fan_speed);
|
fan_speed_range.update_from(move.data.fan_speed);
|
||||||
|
layer_time_range.update_from(move.data.layer_time);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// append end vertex of the move to current polyline
|
// 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.feedrate.update_from(feedrate_range);
|
||||||
preview_data.ranges.volumetric_rate.update_from(volumetric_rate_range);
|
preview_data.ranges.volumetric_rate.update_from(volumetric_rate_range);
|
||||||
preview_data.ranges.fan_speed.update_from(fan_speed_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
|
// 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; });
|
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; });
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
class GCodePreviewData;
|
class GCodePreviewData;
|
||||||
|
class GCodeTimeEstimator;
|
||||||
|
|
||||||
class GCodeAnalyzer
|
class GCodeAnalyzer
|
||||||
{
|
{
|
||||||
@ -59,10 +60,11 @@ public:
|
|||||||
float height; // mm
|
float height; // mm
|
||||||
float feedrate; // mm/s
|
float feedrate; // mm/s
|
||||||
float fan_speed; // percentage
|
float fan_speed; // percentage
|
||||||
|
float layer_time; //s
|
||||||
unsigned int cp_color_id;
|
unsigned int cp_color_id;
|
||||||
|
|
||||||
Metadata();
|
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;
|
bool operator != (const Metadata& other) const;
|
||||||
};
|
};
|
||||||
@ -86,7 +88,7 @@ public:
|
|||||||
Vec3d end_position;
|
Vec3d end_position;
|
||||||
float delta_extruder;
|
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);
|
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
|
// Calculates all data needed for gcode visualization
|
||||||
// throws CanceledException through print->throw_if_canceled() (sent by the caller as callback).
|
// throws CanceledException through print->throw_if_canceled() (sent by the caller as callback).
|
||||||
void calc_gcode_preview_data(GCodePreviewData& preview_data, std::function<void()> cancel_callback = std::function<void()>());
|
void calc_gcode_preview_data(GCodePreviewData& preview_data, GCodeTimeEstimator& time_estimator, std::function<void()> cancel_callback = std::function<void()>());
|
||||||
|
|
||||||
// Return an estimate of the memory consumed by the time estimator.
|
// Return an estimate of the memory consumed by the time estimator.
|
||||||
size_t memory_used() const;
|
size_t memory_used() const;
|
||||||
@ -262,6 +264,9 @@ private:
|
|||||||
void _set_fan_speed(float fan_speed_percentage);
|
void _set_fan_speed(float fan_speed_percentage);
|
||||||
float _get_fan_speed() const;
|
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);
|
void _set_axis_position(EAxis axis, float position);
|
||||||
float _get_axis_position(EAxis axis) const;
|
float _get_axis_position(EAxis axis) const;
|
||||||
|
|
||||||
@ -295,7 +300,7 @@ private:
|
|||||||
bool _is_valid_extrusion_role(int value) const;
|
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).
|
// 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<void()> cancel_callback);
|
void _calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, GCodeTimeEstimator& time_estimator, std::function<void()> cancel_callback);
|
||||||
void _calc_gcode_preview_travel(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
void _calc_gcode_preview_travel(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
||||||
void _calc_gcode_preview_retractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
void _calc_gcode_preview_retractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
||||||
void _calc_gcode_preview_unretractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
void _calc_gcode_preview_unretractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
||||||
|
@ -63,16 +63,33 @@ void GCodePreviewData::Range::update_from(const RangeBase& other)
|
|||||||
max_val = std::max(max_val, other.max());
|
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<float>(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<float>(range_rainbow_colors.size() - 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return (max() - min()) / static_cast<float>(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
|
// Input value scaled to the color range
|
||||||
float step = step_size();
|
float step = step_size(geometric_scale);
|
||||||
const float global_t = (step != 0.0f) ? std::max(0.0f, value - min()) / step_size() : 0.0f; // lower limit of 0.0f
|
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;
|
constexpr std::size_t color_max_idx = range_rainbow_colors.size() - 1;
|
||||||
|
|
||||||
@ -245,6 +262,8 @@ void GCodePreviewData::reset()
|
|||||||
ranges.feedrate.reset();
|
ranges.feedrate.reset();
|
||||||
ranges.fan_speed.reset();
|
ranges.fan_speed.reset();
|
||||||
ranges.volumetric_rate.reset();
|
ranges.volumetric_rate.reset();
|
||||||
|
ranges.fan_speed.reset();
|
||||||
|
ranges.layer_time.reset();
|
||||||
extrusion.layers.clear();
|
extrusion.layers.clear();
|
||||||
travel.polylines.clear();
|
travel.polylines.clear();
|
||||||
retraction.positions.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);
|
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
|
Color GCodePreviewData::get_volumetric_rate_color(float rate) const
|
||||||
{
|
{
|
||||||
return ranges.volumetric_rate.get_color_at(rate);
|
return ranges.volumetric_rate.get_color_at(rate);
|
||||||
@ -354,6 +383,10 @@ std::string GCodePreviewData::get_legend_title() const
|
|||||||
return L("Speed (mm/s)");
|
return L("Speed (mm/s)");
|
||||||
case Extrusion::FanSpeed:
|
case Extrusion::FanSpeed:
|
||||||
return L("Fan Speed (%)");
|
return L("Fan Speed (%)");
|
||||||
|
case Extrusion::LayerTime:
|
||||||
|
return L("Layer Time");
|
||||||
|
case Extrusion::LayerTimeLog:
|
||||||
|
return L("Layer Time (log)");
|
||||||
case Extrusion::VolumetricRate:
|
case Extrusion::VolumetricRate:
|
||||||
return L("Volumetric flow rate (mm³/s)");
|
return L("Volumetric flow rate (mm³/s)");
|
||||||
case Extrusion::Tool:
|
case Extrusion::Tool:
|
||||||
@ -374,11 +407,23 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std::
|
|||||||
{
|
{
|
||||||
struct Helper
|
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());
|
list.reserve(range_rainbow_colors.size());
|
||||||
|
|
||||||
float step = range.step_size();
|
float step = range.step_size(geometric_scale);
|
||||||
if (step == 0.0f)
|
if (step == 0.0f)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
@ -390,7 +435,23 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std::
|
|||||||
for (int i = static_cast<int>(range_rainbow_colors.size()) - 1; i >= 0; --i)
|
for (int i = static_cast<int>(range_rainbow_colors.size()) - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
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]);
|
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);
|
Helper::FillListFromRange(items, ranges.fan_speed, 0, 1.0f);
|
||||||
break;
|
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:
|
case Extrusion::VolumetricRate:
|
||||||
{
|
{
|
||||||
Helper::FillListFromRange(items, ranges.volumetric_rate, 3, 1.0f);
|
Helper::FillListFromRange(items, ranges.volumetric_rate, 3, 1.0f);
|
||||||
|
@ -64,10 +64,10 @@ public:
|
|||||||
virtual float max() const = 0;
|
virtual float max() const = 0;
|
||||||
|
|
||||||
// Gets the step size using min(), max() and colors
|
// 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()
|
// 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.
|
// 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<FeedrateKind> feedrate;
|
MultiRange<FeedrateKind> feedrate;
|
||||||
// Color mapping by fan speed.
|
// Color mapping by fan speed.
|
||||||
Range fan_speed;
|
Range fan_speed;
|
||||||
|
// Color mapping by layer time.
|
||||||
|
Range layer_time;
|
||||||
// Color mapping by volumetric extrusion rate.
|
// Color mapping by volumetric extrusion rate.
|
||||||
Range volumetric_rate;
|
Range volumetric_rate;
|
||||||
};
|
};
|
||||||
@ -224,6 +226,8 @@ public:
|
|||||||
Width,
|
Width,
|
||||||
Feedrate,
|
Feedrate,
|
||||||
FanSpeed,
|
FanSpeed,
|
||||||
|
LayerTime,
|
||||||
|
LayerTimeLog,
|
||||||
VolumetricRate,
|
VolumetricRate,
|
||||||
Tool,
|
Tool,
|
||||||
Filament,
|
Filament,
|
||||||
@ -254,7 +258,9 @@ public:
|
|||||||
uint32_t cp_color_id;
|
uint32_t cp_color_id;
|
||||||
// Fan speed for the extrusion, used for visualization purposes.
|
// Fan speed for the extrusion, used for visualization purposes.
|
||||||
float fan_speed;
|
float fan_speed;
|
||||||
};
|
// Layer time for the extrusion, used for visualization purposes.
|
||||||
|
float layer_time;
|
||||||
|
};
|
||||||
using Paths = std::vector<Path>;
|
using Paths = std::vector<Path>;
|
||||||
|
|
||||||
struct Layer
|
struct Layer
|
||||||
@ -379,6 +385,8 @@ public:
|
|||||||
Color get_width_color(float width) const;
|
Color get_width_color(float width) const;
|
||||||
Color get_feedrate_color(float feedrate) const;
|
Color get_feedrate_color(float feedrate) const;
|
||||||
Color get_fan_speed_color(float fan_speed) 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;
|
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);
|
void set_extrusion_role_color(const std::string& role_name, float red, float green, float blue, float alpha);
|
||||||
|
@ -854,6 +854,7 @@ namespace Slic3r {
|
|||||||
block_time += block.deceleration_time();
|
block_time += block.deceleration_time();
|
||||||
m_time += block_time;
|
m_time += block_time;
|
||||||
block.elapsed_time = m_time;
|
block.elapsed_time = m_time;
|
||||||
|
block.time = block_time;
|
||||||
|
|
||||||
#if ENABLE_MOVE_STATS
|
#if ENABLE_MOVE_STATS
|
||||||
MovesStatsMap::iterator it = _moves_stats.find(block.move_type);
|
MovesStatsMap::iterator it = _moves_stats.find(block.move_type);
|
||||||
@ -1031,6 +1032,7 @@ namespace Slic3r {
|
|||||||
|
|
||||||
// updates axes positions from line
|
// updates axes positions from line
|
||||||
float new_pos[Num_Axis];
|
float new_pos[Num_Axis];
|
||||||
|
long raw_axis_absolute_position;
|
||||||
for (unsigned char a = X; a < Num_Axis; ++a)
|
for (unsigned char a = X; a < Num_Axis; ++a)
|
||||||
{
|
{
|
||||||
new_pos[a] = axis_absolute_position((EAxis)a, line);
|
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);
|
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]));
|
max_abs_delta = std::max(max_abs_delta, std::abs(block.delta_pos[a]));
|
||||||
}
|
}
|
||||||
|
block.z = new_pos[Z];
|
||||||
|
|
||||||
// is it a move ?
|
// is it a move ?
|
||||||
if (max_abs_delta == 0.0f)
|
if (max_abs_delta == 0.0f)
|
||||||
@ -1688,6 +1691,47 @@ namespace Slic3r {
|
|||||||
return std::to_string((int)(::roundf(time_in_secs / 60.0f)));
|
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
|
#if ENABLE_MOVE_STATS
|
||||||
void GCodeTimeEstimator::_log_moves_stats() const
|
void GCodeTimeEstimator::_log_moves_stats() const
|
||||||
{
|
{
|
||||||
|
@ -154,6 +154,7 @@ namespace Slic3r {
|
|||||||
Flags flags;
|
Flags flags;
|
||||||
|
|
||||||
float delta_pos[Num_Axis]; // mm
|
float delta_pos[Num_Axis]; // mm
|
||||||
|
float z;
|
||||||
float acceleration; // mm/s^2
|
float acceleration; // mm/s^2
|
||||||
float max_entry_speed; // mm/s
|
float max_entry_speed; // mm/s
|
||||||
float safe_feedrate; // mm/s
|
float safe_feedrate; // mm/s
|
||||||
@ -161,6 +162,7 @@ namespace Slic3r {
|
|||||||
FeedrateProfile feedrate;
|
FeedrateProfile feedrate;
|
||||||
Trapezoid trapezoid;
|
Trapezoid trapezoid;
|
||||||
float elapsed_time;
|
float elapsed_time;
|
||||||
|
float time;
|
||||||
|
|
||||||
Block();
|
Block();
|
||||||
|
|
||||||
@ -204,6 +206,14 @@ namespace Slic3r {
|
|||||||
|
|
||||||
typedef std::vector<Block> BlocksList;
|
typedef std::vector<Block> BlocksList;
|
||||||
|
|
||||||
|
struct Layer
|
||||||
|
{
|
||||||
|
float z;
|
||||||
|
float time;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<Layer> LayersList;
|
||||||
|
|
||||||
#if ENABLE_MOVE_STATS
|
#if ENABLE_MOVE_STATS
|
||||||
struct MoveStats
|
struct MoveStats
|
||||||
{
|
{
|
||||||
@ -236,6 +246,7 @@ namespace Slic3r {
|
|||||||
Feedrates m_curr;
|
Feedrates m_curr;
|
||||||
Feedrates m_prev;
|
Feedrates m_prev;
|
||||||
BlocksList m_blocks;
|
BlocksList m_blocks;
|
||||||
|
LayersList m_layers;
|
||||||
// Map between g1 line id and blocks id, used to speed up export of remaining times
|
// Map between g1 line id and blocks id, used to speed up export of remaining times
|
||||||
G1LineIdToBlockIdMap m_g1_line_ids;
|
G1LineIdToBlockIdMap m_g1_line_ids;
|
||||||
// Index of the last block already st_synchronized
|
// Index of the last block already st_synchronized
|
||||||
@ -354,6 +365,10 @@ namespace Slic3r {
|
|||||||
void set_additional_time(float timeSec);
|
void set_additional_time(float timeSec);
|
||||||
float get_additional_time() const;
|
float get_additional_time() const;
|
||||||
|
|
||||||
|
void calculate_layer_time();
|
||||||
|
float get_layer_time(float z);
|
||||||
|
void reset_layers();
|
||||||
|
|
||||||
void set_default();
|
void set_default();
|
||||||
|
|
||||||
// Call this method before to start adding lines using add_gcode_line() when reusing an instance of GCodeTimeEstimator
|
// Call this method before to start adding lines using add_gcode_line() when reusing an instance of GCodeTimeEstimator
|
||||||
|
@ -6205,6 +6205,10 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
|
|||||||
return path.feedrate;
|
return path.feedrate;
|
||||||
case GCodePreviewData::Extrusion::FanSpeed:
|
case GCodePreviewData::Extrusion::FanSpeed:
|
||||||
return path.fan_speed;
|
return path.fan_speed;
|
||||||
|
case GCodePreviewData::Extrusion::LayerTime:
|
||||||
|
return path.layer_time;
|
||||||
|
case GCodePreviewData::Extrusion::LayerTimeLog:
|
||||||
|
return path.layer_time;
|
||||||
case GCodePreviewData::Extrusion::VolumetricRate:
|
case GCodePreviewData::Extrusion::VolumetricRate:
|
||||||
return path.feedrate * (float)path.mm3_per_mm;
|
return path.feedrate * (float)path.mm3_per_mm;
|
||||||
case GCodePreviewData::Extrusion::Tool:
|
case GCodePreviewData::Extrusion::Tool:
|
||||||
@ -6233,6 +6237,10 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
|
|||||||
return data.get_feedrate_color(value);
|
return data.get_feedrate_color(value);
|
||||||
case GCodePreviewData::Extrusion::FanSpeed:
|
case GCodePreviewData::Extrusion::FanSpeed:
|
||||||
return data.get_fan_speed_color(value);
|
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:
|
case GCodePreviewData::Extrusion::VolumetricRate:
|
||||||
return data.get_volumetric_rate_color(value);
|
return data.get_volumetric_rate_color(value);
|
||||||
case GCodePreviewData::Extrusion::Tool:
|
case GCodePreviewData::Extrusion::Tool:
|
||||||
|
@ -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("Width")));
|
||||||
m_choice_view_type->Append(_(L("Speed")));
|
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 ? "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(width_screen == tiny ? "Vol. flow" :"Volumetric flow rate")));
|
||||||
m_choice_view_type->Append(_(L("Tool")));
|
m_choice_view_type->Append(_(L("Tool")));
|
||||||
m_choice_view_type->Append(_(L("Filament")));
|
m_choice_view_type->Append(_(L("Filament")));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user