Fixed an issue that the wipe was shorter when it was located where extrusion width was changing.

This commit is contained in:
Lukáš Hejl 2022-07-22 11:50:58 +02:00 committed by Lukas Matena
parent 0c22ca3ece
commit 952a6c882c
5 changed files with 100 additions and 43 deletions

View File

@ -268,13 +268,13 @@ void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extr
{ {
for (const ClipperLib_Z::Path &extrusion_path : extrusion_paths) { for (const ClipperLib_Z::Path &extrusion_path : extrusion_paths) {
ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion_path); ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion_path);
Slic3r::append(dst, thick_polyline_to_extrusion_paths(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON))); Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON)).paths);
} }
} }
void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow) void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow)
{ {
ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion); ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion);
Slic3r::append(dst, thick_polyline_to_extrusion_paths(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON))); Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON)).paths);
} }
} // namespace Slic3r } // namespace Slic3r

View File

@ -426,14 +426,13 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
for (const ThickPolyline &thick_polyline : thick_polylines) { for (const ThickPolyline &thick_polyline : thick_polylines) {
Flow new_flow = surface_fill.params.flow.with_spacing(float(f->spacing)); Flow new_flow = surface_fill.params.flow.with_spacing(float(f->spacing));
ExtrusionPaths paths = thick_polyline_to_extrusion_paths(thick_polyline, surface_fill.params.extrusion_role, new_flow, scaled<float>(0.05), 0); ExtrusionMultiPath multi_path = thick_polyline_to_multi_path(thick_polyline, surface_fill.params.extrusion_role, new_flow, scaled<float>(0.05), float(SCALED_EPSILON));
// Append paths to collection. // Append paths to collection.
if (!paths.empty()) { if (!multi_path.empty()) {
if (paths.front().first_point() == paths.back().last_point()) if (multi_path.paths.front().first_point() == multi_path.paths.back().last_point())
eec->entities.emplace_back(new ExtrusionLoop(std::move(paths))); eec->entities.emplace_back(new ExtrusionLoop(std::move(multi_path.paths)));
else else
for (ExtrusionPath &path : paths) eec->entities.emplace_back(new ExtrusionMultiPath(std::move(multi_path)));
eec->entities.emplace_back(new ExtrusionPath(std::move(path)));
} }
} }

View File

@ -2642,6 +2642,12 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// thus empty path segments will not be produced by G-code export. // thus empty path segments will not be produced by G-code export.
loop.split_at(last_pos, false, scaled<double>(0.0015)); loop.split_at(last_pos, false, scaled<double>(0.0015));
for (auto it = std::next(loop.paths.begin()); it != loop.paths.end(); ++it) {
assert(it->polyline.points.size() >= 2);
assert(std::prev(it)->polyline.last_point() == it->polyline.first_point());
}
assert(loop.paths.front().first_point() == loop.paths.back().last_point());
// 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
// we discard it in that case // we discard it in that case
@ -2670,8 +2676,21 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// reset acceleration // reset acceleration
gcode += m_writer.set_acceleration((unsigned int)(m_config.default_acceleration.value + 0.5)); gcode += m_writer.set_acceleration((unsigned int)(m_config.default_acceleration.value + 0.5));
if (m_wipe.enable) if (m_wipe.enable) {
m_wipe.path = paths.front().polyline; // TODO: don't limit wipe to last path m_wipe.path = paths.front().polyline;
for (auto it = std::next(paths.begin()); it != paths.end(); ++it) {
if (is_bridge(it->role()))
break; // Don't perform a wipe on bridges.
assert(it->polyline.points.size() >= 2);
assert(m_wipe.path.points.back() == it->polyline.first_point());
if (m_wipe.path.points.back() != it->polyline.first_point())
break; // ExtrusionLoop is interrupted in some place.
m_wipe.path.points.insert(m_wipe.path.points.end(), it->polyline.points.begin() + 1, it->polyline.points.end());
}
}
// make a little move inwards before leaving loop // make a little move inwards before leaving loop
if (paths.back().role() == erExternalPerimeter && m_layer != NULL && m_config.perimeters.value > 1 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 3) { if (paths.back().role() == erExternalPerimeter && m_layer != NULL && m_config.perimeters.value > 1 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 3) {
@ -2712,6 +2731,10 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string description, double speed) std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string description, double speed)
{ {
for (auto it = std::next(multipath.paths.begin()); it != multipath.paths.end(); ++it) {
assert(it->polyline.points.size() >= 2);
assert(std::prev(it)->polyline.last_point() == it->polyline.first_point());
}
// extrude along the path // extrude along the path
std::string gcode; std::string gcode;
for (ExtrusionPath path : multipath.paths) { for (ExtrusionPath path : multipath.paths) {
@ -2721,8 +2744,20 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
gcode += this->_extrude(path, description, speed); gcode += this->_extrude(path, description, speed);
} }
if (m_wipe.enable) { if (m_wipe.enable) {
m_wipe.path = std::move(multipath.paths.back().polyline); // TODO: don't limit wipe to last path m_wipe.path = std::move(multipath.paths.back().polyline);
m_wipe.path.reverse(); m_wipe.path.reverse();
for (auto it = std::next(multipath.paths.rbegin()); it != multipath.paths.rend(); ++it) {
if (is_bridge(it->role()))
break; // Do not perform a wipe on bridges.
assert(it->polyline.points.size() >= 2);
assert(m_wipe.path.points.back() == it->polyline.last_point());
if (m_wipe.path.points.back() != it->polyline.last_point())
break; // ExtrusionMultiPath is interrupted in some place.
m_wipe.path.points.insert(m_wipe.path.points.end(), it->polyline.points.rbegin() + 1, it->polyline.points.rend());
}
} }
// reset acceleration // reset acceleration
gcode += m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5)); gcode += m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));

View File

@ -21,9 +21,9 @@
namespace Slic3r { namespace Slic3r {
ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance) ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance)
{ {
ExtrusionPaths paths; ExtrusionMultiPath multi_path;
ExtrusionPath path(role); ExtrusionPath path(role);
ThickLines lines = thick_polyline.thicklines(); ThickLines lines = thick_polyline.thicklines();
@ -38,8 +38,8 @@ ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_poly
path.polyline.points.back() = line.b; // If the variable path is non-empty, connect this tiny line to it. path.polyline.points.back() = line.b; // If the variable path is non-empty, connect this tiny line to it.
else if (i + 1 < (int)lines.size()) // If there is at least one following line, connect this tiny line to it. else if (i + 1 < (int)lines.size()) // If there is at least one following line, connect this tiny line to it.
lines[i + 1].a = line.a; lines[i + 1].a = line.a;
else if (!paths.empty()) else if (!multi_path.paths.empty())
paths.back().polyline.points.back() = line.b; // Connect this tiny line to the last finished path. multi_path.paths.back().polyline.points.back() = line.b; // Connect this tiny line to the last finished path.
// If any of the above isn't satisfied, then remove this tiny line. // If any of the above isn't satisfied, then remove this tiny line.
continue; continue;
@ -103,38 +103,36 @@ ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_poly
path.polyline.append(line.b); path.polyline.append(line.b);
} else { } else {
// we need to initialize a new line // we need to initialize a new line
paths.emplace_back(std::move(path)); multi_path.paths.emplace_back(std::move(path));
path = ExtrusionPath(role); path = ExtrusionPath(role);
-- i; -- i;
} }
} }
} }
if (path.polyline.is_valid()) if (path.polyline.is_valid())
paths.emplace_back(std::move(path)); multi_path.paths.emplace_back(std::move(path));
return paths; return multi_path;
} }
static void variable_width(const ThickPolylines& polylines, ExtrusionRole role, const Flow &flow, std::vector<ExtrusionEntity*> &out) static void variable_width(const ThickPolylines &polylines, ExtrusionRole role, const Flow &flow, std::vector<ExtrusionEntity *> &out)
{ {
// This value determines granularity of adaptive width, as G-code does not allow // This value determines granularity of adaptive width, as G-code does not allow
// variable extrusion within a single move; this value shall only affect the amount // variable extrusion within a single move; this value shall only affect the amount
// of segments, and any pruning shall be performed before we apply this tolerance. // of segments, and any pruning shall be performed before we apply this tolerance.
const auto tolerance = float(scale_(0.05)); const auto tolerance = float(scale_(0.05));
for (const ThickPolyline &p : polylines) { for (const ThickPolyline &p : polylines) {
ExtrusionPaths paths = thick_polyline_to_extrusion_paths(p, role, flow, tolerance, tolerance); ExtrusionMultiPath multi_path = thick_polyline_to_multi_path(p, role, flow, tolerance, tolerance);
// Append paths to collection. // Append paths to collection.
if (!paths.empty()) { if (!multi_path.paths.empty()) {
for (auto it = std::next(paths.begin()); it != paths.end(); ++it) { for (auto it = std::next(multi_path.paths.begin()); it != multi_path.paths.end(); ++it) {
assert(it->polyline.points.size() >= 2); assert(it->polyline.points.size() >= 2);
assert(std::prev(it)->polyline.last_point() == it->polyline.first_point()); assert(std::prev(it)->polyline.last_point() == it->polyline.first_point());
} }
if (paths.front().first_point() == paths.back().last_point()) { if (multi_path.paths.front().first_point() == multi_path.paths.back().last_point())
out.emplace_back(new ExtrusionLoop(std::move(paths))); out.emplace_back(new ExtrusionLoop(std::move(multi_path.paths)));
} else { else
for (ExtrusionPath &path : paths) out.emplace_back(new ExtrusionMultiPath(std::move(multi_path)));
out.emplace_back(new ExtrusionPath(std::move(path)));
}
} }
} }
} }
@ -534,10 +532,35 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &p
else else
extrusion_loop.make_clockwise(); extrusion_loop.make_clockwise();
for (auto it = std::next(extrusion_loop.paths.begin()); it != extrusion_loop.paths.end(); ++it) {
assert(it->polyline.points.size() >= 2);
assert(std::prev(it)->polyline.last_point() == it->polyline.first_point());
}
assert(extrusion_loop.paths.front().first_point() == extrusion_loop.paths.back().last_point());
extrusion_coll.append(std::move(extrusion_loop)); extrusion_coll.append(std::move(extrusion_loop));
} else } else {
for (ExtrusionPath &path : paths) // Because we are processing one ExtrusionLine all ExtrusionPaths should form one connected path.
extrusion_coll.append(ExtrusionPath(std::move(path))); // But there is possibility that due to numerical issue there is poss
assert([&paths = std::as_const(paths)]() -> bool {
for (auto it = std::next(paths.begin()); it != paths.end(); ++it)
if (std::prev(it)->polyline.last_point() != it->polyline.first_point())
return false;
return true;
}());
ExtrusionMultiPath multi_path;
multi_path.paths.emplace_back(std::move(paths.front()));
for (auto it_path = std::next(paths.begin()); it_path != paths.end(); ++it_path) {
if (multi_path.paths.back().last_point() != it_path->first_point()) {
extrusion_coll.append(ExtrusionMultiPath(std::move(multi_path)));
multi_path = ExtrusionMultiPath();
}
multi_path.paths.emplace_back(std::move(*it_path));
}
extrusion_coll.append(ExtrusionMultiPath(std::move(multi_path)));
}
} }
} }

View File

@ -72,7 +72,7 @@ private:
Polygons m_lower_slices_polygons; Polygons m_lower_slices_polygons;
}; };
ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, float tolerance, float merge_tolerance); ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, float tolerance, float merge_tolerance);
} }