Jamba  3.2.0
Lerp.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2019 pongasoft
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  *
16  * @author Yan Pujante
17  */
18 #pragma once
19 
20 #include "Misc.h"
21 
22 namespace pongasoft {
23 namespace Utils {
24 
31 template <typename TFloat, typename X, typename Y>
32 class Lerp
33 {
34 public:
35  Lerp(X iX1, Y iY1, X iX2, Y iY2) :
36  fA((static_cast<TFloat>(iY1 - iY2)) / (static_cast<TFloat>(iX1 - iX2))),
37  fB(static_cast<TFloat>(iY1) - fA * static_cast<TFloat>(iX1)) {}
38 
42  Lerp(Y iY0, Y iY1) : fA(static_cast<TFloat>(iY1 - iY0)), fB(static_cast<TFloat>(iY0)) {};
43 
44  inline Y computeY(X iX) const
45  {
46  return static_cast<Y>((static_cast<TFloat>(iX) * fA) + fB);
47  }
48 
49  inline X computeX(Y iY) const
50  {
51  DCHECK_F(fA != 0);
52  return static_cast<X>((static_cast<TFloat>(iY) - fB) / fA);
53  }
54 
60  static inline Lerp mapRange(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh)
61  {
62  return Lerp(iFromLow, iToLow, iFromHigh, iToHigh);
63  }
64 
76  static Y mapValue(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
77  {
78  // if the first range is empty (computation would be dividing by 0)
79  if(iFromLow == iFromHigh)
80  return iValue <= iFromLow ? iToLow : iToHigh;
81 
82  // if the second range is empty, no need for computation
83  if(iToLow == iToHigh)
84  return iToLow;
85 
86  if(iClamp)
87  {
88  iValue = clampRange(iValue, iFromLow, iFromHigh);
89  }
90 
91  return Lerp(iFromLow, iToLow, iFromHigh, iToHigh).computeY(iValue);
92  }
93 
94 private:
95  const TFloat fA;
96  const TFloat fB;
97 };
98 
99 //------------------------------------------------------------------------
100 // SPLerp - Single Precision Lerp (float)
101 //------------------------------------------------------------------------
102 template<typename X, typename Y>
104 
105 template<typename X>
107 
108 template<typename Y>
110 
112 
115 template<typename X, typename Y>
116 static inline SPLerpXY<X, Y> mapRangeSPXY(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh)
117 {
118  return SPLerpXY<X, Y>(iFromLow, iToLow, iFromHigh, iToHigh);
119 }
120 
121 template<typename Y>
122 constexpr auto mapRangeSPY = mapRangeSPXY<float, Y>;
123 
124 template<typename X>
125 constexpr auto mapRangeSPX = mapRangeSPXY<X, float>;
126 
127 constexpr auto mapRangeSP = mapRangeSPXY<float, float>;
128 
131 template<typename X, typename Y>
132 inline static Y mapValueSPXY(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
133 {
134  return SPLerpXY<X, Y>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
135 }
136 
139 template<typename Y>
140 inline static Y mapValueSPY(float iValue, float iFromLow, float iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
141 {
142  return SPLerpY<Y>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
143 }
144 
147 template<typename X>
148 inline static float mapValueSPX(X iValue, X iFromLow, X iFromHigh, float iToLow, float iToHigh, bool iClamp = true)
149 {
150  return SPLerpX<X>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
151 }
152 
155 inline static float mapValueSP(float iValue, float iFromLow, float iFromHigh, float iToLow, float iToHigh, bool iClamp = true)
156 {
157  return SPLerp::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
158 }
159 
160 
161 //------------------------------------------------------------------------
162 // DPLerp - Double Precision Lerp (double)
163 //------------------------------------------------------------------------
164 template<typename X, typename Y>
166 
167 template<typename X>
169 
170 template<typename Y>
172 
174 
177 template<typename X, typename Y>
178 static inline DPLerpXY<X, Y> mapRangeDPXY(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh)
179 {
180  return DPLerpXY<X, Y>(iFromLow, iToLow, iFromHigh, iToHigh);
181 }
182 
183 template<typename Y>
184 constexpr auto mapRangeDPY = mapRangeDPXY<double, Y>;
185 
186 template<typename X>
187 constexpr auto mapRangeDPX = mapRangeDPXY<X, double>;
188 
189 constexpr auto mapRangeDP = mapRangeDPXY<double, double>;
190 
193 template<typename X, typename Y>
194 inline static Y mapValueDPXY(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
195 {
196  return DPLerpXY<X, Y>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
197 }
198 
201 template<typename Y>
202 inline static Y mapValueDPY(double iValue, double iFromLow, double iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
203 {
204  return DPLerpY<Y>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
205 }
206 
209 template<typename X>
210 inline static double mapValueDPX(X iValue, X iFromLow, X iFromHigh, double iToLow, double iToHigh, bool iClamp = true)
211 {
212  return DPLerpX<X>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
213 }
214 
217 inline static double mapValueDP(double iValue, double iFromLow, double iFromHigh, double iToLow, double iToHigh, bool iClamp = true)
218 {
219  return DPLerp::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
220 }
221 
225 template<typename T>
226 struct Range
227 {
230  using value_type = T;
231 
232  // Empty constructor (no range)
233  Range() = default;
234 
235  // Single value range
236  explicit Range(T iValue) noexcept : fFrom{iValue}, fTo{iValue} {}
237 
238  // Constructor
239  Range(T iFrom, T iTo) : fFrom{iFrom}, fTo{iTo} {}
240 
241  // return true if the range is a single value (aka degenerate range)
242  bool isSingleValue() const { return fFrom == fTo; }
243 
252  bool contains(T iValue) const
253  {
254  if(fFrom < fTo)
255  return iValue >= fFrom && iValue <= fTo;
256  else
257  return iValue <= fFrom && iValue >= fTo;
258  }
259 
265  T clamp(T iValue) const
266  {
267  return Utils::clampRange(iValue, fFrom, fTo);
268  }
269 
277  template<typename U, typename TLerp = DPLerpXY<T, U>>
278  inline U mapValue(T iValue, Range<U> const &iRange, bool iClampToRange = true) const
279  {
280  return TLerp::mapValue(iValue, fFrom, fTo, iRange.fFrom, iRange.fTo, iClampToRange);
281  }
282 
289  template<typename U, typename TLerp = DPLerpXY<T, U>>
290  inline Range<U> mapRange(Range<U> const &iRange, bool iClampToRange = true) const
291  {
292  return mapSubRange<U,TLerp>(*this, iRange, iClampToRange);
293  }
294 
301  template<typename U, typename TLerp = DPLerpXY<T, U>>
302  inline Range<U> mapSubRange(Range<T> const &iSubRange, Range<U> const &iRange, bool iClampToRange = true) const
303  {
305  return Range<U>{mapValue<U,TLerp>(iSubRange.fFrom, iRange, iClampToRange),
306  mapValue<U,TLerp>(iSubRange.fTo, iRange, iClampToRange)};
307  }
308 
312  template<typename U>
313  inline Range<U> cast() const
314  {
315  return Range<U>{static_cast<U>(fFrom), static_cast<U>(fTo)};
316  }
317 
318  // operator==
319  bool operator==(const Range &rhs) const
320  {
321  return fFrom == rhs.fFrom && fTo == rhs.fTo;
322  }
323 
324  // operator!=
325  bool operator!=(const Range &rhs) const
326  {
327  return !(rhs == *this);
328  }
329 
330 public:
331  T fFrom{};
332  T fTo{};
333 };
334 
335 }
336 }
static SPLerpXY< X, Y > mapRangeSPXY(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh)
Definition: Lerp.h:116
bool contains(T iValue) const
Definition: Lerp.h:252
bool isSingleValue() const
Definition: Lerp.h:242
Y computeY(X iX) const
Definition: Lerp.h:44
T clamp(T iValue) const
Definition: Lerp.h:265
T fTo
Definition: Lerp.h:332
Range(T iValue) noexcept
Definition: Lerp.h:236
Definition: Lerp.h:226
Range< U > cast() const
Definition: Lerp.h:313
Definition: Clock.h:22
constexpr auto mapRangeSPY
Definition: Lerp.h:122
constexpr auto mapRangeSPX
Definition: Lerp.h:125
static double mapValueDP(double iValue, double iFromLow, double iFromHigh, double iToLow, double iToHigh, bool iClamp=true)
Definition: Lerp.h:217
const TFloat fA
Definition: Lerp.h:95
U mapValue(T iValue, Range< U > const &iRange, bool iClampToRange=true) const
Definition: Lerp.h:278
static DPLerpXY< X, Y > mapRangeDPXY(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh)
Definition: Lerp.h:178
static Y mapValue(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Definition: Lerp.h:76
Range(T iFrom, T iTo)
Definition: Lerp.h:239
static Lerp mapRange(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh)
Definition: Lerp.h:60
static T clampRange(const U &iValue, const T &iFrom, const T &iTo)
Definition: Misc.h:44
static float mapValueSP(float iValue, float iFromLow, float iFromHigh, float iToLow, float iToHigh, bool iClamp=true)
Definition: Lerp.h:155
Range< U > mapRange(Range< U > const &iRange, bool iClampToRange=true) const
Definition: Lerp.h:290
bool operator==(const Range &rhs) const
Definition: Lerp.h:319
static double mapValueDPX(X iValue, X iFromLow, X iFromHigh, double iToLow, double iToHigh, bool iClamp=true)
Definition: Lerp.h:210
Lerp(Y iY0, Y iY1)
Definition: Lerp.h:42
Lerp(X iX1, Y iY1, X iX2, Y iY2)
Definition: Lerp.h:35
CCoord value_type
Definition: Lerp.h:230
constexpr auto mapRangeDPY
Definition: Lerp.h:184
static Y mapValueDPXY(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Definition: Lerp.h:194
Range< U > mapSubRange(Range< T > const &iSubRange, Range< U > const &iRange, bool iClampToRange=true) const
Definition: Lerp.h:302
Definition: Lerp.h:32
constexpr auto mapRangeDPX
Definition: Lerp.h:187
static Y mapValueDPY(double iValue, double iFromLow, double iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Definition: Lerp.h:202
constexpr auto mapRangeDP
Definition: Lerp.h:189
static Y mapValueSPXY(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Definition: Lerp.h:132
constexpr auto mapRangeSP
Definition: Lerp.h:127
static float mapValueSPX(X iValue, X iFromLow, X iFromHigh, float iToLow, float iToHigh, bool iClamp=true)
Definition: Lerp.h:148
T fFrom
Definition: Lerp.h:331
bool operator!=(const Range &rhs) const
Definition: Lerp.h:325
const TFloat fB
Definition: Lerp.h:96
X computeX(Y iY) const
Definition: Lerp.h:49
static Y mapValueSPY(float iValue, float iFromLow, float iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Definition: Lerp.h:140