/// @file /// @brief Generators for uniform distributions of Values, Circles and Triangles #pragma once #include // std::array #include // std::sqrt, std::sin, std::cos #include // std::numbers::pi #include // std::mt19937, std::uniform_real_distribution #include // std::tuple namespace iue::rnd { using Vec2d = std::array; using Circle = std::tuple; using Triangle = std::array; ///@brief Uniformly distributed speudorandom floating point values struct UniformValue { std::mt19937 algo; ///< Random number generator std::uniform_real_distribution dist; ///< Interval and distribution type /// @brief Constructs an instance producing random values uniformly distributed over an interval /// @param min Lower bound of the interval /// @param max Upper bound of the interval /// @param seed Seed used to initialize the generator algorithm UniformValue(const double min, const double max, const std::size_t seed = 1) : algo(seed), dist(min, max) {} /// @brief Obtains the next random value using current state of the generator /// @return Random value double operator()() { return dist(algo); } }; ///@brief Uniformly distributed circles struct UniformCircle { std::mt19937 algo; ///< Random number generator std::uniform_real_distribution x; ///< Interval and distribution type for the x-coordinate std::uniform_real_distribution y; ///< Interval and distribution type for the y-coordinate std::uniform_real_distribution r; ///< Interval and distribution type for the r-coordinate /// @brief Constructs an instance producing random circles uniformly distributed (center and radius) /// @param c_min Lower bound of the coordinate of the center /// @param c_max Upper bound of the coordinate of the center /// @param r_min Lower bound of the radius /// @param r_max Upper ound of the radius /// @param seed Seed used to initialize the generator algorithm UniformCircle(const Vec2d& c_min, const Vec2d& c_max, double r_min, double r_max, const std::size_t seed = 1) : algo(seed), x(c_min[0], c_max[0]), y(c_min[1], c_max[1]), r(r_min, r_max) {} /// @brief Obtains the next random circle using current state of the generator /// @return Random circle std::tuple, double> operator()() { // random center Vec2d center = {x(algo), y(algo)}; // random raidus double radius = r(algo); // return final configuration return {center, radius}; } }; ///@brief Uniformly distributed triangles struct UniformTriangle { std::mt19937 algo; ///< Random number generators std::uniform_real_distribution c_x; ///< distribution for the x-coordinate of the circumcircle std::uniform_real_distribution c_y; ///< distribution for the y-coordinate of the circumcircle std::uniform_real_distribution c_r; ///< distribution for the radius of the circumcircle std::uniform_real_distribution angle120; ///< distribution for the angles of the corner points std::uniform_real_distribution angle360; ///< distribution for the random rotation of the triangle /// @brief Constructs an instance producing random triangles with /// - uniformly distributed circumcircles, and /// - uniformly distributed corner points w.r.t. three fixed non-overlapping 120-degree segments on the unit circle /// @param c_min Lower bound of the coordinate of the circumcirle /// @param c_max Upper bound of the coordinate of the circumcirle /// @param r_min Lower bound of the radius of the circle /// @param r_max Upper ound of the radius of the circle /// @param seed Seed used to initialize the generator algorithm UniformTriangle(const Vec2d& c_min, const Vec2d& c_max, double r_min, double r_max, const std::size_t seed = 1) : algo(seed), c_x(c_min[0], c_max[0]), c_y(c_min[1], c_max[1]), c_r(r_min, r_max), angle120(0, std::numbers::pi * 2 / 3), angle360(0, std::numbers::pi * 2) {} /// @brief Obtains the next random triangle using current state of the generator /// @return Random circle Triangle operator()() { // three points on the unit circle constraint to three 120deg-segments // these will be the points of the triangle double seg = angle120.max(); double alpha = seg * 0 + angle120(algo); double beta = seg * 1 + angle120(algo); double gamma = seg * 2 + angle120(algo); Vec2d a = {std::sin(alpha), std::cos(alpha)}; Vec2d b = {std::sin(beta), std::cos(beta)}; Vec2d c = {std::sin(gamma), std::cos(gamma)}; Triangle abc = {a, b, c}; // random circumcircle center Vec2d center = {c_x(algo), c_y(algo)}; // random circumcircle radius double r = c_r(algo); // random rotation double rot = angle360(algo); auto rotate = [rot](const Vec2d& p) -> const Vec2d { return {std::cos(rot) * p[0] + (-std::sin(rot)) * p[1], std::sin(rot) * p[0] + std::cos(rot) * p[1]}; }; auto shift = [center](const Vec2d& p) -> const Vec2d { return {p[0] + center[0], p[1] + center[1]}; }; auto scale = [r](const Vec2d& p) -> const Vec2d { return {p[0] * r, p[1] * r}; }; // rotate/scale/shift to final configuration for (auto& coord : abc) { coord = rotate(coord); coord = scale(coord); coord = shift(coord); } // return final configuration return {abc}; } }; } // namespace iue::rnd