Merge remote-tracking branch 'origin/et_lines_g2_g3'
This commit is contained in:
commit
0566e3d6d6
@ -36,6 +36,10 @@ static const float DEFAULT_FILAMENT_DIAMETER = 1.75f;
|
|||||||
static const float DEFAULT_FILAMENT_DENSITY = 1.245f;
|
static const float DEFAULT_FILAMENT_DENSITY = 1.245f;
|
||||||
static const Slic3r::Vec3f DEFAULT_EXTRUDER_OFFSET = Slic3r::Vec3f::Zero();
|
static const Slic3r::Vec3f DEFAULT_EXTRUDER_OFFSET = Slic3r::Vec3f::Zero();
|
||||||
|
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
static const std::string INTERNAL_G2G3_TAG = "!#!#! internal only - from G2/G3 expansion !#!#!";
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
const std::vector<std::string> GCodeProcessor::Reserved_Tags = {
|
const std::vector<std::string> GCodeProcessor::Reserved_Tags = {
|
||||||
@ -1579,6 +1583,10 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool
|
|||||||
switch (cmd[1]) {
|
switch (cmd[1]) {
|
||||||
case '0': { process_G0(line); break; } // Move
|
case '0': { process_G0(line); break; } // Move
|
||||||
case '1': { process_G1(line); break; } // Move
|
case '1': { process_G1(line); break; } // Move
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
case '2': { process_G2_G3(line, true); break; } // CW Arc Move
|
||||||
|
case '3': { process_G2_G3(line, false); break; } // CCW Arc Move
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2433,9 +2441,10 @@ void GCodeProcessor::process_G0(const GCodeReader::GCodeLine& line)
|
|||||||
|
|
||||||
void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
||||||
{
|
{
|
||||||
float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
|
const float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
|
||||||
float filament_radius = 0.5f * filament_diameter;
|
const float filament_radius = 0.5f * filament_diameter;
|
||||||
float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
|
const float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
|
||||||
|
#if !ENABLE_PROCESS_G2_G3_LINES
|
||||||
auto absolute_position = [this, area_filament_cross_section](Axis axis, const GCodeReader::GCodeLine& lineG1) {
|
auto absolute_position = [this, area_filament_cross_section](Axis axis, const GCodeReader::GCodeLine& lineG1) {
|
||||||
bool is_relative = (m_global_positioning_type == EPositioningType::Relative);
|
bool is_relative = (m_global_positioning_type == EPositioningType::Relative);
|
||||||
if (axis == E)
|
if (axis == E)
|
||||||
@ -2451,6 +2460,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
else
|
else
|
||||||
return m_start_position[axis];
|
return m_start_position[axis];
|
||||||
};
|
};
|
||||||
|
#endif // !ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
|
||||||
auto move_type = [this](const AxisCoords& delta_pos) {
|
auto move_type = [this](const AxisCoords& delta_pos) {
|
||||||
EMoveType type = EMoveType::Noop;
|
EMoveType type = EMoveType::Noop;
|
||||||
@ -2478,7 +2488,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
|
|
||||||
// updates axes positions from line
|
// updates axes positions from line
|
||||||
for (unsigned char a = X; a <= E; ++a) {
|
for (unsigned char a = X; a <= E; ++a) {
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
m_end_position[a] = extract_absolute_position_on_axis((Axis)a, line, double(area_filament_cross_section));
|
||||||
|
#else
|
||||||
m_end_position[a] = absolute_position((Axis)a, line);
|
m_end_position[a] = absolute_position((Axis)a, line);
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
}
|
}
|
||||||
|
|
||||||
// updates feedrate from line, if present
|
// updates feedrate from line, if present
|
||||||
@ -2497,11 +2511,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
if (max_abs_delta == 0.0f)
|
if (max_abs_delta == 0.0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EMoveType type = move_type(delta_pos);
|
const EMoveType type = move_type(delta_pos);
|
||||||
if (type == EMoveType::Extrude) {
|
if (type == EMoveType::Extrude) {
|
||||||
float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
|
const float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
|
||||||
float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
|
const float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
|
||||||
float area_toolpath_cross_section = volume_extruded_filament / delta_xyz;
|
const float area_toolpath_cross_section = volume_extruded_filament / delta_xyz;
|
||||||
|
|
||||||
// save extruded volume to the cache
|
// save extruded volume to the cache
|
||||||
m_used_filaments.increase_caches(volume_extruded_filament);
|
m_used_filaments.increase_caches(volume_extruded_filament);
|
||||||
@ -2512,6 +2526,16 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
m_mm3_per_mm_compare.update(area_toolpath_cross_section, m_extrusion_role);
|
m_mm3_per_mm_compare.update(area_toolpath_cross_section, m_extrusion_role);
|
||||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||||
|
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
if (m_forced_height > 0.0f)
|
||||||
|
m_height = m_forced_height;
|
||||||
|
else if (m_layer_id == 0)
|
||||||
|
m_height = (m_end_position[Z] <= double(m_first_layer_height)) ? m_end_position[Z] : m_first_layer_height;
|
||||||
|
else if (line.comment() != INTERNAL_G2G3_TAG){
|
||||||
|
if (m_end_position[Z] > m_extruded_last_z + EPSILON && delta_pos[Z] == 0.0)
|
||||||
|
m_height = m_end_position[Z] - m_extruded_last_z;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (m_forced_height > 0.0f)
|
if (m_forced_height > 0.0f)
|
||||||
m_height = m_forced_height;
|
m_height = m_forced_height;
|
||||||
else if (m_layer_id == 0)
|
else if (m_layer_id == 0)
|
||||||
@ -2520,6 +2544,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
if (m_end_position[Z] > m_extruded_last_z + EPSILON)
|
if (m_end_position[Z] > m_extruded_last_z + EPSILON)
|
||||||
m_height = m_end_position[Z] - m_extruded_last_z;
|
m_height = m_end_position[Z] - m_extruded_last_z;
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
|
||||||
if (m_height == 0.0f)
|
if (m_height == 0.0f)
|
||||||
m_height = DEFAULT_TOOLPATH_HEIGHT;
|
m_height = DEFAULT_TOOLPATH_HEIGHT;
|
||||||
@ -2527,7 +2552,10 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
if (m_end_position[Z] == 0.0f)
|
if (m_end_position[Z] == 0.0f)
|
||||||
m_end_position[Z] = m_height;
|
m_end_position[Z] = m_height;
|
||||||
|
|
||||||
m_extruded_last_z = m_end_position[Z];
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
if (line.comment() != INTERNAL_G2G3_TAG)
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
m_extruded_last_z = m_end_position[Z];
|
||||||
m_options_z_corrector.update(m_height);
|
m_options_z_corrector.update(m_height);
|
||||||
|
|
||||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||||
@ -2567,9 +2595,9 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
return delta_pos[X] == 0.0f && delta_pos[Y] == 0.0f && delta_pos[Z] == 0.0f && delta_pos[E] != 0.0f;
|
return delta_pos[X] == 0.0f && delta_pos[Y] == 0.0f && delta_pos[Z] == 0.0f && delta_pos[E] != 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
float distance = move_length(delta_pos);
|
const float distance = move_length(delta_pos);
|
||||||
assert(distance != 0.0f);
|
assert(distance != 0.0f);
|
||||||
float inv_distance = 1.0f / distance;
|
const float inv_distance = 1.0f / distance;
|
||||||
|
|
||||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||||
TimeMachine& machine = m_time_processor.machines[i];
|
TimeMachine& machine = m_time_processor.machines[i];
|
||||||
@ -2600,7 +2628,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
|
|
||||||
curr.abs_axis_feedrate[a] = std::abs(curr.axis_feedrate[a]);
|
curr.abs_axis_feedrate[a] = std::abs(curr.axis_feedrate[a]);
|
||||||
if (curr.abs_axis_feedrate[a] != 0.0f) {
|
if (curr.abs_axis_feedrate[a] != 0.0f) {
|
||||||
float axis_max_feedrate = get_axis_max_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
const float axis_max_feedrate = get_axis_max_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
||||||
if (axis_max_feedrate != 0.0f)
|
if (axis_max_feedrate != 0.0f)
|
||||||
min_feedrate_factor = std::min<float>(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
|
min_feedrate_factor = std::min<float>(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
|
||||||
}
|
}
|
||||||
@ -2623,7 +2651,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
get_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)));
|
get_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)));
|
||||||
|
|
||||||
for (unsigned char a = X; a <= E; ++a) {
|
for (unsigned char a = X; a <= E; ++a) {
|
||||||
float axis_max_acceleration = get_axis_max_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
const float axis_max_acceleration = get_axis_max_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
||||||
if (acceleration * std::abs(delta_pos[a]) * inv_distance > axis_max_acceleration)
|
if (acceleration * std::abs(delta_pos[a]) * inv_distance > axis_max_acceleration)
|
||||||
acceleration = axis_max_acceleration;
|
acceleration = axis_max_acceleration;
|
||||||
}
|
}
|
||||||
@ -2634,7 +2662,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
curr.safe_feedrate = block.feedrate_profile.cruise;
|
curr.safe_feedrate = block.feedrate_profile.cruise;
|
||||||
|
|
||||||
for (unsigned char a = X; a <= E; ++a) {
|
for (unsigned char a = X; a <= E; ++a) {
|
||||||
float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
const float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
||||||
if (curr.abs_axis_feedrate[a] > axis_max_jerk)
|
if (curr.abs_axis_feedrate[a] > axis_max_jerk)
|
||||||
curr.safe_feedrate = std::min(curr.safe_feedrate, axis_max_jerk);
|
curr.safe_feedrate = std::min(curr.safe_feedrate, axis_max_jerk);
|
||||||
}
|
}
|
||||||
@ -2668,7 +2696,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the jerk depending on whether the axis is coasting in the same direction or reversing a direction.
|
// Calculate the jerk depending on whether the axis is coasting in the same direction or reversing a direction.
|
||||||
float jerk =
|
const float jerk =
|
||||||
(v_exit > v_entry) ?
|
(v_exit > v_entry) ?
|
||||||
((v_entry > 0.0f || v_exit < 0.0f) ?
|
((v_entry > 0.0f || v_exit < 0.0f) ?
|
||||||
// coasting
|
// coasting
|
||||||
@ -2682,7 +2710,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
// axis reversal
|
// axis reversal
|
||||||
std::max(-v_exit, v_entry));
|
std::max(-v_exit, v_entry));
|
||||||
|
|
||||||
float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
const float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
||||||
if (jerk > axis_max_jerk) {
|
if (jerk > axis_max_jerk) {
|
||||||
v_factor *= axis_max_jerk / jerk;
|
v_factor *= axis_max_jerk / jerk;
|
||||||
limited = true;
|
limited = true;
|
||||||
@ -2694,14 +2722,14 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
|
|
||||||
// Now the transition velocity is known, which maximizes the shared exit / entry velocity while
|
// Now the transition velocity is known, which maximizes the shared exit / entry velocity while
|
||||||
// respecting the jerk factors, it may be possible, that applying separate safe exit / entry velocities will achieve faster prints.
|
// respecting the jerk factors, it may be possible, that applying separate safe exit / entry velocities will achieve faster prints.
|
||||||
float vmax_junction_threshold = vmax_junction * 0.99f;
|
const float vmax_junction_threshold = vmax_junction * 0.99f;
|
||||||
|
|
||||||
// Not coasting. The machine will stop and start the movements anyway, better to start the segment from start.
|
// Not coasting. The machine will stop and start the movements anyway, better to start the segment from start.
|
||||||
if (prev.safe_feedrate > vmax_junction_threshold && curr.safe_feedrate > vmax_junction_threshold)
|
if (prev.safe_feedrate > vmax_junction_threshold && curr.safe_feedrate > vmax_junction_threshold)
|
||||||
vmax_junction = curr.safe_feedrate;
|
vmax_junction = curr.safe_feedrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
float v_allowable = max_allowable_speed(-acceleration, curr.safe_feedrate, block.distance);
|
const float v_allowable = max_allowable_speed(-acceleration, curr.safe_feedrate, block.distance);
|
||||||
block.feedrate_profile.entry = std::min(vmax_junction, v_allowable);
|
block.feedrate_profile.entry = std::min(vmax_junction, v_allowable);
|
||||||
|
|
||||||
block.max_entry_speed = vmax_junction;
|
block.max_entry_speed = vmax_junction;
|
||||||
@ -2754,9 +2782,217 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||||||
m_result.spiral_vase_layers.back().second.second = m_result.moves.size() - 1;
|
m_result.spiral_vase_layers.back().second.second = m_result.moves.size() - 1;
|
||||||
|
|
||||||
// store move
|
// store move
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
store_move_vertex(type, line.comment() == INTERNAL_G2G3_TAG);
|
||||||
|
#else
|
||||||
store_move_vertex(type);
|
store_move_vertex(type);
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool clockwise)
|
||||||
|
{
|
||||||
|
if (!line.has('X') || !line.has('Y') || !line.has('I') || !line.has('J'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// relative center
|
||||||
|
Vec3f rel_center = Vec3f::Zero();
|
||||||
|
if (!line.has_value('I', rel_center.x()) || !line.has_value('J', rel_center.y()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// scale center, if needed
|
||||||
|
if (m_units == EUnits::Inches)
|
||||||
|
rel_center *= INCHES_TO_MM;
|
||||||
|
|
||||||
|
struct Arc
|
||||||
|
{
|
||||||
|
Vec3d start{ Vec3d::Zero() };
|
||||||
|
Vec3d end{ Vec3d::Zero() };
|
||||||
|
Vec3d center{ Vec3d::Zero() };
|
||||||
|
|
||||||
|
double angle{ 0.0 };
|
||||||
|
double delta_x() const { return end.x() - start.x(); }
|
||||||
|
double delta_y() const { return end.y() - start.y(); }
|
||||||
|
double delta_z() const { return end.z() - start.z(); }
|
||||||
|
|
||||||
|
double length() const { return angle * start_radius(); }
|
||||||
|
double travel_length() const { return std::sqrt(sqr(length() + sqr(delta_z()))); }
|
||||||
|
double start_radius() const { return (start - center).norm(); }
|
||||||
|
double end_radius() const { return (end - center).norm(); }
|
||||||
|
|
||||||
|
Vec3d relative_start() const { return start - center; }
|
||||||
|
Vec3d relative_end() const { return end - center; }
|
||||||
|
|
||||||
|
bool closed() const { return end.isApprox(start); }
|
||||||
|
};
|
||||||
|
|
||||||
|
Arc arc;
|
||||||
|
|
||||||
|
// arc start endpoint
|
||||||
|
arc.start = Vec3d(m_start_position[X], m_start_position[Y], m_start_position[Z]);
|
||||||
|
|
||||||
|
// arc center
|
||||||
|
arc.center = arc.start + rel_center.cast<double>();
|
||||||
|
|
||||||
|
const float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
|
||||||
|
const float filament_radius = 0.5f * filament_diameter;
|
||||||
|
const float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
|
||||||
|
|
||||||
|
AxisCoords end_position = m_start_position;
|
||||||
|
for (unsigned char a = X; a <= E; ++a) {
|
||||||
|
end_position[a] = extract_absolute_position_on_axis((Axis)a, line, double(area_filament_cross_section));
|
||||||
|
}
|
||||||
|
|
||||||
|
// arc end endpoint
|
||||||
|
arc.end = Vec3d(end_position[X], end_position[Y], end_position[Z]);
|
||||||
|
|
||||||
|
// radii
|
||||||
|
if (std::abs(arc.end_radius() - arc.start_radius()) > EPSILON) {
|
||||||
|
// what to do ???
|
||||||
|
}
|
||||||
|
|
||||||
|
// updates feedrate from line
|
||||||
|
std::optional<float> feedrate;
|
||||||
|
if (line.has_f())
|
||||||
|
feedrate = m_feed_multiply.current * line.f() * MMMIN_TO_MMSEC;
|
||||||
|
|
||||||
|
// updates extrusion from line
|
||||||
|
std::optional<float> extrusion;
|
||||||
|
if (line.has_e())
|
||||||
|
extrusion = end_position[E] - m_start_position[E];
|
||||||
|
|
||||||
|
// relative arc endpoints
|
||||||
|
const Vec3d rel_arc_start = arc.relative_start();
|
||||||
|
const Vec3d rel_arc_end = arc.relative_end();
|
||||||
|
|
||||||
|
// arc angle
|
||||||
|
if (arc.closed())
|
||||||
|
arc.angle = 2.0 * PI;
|
||||||
|
else {
|
||||||
|
arc.angle = std::atan2(rel_arc_start.x() * rel_arc_end.y() - rel_arc_start.y() * rel_arc_end.x(),
|
||||||
|
rel_arc_start.x() * rel_arc_end.x() + rel_arc_start.y() * rel_arc_end.y());
|
||||||
|
if (arc.angle < 0.0)
|
||||||
|
arc.angle += 2.0 * PI;
|
||||||
|
if (clockwise)
|
||||||
|
arc.angle -= 2.0 * PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
const double travel_length = arc.travel_length();
|
||||||
|
if (travel_length < 0.001)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto adjust_target = [this, area_filament_cross_section](const AxisCoords& target, const AxisCoords& prev_position) {
|
||||||
|
AxisCoords ret = target;
|
||||||
|
if (m_global_positioning_type == EPositioningType::Relative) {
|
||||||
|
for (unsigned char a = X; a <= E; ++a) {
|
||||||
|
ret[a] -= prev_position[a];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_e_local_positioning_type == EPositioningType::Relative)
|
||||||
|
ret[E] -= prev_position[E];
|
||||||
|
|
||||||
|
if (m_use_volumetric_e)
|
||||||
|
ret[E] *= area_filament_cross_section;
|
||||||
|
|
||||||
|
const double lengthsScaleFactor = (m_units == EUnits::Inches) ? double(INCHES_TO_MM) : 1.0;
|
||||||
|
for (unsigned char a = X; a <= E; ++a) {
|
||||||
|
ret[a] /= lengthsScaleFactor;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto internal_only_g1_line = [](const AxisCoords& target, bool has_z, const std::optional<float>& feedrate, const std::optional<float>& extrusion) {
|
||||||
|
std::string ret = (boost::format("G1 X%1% Y%2%") % target[X] % target[Y]).str();
|
||||||
|
if (has_z)
|
||||||
|
ret += (boost::format(" Z%1%") % target[Z]).str();
|
||||||
|
if (feedrate.has_value())
|
||||||
|
ret += (boost::format(" F%1%") % *feedrate).str();
|
||||||
|
if (extrusion.has_value())
|
||||||
|
ret += (boost::format(" E%1%") % target[E]).str();
|
||||||
|
|
||||||
|
ret += (boost::format(" ;%1%\n") % INTERNAL_G2G3_TAG).str();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
// calculate arc segments
|
||||||
|
// reference:
|
||||||
|
// Prusa-Firmware\Firmware\motion_control.cpp - mc_arc()
|
||||||
|
|
||||||
|
// segments count
|
||||||
|
static const double MM_PER_ARC_SEGMENT = 1.0;
|
||||||
|
const size_t segments = std::max<size_t>(std::floor(travel_length / MM_PER_ARC_SEGMENT), 1);
|
||||||
|
|
||||||
|
const double theta_per_segment = arc.angle / double(segments);
|
||||||
|
const double z_per_segment = arc.delta_z() / double(segments);
|
||||||
|
const double extruder_per_segment = (extrusion.has_value()) ? *extrusion / double(segments) : 0.0;
|
||||||
|
|
||||||
|
double cos_T = 1.0 - 0.5 * sqr(theta_per_segment); // Small angle approximation
|
||||||
|
double sin_T = theta_per_segment;
|
||||||
|
|
||||||
|
AxisCoords prev_target = m_start_position;
|
||||||
|
AxisCoords arc_target;
|
||||||
|
double sin_Ti;
|
||||||
|
double cos_Ti;
|
||||||
|
double r_axisi;
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
// Initialize the linear axis
|
||||||
|
arc_target[Z] = m_start_position[Z];
|
||||||
|
|
||||||
|
// Initialize the extruder axis
|
||||||
|
arc_target[E] = m_start_position[E];
|
||||||
|
|
||||||
|
static const size_t N_ARC_CORRECTION = 25;
|
||||||
|
|
||||||
|
Vec3d curr_rel_arc_start = arc.relative_start();
|
||||||
|
|
||||||
|
std::string gcode;
|
||||||
|
|
||||||
|
for (size_t i = 1; i < segments; ++i) { // Increment (segments-1)
|
||||||
|
if (count < N_ARC_CORRECTION) {
|
||||||
|
// Apply vector rotation matrix
|
||||||
|
r_axisi = curr_rel_arc_start.x() * sin_T + curr_rel_arc_start.y() * cos_T;
|
||||||
|
curr_rel_arc_start.x() = curr_rel_arc_start.x() * cos_T - curr_rel_arc_start.y() * sin_T;
|
||||||
|
curr_rel_arc_start.y() = r_axisi;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
|
||||||
|
// Compute exact location by applying transformation matrix from initial radius vector(=-offset).
|
||||||
|
cos_Ti = ::cos(double(i) * theta_per_segment);
|
||||||
|
sin_Ti = ::sin(double(i) * theta_per_segment);
|
||||||
|
curr_rel_arc_start.x() = -double(rel_center.x()) * cos_Ti + double(rel_center.y()) * sin_Ti;
|
||||||
|
curr_rel_arc_start.y() = -double(rel_center.x()) * sin_Ti - double(rel_center.y()) * cos_Ti;
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update arc_target location
|
||||||
|
arc_target[X] = arc.center.x() + curr_rel_arc_start.x();
|
||||||
|
arc_target[Y] = arc.center.y() + curr_rel_arc_start.y();
|
||||||
|
arc_target[Z] += z_per_segment;
|
||||||
|
arc_target[E] += extruder_per_segment;
|
||||||
|
|
||||||
|
gcode += internal_only_g1_line(adjust_target(arc_target, prev_target), z_per_segment != 0.0, feedrate, extrusion);
|
||||||
|
prev_target = arc_target;
|
||||||
|
|
||||||
|
// feedrate is constant, we do not need to repeat it
|
||||||
|
feedrate.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure last segment arrives at target location.
|
||||||
|
gcode += internal_only_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, feedrate, extrusion);
|
||||||
|
|
||||||
|
// process fake gcode lines
|
||||||
|
GCodeReader parser;
|
||||||
|
parser.parse_buffer(gcode, [this](GCodeReader&, const GCodeReader::GCodeLine& line) {
|
||||||
|
// force all lines to share the same id
|
||||||
|
--m_line_id;
|
||||||
|
process_gcode_line(line, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
|
||||||
void GCodeProcessor::process_G10(const GCodeReader::GCodeLine& line)
|
void GCodeProcessor::process_G10(const GCodeReader::GCodeLine& line)
|
||||||
{
|
{
|
||||||
// stores retract move
|
// stores retract move
|
||||||
@ -3257,7 +3493,11 @@ void GCodeProcessor::process_T(const std::string_view command)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
void GCodeProcessor::store_move_vertex(EMoveType type, bool internal_only)
|
||||||
|
#else
|
||||||
void GCodeProcessor::store_move_vertex(EMoveType type)
|
void GCodeProcessor::store_move_vertex(EMoveType type)
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
{
|
{
|
||||||
m_last_line_id = (type == EMoveType::Color_change || type == EMoveType::Pause_Print || type == EMoveType::Custom_GCode) ?
|
m_last_line_id = (type == EMoveType::Color_change || type == EMoveType::Pause_Print || type == EMoveType::Custom_GCode) ?
|
||||||
m_line_id + 1 :
|
m_line_id + 1 :
|
||||||
@ -3277,7 +3517,12 @@ void GCodeProcessor::store_move_vertex(EMoveType type)
|
|||||||
m_mm3_per_mm,
|
m_mm3_per_mm,
|
||||||
m_fan_speed,
|
m_fan_speed,
|
||||||
m_extruder_temps[m_extruder_id],
|
m_extruder_temps[m_extruder_id],
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
static_cast<float>(m_result.moves.size()),
|
||||||
|
internal_only
|
||||||
|
#else
|
||||||
static_cast<float>(m_result.moves.size())
|
static_cast<float>(m_result.moves.size())
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
});
|
});
|
||||||
|
|
||||||
// stores stop time placeholders for later use
|
// stores stop time placeholders for later use
|
||||||
@ -3474,5 +3719,24 @@ void GCodeProcessor::update_estimated_times_stats()
|
|||||||
m_result.print_statistics.used_filaments_per_role = m_used_filaments.filaments_per_role;
|
m_result.print_statistics.used_filaments_per_role = m_used_filaments.filaments_per_role;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
double GCodeProcessor::extract_absolute_position_on_axis(Axis axis, const GCodeReader::GCodeLine& line, double area_filament_cross_section)
|
||||||
|
{
|
||||||
|
if (line.has(Slic3r::Axis(axis))) {
|
||||||
|
bool is_relative = (m_global_positioning_type == EPositioningType::Relative);
|
||||||
|
if (axis == E)
|
||||||
|
is_relative |= (m_e_local_positioning_type == EPositioningType::Relative);
|
||||||
|
|
||||||
|
const double lengthsScaleFactor = (m_units == EUnits::Inches) ? double(INCHES_TO_MM) : 1.0;
|
||||||
|
double ret = line.value(Slic3r::Axis(axis)) * lengthsScaleFactor;
|
||||||
|
if (axis == E && m_use_volumetric_e)
|
||||||
|
ret /= area_filament_cross_section;
|
||||||
|
return is_relative ? m_start_position[axis] + ret : m_origin[axis] + ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return m_start_position[axis];
|
||||||
|
}
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
|
||||||
} /* namespace Slic3r */
|
} /* namespace Slic3r */
|
||||||
|
|
||||||
|
@ -113,6 +113,9 @@ namespace Slic3r {
|
|||||||
float fan_speed{ 0.0f }; // percentage
|
float fan_speed{ 0.0f }; // percentage
|
||||||
float temperature{ 0.0f }; // Celsius degrees
|
float temperature{ 0.0f }; // Celsius degrees
|
||||||
float time{ 0.0f }; // s
|
float time{ 0.0f }; // s
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
bool internal_only{ false };
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
|
||||||
float volumetric_rate() const { return feedrate * mm3_per_mm; }
|
float volumetric_rate() const { return feedrate * mm3_per_mm; }
|
||||||
};
|
};
|
||||||
@ -645,6 +648,11 @@ namespace Slic3r {
|
|||||||
void process_G0(const GCodeReader::GCodeLine& line);
|
void process_G0(const GCodeReader::GCodeLine& line);
|
||||||
void process_G1(const GCodeReader::GCodeLine& line);
|
void process_G1(const GCodeReader::GCodeLine& line);
|
||||||
|
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
// Arc Move
|
||||||
|
void process_G2_G3(const GCodeReader::GCodeLine& line, bool clockwise);
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
|
||||||
// Retract
|
// Retract
|
||||||
void process_G10(const GCodeReader::GCodeLine& line);
|
void process_G10(const GCodeReader::GCodeLine& line);
|
||||||
|
|
||||||
@ -745,7 +753,11 @@ namespace Slic3r {
|
|||||||
void process_T(const GCodeReader::GCodeLine& line);
|
void process_T(const GCodeReader::GCodeLine& line);
|
||||||
void process_T(const std::string_view command);
|
void process_T(const std::string_view command);
|
||||||
|
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
void store_move_vertex(EMoveType type, bool internal_only = false);
|
||||||
|
#else
|
||||||
void store_move_vertex(EMoveType type);
|
void store_move_vertex(EMoveType type);
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
|
||||||
void set_extrusion_role(ExtrusionRole role);
|
void set_extrusion_role(ExtrusionRole role);
|
||||||
|
|
||||||
@ -770,6 +782,10 @@ namespace Slic3r {
|
|||||||
void simulate_st_synchronize(float additional_time = 0.0f);
|
void simulate_st_synchronize(float additional_time = 0.0f);
|
||||||
|
|
||||||
void update_estimated_times_stats();
|
void update_estimated_times_stats();
|
||||||
|
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
double extract_absolute_position_on_axis(Axis axis, const GCodeReader::GCodeLine& line, double area_filament_cross_section);
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace Slic3r */
|
} /* namespace Slic3r */
|
||||||
|
@ -75,6 +75,8 @@
|
|||||||
#define ENABLE_NEW_RECTANGLE_SELECTION (1 && ENABLE_2_5_0_ALPHA1)
|
#define ENABLE_NEW_RECTANGLE_SELECTION (1 && ENABLE_2_5_0_ALPHA1)
|
||||||
// Enable alternative version of file_wildcards()
|
// Enable alternative version of file_wildcards()
|
||||||
#define ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR (1 && ENABLE_2_5_0_ALPHA1)
|
#define ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR (1 && ENABLE_2_5_0_ALPHA1)
|
||||||
|
// Enable processing of gcode G2 and G3 lines
|
||||||
|
#define ENABLE_PROCESS_G2_G3_LINES (1 && ENABLE_2_5_0_ALPHA1)
|
||||||
|
|
||||||
|
|
||||||
#endif // _prusaslicer_technologies_h_
|
#endif // _prusaslicer_technologies_h_
|
||||||
|
@ -2284,13 +2284,19 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
|
|||||||
size_t move_id = i - seams_count;
|
size_t move_id = i - seams_count;
|
||||||
|
|
||||||
if (move.type == EMoveType::Extrude) {
|
if (move.type == EMoveType::Extrude) {
|
||||||
// layers zs
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back();
|
if (move.extrusion_role != erNone && !move.internal_only) {
|
||||||
const double z = static_cast<double>(move.position.z());
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z)
|
// layers zs
|
||||||
m_layers.append(z, { last_travel_s_id, move_id });
|
const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back();
|
||||||
else
|
const double z = static_cast<double>(move.position.z());
|
||||||
m_layers.get_ranges().back().last = move_id;
|
if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z)
|
||||||
|
m_layers.append(z, { last_travel_s_id, move_id });
|
||||||
|
else
|
||||||
|
m_layers.get_ranges().back().last = move_id;
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
}
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
// extruder ids
|
// extruder ids
|
||||||
m_extruder_ids.emplace_back(move.extruder_id);
|
m_extruder_ids.emplace_back(move.extruder_id);
|
||||||
// roles
|
// roles
|
||||||
|
@ -859,6 +859,36 @@ void Preview::update_moves_slider()
|
|||||||
if (view.endpoints.last < view.endpoints.first)
|
if (view.endpoints.last < view.endpoints.first)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if ENABLE_PROCESS_G2_G3_LINES
|
||||||
|
assert(view.endpoints.first <= view.current.first && view.current.first <= view.endpoints.last);
|
||||||
|
assert(view.endpoints.first <= view.current.last && view.current.last <= view.endpoints.last);
|
||||||
|
|
||||||
|
std::vector<double> values;
|
||||||
|
values.reserve(view.endpoints.last - view.endpoints.first + 1);
|
||||||
|
std::vector<double> alternate_values;
|
||||||
|
alternate_values.reserve(view.endpoints.last - view.endpoints.first + 1);
|
||||||
|
unsigned int last_gcode_id = view.gcode_ids[view.endpoints.first];
|
||||||
|
for (unsigned int i = view.endpoints.first; i <= view.endpoints.last; ++i) {
|
||||||
|
if (i > view.endpoints.first) {
|
||||||
|
// skip consecutive moves with same gcode id (resulting from processing G2 and G3 lines)
|
||||||
|
if (last_gcode_id == view.gcode_ids[i]) {
|
||||||
|
values.back() = static_cast<double>(i + 1);
|
||||||
|
alternate_values.back() = static_cast<double>(view.gcode_ids[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
last_gcode_id = view.gcode_ids[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
values.emplace_back(static_cast<double>(i + 1));
|
||||||
|
alternate_values.emplace_back(static_cast<double>(view.gcode_ids[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_moves_slider->SetSliderValues(values);
|
||||||
|
m_moves_slider->SetSliderAlternateValues(alternate_values);
|
||||||
|
m_moves_slider->SetMaxValue(int(values.size()) - 1);
|
||||||
|
m_moves_slider->SetSelectionSpan(values.front() - 1, values.back() - 1);
|
||||||
|
#else
|
||||||
std::vector<double> values(view.endpoints.last - view.endpoints.first + 1);
|
std::vector<double> values(view.endpoints.last - view.endpoints.first + 1);
|
||||||
std::vector<double> alternate_values(view.endpoints.last - view.endpoints.first + 1);
|
std::vector<double> alternate_values(view.endpoints.last - view.endpoints.first + 1);
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
@ -873,6 +903,7 @@ void Preview::update_moves_slider()
|
|||||||
m_moves_slider->SetSliderAlternateValues(alternate_values);
|
m_moves_slider->SetSliderAlternateValues(alternate_values);
|
||||||
m_moves_slider->SetMaxValue(view.endpoints.last - view.endpoints.first);
|
m_moves_slider->SetMaxValue(view.endpoints.last - view.endpoints.first);
|
||||||
m_moves_slider->SetSelectionSpan(view.current.first - view.endpoints.first, view.current.last - view.endpoints.first);
|
m_moves_slider->SetSelectionSpan(view.current.first - view.endpoints.first, view.current.last - view.endpoints.first);
|
||||||
|
#endif // ENABLE_PROCESS_G2_G3_LINES
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preview::enable_moves_slider(bool enable)
|
void Preview::enable_moves_slider(bool enable)
|
||||||
|
Loading…
Reference in New Issue
Block a user