From dfbae648bfff75ef7cb6e5d45ba576d52d74ffae Mon Sep 17 00:00:00 2001 From: bubnikv <bubnikv@gmail.com> Date: Wed, 19 Feb 2020 12:57:54 +0100 Subject: [PATCH] Follow up on 6deb6a776d38eacf22bd3da78c4546dd5e3a8ccb: Fixed orientation of contours after Elephant Foot Compensation. --- src/libslic3r/ClipperUtils.cpp | 54 +++++++++++++++++++--- src/libslic3r/ElephantFootCompensation.cpp | 19 ++++++-- 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp index d4c2f05e1..d40d79b3d 100644 --- a/src/libslic3r/ClipperUtils.cpp +++ b/src/libslic3r/ClipperUtils.cpp @@ -855,7 +855,12 @@ Polygons top_level_islands(const Slic3r::Polygons &polygons) } // Outer offset shall not split the input contour into multiples. It is expected, that the solution will be non empty and it will contain just a single polygon. -ClipperLib::Paths fix_after_outer_offset(const ClipperLib::Path &input, ClipperLib::PolyFillType filltype, bool reverse_result) +ClipperLib::Paths fix_after_outer_offset( + const ClipperLib::Path &input, + // combination of default prameters to correspond to void ClipperOffset::Execute(Paths& solution, double delta) + // to produce a CCW output contour from CCW input contour for a positive offset. + ClipperLib::PolyFillType filltype, // = ClipperLib::pftPositive + bool reverse_result) // = false { ClipperLib::Paths solution; if (! input.empty()) { @@ -867,8 +872,13 @@ ClipperLib::Paths fix_after_outer_offset(const ClipperLib::Path &input, ClipperL return solution; } -// Inner offset may split the source contour into multiple contours, but one shall not be inside the other. -ClipperLib::Paths fix_after_inner_offset(const ClipperLib::Path &input, ClipperLib::PolyFillType filltype, bool reverse_result) +// Inner offset may split the source contour into multiple contours, but one resulting contour shall not lie inside the other. +ClipperLib::Paths fix_after_inner_offset( + const ClipperLib::Path &input, + // combination of default prameters to correspond to void ClipperOffset::Execute(Paths& solution, double delta) + // to produce a CCW output contour from CCW input contour for a negative offset. + ClipperLib::PolyFillType filltype, // = ClipperLib::pftNegative + bool reverse_result) // = true { ClipperLib::Paths solution; if (! input.empty()) { @@ -1041,12 +1051,20 @@ Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector<std::v // 1) Offset the outer contour. ClipperLib::Paths contours = fix_after_inner_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftNegative, true); +#ifndef NDEBUG + for (auto &c : contours) + assert(ClipperLib::Area(c) > 0.); +#endif /* NDEBUG */ // 2) Offset the holes one by one, collect the results. ClipperLib::Paths holes; holes.reserve(expoly.holes.size()); for (const Polygon& hole : expoly.holes) - append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftPositive, false)); + append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftNegative, false)); +#ifndef NDEBUG + for (auto &c : holes) + assert(ClipperLib::Area(c) > 0.); +#endif /* NDEBUG */ // 3) Subtract holes from the contours. ClipperLib::Paths output; @@ -1077,12 +1095,20 @@ for (const std::vector<float>& ds : deltas) // 1) Offset the outer contour. ClipperLib::Paths contours = fix_after_outer_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftPositive, false); +#ifndef NDEBUG + for (auto &c : contours) + assert(ClipperLib::Area(c) > 0.); +#endif /* NDEBUG */ // 2) Offset the holes one by one, collect the results. ClipperLib::Paths holes; holes.reserve(expoly.holes.size()); for (const Polygon& hole : expoly.holes) append(holes, fix_after_inner_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftPositive, true)); +#ifndef NDEBUG + for (auto &c : holes) + assert(ClipperLib::Area(c) > 0.); +#endif /* NDEBUG */ // 3) Subtract holes from the contours. ClipperLib::Paths output; @@ -1113,12 +1139,20 @@ for (const std::vector<float>& ds : deltas) // 1) Offset the outer contour. ClipperLib::Paths contours = fix_after_outer_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftPositive, false); +#ifndef NDEBUG + for (auto &c : contours) + assert(ClipperLib::Area(c) > 0.); +#endif /* NDEBUG */ // 2) Offset the holes one by one, collect the results. ClipperLib::Paths holes; holes.reserve(expoly.holes.size()); for (const Polygon& hole : expoly.holes) append(holes, fix_after_inner_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftPositive, true)); +#ifndef NDEBUG + for (auto &c : holes) + assert(ClipperLib::Area(c) > 0.); +#endif /* NDEBUG */ // 3) Subtract holes from the contours. unscaleClipperPolygons(contours); @@ -1152,13 +1186,21 @@ ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<s #endif /* NDEBUG */ // 1) Offset the outer contour. - ClipperLib::Paths contours = fix_after_inner_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftNegative, false); + ClipperLib::Paths contours = fix_after_inner_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftNegative, true); +#ifndef NDEBUG + for (auto &c : contours) + assert(ClipperLib::Area(c) > 0.); +#endif /* NDEBUG */ // 2) Offset the holes one by one, collect the results. ClipperLib::Paths holes; holes.reserve(expoly.holes.size()); for (const Polygon& hole : expoly.holes) - append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftNegative, true)); + append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftNegative, false)); +#ifndef NDEBUG + for (auto &c : holes) + assert(ClipperLib::Area(c) > 0.); +#endif /* NDEBUG */ // 3) Subtract holes from the contours. unscaleClipperPolygons(contours); diff --git a/src/libslic3r/ElephantFootCompensation.cpp b/src/libslic3r/ElephantFootCompensation.cpp index 130f1b58f..c11157627 100644 --- a/src/libslic3r/ElephantFootCompensation.cpp +++ b/src/libslic3r/ElephantFootCompensation.cpp @@ -524,8 +524,20 @@ static inline void smooth_compensation_banded(const Points &contour, float band, } } +#ifndef NDEBUG +static bool validate_expoly_orientation(const ExPolygon &expoly) +{ + bool valid = expoly.contour.is_counter_clockwise(); + for (auto &h : expoly.holes) + valid &= h.is_clockwise(); + return valid; +} +#endif /* NDEBUG */ + ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, double min_contour_width, const double compensation) { + assert(validate_expoly_orientation(input_expoly)); + double scaled_compensation = scale_(compensation); min_contour_width = scale_(min_contour_width); double min_contour_width_compensated = min_contour_width + 2. * scaled_compensation; @@ -546,6 +558,7 @@ ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, double min_c { EdgeGrid::Grid grid; ExPolygon simplified = input_expoly.simplify(SCALED_EPSILON).front(); + assert(validate_expoly_orientation(simplified)); BoundingBox bbox = get_extents(simplified.contour); bbox.offset(SCALED_EPSILON); grid.set_bbox(bbox); @@ -558,6 +571,7 @@ ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, double min_c Polygon &poly = (idx_contour == 0) ? resampled.contour : resampled.holes[idx_contour - 1]; std::vector<ResampledPoint> resampled_point_parameters; poly.points = resample_polygon(poly.points, resample_interval, resampled_point_parameters); + assert(poly.is_counter_clockwise() == (idx_contour == 0)); std::vector<float> dists = contour_distance2(grid, idx_contour, poly.points, resampled_point_parameters, scaled_compensation, search_radius); for (float &d : dists) { // printf("Point %d, Distance: %lf\n", int(&d - dists.data()), unscale<double>(d)); @@ -593,10 +607,7 @@ ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, double min_c } } - // FIXME: orientations are messed up (Tamas) - out.contour.make_counter_clockwise(); - for (auto &h : out.holes) h.make_clockwise(); - + assert(validate_expoly_orientation(out)); return out; }