#pragma once #include #include #include #include #include #include #include #include #include namespace mbgl { namespace util { float interpolationFactor(float base, Range range, float z); template struct Interpolator; template T interpolate(const T& a, const T& b, const double t) { return Interpolator()(a, b, t); } template struct Interpolator { T operator()(const T& a, const T& b, const double t) const { return a * (1.0 - t) + b * t; } }; template struct Interpolator> { private: using Array = std::array; template Array operator()(const Array& a, const Array& b, const double t, std::index_sequence) { return {{ interpolate(a[I], b[I], t)... }}; } public: Array operator()(const Array& a, const Array& b, const double t) { return operator()(a, b, t, std::make_index_sequence()); } }; // In order to accept Array as an output value for Curve // expressions, we need to have an interpolatable std::vector type. // However, style properties like line-dasharray are represented using // std::vector, and should NOT be considered interpolatable. // So, we use std::vector to represent expression array values, // asserting that (a) the vectors are the same size, and (b) they contain // only numeric values. (These invariants should be relatively safe, // being enforced by the expression type system.) template<> struct Interpolator> { std::vector operator()(const std::vector& a, const std::vector& b, const double t) const { assert(a.size() == b.size()); if (a.size() == 0) return {}; std::vector result; for (std::size_t i = 0; i < a.size(); i++) { assert(a[i].template is()); assert(b[i].template is()); style::expression::Value item = interpolate( a[i].template get(), b[i].template get(), t); result.push_back(item); } return result; } }; template <> struct Interpolator { public: style::Position operator()(const style::Position& a, const style::Position& b, const double t) { auto pos = style::Position(); auto interpolated = interpolate(a.getCartesian(), b.getCartesian(), t); pos.setCartesian(interpolated); return { pos }; } }; template <> struct Interpolator { public: Color operator()(const Color& a, const Color& b, const double t) { return { interpolate(a.r, b.r, t), interpolate(a.g, b.g, t), interpolate(a.b, b.b, t), interpolate(a.a, b.a, t) }; } }; struct Uninterpolated { template T operator()(const T& a, const T&, const double) const { return a; } }; template <> struct Interpolator : Uninterpolated {}; template struct Interpolator::value>> : Uninterpolated {}; template <> struct Interpolator : Uninterpolated {}; template struct Interpolator> : Uninterpolated {}; template struct Interpolatable : std::conditional_t< !std::is_base_of>::value, std::true_type, std::false_type> {}; } // namespace util } // namespace mbgl