Replace last_pos and helpers with optional in GCode.cpp

This commit is contained in:
SachCZ 2024-01-05 16:36:09 +01:00 committed by Martin Šach
parent 7f397cd7b3
commit ff30d7aad3
5 changed files with 54 additions and 48 deletions

View File

@ -1213,7 +1213,7 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer
m_avoid_crossing_perimeters.use_external_mp_once(); m_avoid_crossing_perimeters.use_external_mp_once();
file.write(this->retract_and_wipe()); file.write(this->retract_and_wipe());
file.write(this->travel_to(Point(0, 0), ExtrusionRole::None, "move to origin position for next object")); file.write(this->travel_to(*this->last_position, Point(0, 0), ExtrusionRole::None, "move to origin position for next object"));
m_enable_cooling_markers = true; m_enable_cooling_markers = true;
// Disable motion planner when traveling to first object point. // Disable motion planner when traveling to first object point.
m_avoid_crossing_perimeters.disable_once(); m_avoid_crossing_perimeters.disable_once();
@ -1636,7 +1636,7 @@ std::string GCodeGenerator::placeholder_parser_process(
if (const std::vector<double> &pos = ppi.opt_position->values; ppi.position != pos) { if (const std::vector<double> &pos = ppi.opt_position->values; ppi.position != pos) {
// Update G-code writer. // Update G-code writer.
m_writer.update_position({ pos[0], pos[1], pos[2] }); m_writer.update_position({ pos[0], pos[1], pos[2] });
this->set_last_pos(this->gcode_to_point({ pos[0], pos[1] })); this->last_position = this->gcode_to_point({ pos[0], pos[1] });
} }
for (const Extruder &e : m_writer.extruders()) { for (const Extruder &e : m_writer.extruders()) {
@ -2534,9 +2534,10 @@ void GCodeGenerator::process_layer_single_object(
init_layer_delayed(); init_layer_delayed();
m_config.apply(region.config()); m_config.apply(region.config());
const auto extrusion_name = ironing ? "ironing"sv : "infill"sv; const auto extrusion_name = ironing ? "ironing"sv : "infill"sv;
for (const ExtrusionEntityReference &fill : chain_extrusion_references(temp_fill_extrusions, &m_last_pos)) const Point* start_near = this->last_position ? &(*(this->last_position)) : nullptr;
for (const ExtrusionEntityReference &fill : chain_extrusion_references(temp_fill_extrusions, start_near))
if (auto *eec = dynamic_cast<const ExtrusionEntityCollection*>(&fill.extrusion_entity()); eec) { if (auto *eec = dynamic_cast<const ExtrusionEntityCollection*>(&fill.extrusion_entity()); eec) {
for (const ExtrusionEntityReference &ee : chain_extrusion_references(*eec, &m_last_pos, fill.flipped())) for (const ExtrusionEntityReference &ee : chain_extrusion_references(*eec, start_near, fill.flipped()))
gcode += this->extrude_entity(ee, smooth_path_cache, extrusion_name); gcode += this->extrude_entity(ee, smooth_path_cache, extrusion_name);
} else } else
gcode += this->extrude_entity(fill, smooth_path_cache, extrusion_name); gcode += this->extrude_entity(fill, smooth_path_cache, extrusion_name);
@ -2658,7 +2659,7 @@ void GCodeGenerator::set_origin(const Vec2d &pointf)
{ {
// if origin increases (goes towards right), last_pos decreases because it goes towards left // if origin increases (goes towards right), last_pos decreases because it goes towards left
const auto offset = Point::new_scale(m_origin - pointf); const auto offset = Point::new_scale(m_origin - pointf);
m_last_pos += offset; *(this->last_position) += offset;
m_wipe.offset_path(offset); m_wipe.offset_path(offset);
m_origin = pointf; m_origin = pointf;
} }
@ -2693,8 +2694,8 @@ std::string GCodeGenerator::change_layer(
new_position.z() = print_z; new_position.z() = print_z;
this->writer().update_position(new_position); this->writer().update_position(new_position);
m_previous_layer_last_position = this->m_last_pos_defined ? m_previous_layer_last_position = this->last_position ?
std::optional{to_3d(this->point_to_gcode(this->last_pos()), previous_layer_z)} : std::optional{to_3d(this->point_to_gcode(*this->last_position), previous_layer_z)} :
std::nullopt; std::nullopt;
gcode += GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Layer_Change_Travel); gcode += GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Layer_Change_Travel);
@ -2724,10 +2725,10 @@ std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GC
{ {
// Extrude all loops CCW. // Extrude all loops CCW.
bool is_hole = loop_src.is_clockwise(); bool is_hole = loop_src.is_clockwise();
Point seam_point = this->last_pos(); Point seam_point = *this->last_position;
if (! m_config.spiral_vase && comment_is_perimeter(description)) { if (! m_config.spiral_vase && comment_is_perimeter(description)) {
assert(m_layer != nullptr); assert(m_layer != nullptr);
seam_point = m_seam_placer.place_seam(m_layer, loop_src, m_config.external_perimeters_first, this->last_pos()); seam_point = m_seam_placer.place_seam(m_layer, loop_src, m_config.external_perimeters_first, *this->last_position);
} }
// Because the G-code export has 1um resolution, don't generate segments shorter than 1.5 microns, // Because the G-code export has 1um resolution, don't generate segments shorter than 1.5 microns,
// thus empty path segments will not be produced by G-code export. // thus empty path segments will not be produced by G-code export.
@ -2766,7 +2767,7 @@ std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GC
if (std::optional<Point> pt = wipe_hide_seam(smooth_path, is_hole, scale_(EXTRUDER_CONFIG(nozzle_diameter))); pt) { if (std::optional<Point> pt = wipe_hide_seam(smooth_path, is_hole, scale_(EXTRUDER_CONFIG(nozzle_diameter))); pt) {
// Generate the seam hiding travel move. // Generate the seam hiding travel move.
gcode += m_writer.travel_to_xy(this->point_to_gcode(*pt), "move inwards before travel"); gcode += m_writer.travel_to_xy(this->point_to_gcode(*pt), "move inwards before travel");
this->set_last_pos(*pt); this->last_position = *pt;
} }
} }
@ -2779,7 +2780,7 @@ std::string GCodeGenerator::extrude_skirt(
{ {
assert(loop_src.is_counter_clockwise()); assert(loop_src.is_counter_clockwise());
GCode::SmoothPath smooth_path = smooth_path_cache.resolve_or_fit_split_with_seam( GCode::SmoothPath smooth_path = smooth_path_cache.resolve_or_fit_split_with_seam(
loop_src, false, m_scaled_resolution, this->last_pos(), scaled<double>(0.0015)); loop_src, false, m_scaled_resolution, *this->last_position, scaled<double>(0.0015));
// Clip the path to avoid the extruder to get exactly on the first point of the loop; // Clip the path to avoid the extruder to get exactly on the first point of the loop;
// if polyline was shorter than the clipping distance we'd get a null polyline, so // if polyline was shorter than the clipping distance we'd get a null polyline, so
@ -2971,25 +2972,25 @@ std::string GCodeGenerator::_extrude(
// Make the first travel just one G1. // Make the first travel just one G1.
const Vec3crd point = to_3d(path.front().point, scaled(this->m_last_layer_z + this->m_config.z_offset.value)); const Vec3crd point = to_3d(path.front().point, scaled(this->m_last_layer_z + this->m_config.z_offset.value));
const Vec3d gcode_point = to_3d(this->point_to_gcode(point.head<2>()), unscaled(point.z())); const Vec3d gcode_point = to_3d(this->point_to_gcode(point.head<2>()), unscaled(point.z()));
this->set_last_pos(path.front().point); this->last_position = path.front().point;
this->writer().update_position(gcode_point); this->writer().update_position(gcode_point);
gcode += this->writer().get_travel_to_xy_gcode(gcode_point.head<2>(), "move to first layer point"); gcode += this->writer().get_travel_to_xy_gcode(gcode_point.head<2>(), "move to first layer point");
gcode += this->writer().get_travel_to_z_gcode(gcode_point.z(), "move to first layer point"); gcode += this->writer().get_travel_to_z_gcode(gcode_point.z(), "move to first layer point");
m_current_layer_first_position = gcode_point; m_current_layer_first_position = gcode_point;
} else { } else {
// go to first point of extrusion path // go to first point of extrusion path
if (!m_last_pos_defined) { if (!this->last_position) {
const double z = this->m_last_layer_z + this->m_config.z_offset.value; const double z = this->m_last_layer_z + this->m_config.z_offset.value;
const std::string comment{"move to print after unknown position"}; const std::string comment{"move to print after unknown position"};
gcode += this->retract_and_wipe(); gcode += this->retract_and_wipe();
gcode += this->m_writer.travel_to_xy(this->point_to_gcode(path.front().point), comment); gcode += this->m_writer.travel_to_xy(this->point_to_gcode(path.front().point), comment);
gcode += this->m_writer.get_travel_to_z_gcode(z, comment); gcode += this->m_writer.get_travel_to_z_gcode(z, comment);
} else if ( m_last_pos != path.front().point) { } else if ( this->last_position != path.front().point) {
std::string comment = "move to first "; std::string comment = "move to first ";
comment += description; comment += description;
comment += description_bridge; comment += description_bridge;
comment += " point"; comment += " point";
const std::string travel_gcode{this->travel_to(path.front().point, path_attr.role, comment)}; const std::string travel_gcode{this->travel_to(*this->last_position, path.front().point, path_attr.role, comment)};
gcode += travel_gcode; gcode += travel_gcode;
} }
} }
@ -3213,7 +3214,7 @@ std::string GCodeGenerator::_extrude(
if (dynamic_speed_and_fan_speed.second >= 0) if (dynamic_speed_and_fan_speed.second >= 0)
gcode += ";_RESET_FAN_SPEED\n"; gcode += ";_RESET_FAN_SPEED\n";
this->set_last_pos(path.back().point); this->last_position = path.back().point;
return gcode; return gcode;
} }
@ -3238,7 +3239,7 @@ std::string GCodeGenerator::generate_travel_gcode(
const Vec3d gcode_point{this->point_to_gcode(point)}; const Vec3d gcode_point{this->point_to_gcode(point)};
gcode += this->m_writer.travel_to_xyz(previous_point, gcode_point, comment); gcode += this->m_writer.travel_to_xyz(previous_point, gcode_point, comment);
this->set_last_pos(point.head<2>()); this->last_position = point.head<2>();
previous_point = gcode_point; previous_point = gcode_point;
} }
@ -3331,18 +3332,16 @@ Polyline GCodeGenerator::generate_travel_xy_path(
} }
// This method accepts &point in print coordinates. // This method accepts &point in print coordinates.
std::string GCodeGenerator::travel_to(const Point &point, ExtrusionRole role, std::string comment) std::string GCodeGenerator::travel_to(
{ const Point &start_point, const Point &end_point, ExtrusionRole role, const std::string &comment
) {
const Point start_point = this->last_pos();
// check whether a straight travel move would need retraction // check whether a straight travel move would need retraction
bool could_be_wipe_disabled {false}; bool could_be_wipe_disabled {false};
bool needs_retraction = this->needs_retraction(Polyline{start_point, point}, role); bool needs_retraction = this->needs_retraction(Polyline{start_point, end_point}, role);
Polyline xy_path{generate_travel_xy_path( Polyline xy_path{generate_travel_xy_path(
start_point, point, needs_retraction, could_be_wipe_disabled start_point, end_point, needs_retraction, could_be_wipe_disabled
)}; )};
needs_retraction = this->needs_retraction(xy_path, role); needs_retraction = this->needs_retraction(xy_path, role);
@ -3353,12 +3352,12 @@ std::string GCodeGenerator::travel_to(const Point &point, ExtrusionRole role, st
m_wipe.reset_path(); m_wipe.reset_path();
} }
Point position_before_wipe{this->last_pos()}; Point position_before_wipe{*this->last_position};
wipe_retract_gcode = this->retract_and_wipe(); wipe_retract_gcode = this->retract_and_wipe();
if (this->last_pos() != position_before_wipe) { if (*this->last_position != position_before_wipe) {
xy_path = generate_travel_xy_path( xy_path = generate_travel_xy_path(
this->last_pos(), point, needs_retraction, could_be_wipe_disabled *this->last_position, end_point, needs_retraction, could_be_wipe_disabled
); );
} }
} else { } else {
@ -3522,7 +3521,7 @@ std::string GCodeGenerator::set_extruder(unsigned int extruder_id, double print_
gcode += m_ooze_prevention.post_toolchange(*this); gcode += m_ooze_prevention.post_toolchange(*this);
// The position is now known after the tool change. // The position is now known after the tool change.
this->m_last_pos_defined = false; this->last_position = std::nullopt;
return gcode; return gcode;
} }

View File

@ -103,7 +103,6 @@ public:
m_layer(nullptr), m_layer(nullptr),
m_object_layer_over_raft(false), m_object_layer_over_raft(false),
m_volumetric_speed(0), m_volumetric_speed(0),
m_last_pos_defined(false),
m_last_extrusion_role(GCodeExtrusionRole::None), m_last_extrusion_role(GCodeExtrusionRole::None),
m_last_width(0.0f), m_last_width(0.0f),
#if ENABLE_GCODE_VIEWER_DATA_CHECKING #if ENABLE_GCODE_VIEWER_DATA_CHECKING
@ -124,7 +123,6 @@ public:
const Vec2d& origin() const { return m_origin; } const Vec2d& origin() const { return m_origin; }
void set_origin(const Vec2d &pointf); void set_origin(const Vec2d &pointf);
void set_origin(const coordf_t x, const coordf_t y) { this->set_origin(Vec2d(x, y)); } void set_origin(const coordf_t x, const coordf_t y) { this->set_origin(Vec2d(x, y)); }
const Point& last_pos() const { return m_last_pos; }
// Convert coordinates of the active object to G-code coordinates, possibly adjusted for extruder offset. // Convert coordinates of the active object to G-code coordinates, possibly adjusted for extruder offset.
template<typename Derived> template<typename Derived>
Eigen::Matrix<double, Derived::SizeAtCompileTime, 1, Eigen::DontAlign> point_to_gcode(const Eigen::MatrixBase<Derived> &point) const { Eigen::Matrix<double, Derived::SizeAtCompileTime, 1, Eigen::DontAlign> point_to_gcode(const Eigen::MatrixBase<Derived> &point) const {
@ -186,6 +184,8 @@ public:
}; };
using ObjectsLayerToPrint = std::vector<ObjectLayerToPrint>; using ObjectsLayerToPrint = std::vector<ObjectLayerToPrint>;
std::optional<Point> last_position;
private: private:
class GCodeOutputStream { class GCodeOutputStream {
public: public:
@ -266,8 +266,6 @@ private:
const GCode::SmoothPathCache &smooth_path_cache_global, const GCode::SmoothPathCache &smooth_path_cache_global,
GCodeOutputStream &output_stream); GCodeOutputStream &output_stream);
void set_last_pos(const Point &pos) { m_last_pos = pos; m_last_pos_defined = true; }
bool last_pos_defined() const { return m_last_pos_defined; }
void set_extruders(const std::vector<unsigned int> &extruder_ids); void set_extruders(const std::vector<unsigned int> &extruder_ids);
std::string preamble(); std::string preamble();
std::string change_layer( std::string change_layer(
@ -332,7 +330,12 @@ private:
const bool needs_retraction, const bool needs_retraction,
bool& could_be_wipe_disabled bool& could_be_wipe_disabled
); );
std::string travel_to(const Point &point, ExtrusionRole role, std::string comment); std::string travel_to(
const Point &start_point,
const Point &end_point,
ExtrusionRole role,
const std::string &comment
);
bool needs_retraction(const Polyline &travel, ExtrusionRole role = ExtrusionRole::None); bool needs_retraction(const Polyline &travel, ExtrusionRole role = ExtrusionRole::None);
std::string retract_and_wipe(bool toolchange = false); std::string retract_and_wipe(bool toolchange = false);
@ -421,8 +424,6 @@ private:
double m_last_mm3_per_mm; double m_last_mm3_per_mm;
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
Point m_last_pos;
bool m_last_pos_defined;
std::optional<Vec3d> m_previous_layer_last_position; std::optional<Vec3d> m_previous_layer_last_position;
// This needs to be populated during the layer processing! // This needs to be populated during the layer processing!
std::optional<Vec3d> m_current_layer_first_position; std::optional<Vec3d> m_current_layer_first_position;

View File

@ -1177,7 +1177,7 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCodeGenerator &gcodegen, cons
// Otherwise perform the path planning in the coordinate system of the active object. // Otherwise perform the path planning in the coordinate system of the active object.
bool use_external = m_use_external_mp || m_use_external_mp_once; bool use_external = m_use_external_mp || m_use_external_mp_once;
Point scaled_origin = use_external ? Point::new_scale(gcodegen.origin()(0), gcodegen.origin()(1)) : Point(0, 0); Point scaled_origin = use_external ? Point::new_scale(gcodegen.origin()(0), gcodegen.origin()(1)) : Point(0, 0);
const Point start = gcodegen.last_pos() + scaled_origin; const Point start = *gcodegen.last_position + scaled_origin;
const Point end = point + scaled_origin; const Point end = point + scaled_origin;
const Line travel(start, end); const Line travel(start, end);

View File

@ -164,7 +164,7 @@ std::string Wipe::wipe(GCodeGenerator &gcodegen, bool toolchange)
return done; return done;
}; };
// Start with the current position, which may be different from the wipe path start in case of loop clipping. // Start with the current position, which may be different from the wipe path start in case of loop clipping.
Vec2d prev = gcodegen.point_to_gcode_quantized(gcodegen.last_pos()); Vec2d prev = gcodegen.point_to_gcode_quantized(*gcodegen.last_position);
auto it = this->path().begin(); auto it = this->path().begin();
Vec2d p = gcodegen.point_to_gcode(it->point + m_offset); Vec2d p = gcodegen.point_to_gcode(it->point + m_offset);
++ it; ++ it;
@ -192,7 +192,7 @@ std::string Wipe::wipe(GCodeGenerator &gcodegen, bool toolchange)
// add tag for processor // add tag for processor
assert(p == GCodeFormatter::quantize(p)); assert(p == GCodeFormatter::quantize(p));
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_End) + "\n"; gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_End) + "\n";
gcodegen.set_last_pos(gcodegen.gcode_to_point(p)); gcodegen.last_position = gcodegen.gcode_to_point(p);
} }
} }

View File

@ -57,22 +57,28 @@ std::string WipeTowerIntegration::append_tcr(GCodeGenerator &gcodegen, const Wip
|| is_ramming || is_ramming
|| will_go_down); // don't dig into the print || will_go_down); // don't dig into the print
if (should_travel_to_tower) { if (should_travel_to_tower) {
const Point xy_point = wipe_tower_point_to_object_point(gcodegen, start_pos); const Point xy_point = wipe_tower_point_to_object_point(gcodegen, start_pos);
gcode += gcodegen.retract_and_wipe(); gcode += gcodegen.retract_and_wipe();
gcodegen.m_avoid_crossing_perimeters.use_external_mp_once(); gcodegen.m_avoid_crossing_perimeters.use_external_mp_once();
if (gcodegen.m_current_layer_first_position) { if (gcodegen.m_current_layer_first_position) {
gcode += gcodegen.travel_to( const std::string comment{"Travel to a Wipe Tower"};
xy_point, if (gcodegen.last_position) {
ExtrusionRole::Mixed, gcode += gcodegen.travel_to(
"Travel to a Wipe Tower"); *gcodegen.last_position, xy_point, ExtrusionRole::Mixed, comment
);
} else {
gcode += gcodegen.writer().travel_to_xy(gcodegen.point_to_gcode(xy_point), comment);
gcode += gcodegen.writer().get_travel_to_z_gcode(z, comment);
}
} else { } else {
const Vec3crd point = to_3d(xy_point, scaled(z)); const Vec3crd point = to_3d(xy_point, scaled(z));
const Vec3d gcode_point = to_3d(gcodegen.point_to_gcode(point.head<2>()), z); const Vec3d gcode_point = to_3d(gcodegen.point_to_gcode(point.head<2>()), z);
gcodegen.set_last_pos(point.head<2>()); gcodegen.last_position = point.head<2>();
gcodegen.writer().update_position(gcode_point); gcodegen.writer().update_position(gcode_point);
gcode += gcodegen.writer().get_travel_to_xy_gcode(gcode_point.head<2>(), "move to first layer point"); gcode += gcodegen.writer()
gcode += gcodegen.writer().get_travel_to_z_gcode(gcode_point.z(), "move to first layer point"); .get_travel_to_xy_gcode(gcode_point.head<2>(), "move to first layer point");
gcode += gcodegen.writer()
.get_travel_to_z_gcode(gcode_point.z(), "move to first layer point");
gcodegen.m_current_layer_first_position = gcode_point; gcodegen.m_current_layer_first_position = gcode_point;
} }
gcode += gcodegen.unretract(); gcode += gcodegen.unretract();
@ -110,7 +116,7 @@ std::string WipeTowerIntegration::append_tcr(GCodeGenerator &gcodegen, const Wip
// A phony move to the end position at the wipe tower. // A phony move to the end position at the wipe tower.
gcodegen.writer().travel_to_xy(end_pos.cast<double>()); gcodegen.writer().travel_to_xy(end_pos.cast<double>());
gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, end_pos)); gcodegen.last_position = wipe_tower_point_to_object_point(gcodegen, end_pos);
if (!is_approx(z, current_z)) { if (!is_approx(z, current_z)) {
gcode += gcodegen.writer().retract(); gcode += gcodegen.writer().retract();
gcode += gcodegen.writer().travel_to_z(current_z, "Travel back up to the topmost object layer."); gcode += gcodegen.writer().travel_to_z(current_z, "Travel back up to the topmost object layer.");
@ -259,7 +265,7 @@ std::string WipeTowerIntegration::finalize(GCodeGenerator &gcodegen)
std::string gcode; std::string gcode;
if (std::abs(gcodegen.writer().get_position().z() - m_final_purge.print_z) > EPSILON) if (std::abs(gcodegen.writer().get_position().z() - m_final_purge.print_z) > EPSILON)
gcode += gcodegen.generate_travel_gcode( gcode += gcodegen.generate_travel_gcode(
{{gcodegen.last_pos().x(), gcodegen.last_pos().y(), scaled(m_final_purge.print_z)}}, {{gcodegen.last_position->x(), gcodegen.last_position->y(), scaled(m_final_purge.print_z)}},
"move to safe place for purging" "move to safe place for purging"
); );
gcode += append_tcr(gcodegen, m_final_purge, -1); gcode += append_tcr(gcodegen, m_final_purge, -1);