From 3c6372901bd9c94c4a3c7d3f97a0e363d4951823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Tue, 8 Oct 2024 18:07:12 +0200 Subject: [PATCH] SPE-2486: Fix weak randomness of fuzzy skin. Co-authored-by: Ryan Cavanaugh Co-authored-by: Noisyfox --- src/libslic3r/PerimeterGenerator.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 1b9a000bb3..709c75401d 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,15 @@ namespace Slic3r { +// Produces a random value between 0 and 1. Thread-safe. +static double random_value() { + thread_local std::random_device rd; + // Hash thread ID for random number seed if no hardware rng seed is available + thread_local std::mt19937 gen(rd.entropy() > 0 ? rd() : std::hash()(std::this_thread::get_id())); + thread_local std::uniform_real_distribution dist(0.0, 1.0); + return dist(gen); +} + ExtrusionMultiPath PerimeterGenerator::thick_polyline_to_multi_path(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance) { ExtrusionMultiPath multi_path; @@ -196,11 +206,11 @@ public: }; // Thanks Cura developers for this function. -static void fuzzy_polygon(Polygon &poly, double fuzzy_skin_thickness, double fuzzy_skin_point_dist) +static void fuzzy_polygon(Polygon &poly, double fuzzy_skin_thickness, double fuzzy_skin_point_distance) { - const double min_dist_between_points = fuzzy_skin_point_dist * 3. / 4.; // hardcoded: the point distance may vary between 3/4 and 5/4 the supplied value - const double range_random_point_dist = fuzzy_skin_point_dist / 2.; - double dist_left_over = double(rand()) * (min_dist_between_points / 2) / double(RAND_MAX); // the distance to be traversed on the line before making the first new point + const double min_dist_between_points = fuzzy_skin_point_distance * 3. / 4.; // hardcoded: the point distance may vary between 3/4 and 5/4 the supplied value + const double range_random_point_dist = fuzzy_skin_point_distance / 2.; + double dist_left_over = random_value() * (min_dist_between_points / 2.); // the distance to be traversed on the line before making the first new point Point* p0 = &poly.points.back(); Points out; out.reserve(poly.points.size()); @@ -210,9 +220,9 @@ static void fuzzy_polygon(Polygon &poly, double fuzzy_skin_thickness, double fuz double p0p1_size = p0p1.norm(); double p0pa_dist = dist_left_over; for (; p0pa_dist < p0p1_size; - p0pa_dist += min_dist_between_points + double(rand()) * range_random_point_dist / double(RAND_MAX)) + p0pa_dist += min_dist_between_points + random_value() * range_random_point_dist) { - double r = double(rand()) * (fuzzy_skin_thickness * 2.) / double(RAND_MAX) - fuzzy_skin_thickness; + double r = random_value() * (fuzzy_skin_thickness * 2.) - fuzzy_skin_thickness; out.emplace_back(*p0 + (p0p1 * (p0pa_dist / p0p1_size) + perp(p0p1).cast().normalized() * r).cast()); } dist_left_over = p0pa_dist - p0p1_size; @@ -234,7 +244,7 @@ static void fuzzy_extrusion_line(Arachne::ExtrusionLine &ext_lines, double fuzzy { const double min_dist_between_points = fuzzy_skin_point_dist * 3. / 4.; // hardcoded: the point distance may vary between 3/4 and 5/4 the supplied value const double range_random_point_dist = fuzzy_skin_point_dist / 2.; - double dist_left_over = double(rand()) * (min_dist_between_points / 2) / double(RAND_MAX); // the distance to be traversed on the line before making the first new point + double dist_left_over = random_value() * (min_dist_between_points / 2.); // the distance to be traversed on the line before making the first new point auto *p0 = &ext_lines.front(); std::vector out; @@ -249,8 +259,8 @@ static void fuzzy_extrusion_line(Arachne::ExtrusionLine &ext_lines, double fuzzy Vec2d p0p1 = (p1.p - p0->p).cast(); double p0p1_size = p0p1.norm(); double p0pa_dist = dist_left_over; - for (; p0pa_dist < p0p1_size; p0pa_dist += min_dist_between_points + double(rand()) * range_random_point_dist / double(RAND_MAX)) { - double r = double(rand()) * (fuzzy_skin_thickness * 2.) / double(RAND_MAX) - fuzzy_skin_thickness; + for (; p0pa_dist < p0p1_size; p0pa_dist += min_dist_between_points + random_value() * range_random_point_dist) { + double r = random_value() * (fuzzy_skin_thickness * 2.) - fuzzy_skin_thickness; out.emplace_back(p0->p + (p0p1 * (p0pa_dist / p0p1_size) + perp(p0p1).cast().normalized() * r).cast(), p1.w, p1.perimeter_index); } dist_left_over = p0pa_dist - p0p1_size;