Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2017-01-02 18:51:43 +0300
committerbubnikv <bubnikv@gmail.com>2017-01-02 18:51:43 +0300
commit17db5bff8d722369b648d41644782772f285ecd0 (patch)
tree05ab2ab9368317d690ba8e8c248ca2dc947065ed /xs/src/libslic3r/ClipperUtils.cpp
parent479f71662516717ea2c996b1241aa80338aaa99c (diff)
Fix of
Number of solid top/bottom layers ignored, Ensure Vertical Shell Thickness interferes with solid top layer count https://github.com/prusa3d/Slic3r/issues/79 https://github.com/prusa3d/Slic3r/issues/60
Diffstat (limited to 'xs/src/libslic3r/ClipperUtils.cpp')
-rw-r--r--xs/src/libslic3r/ClipperUtils.cpp118
1 files changed, 80 insertions, 38 deletions
diff --git a/xs/src/libslic3r/ClipperUtils.cpp b/xs/src/libslic3r/ClipperUtils.cpp
index 7625cba49..b04a018a7 100644
--- a/xs/src/libslic3r/ClipperUtils.cpp
+++ b/xs/src/libslic3r/ClipperUtils.cpp
@@ -278,7 +278,9 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta,
// 3) Subtract holes from the contours.
ClipperLib::Paths output;
- {
+ if (holes.empty()) {
+ output = std::move(contours);
+ } else {
ClipperLib::Clipper clipper;
clipper.Clear();
clipper.AddPaths(contours, ClipperLib::ptSubject, true);
@@ -291,26 +293,22 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta,
return output;
}
-// This is a safe variant of the polygon offset, tailored for a single ExPolygon:
-// a single polygon with multiple non-overlapping holes.
-// Each contour and hole is offsetted separately, then the holes are subtracted from the outer contours.
+// This is a safe variant of the polygons offset, tailored for multiple ExPolygons.
+// It is required, that the input expolygons do not overlap and that the holes of each ExPolygon don't intersect with their respective outer contours.
+// Each ExPolygon is offsetted separately, then the offsetted ExPolygons are united.
ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delta,
ClipperLib::JoinType joinType, double miterLimit)
{
-// printf("new ExPolygon offset\n");
const float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE);
- ClipperLib::Paths contours;
- ClipperLib::Paths holes;
- contours.reserve(expolygons.size());
- {
- size_t n_holes = 0;
- for (size_t i = 0; i < expolygons.size(); ++ i)
- n_holes += expolygons[i].holes.size();
- holes.reserve(n_holes);
- }
-
+ // Offsetted ExPolygons before they are united.
+ ClipperLib::Paths contours_cummulative;
+ contours_cummulative.reserve(expolygons.size());
+ // How many non-empty offsetted expolygons were actually collected into contours_cummulative?
+ // If only one, then there is no need to do a final union.
+ size_t expolygons_collected = 0;
for (Slic3r::ExPolygons::const_iterator it_expoly = expolygons.begin(); it_expoly != expolygons.end(); ++ it_expoly) {
// 1) Offset the outer contour.
+ ClipperLib::Paths contours;
{
ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath(it_expoly->contour);
scaleClipperPolygon(input);
@@ -320,37 +318,81 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delt
else
co.MiterLimit = miterLimit;
co.AddPath(input, joinType, ClipperLib::etClosedPolygon);
- ClipperLib::Paths out;
- co.Execute(out, delta_scaled);
- contours.insert(contours.end(), out.begin(), out.end());
+ co.Execute(contours, delta_scaled);
}
+ if (contours.empty())
+ // No need to try to offset the holes.
+ continue;
+
+ if (it_expoly->holes.empty()) {
+ // No need to subtract holes from the offsetted expolygon, we are done.
+ contours_cummulative.insert(contours_cummulative.end(), contours.begin(), contours.end());
+ ++ expolygons_collected;
+ } else {
+ // 2) Offset the holes one by one, collect the offsetted holes.
+ ClipperLib::Paths holes;
+ {
+ for (Polygons::const_iterator it_hole = it_expoly->holes.begin(); it_hole != it_expoly->holes.end(); ++ it_hole) {
+ ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath_reversed(*it_hole);
+ scaleClipperPolygon(input);
+ ClipperLib::ClipperOffset co;
+ if (joinType == jtRound)
+ co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
+ else
+ co.MiterLimit = miterLimit;
+ co.AddPath(input, joinType, ClipperLib::etClosedPolygon);
+ ClipperLib::Paths out;
+ co.Execute(out, - delta_scaled);
+ holes.insert(holes.end(), out.begin(), out.end());
+ }
+ }
- // 2) Offset the holes one by one, collect the results.
- {
- for (Polygons::const_iterator it_hole = it_expoly->holes.begin(); it_hole != it_expoly->holes.end(); ++ it_hole) {
- ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath_reversed(*it_hole);
- scaleClipperPolygon(input);
- ClipperLib::ClipperOffset co;
- if (joinType == jtRound)
- co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
- else
- co.MiterLimit = miterLimit;
- co.AddPath(input, joinType, ClipperLib::etClosedPolygon);
- ClipperLib::Paths out;
- co.Execute(out, - delta_scaled);
- holes.insert(holes.end(), out.begin(), out.end());
+ // 3) Subtract holes from the contours.
+ if (holes.empty()) {
+ // No hole remaining after an offset. Just copy the outer contour.
+ contours_cummulative.insert(contours_cummulative.end(), contours.begin(), contours.end());
+ ++ expolygons_collected;
+ } else if (delta < 0) {
+ // Negative offset. There is a chance, that the offsetted hole intersects the outer contour.
+ // Subtract the offsetted holes from the offsetted contours.
+ ClipperLib::Clipper clipper;
+ clipper.Clear();
+ clipper.AddPaths(contours, ClipperLib::ptSubject, true);
+ clipper.AddPaths(holes, ClipperLib::ptClip, true);
+ ClipperLib::Paths output;
+ clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
+ if (! output.empty()) {
+ contours_cummulative.insert(contours_cummulative.end(), output.begin(), output.end());
+ ++ expolygons_collected;
+ } else {
+ // The offsetted holes have eaten up the offsetted outer contour.
+ }
+ } else {
+ // Positive offset. As long as the Clipper offset does what one expects it to do, the offsetted hole will have a smaller
+ // area than the original hole or even disappear, therefore there will be no new intersections.
+ // Just collect the reversed holes.
+ contours_cummulative.reserve(contours.size() + holes.size());
+ contours_cummulative.insert(contours_cummulative.end(), contours.begin(), contours.end());
+ // Reverse the holes in place.
+ for (size_t i = 0; i < holes.size(); ++ i)
+ std::reverse(holes[i].begin(), holes[i].end());
+ contours_cummulative.insert(contours_cummulative.end(), holes.begin(), holes.end());
+ ++ expolygons_collected;
}
}
}
- // 3) Subtract holes from the contours.
+ // 4) Unite the offsetted expolygons.
ClipperLib::Paths output;
- {
+ if (expolygons_collected > 1 && delta > 0) {
+ // There is a chance that the outwards offsetted expolygons may intersect. Perform a union.
ClipperLib::Clipper clipper;
- clipper.Clear();
- clipper.AddPaths(contours, ClipperLib::ptSubject, true);
- clipper.AddPaths(holes, ClipperLib::ptClip, true);
- clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
+ clipper.Clear();
+ clipper.AddPaths(contours_cummulative, ClipperLib::ptSubject, true);
+ clipper.Execute(ClipperLib::ctUnion, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
+ } else {
+ // Negative offset. The shrunk expolygons shall not mutually intersect. Just copy the output.
+ output = std::move(contours_cummulative);
}
// 4) Unscale the output.