From a358fe27046dd18c3935a7bd76513c64bc295648 Mon Sep 17 00:00:00 2001 From: supermerill Date: Tue, 21 Dec 2021 20:25:24 +0100 Subject: Fix medial axis creating points on top of each other. supermerill/SuperSlicer#2099 supermerill/SuperSlicer#2102 --- src/libslic3r/MedialAxis.cpp | 32 +++++++++++++++++++++++++++++--- src/libslic3r/libslic3r.h | 26 ++++++++++---------------- 2 files changed, 39 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/libslic3r/MedialAxis.cpp b/src/libslic3r/MedialAxis.cpp index db05fbd17..02b4816e2 100644 --- a/src/libslic3r/MedialAxis.cpp +++ b/src/libslic3r/MedialAxis.cpp @@ -1330,8 +1330,12 @@ MedialAxis::concatenate_polylines_with_crossing(ThickPolylines& pp) && polyline.width.back() > best_candidate->width[1]) { polyline.width.back() = std::min(polyline.width[polyline.width.size() - 2], best_candidate->width[1]); } - polyline.points.insert(polyline.points.end(), best_candidate->points.begin() + 1, best_candidate->points.end()); - polyline.width.insert(polyline.width.end(), best_candidate->width.begin() + 1, best_candidate->width.end()); + //be far enough + int far_idx = 1; + while (far_idx < best_candidate->points.size() && polyline.last_point().coincides_with_epsilon(best_candidate->points[far_idx])) + far_idx++; + polyline.points.insert(polyline.points.end(), best_candidate->points.begin() + far_idx, best_candidate->points.end()); + polyline.width.insert(polyline.width.end(), best_candidate->width.begin() + far_idx, best_candidate->width.end()); polyline.endpoints.second = best_candidate->endpoints.second; assert(polyline.width.size() == polyline.points.size()); if (best_idx < i) i--; @@ -1799,6 +1803,24 @@ MedialAxis::build(ThickPolylines &polylines_out) // pp.erase(pp.begin() + tp_idx); // --tp_idx; //} + //voronoi problem: can put two consecutive points at the same position. Delete one. + for (size_t i = 1; i < tp.points.size()-1; i++) { + if (tp.points[i-1].distance_to_square(tp.points[i]) < SCALED_EPSILON) { + tp.points.erase(tp.points.begin() + i); + tp.width.erase(tp.width.begin() + i); + i--; + } + } + //delete the inner one + if (tp.points.size()>2 && tp.points[tp.points.size() - 2].distance_to_square(tp.points.back()) < SCALED_EPSILON) { + tp.points.erase(tp.points.end() - 2); + tp.width.erase(tp.width.end() - 2); + } + //delete null-length polylines + if (tp.length() < SCALED_EPSILON && tp.first_point().coincides_with_epsilon(tp.last_point())) { + pp.erase(pp.begin() + tp_idx); + --tp_idx; + } } //std::cout << "polyline_from_voronoi\n"; //{ @@ -2078,8 +2100,11 @@ thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow fl continue; } } else if (i > 0 && resolution_internal > line_len + prev_line_len) { - ThickLine& prev_line = lines[i - 1]; //merge lines? + //if it's a loop, merge only if the distance is high enough + if (p.first_point() == p.last_point() && p.length() < (line_len + prev_line_len) * 6) + continue; + ThickLine& prev_line = lines[i - 1]; coordf_t width = prev_line_len * (prev_line.a_width + prev_line.b_width) / 2; width += line_len * (line.a_width + line.b_width) / 2; prev_line.b = line.b; @@ -2149,6 +2174,7 @@ thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow fl path.height = flow.height; } } + assert(path.polyline.points.size() > 2 || path.first_point() != path.last_point()); } if (path.polyline.is_valid()) paths.emplace_back(std::move(path)); diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 3b4f34264..d1c816bcb 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -34,32 +34,27 @@ using coord_t = int64_t; using coordf_t = double; -//FIXME This epsilon value is used for many non-related purposes: -// For a threshold of a squared Euclidean distance, -// for a trheshold in a difference of radians, -// for a threshold of a cross product of two non-normalized vectors etc. -static constexpr double EPSILON = 1e-4; // Scaling factor for a conversion from coord_t to coordf_t: 10e-6 // This scaling generates a following fixed point representation with for a 32bit integer: // 0..4294mm with 1nm resolution // int32_t fits an interval of (-2147.48mm, +2147.48mm) // with int64_t we don't have to worry anymore about the size of the int. static constexpr double SCALING_FACTOR = 0.000001; -#ifdef __linux__ -static constexpr double UNSCALING_FACTOR = 1000000; -#else -static constexpr double UNSCALING_FACTOR = 1 / SCALING_FACTOR; -#endif +static constexpr double UNSCALING_FACTOR = 1000000; // 1 / SCALING_FACTOR; + +//FIXME This epsilon value is used for many non-related purposes: +// For a threshold of a squared Euclidean distance, +// for a trheshold in a difference of radians, +// for a threshold of a cross product of two non-normalized vectors etc. +static constexpr double EPSILON = 1e-4; +static constexpr coord_t SCALED_EPSILON = 100; // coord_t(EPSILON/ SCALING_FACTOR); // RESOLUTION, SCALED_RESOLUTION: Used as an error threshold for a Douglas-Peucker polyline simplification algorithm. //#define RESOLUTION 0.0125 //#define SCALED_RESOLUTION 12500 //#define SCALED_RESOLUTION (RESOLUTION / SCALING_FACTOR) static constexpr coordf_t RESOLUTION = 0.0125; -#ifdef __linux__ -static constexpr coord_t SCALED_RESOLUTION = 12500; -#else -static constexpr coord_t SCALED_RESOLUTION = coord_t(0.0125 * UNSCALING_FACTOR); -#endif +static constexpr coord_t SCALED_RESOLUTION = 12500; // coord_t(0.0125 * UNSCALING_FACTOR); + //for creating circles (for brim_ear) #define POLY_SIDES 24 #define PI 3.141592653589793238 @@ -72,7 +67,6 @@ static constexpr double INSET_OVERLAP_TOLERANCE = 0.4; //inline coord_t scale_(coordf_t v) { return coord_t(floor(v / SCALING_FACTOR + 0.5f)); } #define scale_(val) (coord_t)((val) / SCALING_FACTOR) -#define SCALED_EPSILON scale_(EPSILON) #define SLIC3R_DEBUG_OUT_PATH_PREFIX "out/" -- cgit v1.2.3