diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 01a1d2c56..ebb421dba 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -9,6 +9,8 @@ #include "Line.hpp" #include #include +#include +#include #include "libslic3r/AABBTreeLines.hpp" static const int overhang_sampling_number = 6; static const double narrow_loop_length_threshold = 10; @@ -22,6 +24,15 @@ static constexpr double SMALLER_EXT_INSET_OVERLAP_TOLERANCE = 0.22; 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); +} + // Hierarchy of perimeters. class PerimeterGeneratorLoop { public: @@ -52,7 +63,7 @@ static void fuzzy_polygon(Polygon &poly, double fuzzy_skin_thickness, double fuz { 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 = 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 Point* p0 = &poly.points.back(); Points out; out.reserve(poly.points.size()); @@ -60,16 +71,14 @@ static void fuzzy_polygon(Polygon &poly, double fuzzy_skin_thickness, double fuz { // 'a' is the (next) new point between p0 and p1 Vec2d p0p1 = (p1 - *p0).cast(); double p0p1_size = p0p1.norm(); - // so that p0p1_size - dist_last_point evaulates to dist_left_over - p0p1_size - double dist_last_point = dist_left_over + p0p1_size * 2.; - for (double p0pa_dist = dist_left_over; p0pa_dist < p0p1_size; - p0pa_dist += min_dist_between_points + double(rand()) * range_random_point_dist / double(RAND_MAX)) + double p0pa_dist = dist_left_over; + for (; p0pa_dist < p0p1_size; + 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_last_point = p0pa_dist; } - dist_left_over = p0p1_size - dist_last_point; + dist_left_over = p0p1_size - p0pa_dist; p0 = &p1; } while (out.size() < 3) {