diff options
author | Lukáš Hejl <hejl.lukas@gmail.com> | 2022-07-21 21:06:12 +0300 |
---|---|---|
committer | Lukáš Hejl <hejl.lukas@gmail.com> | 2022-07-22 09:33:27 +0300 |
commit | e14da6224ac21de5adee89f7039d645cdc83f718 (patch) | |
tree | f6e121d585339ef558e0233154e36c1ecdb25640 | |
parent | 2a865919a0debd4ada519b02385dc44da33cc59c (diff) |
Fixed an issue when an open perimeter containing part of an overhang perimeter was split into two parts and wasn't extruded as continuous extrusion.
-rw-r--r-- | src/libslic3r/PerimeterGenerator.cpp | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 7ebd93659..8db77cb6b 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -10,6 +10,7 @@ #include <cmath> #include <cassert> #include <stack> +#include <unordered_map> namespace Slic3r { @@ -478,8 +479,40 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &p // Reapply the nearest point search for starting point. // We allow polyline reversal because Clipper may have randomly reversed polylines during clipping. // Arachne sometimes creates extrusion with zero-length (just two same endpoints); - if (!paths.empty()) - chain_and_reorder_extrusion_paths(paths, &paths.front().first_point()); + if (!paths.empty()) { + Point start_point = paths.front().first_point(); + if (!extrusion->is_closed) { + // Especially for open extrusion, we need to select a starting point that is at the start + // or the end of the extrusions to make one continuous line. Also, we prefer a non-overhang + // starting point. + struct PointInfo + { + size_t occurrence = 0; + bool is_overhang = false; + }; + std::unordered_map<Point, PointInfo, PointHash> point_occurrence; + for (const ExtrusionPath &path : paths) { + ++point_occurrence[path.polyline.first_point()].occurrence; + ++point_occurrence[path.polyline.last_point()].occurrence; + if (path.role() == erOverhangPerimeter) { + point_occurrence[path.polyline.first_point()].is_overhang = true; + point_occurrence[path.polyline.last_point()].is_overhang = true; + } + } + + // Prefer non-overhang point as a starting point. + for (const std::pair<Point, PointInfo> pt : point_occurrence) + if (pt.second.occurrence == 1) { + start_point = pt.first; + if (!pt.second.is_overhang) { + start_point = pt.first; + break; + } + } + } + + chain_and_reorder_extrusion_paths(paths, &start_point); + } } else { extrusion_paths_append(paths, *extrusion, role, is_external ? perimeter_generator.ext_perimeter_flow : perimeter_generator.perimeter_flow); } |