diff options
-rw-r--r-- | voronoi.cc | 74 |
1 files changed, 38 insertions, 36 deletions
@@ -6,9 +6,9 @@ #include <algorithm> double minkowski_metric( - const double p, - const imgen::vector& a, - const imgen::vector& b + const double p, + const imgen::vector a, + const imgen::vector b ) { return std::pow( std::pow(std::abs(std::get<0>(a) - std::get<0>(b)), p) @@ -17,16 +17,11 @@ double minkowski_metric( ); } -double manhattan_metric(const imgen::vector& a, const imgen::vector& b) { - return minkowski_metric(1, a, b); -} - -double euclidean_metric(const imgen::vector& a, const imgen::vector& b) { - return minkowski_metric(2, a, b); -} - -void generate_minkowski_voronoi(const double p) { - constexpr std::array<imgen::colored_vector, 9> ref{ +std::pair<double, imgen::colored_vector> get_distance_to_nearest( + const std::function<double(imgen::vector, imgen::vector)>& metric, + const imgen::vector a +) { + constexpr std::array<imgen::colored_vector, 9> reference_vectors{ imgen::colored_vector{ 0, 0, imgen::red() }, imgen::colored_vector{ 240, 200, imgen::color{220, 220, 220} }, imgen::colored_vector{-100, 230, imgen::color{ 94, 113, 106} }, @@ -38,37 +33,44 @@ void generate_minkowski_voronoi(const double p) { imgen::colored_vector{-240, -20, imgen::color{ 54, 69, 79} } }; + std::array<double, 9> distances; + + std::transform( + reference_vectors.begin(), + reference_vectors.end(), + distances.begin(), + [&a, &metric](const imgen::colored_vector b) { + return metric(a, imgen::vector{std::get<0>(b), std::get<1>(b)}); + } + ); + + const auto& minimal_distance{ + std::min_element(distances.begin(), distances.end())}; + const imgen::colored_vector& nearest{ + reference_vectors[std::distance(distances.begin(), minimal_distance)]}; + + return std::make_pair(*minimal_distance, nearest); +} + +void generate_minkowski_voronoi(const double p) { + const auto metric{[p](const imgen::vector a, const imgen::vector b) -> double { + return minkowski_metric(p, a, b); + }}; + imgen::write_ppm( "voronoi_" + std::to_string(p) + ".ppm", 512, 512, - [&ref, p](std::ptrdiff_t x, std::ptrdiff_t y) -> imgen::color { - std::array<double, 9> distances; - - std::transform( - ref.begin(), - ref.end(), - distances.begin(), - [x, y, p](const imgen::colored_vector& pos) { - return minkowski_metric( - p, - imgen::vector{std::get<0>(pos), std::get<1>(pos)}, - imgen::vector{x, y} - ); - }); - - const auto& minimal_distance = std::min_element( - distances.begin(), - distances.end() + [&metric](std::ptrdiff_t x, std::ptrdiff_t y) -> imgen::color { + const auto& nearest = get_distance_to_nearest( + metric, + imgen::vector{x, y} ); - const imgen::colored_vector& nearest = ref[ - std::distance(distances.begin(), minimal_distance) - ]; - if ( *minimal_distance <= 5.0 ) { + if ( nearest.first <= 5.0 ) { return imgen::black(); } else { - return std::get<2>(nearest); + return std::get<2>(nearest.second); } } ); |