From 4c735192ef5d5e58a1d634c90e4398a4eb0b3764 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 4 Nov 2019 11:26:36 +0100 Subject: [PATCH] Bugfixes of the new adaptive elephant foot compensation. --- src/libslic3r/ClipperUtils.cpp | 48 +++++++++++++--------- src/libslic3r/ElephantFootCompensation.cpp | 4 +- src/libslic3r/PrintObject.cpp | 5 ++- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp index 3db2f1f00..25100b22f 100644 --- a/src/libslic3r/ClipperUtils.cpp +++ b/src/libslic3r/ClipperUtils.cpp @@ -951,6 +951,7 @@ ClipperLib::Paths fix_after_inner_offset(const ClipperLib::Path &input, ClipperL ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::vector &deltas, double miter_limit) { assert(contour.size() == deltas.size()); + #ifndef NDEBUG // Verify that the deltas are either all positive, or all negative. bool positive = false; @@ -986,7 +987,10 @@ ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::v double lmin = *std::max_element(deltas.begin(), deltas.end()) * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR; double l2min = lmin * lmin; // Minimum angle to consider two edges to be parallel. - double sin_min_parallel = EPSILON + 1. / double(CLIPPER_OFFSET_SCALE); + // Vojtech's estimate. +// const double sin_min_parallel = EPSILON + 1. / double(CLIPPER_OFFSET_SCALE); + // Implementation equal to Clipper. + const double sin_min_parallel = 1.; // Find the last point further from pt by l2min. Vec2d pt = contour.front().cast(); @@ -1012,8 +1016,12 @@ ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::v if (l2 > l2min) break; } - if (j > ilast) + if (j > ilast) { + assert(i <= ilast); + // If the last edge is too short, merge it with the previous edge. + i = ilast; ptnext = contour.front().cast(); + } // Normal to the (ptnext - pt) segment. Vec2d nnext = perp(ptnext - pt).normalized(); @@ -1026,27 +1034,29 @@ ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::v add_offset_point(pt + nprev * delta); add_offset_point(pt); add_offset_point(pt + nnext * delta); - } else if (convex < sin_min_parallel) { - // Nearly parallel. - add_offset_point((nprev.dot(nnext) > 0.) ? (pt + nprev * delta) : pt); } else { - // Convex corner double dot = nprev.dot(nnext); - double r = 1. + dot; - if (r >= miter_limit) - add_offset_point(pt + (nprev + nnext) * (delta / r)); - else { - double dx = std::tan(std::atan2(sin_a, dot) / 4.); - Vec2d newpt1 = pt + (nprev - perp(nprev) * dx) * delta; - Vec2d newpt2 = pt + (nnext + perp(nnext) * dx) * delta; + if (convex < sin_min_parallel && dot > 0.) { + // Nearly parallel. + add_offset_point((nprev.dot(nnext) > 0.) ? (pt + nprev * delta) : pt); + } else { + // Convex corner, possibly extremely sharp if convex < sin_min_parallel. + double r = 1. + dot; + if (r >= miter_limit) + add_offset_point(pt + (nprev + nnext) * (delta / r)); + else { + double dx = std::tan(std::atan2(sin_a, dot) / 4.); + Vec2d newpt1 = pt + (nprev - perp(nprev) * dx) * delta; + Vec2d newpt2 = pt + (nnext + perp(nnext) * dx) * delta; #ifndef NDEBUG - Vec2d vedge = 0.5 * (newpt1 + newpt2) - pt; - double dist_norm = vedge.norm(); - assert(std::abs(dist_norm - delta) < EPSILON); + Vec2d vedge = 0.5 * (newpt1 + newpt2) - pt; + double dist_norm = vedge.norm(); + assert(std::abs(dist_norm - std::abs(delta)) < SCALED_EPSILON); #endif /* NDEBUG */ - add_offset_point(newpt1); - add_offset_point(newpt2); - } + add_offset_point(newpt1); + add_offset_point(newpt2); + } + } } if (i == ilast) diff --git a/src/libslic3r/ElephantFootCompensation.cpp b/src/libslic3r/ElephantFootCompensation.cpp index 5bdeaa954..8b3dda8ae 100644 --- a/src/libslic3r/ElephantFootCompensation.cpp +++ b/src/libslic3r/ElephantFootCompensation.cpp @@ -88,7 +88,7 @@ std::vector contour_distance(const EdgeGrid::Grid &grid, const size_t idx if (std::abs(denom) >= EPSILON) { double t = cross2(dir2, vptpt2) / denom; - assert(t > 0. && t <= 1.); + assert(t > - EPSILON && t < 1. + EPSILON); bool this_valid = true; if (it_contour_and_segment->first == idx_contour) { // The intersected segment originates from the same contour as the starting point. @@ -105,7 +105,7 @@ std::vector contour_distance(const EdgeGrid::Grid &grid, const size_t idx auto it = std::lower_bound(resampled_point_parameters.begin(), resampled_point_parameters.end(), key, lower); assert(it != resampled_point_parameters.end() && it->idx_src == ipt && ! it->interpolated); double t2 = cross2(dir, vptpt2) / denom; - assert(t2 >= 0. && t2 <= 1.); + assert(t2 > - EPSILON && t2 < 1. + EPSILON); if (++ ipt == ipts.size()) param_hi = t2 * dir2.norm(); else diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index b334b70fc..d717fe872 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1819,11 +1819,12 @@ end: if (delta < 0.f || elephant_foot_compensation > 0.f) { // Apply the negative XY compensation. Polygons trimming; + static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5); if (elephant_foot_compensation > 0.f) { - trimming = to_polygons(Slic3r::elephant_foot_compensation(offset_ex(layer->merged(float(EPSILON)), std::min(delta, 0.f) - float(EPSILON)), + trimming = to_polygons(Slic3r::elephant_foot_compensation(offset_ex(layer->merged(eps), std::min(delta, 0.f) - eps), layer->m_regions.front()->flow(frExternalPerimeter), unscale(elephant_foot_compensation))); } else - trimming = offset(layer->merged(float(EPSILON)), delta - float(EPSILON)); + trimming = offset(layer->merged(float(SCALED_EPSILON)), delta - float(SCALED_EPSILON)); for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) layer->m_regions[region_id]->trim_surfaces(trimming); }