1 | #pragma once |
2 | |
3 | #include <mbgl/util/color.hpp> |
4 | #include <mbgl/util/range.hpp> |
5 | #include <mbgl/style/position.hpp> |
6 | #include <mbgl/style/expression/value.hpp> |
7 | |
8 | #include <array> |
9 | #include <vector> |
10 | #include <string> |
11 | #include <type_traits> |
12 | #include <utility> |
13 | |
14 | namespace mbgl { |
15 | namespace util { |
16 | |
17 | float interpolationFactor(float base, Range<float> range, float z); |
18 | |
19 | template <class T, class Enabled = void> |
20 | struct Interpolator; |
21 | |
22 | template <typename T> |
23 | T interpolate(const T& a, const T& b, const double t) { |
24 | return Interpolator<T>()(a, b, t); |
25 | } |
26 | |
27 | |
28 | template <class T, class Enabled> |
29 | struct Interpolator { |
30 | T operator()(const T& a, const T& b, const double t) const { |
31 | return a * (1.0 - t) + b * t; |
32 | } |
33 | }; |
34 | |
35 | template <class T, std::size_t N> |
36 | struct Interpolator<std::array<T, N>> { |
37 | private: |
38 | using Array = std::array<T, N>; |
39 | |
40 | template <std::size_t... I> |
41 | Array operator()(const Array& a, const Array& b, const double t, std::index_sequence<I...>) { |
42 | return {{ interpolate(a[I], b[I], t)... }}; |
43 | } |
44 | |
45 | public: |
46 | Array operator()(const Array& a, const Array& b, const double t) { |
47 | return operator()(a, b, t, std::make_index_sequence<N>()); |
48 | } |
49 | }; |
50 | |
51 | |
52 | // In order to accept Array<Number, N> as an output value for Curve |
53 | // expressions, we need to have an interpolatable std::vector type. |
54 | // However, style properties like line-dasharray are represented using |
55 | // std::vector<float>, and should NOT be considered interpolatable. |
56 | // So, we use std::vector<Value> to represent expression array values, |
57 | // asserting that (a) the vectors are the same size, and (b) they contain |
58 | // only numeric values. (These invariants should be relatively safe, |
59 | // being enforced by the expression type system.) |
60 | template<> |
61 | struct Interpolator<std::vector<style::expression::Value>> { |
62 | std::vector<style::expression::Value> operator()(const std::vector<style::expression::Value>& a, |
63 | const std::vector<style::expression::Value>& b, |
64 | const double t) const { |
65 | assert(a.size() == b.size()); |
66 | if (a.size() == 0) return {}; |
67 | std::vector<style::expression::Value> result; |
68 | for (std::size_t i = 0; i < a.size(); i++) { |
69 | assert(a[i].template is<double>()); |
70 | assert(b[i].template is<double>()); |
71 | style::expression::Value item = interpolate( |
72 | a: a[i].template get<double>(), |
73 | b: b[i].template get<double>(), |
74 | t); |
75 | result.push_back(x: item); |
76 | } |
77 | return result; |
78 | } |
79 | }; |
80 | |
81 | template <> |
82 | struct Interpolator<style::Position> { |
83 | public: |
84 | style::Position operator()(const style::Position& a, const style::Position& b, const double t) { |
85 | auto pos = style::Position(); |
86 | auto interpolated = interpolate(a: a.getCartesian(), b: b.getCartesian(), t); |
87 | pos.setCartesian(interpolated); |
88 | return { pos }; |
89 | } |
90 | }; |
91 | |
92 | template <> |
93 | struct Interpolator<Color> { |
94 | public: |
95 | Color operator()(const Color& a, const Color& b, const double t) { |
96 | return { |
97 | interpolate(a: a.r, b: b.r, t), |
98 | interpolate(a: a.g, b: b.g, t), |
99 | interpolate(a: a.b, b: b.b, t), |
100 | interpolate(a: a.a, b: b.a, t) |
101 | }; |
102 | } |
103 | }; |
104 | |
105 | struct Uninterpolated { |
106 | template <class T> |
107 | T operator()(const T& a, const T&, const double) const { |
108 | return a; |
109 | } |
110 | }; |
111 | |
112 | template <> |
113 | struct Interpolator<bool> |
114 | : Uninterpolated {}; |
115 | |
116 | template <class T> |
117 | struct Interpolator<T, typename std::enable_if_t<std::is_enum<T>::value>> |
118 | : Uninterpolated {}; |
119 | |
120 | template <> |
121 | struct Interpolator<std::string> |
122 | : Uninterpolated {}; |
123 | |
124 | template <class T> |
125 | struct Interpolator<std::vector<T>> |
126 | : Uninterpolated {}; |
127 | |
128 | template <class T> |
129 | struct Interpolatable |
130 | : std::conditional_t< |
131 | !std::is_base_of<Uninterpolated, Interpolator<T>>::value, |
132 | std::true_type, |
133 | std::false_type> {}; |
134 | |
135 | |
136 | |
137 | } // namespace util |
138 | } // namespace mbgl |
139 | |