Quantization of G-code export to achieve more precise extrusion
width control.
This commit is contained in:
parent
1138c563b2
commit
199dc121a5
6 changed files with 138 additions and 135 deletions
src/libslic3r
|
@ -27,7 +27,6 @@
|
|||
#include <boost/foreach.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/beast/core/detail/base64.hpp>
|
||||
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
@ -155,63 +154,52 @@ namespace Slic3r {
|
|||
|
||||
std::string Wipe::wipe(GCode& gcodegen, bool toolchange)
|
||||
{
|
||||
std::string gcode;
|
||||
std::string gcode;
|
||||
const Extruder &extruder = *gcodegen.writer().extruder();
|
||||
|
||||
/* Reduce feedrate a bit; travel speed is often too high to move on existing material.
|
||||
Too fast = ripping of existing material; too slow = short wipe path, thus more blob. */
|
||||
double wipe_speed = gcodegen.writer().config.travel_speed.value * 0.8;
|
||||
|
||||
// get the retraction length
|
||||
double length = toolchange
|
||||
? gcodegen.writer().extruder()->retract_length_toolchange()
|
||||
: gcodegen.writer().extruder()->retract_length();
|
||||
// Shorten the retraction length by the amount already retracted before wipe.
|
||||
length *= (1. - gcodegen.writer().extruder()->retract_before_wipe());
|
||||
|
||||
if (length > 0) {
|
||||
/* Calculate how long we need to travel in order to consume the required
|
||||
amount of retraction. In other words, how far do we move in XY at wipe_speed
|
||||
for the time needed to consume retract_length at retract_speed? */
|
||||
double wipe_dist = scale_(length / gcodegen.writer().extruder()->retract_speed() * wipe_speed);
|
||||
|
||||
/* Take the stored wipe path and replace first point with the current actual position
|
||||
(they might be different, for example, in case of loop clipping). */
|
||||
Polyline wipe_path;
|
||||
wipe_path.append(gcodegen.last_pos());
|
||||
wipe_path.append(
|
||||
this->path.points.begin() + 1,
|
||||
this->path.points.end()
|
||||
);
|
||||
|
||||
wipe_path.clip_end(wipe_path.length() - wipe_dist);
|
||||
|
||||
// subdivide the retraction in segments
|
||||
if (!wipe_path.empty()) {
|
||||
// add tag for processor
|
||||
// Remaining quantized retraction length.
|
||||
if (double retract_length = extruder.retract_to_go(toolchange ? extruder.retract_length_toolchange() : extruder.retract_length());
|
||||
retract_length > 0 && this->path.size() >= 2) {
|
||||
// Reduce feedrate a bit; travel speed is often too high to move on existing material.
|
||||
// Too fast = ripping of existing material; too slow = short wipe path, thus more blob.
|
||||
const double wipe_speed = gcodegen.writer().config.travel_speed.value * 0.8;
|
||||
// Reduce retraction length a bit to avoid effective retraction speed to be greater than the configured one
|
||||
// due to rounding (TODO: test and/or better math for this).
|
||||
const double xy_to_e = 0.95 * extruder.retract_speed() / wipe_speed;
|
||||
// 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());
|
||||
auto it = this->path.points.begin();
|
||||
Vec2d p = gcodegen.point_to_gcode_quantized(*(++ it));
|
||||
if (p != prev) {
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Start) + "\n";
|
||||
for (const Line& line : wipe_path.lines()) {
|
||||
double segment_length = line.length();
|
||||
/* Reduce retraction length a bit to avoid effective retraction speed to be greater than the configured one
|
||||
due to rounding (TODO: test and/or better math for this) */
|
||||
double dE = length * (segment_length / wipe_dist) * 0.95;
|
||||
auto end = this->path.points.end();
|
||||
bool done = false;
|
||||
for (; it != end; ++ it) {
|
||||
p = gcodegen.point_to_gcode_quantized(*it);
|
||||
double segment_length = (p - prev).norm();
|
||||
double dE = GCodeFormatter::quantize_e(xy_to_e * segment_length);
|
||||
if (dE > retract_length - EPSILON) {
|
||||
if (dE > retract_length + EPSILON)
|
||||
// Shorten the segment.
|
||||
p = prev + (p - prev) * (retract_length / dE);
|
||||
dE = retract_length;
|
||||
done = true;
|
||||
}
|
||||
//FIXME one shall not generate the unnecessary G1 Fxxx commands, here wipe_speed is a constant inside this cycle.
|
||||
// Is it here for the cooling markers? Or should it be outside of the cycle?
|
||||
gcode += gcodegen.writer().set_speed(wipe_speed * 60, "", gcodegen.enable_cooling_markers() ? ";_WIPE" : "");
|
||||
gcode += gcodegen.writer().extrude_to_xy(
|
||||
gcodegen.point_to_gcode(line.b),
|
||||
-dE,
|
||||
"wipe and retract"
|
||||
);
|
||||
gcode += gcodegen.writer().set_speed(wipe_speed * 60, {}, gcodegen.enable_cooling_markers() ? ";_WIPE" : "");
|
||||
gcode += gcodegen.writer().extrude_to_xy(p, -dE, "wipe and retract");
|
||||
prev = p;
|
||||
retract_length -= dE;
|
||||
}
|
||||
// add tag for processor
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_End) + "\n";
|
||||
gcodegen.set_last_pos(wipe_path.points.back());
|
||||
gcodegen.set_last_pos(gcodegen.gcode_to_point(prev));
|
||||
}
|
||||
|
||||
// prevent wiping again on same path
|
||||
this->reset_path();
|
||||
}
|
||||
|
||||
// Prevent wiping again on the same path.
|
||||
this->reset_path();
|
||||
return gcode;
|
||||
}
|
||||
|
||||
|
@ -3010,13 +2998,15 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||
double path_length = 0.;
|
||||
{
|
||||
std::string comment = m_config.gcode_comments ? description : "";
|
||||
for (const Line &line : path.polyline.lines()) {
|
||||
const double line_length = line.length() * SCALING_FACTOR;
|
||||
Vec2d prev = this->point_to_gcode_quantized(path.polyline.points.front());
|
||||
auto it = path.polyline.points.begin();
|
||||
auto end = path.polyline.points.end();
|
||||
for (++ it; it != end; ++ it) {
|
||||
Vec2d p = this->point_to_gcode_quantized(*it);
|
||||
const double line_length = (p - prev).norm();
|
||||
path_length += line_length;
|
||||
gcode += m_writer.extrude_to_xy(
|
||||
this->point_to_gcode(line.b),
|
||||
e_per_mm * line_length,
|
||||
comment);
|
||||
gcode += m_writer.extrude_to_xy(p, e_per_mm * line_length, comment);
|
||||
prev = p;
|
||||
}
|
||||
}
|
||||
if (m_enable_cooling_markers)
|
||||
|
@ -3239,7 +3229,13 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
|||
Vec2d GCode::point_to_gcode(const Point &point) const
|
||||
{
|
||||
Vec2d extruder_offset = EXTRUDER_CONFIG(extruder_offset);
|
||||
return unscale(point) + m_origin - extruder_offset;
|
||||
return unscaled<double>(point) + m_origin - extruder_offset;
|
||||
}
|
||||
|
||||
Vec2d GCode::point_to_gcode_quantized(const Point &point) const
|
||||
{
|
||||
Vec2d p = this->point_to_gcode(point);
|
||||
return { GCodeFormatter::quantize_xyzf(p.x()), GCodeFormatter::quantize_xyzf(p.y()) };
|
||||
}
|
||||
|
||||
// convert a model-space scaled point into G-code coordinates
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue