Jamba C++ API 7.5.0
Loading...
Searching...
No Matches
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 or the MIT license,
5 * at your option. You may not use this file except in compliance with
6 * one of these licenses. You may obtain copies of the licenses at:
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 * https://opensource.org/licenses/MIT
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations under
15 * the License.
16 *
17 * @author Yan Pujante
18 */
19#pragma once
20
21#include "Misc.h"
22
23namespace pongasoft::Utils {
24
31template <typename TFloat, typename X, typename Y>
32class Lerp
33{
34public:
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
80 static Y mapValue(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
81 {
82 // if the first range is empty (computation would be dividing by 0)
83 if(iFromLow == iFromHigh)
84 return iValue <= iFromLow ? iToLow : iToHigh;
85
86 // if the second range is empty, no need for computation
87 if(iToLow == iToHigh)
88 return iToLow;
89
90 if(iClamp)
91 {
92 iValue = clampRange(iValue, iFromLow, iFromHigh);
93 }
94
95 return Lerp(iFromLow, iToLow, iFromHigh, iToHigh).computeY(iValue);
96 }
97
98private:
99 const TFloat fA;
100 const TFloat fB;
101};
102
103//------------------------------------------------------------------------
104// SPLerp - Single Precision Lerp (float)
105//------------------------------------------------------------------------
106template<typename X, typename Y>
108
109template<typename X>
111
112template<typename Y>
114
116
119template<typename X, typename Y>
120static inline SPLerpXY<X, Y> mapRangeSPXY(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh)
121{
122 return SPLerpXY<X, Y>(iFromLow, iToLow, iFromHigh, iToHigh);
123}
124
125template<typename Y>
127
128template<typename X>
130
132
135template<typename X, typename Y>
136inline static Y mapValueSPXY(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
137{
138 return SPLerpXY<X, Y>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
139}
140
143template<typename Y>
144inline static Y mapValueSPY(float iValue, float iFromLow, float iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
145{
146 return SPLerpY<Y>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
147}
148
151template<typename X>
152inline static float mapValueSPX(X iValue, X iFromLow, X iFromHigh, float iToLow, float iToHigh, bool iClamp = true)
153{
154 return SPLerpX<X>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
155}
156
159inline static float mapValueSP(float iValue, float iFromLow, float iFromHigh, float iToLow, float iToHigh, bool iClamp = true)
160{
161 return SPLerp::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
162}
163
164
165//------------------------------------------------------------------------
166// DPLerp - Double Precision Lerp (double)
167//------------------------------------------------------------------------
168template<typename X, typename Y>
170
171template<typename X>
173
174template<typename Y>
176
178
181template<typename X, typename Y>
182static inline DPLerpXY<X, Y> mapRangeDPXY(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh)
183{
184 return DPLerpXY<X, Y>(iFromLow, iToLow, iFromHigh, iToHigh);
185}
186
187template<typename Y>
189
190template<typename X>
192
194
197template<typename X, typename Y>
198inline static Y mapValueDPXY(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
199{
200 return DPLerpXY<X, Y>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
201}
202
205template<typename Y>
206inline static Y mapValueDPY(double iValue, double iFromLow, double iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
207{
208 return DPLerpY<Y>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
209}
210
213template<typename X>
214inline static double mapValueDPX(X iValue, X iFromLow, X iFromHigh, double iToLow, double iToHigh, bool iClamp = true)
215{
216 return DPLerpX<X>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
217}
218
221inline static double mapValueDP(double iValue, double iFromLow, double iFromHigh, double iToLow, double iToHigh, bool iClamp = true)
222{
223 return DPLerp::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
224}
225
229template<typename T>
230struct Range
231{
234 using value_type = T;
235
236 // Empty constructor (no range)
237 Range() = default;
238
239 // Single value range
240 explicit Range(T iValue) noexcept : fFrom{iValue}, fTo{iValue} {}
241
242 // Constructor
243 Range(T iFrom, T iTo) : fFrom{iFrom}, fTo{iTo} {}
244
245 // return true if the range is a single value (aka degenerate range)
246 bool isSingleValue() const { return fFrom == fTo; }
247
258 bool contains(T iValue) const
259 {
260 if(fFrom < fTo)
261 return iValue >= fFrom && iValue <= fTo;
262 else
263 return iValue <= fFrom && iValue >= fTo;
264 }
265
271 T clamp(T iValue) const
272 {
273 return Utils::clampRange(iValue, fFrom, fTo);
274 }
275
284 template<typename U, typename TLerp = DPLerpXY<T, U>>
285 inline U mapValue(T iValue, Range<U> const &iRange, bool iClampToRange = true) const
286 {
287 return TLerp::mapValue(iValue, fFrom, fTo, iRange.fFrom, iRange.fTo, iClampToRange);
288 }
289
296 template<typename U, typename TLerp = DPLerpXY<T, U>>
297 inline Range<U> mapRange(Range<U> const &iRange) const
298 {
299 // obviously *this* range is already clamped...
300 return mapSubRange<U,TLerp>(*this, iRange, true);
301 }
302
311 template<typename U, typename TLerp = DPLerpXY<T, U>>
312 inline Range<U> mapSubRange(Range<T> const &iSubRange, Range<U> const &iRange, bool iClampToRange = true) const
313 {
315 return Range<U>{mapValue<U,TLerp>(iSubRange.fFrom, iRange, iClampToRange),
316 mapValue<U,TLerp>(iSubRange.fTo, iRange, iClampToRange)};
317 }
318
322 template<typename U>
323 inline Range<U> cast() const
324 {
325 return Range<U>{static_cast<U>(fFrom), static_cast<U>(fTo)};
326 }
327
328 // operator==
329 bool operator==(const Range &rhs) const
330 {
331 return fFrom == rhs.fFrom && fTo == rhs.fTo;
332 }
333
334 // operator!=
335 bool operator!=(const Range &rhs) const
336 {
337 return !(rhs == *this);
338 }
339
340public:
341 T fFrom{};
342 T fTo{};
343};
344
345}
Util class to compute linear interpolation.
Definition Lerp.h:33
const float fA
Definition Lerp.h:99
Lerp(X iX1, Y iY1, X iX2, Y iY2)
Definition Lerp.h:35
static Y mapValue(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Inspired by the map function in Processing language, another way to look at Lerp is to map a range of...
Definition Lerp.h:80
Lerp(Y iY0, Y iY1)
Shortcut for when x=0 => iY0 and x=1.0 => iY1.
Definition Lerp.h:42
const float fB
Definition Lerp.h:100
Y computeY(X iX) const
Definition Lerp.h:44
static Lerp mapRange(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh)
Inspired by the map function in Processing language, another way to look at Lerp is to map a range of...
Definition Lerp.h:60
X computeX(Y iY) const
Definition Lerp.h:49
Definition CircularBuffer.h:26
Lerp< float, X, Y > SPLerpXY
Definition Lerp.h:107
Lerp< double, X, double > DPLerpX
Definition Lerp.h:172
static Y mapValueSPXY(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:136
static float mapValueSP(float iValue, float iFromLow, float iFromHigh, float iToLow, float iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:159
static double mapValueDPX(X iValue, X iFromLow, X iFromHigh, double iToLow, double iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:214
Lerp< double, X, Y > DPLerpXY
Definition Lerp.h:169
Lerp< double, double, double > DPLerp
Definition Lerp.h:177
static double mapValueDP(double iValue, double iFromLow, double iFromHigh, double iToLow, double iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:221
constexpr auto mapRangeDPY
Definition Lerp.h:188
constexpr auto mapRangeSPX
Definition Lerp.h:129
static Y mapValueSPY(float iValue, float iFromLow, float iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:144
Lerp< float, X, float > SPLerpX
Definition Lerp.h:110
Lerp< float, float, float > SPLerp
Definition Lerp.h:115
Lerp< float, float, Y > SPLerpY
Definition Lerp.h:113
constexpr auto mapRangeDPX
Definition Lerp.h:191
constexpr auto mapRangeSPY
Definition Lerp.h:126
Lerp< double, double, Y > DPLerpY
Definition Lerp.h:175
static Y mapValueDPXY(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:198
constexpr auto mapRangeDP
Definition Lerp.h:193
constexpr auto mapRangeSP
Definition Lerp.h:131
static Y mapValueDPY(double iValue, double iFromLow, double iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:206
static T clampRange(const U &iValue, const T &iFrom, const T &iTo)
Make sure that the value remains within its bounds.
Definition Misc.h:45
static float mapValueSPX(X iValue, X iFromLow, X iFromHigh, float iToLow, float iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:152
static DPLerpXY< X, Y > mapRangeDPXY(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh)
Convenient shortcut for double precision.
Definition Lerp.h:182
static SPLerpXY< X, Y > mapRangeSPXY(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh)
Convenient shortcut for single precision.
Definition Lerp.h:120
Range(T iValue) noexcept
Definition Lerp.h:240
bool isSingleValue() const
Definition Lerp.h:246
Range(T iFrom, T iTo)
Definition Lerp.h:243
CCoord fFrom
Definition Lerp.h:341
Range< U > cast() const
Cast this range to another one.
Definition Lerp.h:323
bool operator!=(const Range &rhs) const
Definition Lerp.h:335
Range< U > mapRange(Range< U > const &iRange) const
Map this range to the other range.
Definition Lerp.h:297
T fTo
Definition Lerp.h:342
bool contains(T iValue) const
This method assumes that fFrom and fTo are part of the range or another way to put it:
Definition Lerp.h:258
bool operator==(const Range &rhs) const
Definition Lerp.h:329
U mapValue(T iValue, Range< U > const &iRange, bool iClampToRange=true) const
Map the value from this range into the provide range.
Definition Lerp.h:285
Range< U > mapSubRange(Range< T > const &iSubRange, Range< U > const &iRange, bool iClampToRange=true) const
Map a sub range of this range to the other range.
Definition Lerp.h:312
T clamp(T iValue) const
Clamp the value to this range.
Definition Lerp.h:271
T value_type
Gives access to the type of elements in the range.
Definition Lerp.h:234