SPE-1872: Added visualization of actual speed in gcode preview

This commit is contained in:
enricoturri1966 2024-02-02 15:57:54 +01:00 committed by Lukas Matena
parent 82001626dd
commit e4a3fb3b45
9 changed files with 509 additions and 23 deletions

View File

@ -113,7 +113,7 @@ static float intersection_distance(float initial_rate, float final_rate, float a
static float speed_from_distance(float initial_feedrate, float distance, float acceleration)
{
// to avoid invalid negative numbers due to numerical errors
float value = std::max(0.0f, sqr(initial_feedrate) + 2.0f * acceleration * distance);
const float value = std::max(0.0f, sqr(initial_feedrate) + 2.0f * acceleration * distance);
return ::sqrt(value);
}
@ -122,7 +122,7 @@ static float speed_from_distance(float initial_feedrate, float distance, float a
static float max_allowable_speed(float acceleration, float target_velocity, float distance)
{
// to avoid invalid negative numbers due to numerical errors
float value = std::max(0.0f, sqr(target_velocity) - 2.0f * acceleration * distance);
const float value = std::max(0.0f, sqr(target_velocity) - 2.0f * acceleration * distance);
return std::sqrt(value);
}
@ -145,30 +145,42 @@ void GCodeProcessor::CpColor::reset()
float GCodeProcessor::Trapezoid::acceleration_time(float entry_feedrate, float acceleration) const
{
#if ENABLE_ET_SPE1872
return acceleration_time_from_distance(entry_feedrate, acceleration_distance(), acceleration);
#else
return acceleration_time_from_distance(entry_feedrate, accelerate_until, acceleration);
#endif // ENABLE_ET_SPE1872
}
#if !ENABLE_ET_SPE1872
float GCodeProcessor::Trapezoid::cruise_time() const
{
return (cruise_feedrate != 0.0f) ? cruise_distance() / cruise_feedrate : 0.0f;
}
#endif // !ENABLE_ET_SPE1872
float GCodeProcessor::Trapezoid::deceleration_time(float distance, float acceleration) const
{
return acceleration_time_from_distance(cruise_feedrate, (distance - decelerate_after), -acceleration);
#if ENABLE_ET_SPE1872
return acceleration_time_from_distance(cruise_feedrate, deceleration_distance(distance), -acceleration);
#else
return acceleration_time_from_distance(cruise_feedrate, distance - decelerate_after, -acceleration);
#endif // ENABLE_ET_SPE1872
}
#if !ENABLE_ET_SPE1872
float GCodeProcessor::Trapezoid::cruise_distance() const
{
return decelerate_after - accelerate_until;
}
#endif // !ENABLE_ET_SPE1872
void GCodeProcessor::TimeBlock::calculate_trapezoid()
{
trapezoid.cruise_feedrate = feedrate_profile.cruise;
float accelerate_distance = std::max(0.0f, estimated_acceleration_distance(feedrate_profile.entry, feedrate_profile.cruise, acceleration));
float decelerate_distance = std::max(0.0f, estimated_acceleration_distance(feedrate_profile.cruise, feedrate_profile.exit, -acceleration));
const float decelerate_distance = std::max(0.0f, estimated_acceleration_distance(feedrate_profile.cruise, feedrate_profile.exit, -acceleration));
float cruise_distance = distance - accelerate_distance - decelerate_distance;
// Not enough space to reach the nominal feedrate.
@ -182,14 +194,26 @@ void GCodeProcessor::TimeBlock::calculate_trapezoid()
trapezoid.accelerate_until = accelerate_distance;
trapezoid.decelerate_after = accelerate_distance + cruise_distance;
#if ENABLE_ET_SPE1872
const float new_exit_speed = feedrate_profile.entry +
acceleration * trapezoid.acceleration_time(feedrate_profile.entry, acceleration) -
acceleration * trapezoid.deceleration_time(distance, acceleration);
const float delta_exit_speed_percent = std::abs(100.0f * (new_exit_speed - feedrate_profile.exit) / feedrate_profile.exit);
if (delta_exit_speed_percent > 1.0f) {
// what to do in this case ?
}
#endif // ENABLE_ET_SPE1872
}
#if !ENABLE_ET_SPE1872
float GCodeProcessor::TimeBlock::time() const
{
return trapezoid.acceleration_time(feedrate_profile.entry, acceleration)
+ trapezoid.cruise_time()
+ trapezoid.deceleration_time(distance, acceleration);
return trapezoid.acceleration_time(feedrate_profile.entry, acceleration) +
trapezoid.cruise_time() +
trapezoid.deceleration_time(distance, acceleration);
}
#endif // !ENABLE_ET_SPE1872
void GCodeProcessor::TimeMachine::State::reset()
{
@ -236,30 +260,54 @@ void GCodeProcessor::TimeMachine::reset()
}
#if ENABLE_NEW_GCODE_VIEWER
#if !ENABLE_ET_SPE1872
void GCodeProcessor::TimeMachine::simulate_st_synchronize(GCodeProcessorResult& result, PrintEstimatedStatistics::ETimeMode mode, float additional_time)
#else
void GCodeProcessor::TimeMachine::simulate_st_synchronize(float additional_time)
#endif // ENABLE_NEW_GCODE_VIEWER
{
if (!enabled)
return;
#if ENABLE_NEW_GCODE_VIEWER
calculate_time(result, mode, 0, additional_time);
#else
calculate_time(0, additional_time);
#endif // ENABLE_NEW_GCODE_VIEWER
}
static void planner_forward_pass_kernel(GCodeProcessor::TimeBlock& prev, GCodeProcessor::TimeBlock& curr)
#endif // !ENABLE_ET_SPE1872
#else
void GCodeProcessor::TimeMachine::simulate_st_synchronize(float additional_time)
{
if (!enabled)
return;
calculate_time(0, additional_time);
}
#endif // ENABLE_NEW_GCODE_VIEWER
static void planner_forward_pass_kernel(const GCodeProcessor::TimeBlock& prev, GCodeProcessor::TimeBlock& curr)
{
#if ENABLE_ET_SPE1872_FIRMWARE_BUDDY
//
// C:\prusa\firmware\Prusa-Firmware-Buddy\lib\Marlin\Marlin\src\module\planner.cpp
// Line 954
//
// If the previous block is an acceleration block, too short to complete the full speed
// change, adjust the entry speed accordingly. Entry speeds have already been reset,
// maximized, and reverse-planned. If nominal length is set, max junction speed is
// guaranteed to be reached. No need to recheck.
if (!prev.flags.nominal_length && prev.feedrate_profile.entry < curr.feedrate_profile.entry) {
// Compute the maximum allowable speed
const float new_entry_speed = max_allowable_speed(-prev.acceleration, prev.feedrate_profile.entry, prev.distance);
// If true, current block is full-acceleration and we can move the planned pointer forward.
if (new_entry_speed < curr.feedrate_profile.entry) {
// Always <= max_entry_speed_sqr. Backward pass sets this.
curr.feedrate_profile.entry = new_entry_speed;
curr.flags.recalculate = true;
}
}
#else
// If the previous block is an acceleration block, but it is not long enough to complete the
// full speed change within the block, we need to adjust the entry speed accordingly. Entry
// speeds have already been reset, maximized, and reverse planned by reverse planner.
// If nominal length is true, max junction speed is guaranteed to be reached. No need to recheck.
if (!prev.flags.nominal_length) {
if (prev.feedrate_profile.entry < curr.feedrate_profile.entry) {
float entry_speed = std::min(curr.feedrate_profile.entry, max_allowable_speed(-prev.acceleration, prev.feedrate_profile.entry, prev.distance));
const float entry_speed = std::min(curr.feedrate_profile.entry, max_allowable_speed(-prev.acceleration, prev.feedrate_profile.entry, prev.distance));
// Check for junction speed change
if (curr.feedrate_profile.entry != entry_speed) {
@ -268,10 +316,40 @@ static void planner_forward_pass_kernel(GCodeProcessor::TimeBlock& prev, GCodePr
}
}
}
#endif // ENABLE_ET_SPE1872_FIRMWARE_BUDDY
}
void planner_reverse_pass_kernel(GCodeProcessor::TimeBlock& curr, GCodeProcessor::TimeBlock& next)
static void planner_reverse_pass_kernel(GCodeProcessor::TimeBlock& curr, const GCodeProcessor::TimeBlock& next)
{
#if ENABLE_ET_SPE1872_FIRMWARE_BUDDY
//
// C:\prusa\firmware\Prusa-Firmware-Buddy\lib\Marlin\Marlin\src\module\planner.cpp
// Line 857
//
// If entry speed is already at the maximum entry speed, and there was no change of speed
// in the next block, there is no need to recheck. Block is cruising and there is no need to
// compute anything for this block,
// If not, block entry speed needs to be recalculated to ensure maximum possible planned speed.
const float max_entry_speed = curr.max_entry_speed;
// Compute maximum entry speed decelerating over the current block from its exit speed.
// If not at the maximum entry speed, or the previous block entry speed changed
if (curr.feedrate_profile.entry != max_entry_speed || next.flags.recalculate) {
// If nominal length true, max junction speed is guaranteed to be reached.
// If a block can de/ac-celerate from nominal speed to zero within the length of the block, then
// the current block and next block junction speeds are guaranteed to always be at their maximum
// junction speeds in deceleration and acceleration, respectively. This is due to how the current
// block nominal speed limits both the current and next maximum junction speeds. Hence, in both
// the reverse and forward planners, the corresponding block junction speed will always be at the
// the maximum junction speed and may always be ignored for any speed reduction checks.
const float new_entry_speed = curr.flags.nominal_length ? max_entry_speed :
std::min(max_entry_speed, max_allowable_speed(-curr.acceleration, next.feedrate_profile.entry, curr.distance));
if (curr.feedrate_profile.entry != new_entry_speed) {
// Just Set the new entry speed.
curr.feedrate_profile.entry = new_entry_speed;
curr.flags.recalculate = true;
}
}
#else
// If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising.
// If not, block in state of acceleration or deceleration. Reset entry speed to maximum and
// check for maximum allowable speed reductions to ensure maximum possible planned speed.
@ -285,6 +363,7 @@ void planner_reverse_pass_kernel(GCodeProcessor::TimeBlock& curr, GCodeProcessor
curr.flags.recalculate = true;
}
#endif // ENABLE_ET_SPE1872_FIRMWARE_BUDDY
}
static void recalculate_trapezoids(std::vector<GCodeProcessor::TimeBlock>& blocks)
@ -338,12 +417,13 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks, floa
}
// reverse_pass
for (int i = static_cast<int>(blocks.size()) - 1; i > 0; --i)
for (int i = static_cast<int>(blocks.size()) - 1; i > 0; --i) {
planner_reverse_pass_kernel(blocks[i - 1], blocks[i]);
}
recalculate_trapezoids(blocks);
size_t n_blocks_process = blocks.size() - keep_last_n_blocks;
const size_t n_blocks_process = blocks.size() - keep_last_n_blocks;
for (size_t i = 0; i < n_blocks_process; ++i) {
const TimeBlock& block = blocks[i];
float block_time = block.time();
@ -356,6 +436,53 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks, floa
gcode_time.cache += block_time;
if (block.layer_id == 1)
first_layer_time += block_time;
#if ENABLE_ET_SPE1872
// detect actual speed moves required to render toolpaths using actual speed
if (mode == PrintEstimatedStatistics::ETimeMode::Normal) {
GCodeProcessorResult::MoveVertex& curr_move = result.moves[block.move_id];
const GCodeProcessorResult::MoveVertex& prev_move = result.moves[block.move_id - 1];
const Vec3f move_vector = curr_move.position - prev_move.position;
assert(curr_move.actual_speed == 0.0f);
// acceleration phase
if (EPSILON < block.trapezoid.accelerate_until && block.trapezoid.accelerate_until < block.distance - EPSILON) {
const float t = block.trapezoid.accelerate_until / block.distance;
const float width = (prev_move.type == EMoveType::Extrude) ? prev_move.width + t * (curr_move.width - prev_move.width) : curr_move.width;
const float height = (prev_move.type == EMoveType::Extrude) ? prev_move.height + t * (curr_move.height - prev_move.height) : curr_move.height;
actual_speed_moves.push_back({
block.move_id,
block.feedrate_profile.cruise,
prev_move.position + t * move_vector,
width,
height,
});
}
// cruise phase
if (block.trapezoid.accelerate_until + EPSILON < block.trapezoid.decelerate_after &&
block.trapezoid.decelerate_after < block.distance - EPSILON) {
const float t = block.trapezoid.decelerate_after / block.distance;
const float width = (prev_move.type == EMoveType::Extrude) ? prev_move.width + t * (curr_move.width - prev_move.width) : curr_move.width;
const float height = (prev_move.type == EMoveType::Extrude) ? prev_move.height + t * (curr_move.height - prev_move.height) : curr_move.height;
actual_speed_moves.push_back({
block.move_id,
block.feedrate_profile.cruise,
prev_move.position + t * move_vector,
width,
height,
});
}
// deceleration/exit phase
actual_speed_moves.push_back({
block.move_id,
block.feedrate_profile.exit,
std::nullopt,
std::nullopt,
std::nullopt
});
}
#endif // ENABLE_ET_SPE1872
#else
if (block.move_type == EMoveType::Travel)
travel_time += block_time;
@ -1381,12 +1508,18 @@ void GCodeProcessor::finalize(bool perform_post_process)
}
}
#if ENABLE_ET_SPE1872
calculate_time(m_result);
#endif // ENABLE_ET_SPE1872
// process the time blocks
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
TimeMachine& machine = m_time_processor.machines[i];
TimeMachine::CustomGCodeTime& gcode_time = machine.gcode_time;
#if ENABLE_NEW_GCODE_VIEWER
#if !ENABLE_ET_SPE1872
machine.calculate_time(m_result, static_cast<PrintEstimatedStatistics::ETimeMode>(i));
#endif // !ENABLE_ET_SPE1872
#else
machine.calculate_time();
#endif // ENABLE_NEW_GCODE_VIEWER
@ -2937,14 +3070,21 @@ void GCodeProcessor::process_G1(const std::array<std::optional<double>, 4>& axes
blocks.push_back(block);
#if !ENABLE_ET_SPE1872
if (blocks.size() > TimeProcessor::Planner::refresh_threshold)
#if ENABLE_NEW_GCODE_VIEWER
machine.calculate_time(m_result, static_cast<PrintEstimatedStatistics::ETimeMode>(i), TimeProcessor::Planner::queue_size);
#else
machine.calculate_time(TimeProcessor::Planner::queue_size);
#endif // ENABLE_NEW_GCODE_VIEWER
#endif // !ENABLE_ET_SPE1872
}
#if ENABLE_ET_SPE1872
if (m_time_processor.machines[0].blocks.size() > TimeProcessor::Planner::refresh_threshold)
calculate_time(m_result, TimeProcessor::Planner::queue_size);
#endif // ENABLE_ET_SPE1872
if (m_seams_detector.is_active()) {
// check for seam starting vertex
if (type == EMoveType::Extrude && m_extrusion_role == GCodeExtrusionRole::ExternalPerimeter && !m_seams_detector.has_first_vertex())
@ -4516,6 +4656,9 @@ void GCodeProcessor::store_move_vertex(EMoveType type, bool internal_only)
Vec3f(m_end_position[X], m_end_position[Y], m_end_position[Z] - m_z_offset) + m_extruder_offsets[m_extruder_id],
static_cast<float>(m_end_position[E] - m_start_position[E]),
m_feedrate,
#if ENABLE_ET_SPE1872
0.0f,
#endif // ENABLE_ET_SPE1872
m_width,
m_height,
m_mm3_per_mm,
@ -4670,6 +4813,11 @@ float GCodeProcessor::get_filament_unload_time(size_t extruder_id)
void GCodeProcessor::process_custom_gcode_time(CustomGCode::Type code)
{
#if ENABLE_ET_SPE1872
//FIXME this simulates st_synchronize! is it correct?
// The estimated time may be longer than the real print time.
simulate_st_synchronize();
#endif // ENABLE_ET_SPE1872
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
TimeMachine& machine = m_time_processor.machines[i];
if (!machine.enabled)
@ -4680,7 +4828,9 @@ void GCodeProcessor::process_custom_gcode_time(CustomGCode::Type code)
//FIXME this simulates st_synchronize! is it correct?
// The estimated time may be longer than the real print time.
#if ENABLE_NEW_GCODE_VIEWER
#if !ENABLE_ET_SPE1872
machine.simulate_st_synchronize(m_result, static_cast<PrintEstimatedStatistics::ETimeMode>(i));
#endif // !ENABLE_ET_SPE1872
#else
machine.simulate_st_synchronize();
#endif // ENABLE_NEW_GCODE_VIEWER
@ -4700,6 +4850,68 @@ void GCodeProcessor::process_filaments(CustomGCode::Type code)
m_used_filaments.process_extruder_cache(m_extruder_id);
}
#if ENABLE_ET_SPE1872
void GCodeProcessor::calculate_time(GCodeProcessorResult& result, size_t keep_last_n_blocks, float additional_time)
{
// calculate times
std::vector<TimeMachine::ActualSpeedMove> actual_speed_moves;
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
TimeMachine& machine = m_time_processor.machines[i];
machine.calculate_time(m_result, static_cast<PrintEstimatedStatistics::ETimeMode>(i), keep_last_n_blocks, additional_time);
if (static_cast<PrintEstimatedStatistics::ETimeMode>(i) == PrintEstimatedStatistics::ETimeMode::Normal)
actual_speed_moves = std::move(machine.actual_speed_moves);
}
// insert actual speed moves into the move list
unsigned int inserted_actual_speed_moves_count = 0;
std::vector<GCodeProcessorResult::MoveVertex> new_moves;
std::map<unsigned int, unsigned int> id_map;
for (auto it = actual_speed_moves.begin(); it != actual_speed_moves.end(); ++it) {
const unsigned int base_id = it->move_id + inserted_actual_speed_moves_count;
if (it->position.has_value()) {
// insert actual speed move into the move list
// clone from existing move
GCodeProcessorResult::MoveVertex new_move = result.moves[base_id];
// override modified parameters
new_move.time = { 0.0f, 0.0f };
new_move.position = *it->position;
new_move.actual_speed = it->feedrate;
if (it->width.has_value())
new_move.width = *it->width;
if (it->height.has_value())
new_move.height = *it->height;
new_move.internal_only = true;
new_moves.push_back(new_move);
}
else {
result.moves.insert(result.moves.begin() + base_id, new_moves.begin(), new_moves.end());
id_map[it->move_id] = base_id + new_moves.size();
// update move actual speed
result.moves[base_id + new_moves.size()].actual_speed = it->feedrate;
inserted_actual_speed_moves_count += new_moves.size();
new_moves.clear();
}
}
// synchronize blocks' move_ids with after actual speed moves insertion
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
for (GCodeProcessor::TimeBlock& block : m_time_processor.machines[i].blocks) {
auto it = id_map.find(block.move_id);
if (it != id_map.end()) {
int a = 0;
}
block.move_id = (it != id_map.end()) ? it->second : block.move_id + inserted_actual_speed_moves_count;
}
}
}
#endif // ENABLE_ET_SPE1872
#if ENABLE_ET_SPE1872
void GCodeProcessor::simulate_st_synchronize(float additional_time)
{
calculate_time(m_result, 0, additional_time);
}
#else
void GCodeProcessor::simulate_st_synchronize(float additional_time)
{
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
@ -4710,6 +4922,7 @@ void GCodeProcessor::simulate_st_synchronize(float additional_time)
#endif // ENABLE_NEW_GCODE_VIEWER
}
}
#endif // ENABLE_ET_SPE1872
void GCodeProcessor::update_estimated_statistics()
{

View File

@ -140,6 +140,9 @@ namespace Slic3r {
Vec3f position{ Vec3f::Zero() }; // mm
float delta_extruder{ 0.0f }; // mm
float feedrate{ 0.0f }; // mm/s
#if ENABLE_ET_SPE1872
float actual_speed{ 0.0f }; // mm/s
#endif // ENABLE_ET_SPE1872
float width{ 0.0f }; // mm
float height{ 0.0f }; // mm
float mm3_per_mm{ 0.0f };
@ -280,9 +283,19 @@ namespace Slic3r {
float cruise_feedrate{ 0.0f }; // mm/sec
float acceleration_time(float entry_feedrate, float acceleration) const;
#if ENABLE_ET_SPE1872
float cruise_time() const { return (cruise_feedrate != 0.0f) ? cruise_distance() / cruise_feedrate : 0.0f; }
#else
float cruise_time() const;
#endif // ENABLE_ET_SPE1872
float deceleration_time(float distance, float acceleration) const;
#if ENABLE_ET_SPE1872
float acceleration_distance() const { return accelerate_until; }
float cruise_distance() const { return decelerate_after - accelerate_until; }
float deceleration_distance(float distance) const { return distance - decelerate_after; }
#else
float cruise_distance() const;
#endif // ENABLE_ET_SPE1872
};
struct TimeBlock
@ -312,7 +325,14 @@ namespace Slic3r {
// Calculates this block's trapezoid
void calculate_trapezoid();
#if ENABLE_ET_SPE1872
float time() const {
return trapezoid.acceleration_time(feedrate_profile.entry, acceleration) +
trapezoid.cruise_time() + trapezoid.deceleration_time(distance, acceleration);
}
#else
float time() const;
#endif // ENABLE_ET_SPE1872
};
private:
@ -344,6 +364,17 @@ namespace Slic3r {
float elapsed_time;
};
#if ENABLE_ET_SPE1872
struct ActualSpeedMove
{
unsigned int move_id{ 0 };
float feedrate{ 0.0f };
std::optional<Vec3f> position;
std::optional<float> width{ 0.0f };
std::optional<float> height{ 0.0f };
};
#endif // ENABLE_ET_SPE1872
bool enabled;
float acceleration; // mm/s^2
// hard limit for the acceleration, to which the firmware will clamp.
@ -379,12 +410,17 @@ namespace Slic3r {
std::array<float, static_cast<size_t>(GCodeExtrusionRole::Count)> roles_time;
std::vector<float> layers_time;
#endif // ENABLE_NEW_GCODE_VIEWER
#if ENABLE_ET_SPE1872
std::vector<ActualSpeedMove> actual_speed_moves;
#endif // ENABLE_ET_SPE1872
void reset();
// Simulates firmware st_synchronize() call
#if ENABLE_NEW_GCODE_VIEWER
#if !ENABLE_ET_SPE1872
void simulate_st_synchronize(GCodeProcessorResult& result, PrintEstimatedStatistics::ETimeMode mode, float additional_time = 0.0f);
#endif // !ENABLE_ET_SPE1872
void calculate_time(GCodeProcessorResult& result, PrintEstimatedStatistics::ETimeMode mode, size_t keep_last_n_blocks = 0, float additional_time = 0.0f);
#else
void simulate_st_synchronize(float additional_time = 0.0f);
@ -885,6 +921,10 @@ namespace Slic3r {
void process_custom_gcode_time(CustomGCode::Type code);
void process_filaments(CustomGCode::Type code);
#if ENABLE_ET_SPE1872
void calculate_time(GCodeProcessorResult& result, size_t keep_last_n_blocks = 0, float additional_time = 0.0f);
#endif // ENABLE_ET_SPE1872
// Simulates firmware st_synchronize() call
void simulate_st_synchronize(float additional_time = 0.0f);

View File

@ -62,6 +62,10 @@
#define ENABLE_NEW_GCODE_VIEWER 1
#define ENABLE_NEW_GCODE_VIEWER_DEBUG (1 && ENABLE_NEW_GCODE_VIEWER)
// requires VGCODE_ENABLE_ET_SPE1872 set to 1 in libvgcode (Types.hpp)
#define ENABLE_ET_SPE1872 (1 && ENABLE_NEW_GCODE_VIEWER)
#define ENABLE_ET_SPE1872_FIRMWARE_BUDDY (1 && ENABLE_ET_SPE1872)
// Enable G-Code viewer statistics imgui dialog
#define ENABLE_GCODE_VIEWER_STATISTICS (0 && !ENABLE_NEW_GCODE_VIEWER)

View File

@ -32,6 +32,12 @@ struct PathVertex
// Segment speed
//
float feedrate{ 0.0f };
#if VGCODE_ENABLE_ET_SPE1872
//
// Segment actual speed
//
float actual_speed{ 0.0f };
#endif // VGCODE_ENABLE_ET_SPE1872
//
// Segment fan speed
//

View File

@ -6,6 +6,7 @@
#define VGCODE_TYPES_HPP
#define VGCODE_ENABLE_COG_AND_TOOL_MARKERS 0
#define VGCODE_ENABLE_ET_SPE1872 1
#include <array>
#include <vector>
@ -83,6 +84,9 @@ enum class EViewType : uint8_t
Height,
Width,
Speed,
#if VGCODE_ENABLE_ET_SPE1872
ActualSpeed,
#endif // VGCODE_ENABLE_ET_SPE1872
FanSpeed,
Temperature,
VolumetricFlowRate,

View File

@ -969,6 +969,12 @@ Color ViewerImpl::get_vertex_color(const PathVertex& v) const
{
return m_speed_range.get_color_at(v.feedrate);
}
#if VGCODE_ENABLE_ET_SPE1872
case EViewType::ActualSpeed:
{
return m_actual_speed_range.get_color_at(v.actual_speed);
}
#endif // VGCODE_ENABLE_ET_SPE1872
case EViewType::FanSpeed:
{
return v.is_travel() ? get_option_color(move_type_to_option(v.type)) : m_fan_speed_range.get_color_at(v.fan_speed);
@ -1066,6 +1072,9 @@ const ColorRange& ViewerImpl::get_color_range(EViewType type) const
case EViewType::Height: { return m_height_range; }
case EViewType::Width: { return m_width_range; }
case EViewType::Speed: { return m_speed_range; }
#if VGCODE_ENABLE_ET_SPE1872
case EViewType::ActualSpeed: { return m_actual_speed_range; }
#endif // VGCODE_ENABLE_ET_SPE1872
case EViewType::FanSpeed: { return m_fan_speed_range; }
case EViewType::Temperature: { return m_temperature_range; }
case EViewType::VolumetricFlowRate: { return m_volumetric_rate_range; }
@ -1082,6 +1091,9 @@ void ViewerImpl::set_color_range_palette(EViewType type, const Palette& palette)
case EViewType::Height: { m_height_range.set_palette(palette); }
case EViewType::Width: { m_width_range.set_palette(palette); }
case EViewType::Speed: { m_speed_range.set_palette(palette); }
#if VGCODE_ENABLE_ET_SPE1872
case EViewType::ActualSpeed: { m_actual_speed_range.set_palette(palette); }
#endif // VGCODE_ENABLE_ET_SPE1872
case EViewType::FanSpeed: { m_fan_speed_range.set_palette(palette); }
case EViewType::Temperature: { m_temperature_range.set_palette(palette); }
case EViewType::VolumetricFlowRate: { m_volumetric_rate_range.set_palette(palette); }
@ -1117,6 +1129,9 @@ size_t ViewerImpl::get_used_cpu_memory() const
ret += m_height_range.size_in_bytes_cpu();
ret += m_width_range.size_in_bytes_cpu();
ret += m_speed_range.size_in_bytes_cpu();
#if VGCODE_ENABLE_ET_SPE1872
ret += m_actual_speed_range.size_in_bytes_cpu();
#endif // VGCODE_ENABLE_ET_SPE1872
ret += m_fan_speed_range.size_in_bytes_cpu();
ret += m_temperature_range.size_in_bytes_cpu();
ret += m_volumetric_rate_range.size_in_bytes_cpu();
@ -1254,6 +1269,9 @@ void ViewerImpl::update_color_ranges()
m_width_range.reset();
m_height_range.reset();
m_speed_range.reset();
#if VGCODE_ENABLE_ET_SPE1872
m_actual_speed_range.reset();
#endif // VGCODE_ENABLE_ET_SPE1872
m_fan_speed_range.reset();
m_temperature_range.reset();
m_volumetric_rate_range.reset();
@ -1271,8 +1289,15 @@ void ViewerImpl::update_color_ranges()
m_fan_speed_range.update(v.fan_speed);
m_temperature_range.update(v.temperature);
}
#if VGCODE_ENABLE_ET_SPE1872
if ((v.is_travel() && m_settings.options_visibility.at(EOptionType::Travels)) || v.is_extrusion()) {
m_speed_range.update(v.feedrate);
m_actual_speed_range.update(v.actual_speed);
}
#else
if ((v.is_travel() && m_settings.options_visibility.at(EOptionType::Travels)) || v.is_extrusion())
m_speed_range.update(v.feedrate);
#endif // VGCODE_ENABLE_ET_SPE1872
}
const std::vector<float> times = m_layers.get_times(m_settings.time_mode);

View File

@ -284,6 +284,9 @@ private:
ColorRange m_height_range;
ColorRange m_width_range;
ColorRange m_speed_range;
#if VGCODE_ENABLE_ET_SPE1872
ColorRange m_actual_speed_range;
#endif // VGCODE_ENABLE_ET_SPE1872
ColorRange m_fan_speed_range;
ColorRange m_temperature_range;
ColorRange m_volumetric_rate_range;

View File

@ -1148,6 +1148,100 @@ void GCodeViewer::load_as_gcode(const GCodeProcessorResult& gcode_result, const
// convert data from PrusaSlicer format to libvgcode format
libvgcode::GCodeInputData data = libvgcode::convert(gcode_result, str_tool_colors, str_color_print_colors, m_viewer);
//#define ENABLE_DATA_EXPORT 1
//#if ENABLE_DATA_EXPORT
// auto extrusion_role_to_string = [](libvgcode::EGCodeExtrusionRole role) {
// switch (role) {
// case libvgcode::EGCodeExtrusionRole::None: { return "EGCodeExtrusionRole::None"; }
// case libvgcode::EGCodeExtrusionRole::Perimeter: { return "EGCodeExtrusionRole::Perimeter"; }
// case libvgcode::EGCodeExtrusionRole::ExternalPerimeter: { return "EGCodeExtrusionRole::ExternalPerimeter"; }
// case libvgcode::EGCodeExtrusionRole::OverhangPerimeter: { return "EGCodeExtrusionRole::OverhangPerimeter"; }
// case libvgcode::EGCodeExtrusionRole::InternalInfill: { return "EGCodeExtrusionRole::InternalInfill"; }
// case libvgcode::EGCodeExtrusionRole::SolidInfill: { return "EGCodeExtrusionRole::SolidInfill"; }
// case libvgcode::EGCodeExtrusionRole::TopSolidInfill: { return "EGCodeExtrusionRole::TopSolidInfill"; }
// case libvgcode::EGCodeExtrusionRole::Ironing: { return "EGCodeExtrusionRole::Ironing"; }
// case libvgcode::EGCodeExtrusionRole::BridgeInfill: { return "EGCodeExtrusionRole::BridgeInfill"; }
// case libvgcode::EGCodeExtrusionRole::GapFill: { return "EGCodeExtrusionRole::GapFill"; }
// case libvgcode::EGCodeExtrusionRole::Skirt: { return "EGCodeExtrusionRole::Skirt"; }
// case libvgcode::EGCodeExtrusionRole::SupportMaterial: { return "EGCodeExtrusionRole::SupportMaterial"; }
// case libvgcode::EGCodeExtrusionRole::SupportMaterialInterface: { return "EGCodeExtrusionRole::SupportMaterialInterface"; }
// case libvgcode::EGCodeExtrusionRole::WipeTower: { return "EGCodeExtrusionRole::WipeTower"; }
// case libvgcode::EGCodeExtrusionRole::Custom: { return "EGCodeExtrusionRole::Custom"; }
// case libvgcode::EGCodeExtrusionRole::COUNT: { return "EGCodeExtrusionRole::COUNT"; }
// }
// };
//
// auto move_type_to_string = [](libvgcode::EMoveType type) {
// switch (type) {
// case libvgcode::EMoveType::Noop: { return "EMoveType::Noop"; }
// case libvgcode::EMoveType::Retract: { return "EMoveType::Retract"; }
// case libvgcode::EMoveType::Unretract: { return "EMoveType::Unretract"; }
// case libvgcode::EMoveType::Seam: { return "EMoveType::Seam"; }
// case libvgcode::EMoveType::ToolChange: { return "EMoveType::ToolChange"; }
// case libvgcode::EMoveType::ColorChange: { return "EMoveType::ColorChange"; }
// case libvgcode::EMoveType::PausePrint: { return "EMoveType::PausePrint"; }
// case libvgcode::EMoveType::CustomGCode: { return "EMoveType::CustomGCode"; }
// case libvgcode::EMoveType::Travel: { return "EMoveType::Travel"; }
// case libvgcode::EMoveType::Wipe: { return "EMoveType::Wipe"; }
// case libvgcode::EMoveType::Extrude: { return "EMoveType::Extrude"; }
// case libvgcode::EMoveType::COUNT: { return "EMoveType::COUNT"; }
// }
// };
//
// FilePtr out{ boost::nowide::fopen("C:/prusa/slicer/test_output/spe1872/test.data", "wb") };
// if (out.f != nullptr) {
// const size_t vertices_count = data.vertices.size();
// fwrite((void*)&vertices_count, 1, sizeof(size_t), out.f);
// for (const libvgcode::PathVertex& v : data.vertices) {
// fwrite((void*)&v.position[0], 1, sizeof(float), out.f);
// fwrite((void*)&v.position[1], 1, sizeof(float), out.f);
// fwrite((void*)&v.position[2], 1, sizeof(float), out.f);
// fwrite((void*)&v.height, 1, sizeof(float), out.f);
// fwrite((void*)&v.width, 1, sizeof(float), out.f);
// fwrite((void*)&v.feedrate, 1, sizeof(float), out.f);
//#if ENABLE_ET_SPE1872
// fwrite((void*)&v.actual_speed, 1, sizeof(float), out.f);
//#endif // ENABLE_ET_SPE1872
// fwrite((void*)&v.fan_speed, 1, sizeof(float), out.f);
// fwrite((void*)&v.temperature, 1, sizeof(float), out.f);
// fwrite((void*)&v.volumetric_rate, 1, sizeof(float), out.f);
// fwrite((void*)&v.role, 1, sizeof(uint8_t), out.f);
// fwrite((void*)&v.type, 1, sizeof(uint8_t), out.f);
// fwrite((void*)&v.gcode_id, 1, sizeof(uint32_t), out.f);
// fwrite((void*)&v.layer_id, 1, sizeof(uint32_t), out.f);
// fwrite((void*)&v.extruder_id, 1, sizeof(uint32_t), out.f);
// fwrite((void*)&v.color_id, 1, sizeof(uint32_t), out.f);
// fwrite((void*)&v.times[0], 1, sizeof(float), out.f);
// fwrite((void*)&v.times[1], 1, sizeof(float), out.f);
//#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
// const float weight = v.weight;
//#else
// const float weight = 0.0f;
//#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
// fwrite((void*)&weight, 1, sizeof(float), out.f);
// }
//
// const uint8_t spiral_vase_mode = data.spiral_vase_mode ? 1 : 0;
// fwrite((void*)&spiral_vase_mode, 1, sizeof(uint8_t), out.f);
//
// const size_t tool_colors_count = data.tools_colors.size();
// fwrite((void*)&tool_colors_count, 1, sizeof(size_t), out.f);
// for (const libvgcode::Color& c : data.tools_colors) {
// fwrite((void*)&c[0], 1, sizeof(uint8_t), out.f);
// fwrite((void*)&c[1], 1, sizeof(uint8_t), out.f);
// fwrite((void*)&c[2], 1, sizeof(uint8_t), out.f);
// }
//
// const size_t color_print_colors_count = data.color_print_colors.size();
// fwrite((void*)&color_print_colors_count, 1, sizeof(size_t), out.f);
// for (const libvgcode::Color& c : data.color_print_colors) {
// fwrite((void*)&c[0], 1, sizeof(uint8_t), out.f);
// fwrite((void*)&c[1], 1, sizeof(uint8_t), out.f);
// fwrite((void*)&c[2], 1, sizeof(uint8_t), out.f);
// }
// }
//#endif // ENABLE_DATA_EXPORT
// send data to the viewer
m_viewer.reset_default_extrusion_roles_colors();
m_viewer.load(std::move(data));
@ -4888,12 +4982,52 @@ void GCodeViewer::render_legend(float& legend_height)
#else
if (!m_layers_times.empty() && m_layers.size() == m_layers_times.front().size()) {
#endif // ENABLE_NEW_GCODE_VIEWER
#if ENABLE_ET_SPE1872
view_options = { _u8L("Feature type"), _u8L("Height (mm)"), _u8L("Width (mm)"), _u8L("Speed (mm/s)"), _u8L("Actual speed (mm/s)"),
_u8L("Fan speed (%)"), _u8L("Temperature (°C)"), _u8L("Volumetric flow rate (mm³/s)"), _u8L("Layer time (linear)"),
_u8L("Layer time (logarithmic)"), _u8L("Tool"), _u8L("Color Print") };
view_options_id = { static_cast<int>(libvgcode::EViewType::FeatureType),
static_cast<int>(libvgcode::EViewType::Height),
static_cast<int>(libvgcode::EViewType::Width),
static_cast<int>(libvgcode::EViewType::Speed),
static_cast<int>(libvgcode::EViewType::ActualSpeed),
static_cast<int>(libvgcode::EViewType::FanSpeed),
static_cast<int>(libvgcode::EViewType::Temperature),
static_cast<int>(libvgcode::EViewType::VolumetricFlowRate),
static_cast<int>(libvgcode::EViewType::LayerTimeLinear),
static_cast<int>(libvgcode::EViewType::LayerTimeLogarithmic),
static_cast<int>(libvgcode::EViewType::Tool),
static_cast<int>(libvgcode::EViewType::ColorPrint) };
#else
view_options = { _u8L("Feature type"), _u8L("Height (mm)"), _u8L("Width (mm)"), _u8L("Speed (mm/s)"), _u8L("Fan speed (%)"),
_u8L("Temperature (°C)"), _u8L("Volumetric flow rate (mm³/s)"), _u8L("Layer time (linear)"), _u8L("Layer time (logarithmic)"),
_u8L("Tool"), _u8L("Color Print") };
view_options_id = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
#endif // ENABLE_ET_SPE1872
}
else {
#if ENABLE_ET_SPE1872
view_options = { _u8L("Feature type"), _u8L("Height (mm)"), _u8L("Width (mm)"), _u8L("Speed (mm/s)"), _u8L("Actual speed (mm/s)"),
_u8L("Fan speed (%)"), _u8L("Temperature (°C)"), _u8L("Volumetric flow rate (mm³/s)"), _u8L("Tool"), _u8L("Color Print") };
view_options_id = { static_cast<int>(libvgcode::EViewType::FeatureType),
static_cast<int>(libvgcode::EViewType::Height),
static_cast<int>(libvgcode::EViewType::Width),
static_cast<int>(libvgcode::EViewType::Speed),
static_cast<int>(libvgcode::EViewType::ActualSpeed),
static_cast<int>(libvgcode::EViewType::FanSpeed),
static_cast<int>(libvgcode::EViewType::Temperature),
static_cast<int>(libvgcode::EViewType::VolumetricFlowRate),
static_cast<int>(libvgcode::EViewType::Tool),
static_cast<int>(libvgcode::EViewType::ColorPrint) };
#if ENABLE_NEW_GCODE_VIEWER
if (new_view_type_i == static_cast<int>(libvgcode::EViewType::LayerTimeLinear) ||
new_view_type_i == static_cast<int>(libvgcode::EViewType::LayerTimeLogarithmic))
new_view_type_i = 0;
#else
if (view_type == 8 || view_type == 8)
view_type = 0;
#endif // ENABLE_NEW_GCODE_VIEWER
#else
view_options = { _u8L("Feature type"), _u8L("Height (mm)"), _u8L("Width (mm)"), _u8L("Speed (mm/s)"), _u8L("Fan speed (%)"),
_u8L("Temperature (°C)"), _u8L("Volumetric flow rate (mm³/s)"), _u8L("Tool"), _u8L("Color Print") };
view_options_id = { 0, 1, 2, 3, 4, 5, 6, 9, 10 };
@ -4904,6 +5038,7 @@ void GCodeViewer::render_legend(float& legend_height)
if (view_type == 7 || view_type == 8)
view_type = 0;
#endif // ENABLE_NEW_GCODE_VIEWER
#endif // ENABLE_ET_SPE1872
}
#if ENABLE_NEW_GCODE_VIEWER
auto new_view_type_it = std::find(view_options_id.begin(), view_options_id.end(), new_view_type_i);
@ -5020,6 +5155,9 @@ void GCodeViewer::render_legend(float& legend_height)
case libvgcode::EViewType::Height: { append_range(m_viewer.get_color_range(libvgcode::EViewType::Height), 3); break; }
case libvgcode::EViewType::Width: { append_range(m_viewer.get_color_range(libvgcode::EViewType::Width), 3); break; }
case libvgcode::EViewType::Speed: { append_range(m_viewer.get_color_range(libvgcode::EViewType::Speed), 1); break; }
#if ENABLE_ET_SPE1872
case libvgcode::EViewType::ActualSpeed: { append_range(m_viewer.get_color_range(libvgcode::EViewType::ActualSpeed), 1); break; }
#endif // ENABLE_ET_SPE1872
case libvgcode::EViewType::FanSpeed: { append_range(m_viewer.get_color_range(libvgcode::EViewType::FanSpeed), 0); break; }
case libvgcode::EViewType::Temperature: { append_range(m_viewer.get_color_range(libvgcode::EViewType::Temperature), 0); break; }
case libvgcode::EViewType::VolumetricFlowRate: { append_range(m_viewer.get_color_range(libvgcode::EViewType::VolumetricFlowRate), 3); break; }

View File

@ -212,6 +212,19 @@ GCodeInputData convert(const Slic3r::GCodeProcessorResult& result, const std::ve
// to allow libvgcode to properly detect the start/end of a path we need to add a 'phantom' vertex
// equal to the current one with the exception of the position, which should match the previous move position,
// and the times, which are set to zero
#if ENABLE_ET_SPE1872
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
const libvgcode::PathVertex vertex = { convert(prev.position), height, width, curr.feedrate, prev.actual_speed,
curr.fan_speed, curr.temperature, curr.volumetric_rate(), 0.0f, convert(curr.extrusion_role), curr_type,
static_cast<uint32_t>(curr.gcode_id), static_cast<uint32_t>(curr.layer_id),
static_cast<uint8_t>(curr.extruder_id), static_cast<uint8_t>(curr.cp_color_id), { 0.0f, 0.0f } };
#else
const libvgcode::PathVertex vertex = { convert(prev.position), height, width, curr.feedrate, prev.actual_speed,
curr.fan_speed, curr.temperature, curr.volumetric_rate(), convert(curr.extrusion_role), curr_type,
static_cast<uint32_t>(curr.gcode_id), static_cast<uint32_t>(curr.layer_id),
static_cast<uint8_t>(curr.extruder_id), static_cast<uint8_t>(curr.cp_color_id), { 0.0f, 0.0f } };
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#else
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
const libvgcode::PathVertex vertex = { convert(prev.position), height, width, curr.feedrate, curr.fan_speed,
curr.temperature, curr.volumetric_rate(), 0.0f, convert(curr.extrusion_role), curr_type,
@ -223,10 +236,25 @@ GCodeInputData convert(const Slic3r::GCodeProcessorResult& result, const std::ve
static_cast<uint32_t>(curr.gcode_id), static_cast<uint32_t>(curr.layer_id),
static_cast<uint8_t>(curr.extruder_id), static_cast<uint8_t>(curr.cp_color_id), { 0.0f, 0.0f } };
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#endif // ENABLE_ET_SPE1872
ret.vertices.emplace_back(vertex);
}
}
#if ENABLE_ET_SPE1872
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
const libvgcode::PathVertex vertex = { convert(curr.position), height, width, curr.feedrate, curr.actual_speed,
curr.fan_speed, curr.temperature, curr.volumetric_rate(),
result.filament_densities[curr.extruder_id] * curr.mm3_per_mm * (curr.position - prev.position).norm(),
convert(curr.extrusion_role), curr_type, static_cast<uint32_t>(curr.gcode_id), static_cast<uint32_t>(curr.layer_id),
static_cast<uint8_t>(curr.extruder_id), static_cast<uint8_t>(curr.cp_color_id), curr.time };
#else
const libvgcode::PathVertex vertex = { convert(curr.position), height, width, curr.feedrate, curr.actual_speed,
curr.fan_speed, curr.temperature, curr.volumetric_rate(), convert(curr.extrusion_role), curr_type,
static_cast<uint32_t>(curr.gcode_id), static_cast<uint32_t>(curr.layer_id), static_cast<uint8_t>(curr.extruder_id),
static_cast<uint8_t>(curr.cp_color_id), curr.time };
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#else
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
const libvgcode::PathVertex vertex = { convert(curr.position), height, width, curr.feedrate, curr.fan_speed,
curr.temperature, curr.volumetric_rate(), result.filament_densities[curr.extruder_id] * curr.mm3_per_mm * (curr.position - prev.position).norm(),
@ -237,6 +265,7 @@ GCodeInputData convert(const Slic3r::GCodeProcessorResult& result, const std::ve
curr.temperature, curr.volumetric_rate(), convert(curr.extrusion_role), curr_type, static_cast<uint32_t>(curr.gcode_id),
static_cast<uint32_t>(curr.layer_id), static_cast<uint8_t>(curr.extruder_id), static_cast<uint8_t>(curr.cp_color_id), curr.time };
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#endif // ENABLE_ET_SPE1872
ret.vertices.emplace_back(vertex);
}
ret.vertices.shrink_to_fit();
@ -261,6 +290,17 @@ static void convert_lines_to_vertices(const Slic3r::Lines& lines, const std::vec
if (ii == 0) {
// add a dummy vertex at the start, to separate the current line from the others
const Slic3r::Vec2f a = unscale(line.a).cast<float>();
#if ENABLE_ET_SPE1872
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
libvgcode::PathVertex vertex = { convert(Slic3r::Vec3f(a.x(), a.y(), top_z)), heights[i], widths[i], 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, extrusion_role, EMoveType::Noop, 0, static_cast<uint32_t>(layer_id),
static_cast<uint8_t>(extruder_id), static_cast<uint8_t>(color_id), { 0.0f, 0.0f } };
#else
libvgcode::PathVertex vertex = { convert(Slic3r::Vec3f(a.x(), a.y(), top_z)), heights[i], widths[i], 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, extrusion_role, EMoveType::Noop, 0, static_cast<uint32_t>(layer_id),
static_cast<uint8_t>(extruder_id), static_cast<uint8_t>(color_id), { 0.0f, 0.0f } };
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#else
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
libvgcode::PathVertex vertex = { convert(Slic3r::Vec3f(a.x(), a.y(), top_z)), heights[i], widths[i], 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, extrusion_role, EMoveType::Noop, 0, static_cast<uint32_t>(layer_id),
@ -270,6 +310,7 @@ static void convert_lines_to_vertices(const Slic3r::Lines& lines, const std::vec
0.0f, 0.0f, extrusion_role, EMoveType::Noop, 0, static_cast<uint32_t>(layer_id),
static_cast<uint8_t>(extruder_id), static_cast<uint8_t>(color_id), { 0.0f, 0.0f } };
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#endif // ENABLE_ET_SPE187
vertices.emplace_back(vertex);
// add the starting vertex of the segment
vertex.type = EMoveType::Extrude;
@ -277,6 +318,17 @@ static void convert_lines_to_vertices(const Slic3r::Lines& lines, const std::vec
}
// add the ending vertex of the segment
const Slic3r::Vec2f b = unscale(line.b).cast<float>();
#if ENABLE_ET_SPE1872
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
const libvgcode::PathVertex vertex = { convert(Slic3r::Vec3f(b.x(), b.y(), top_z)), heights[i], widths[i], 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, extrusion_role, EMoveType::Extrude, 0, static_cast<uint32_t>(layer_id),
static_cast<uint8_t>(extruder_id), static_cast<uint8_t>(color_id), { 0.0f, 0.0f } };
#else
const libvgcode::PathVertex vertex = { convert(Slic3r::Vec3f(b.x(), b.y(), top_z)), heights[i], widths[i], 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, extrusion_role, EMoveType::Extrude, 0, static_cast<uint32_t>(layer_id),
static_cast<uint8_t>(extruder_id), static_cast<uint8_t>(color_id), { 0.0f, 0.0f } };
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#else
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
const libvgcode::PathVertex vertex = { convert(Slic3r::Vec3f(b.x(), b.y(), top_z)), heights[i], widths[i], 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, extrusion_role, EMoveType::Extrude, 0, static_cast<uint32_t>(layer_id),
@ -286,6 +338,7 @@ static void convert_lines_to_vertices(const Slic3r::Lines& lines, const std::vec
0.0f, 0.0f, extrusion_role, EMoveType::Extrude, 0, static_cast<uint32_t>(layer_id),
static_cast<uint8_t>(extruder_id), static_cast<uint8_t>(color_id), { 0.0f, 0.0f } };
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
#endif // ENABLE_ET_SPE1872
vertices.emplace_back(vertex);
}
}