diff options
Diffstat (limited to 'lib/collections.h')
-rw-r--r-- | lib/collections.h | 86 |
1 files changed, 82 insertions, 4 deletions
diff --git a/lib/collections.h b/lib/collections.h index ea5d5dc..e182af5 100644 --- a/lib/collections.h +++ b/lib/collections.h @@ -3,6 +3,7 @@ #include <algorithm> #include <array> #include <cstdint> +#include <ranges> #include <span> #include <tuple> #include <utility> @@ -44,6 +45,7 @@ operator*(const std::array<T, first> & a, const std::array<V, second> & b) template<typename T, std::size_t N> [[nodiscard]] constexpr auto operator*(const std::array<T, N> & in, auto && f) + requires requires { f(in.front()); } { std::array<decltype(f(in[0])), N> out; @@ -106,6 +108,15 @@ operator+=(std::vector<T...> & in, std::vector<T...> && src) return in; } +template<typename... T> +constexpr auto +operator+(std::vector<T...> in1, std::vector<T...> in2) +{ + in1.reserve(in1.size() + in2.size()); + std::move(in2.begin(), in2.end(), std::back_inserter(in1)); + return in1; +} + template<typename... T, typename Vn> [[nodiscard]] constexpr auto operator+(const std::vector<T...> & in, Vn && vn) @@ -129,16 +140,16 @@ vectorOfN(std::integral auto N, T start = {}, T step = 1) template<template<typename...> typename Rtn = std::vector, typename In> [[nodiscard]] auto -materializeRange(const In begin, const In end) +materializeRange(In && begin, In && end) { - return Rtn(begin, end); + return Rtn(std::forward<In>(begin), std::forward<In>(end)); } template<template<typename...> typename Rtn = std::vector, IterableCollection In> [[nodiscard]] auto -materializeRange(const In & in) +materializeRange(In && in) { - return materializeRange<Rtn>(in.begin(), in.end()); + return materializeRange<Rtn>(std::forward<In>(in).begin(), std::forward<In>(in).end()); } template<template<typename...> typename Rtn = std::vector, typename In> @@ -187,6 +198,14 @@ template<typename iter> struct stripiter { return *this; } + constexpr stripiter + operator++(int) + { + auto out {*this}; + ++*this; + return out; + } + constexpr stripiter & operator--() { @@ -195,6 +214,14 @@ template<typename iter> struct stripiter { return *this; } + constexpr stripiter + operator--(int) + { + auto out {*this}; + --*this; + return out; + } + constexpr auto operator-(const stripiter & other) const { @@ -224,3 +251,54 @@ strip_end(IterableCollection auto & cont) { return stripiter {cont.end()}; } + +inline constexpr auto dereference = std::views::transform([](const auto & iter) -> decltype(auto) { + return *iter; +}); + +struct TriangleTriples : public std::ranges::range_adaptor_closure<TriangleTriples> { + decltype(auto) + operator()(const auto & triangleStrip) const + { + return std::views::iota(strip_begin(triangleStrip), strip_end(triangleStrip)) | dereference; + } +}; + +inline constexpr TriangleTriples triangleTriples; + +template<typename T, typename Dist, typename Merger> +void +mergeClose(std::vector<T> & range, const Dist & dist, const Merger & merger, + decltype(dist(range.front(), range.front())) tolerance) +{ + using DistanceType = decltype(tolerance); + std::vector<DistanceType> distances; + distances.reserve(range.size() - 1); + std::ranges::transform(range | std::views::pairwise, std::back_inserter(distances), [&dist](const auto & pair) { + return (std::apply(dist, pair)); + }); + while (distances.size() > 1) { + const auto closestPair = std::ranges::min_element(distances); + if (*closestPair > tolerance) { + return; + } + const auto offset = std::distance(distances.begin(), closestPair); + const auto idx = static_cast<std::size_t>(offset); + if (closestPair == distances.begin()) { + // Remove second element + range.erase(range.begin() + 1); + distances.erase(distances.begin()); + } + else if (closestPair == --distances.end()) { + // Remove second from last element + range.erase(range.end() - 2); + distances.erase(distances.end() - 1); + } + else { + range[idx] = merger(range[idx], range[idx + 1]); + range.erase(range.begin() + offset + 1); + distances.erase(distances.begin() + offset); + } + distances[idx] = dist(range[idx], range[idx + 1]); + } +} |