Jamba C++ API 8.0.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#include <concepts>
23
24namespace pongasoft::Utils {
25
27template<typename T, typename X, typename Y>
29 requires(X value, X from, X to, Y outFrom, Y outTo, bool clamp)
30{
31 { T::mapValue(value, from, to, outFrom, outTo, clamp) } -> std::convertible_to<Y>;
32};
33
40template <typename TFloat, typename X, typename Y>
41class Lerp
42{
43public:
44 constexpr Lerp(X iX1, Y iY1, X iX2, Y iY2) noexcept :
45 fA((static_cast<TFloat>(iY1 - iY2)) / (static_cast<TFloat>(iX1 - iX2))),
46 fB(static_cast<TFloat>(iY1) - fA * static_cast<TFloat>(iX1)) {}
47
51 constexpr Lerp(Y iY0, Y iY1) noexcept : fA(static_cast<TFloat>(iY1 - iY0)), fB(static_cast<TFloat>(iY0)) {};
52
53 constexpr Y computeY(X iX) const
54 {
55 return static_cast<Y>((static_cast<TFloat>(iX) * fA) + fB);
56 }
57
58 constexpr X computeX(Y iY) const
59 {
60 DCHECK_F(fA != 0);
61 return static_cast<X>((static_cast<TFloat>(iY) - fB) / fA);
62 }
63
69 static constexpr Lerp mapRange(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh) noexcept
70 {
71 return Lerp(iFromLow, iToLow, iFromHigh, iToHigh);
72 }
73
89 static constexpr Y mapValue(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
90 {
91 // if the first range is empty (computation would be dividing by 0)
92 if(iFromLow == iFromHigh)
93 return iValue <= iFromLow ? iToLow : iToHigh;
94
95 // if the second range is empty, no need for computation
96 if(iToLow == iToHigh)
97 return iToLow;
98
99 if(iClamp)
100 {
101 iValue = clampRange(iValue, iFromLow, iFromHigh);
102 }
103
104 return Lerp(iFromLow, iToLow, iFromHigh, iToHigh).computeY(iValue);
105 }
106
107private:
108 const TFloat fA;
109 const TFloat fB;
110};
111
112//------------------------------------------------------------------------
113// SPLerp - Single Precision Lerp (float)
114//------------------------------------------------------------------------
115template<typename X, typename Y>
117
118template<typename X>
120
121template<typename Y>
123
125
128template<typename X, typename Y>
129constexpr static SPLerpXY<X, Y> mapRangeSPXY(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh) noexcept
130{
131 return SPLerpXY<X, Y>(iFromLow, iToLow, iFromHigh, iToHigh);
132}
133
134template<typename Y>
136
137template<typename X>
139
141
144template<typename X, typename Y>
145constexpr static Y mapValueSPXY(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
146{
147 return SPLerpXY<X, Y>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
148}
149
152template<typename Y>
153constexpr static Y mapValueSPY(float iValue, float iFromLow, float iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
154{
155 return SPLerpY<Y>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
156}
157
160template<typename X>
161constexpr static float mapValueSPX(X iValue, X iFromLow, X iFromHigh, float iToLow, float iToHigh, bool iClamp = true)
162{
163 return SPLerpX<X>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
164}
165
168constexpr static float mapValueSP(float iValue, float iFromLow, float iFromHigh, float iToLow, float iToHigh, bool iClamp = true)
169{
170 return SPLerp::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
171}
172
173
174//------------------------------------------------------------------------
175// DPLerp - Double Precision Lerp (double)
176//------------------------------------------------------------------------
177template<typename X, typename Y>
179
180template<typename X>
182
183template<typename Y>
185
187
190template<typename X, typename Y>
191static constexpr DPLerpXY<X, Y> mapRangeDPXY(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh)
192{
193 return DPLerpXY<X, Y>(iFromLow, iToLow, iFromHigh, iToHigh);
194}
195
196template<typename Y>
198
199template<typename X>
201
203
206template<typename X, typename Y>
207constexpr static Y mapValueDPXY(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
208{
209 return DPLerpXY<X, Y>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
210}
211
214template<typename Y>
215constexpr static Y mapValueDPY(double iValue, double iFromLow, double iFromHigh, Y iToLow, Y iToHigh, bool iClamp = true)
216{
217 return DPLerpY<Y>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
218}
219
222template<typename X>
223constexpr static double mapValueDPX(X iValue, X iFromLow, X iFromHigh, double iToLow, double iToHigh, bool iClamp = true)
224{
225 return DPLerpX<X>::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
226}
227
230constexpr static double mapValueDP(double iValue, double iFromLow, double iFromHigh, double iToLow, double iToHigh, bool iClamp = true)
231{
232 return DPLerp::mapValue(iValue, iFromLow, iFromHigh, iToLow, iToHigh, iClamp);
233}
234
238template<typename T>
239struct Range
240{
243 using value_type = T;
244
245 // Empty constructor (no range)
246 constexpr Range() = default;
247
248 // Single value range
249 constexpr explicit Range(T iValue) noexcept : fFrom{iValue}, fTo{iValue} {}
250
251 // Constructor
252 constexpr Range(T iFrom, T iTo) noexcept : fFrom{iFrom}, fTo{iTo} {}
253
254 // return true if the range is a single value (aka degenerate range)
255 constexpr bool isSingleValue() const { return fFrom == fTo; }
256
267 constexpr bool contains(T iValue) const
268 {
269 if(fFrom < fTo)
270 return iValue >= fFrom && iValue <= fTo;
271 else
272 return iValue <= fFrom && iValue >= fTo;
273 }
274
280 constexpr T clamp(T iValue) const
281 {
282 return Utils::clampRange(iValue, fFrom, fTo);
283 }
284
293 template<typename U, HasStaticMapValue<T, U> TLerp = DPLerpXY<T, U>>
294 constexpr U mapValue(T iValue, Range<U> const &iRange, bool iClampToRange = true) const
295 {
296 return TLerp::mapValue(iValue, fFrom, fTo, iRange.fFrom, iRange.fTo, iClampToRange);
297 }
298
305 template<typename U, HasStaticMapValue<T, U> TLerp = DPLerpXY<T, U>>
306 constexpr Range<U> mapRange(Range<U> const &iRange) const
307 {
308 // obviously *this* range is already clamped...
309 return mapSubRange<U,TLerp>(*this, iRange, true);
310 }
311
320 template<typename U, HasStaticMapValue<T, U> TLerp = DPLerpXY<T, U>>
321 constexpr Range<U> mapSubRange(Range<T> const &iSubRange, Range<U> const &iRange, bool iClampToRange = true) const
322 {
324 return Range<U>{mapValue<U,TLerp>(iSubRange.fFrom, iRange, iClampToRange),
325 mapValue<U,TLerp>(iSubRange.fTo, iRange, iClampToRange)};
326 }
327
331 template<typename U>
332 constexpr Range<U> cast() const
333 {
334 return Range<U>{static_cast<U>(fFrom), static_cast<U>(fTo)};
335 }
336
337 // operator==
338 bool operator==(const Range &rhs) const
339 {
340 return fFrom == rhs.fFrom && fTo == rhs.fTo;
341 }
342
343 // operator!=
344 bool operator!=(const Range &rhs) const
345 {
346 return !(rhs == *this);
347 }
348
349public:
350 T fFrom{};
351 T fTo{};
352};
353
354}
Util class to compute linear interpolation.
Definition Lerp.h:42
const TFloat fA
Definition Lerp.h:108
static constexpr Lerp mapRange(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh) noexcept
Inspired by the map function in Processing language, another way to look at Lerp is to map a range of...
Definition Lerp.h:69
constexpr Lerp(Y iY0, Y iY1) noexcept
Shortcut for when x=0 => iY0 and x=1.0 => iY1.
Definition Lerp.h:51
constexpr X computeX(Y iY) const
Definition Lerp.h:58
const TFloat fB
Definition Lerp.h:109
constexpr Lerp(X iX1, Y iY1, X iX2, Y iY2) noexcept
Definition Lerp.h:44
constexpr Y computeY(X iX) const
Definition Lerp.h:53
static constexpr 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:89
Concept for a static mapValue function.
Definition Lerp.h:28
Definition CircularBuffer.h:27
Lerp< float, X, Y > SPLerpXY
Definition Lerp.h:116
Lerp< double, X, double > DPLerpX
Definition Lerp.h:181
Lerp< double, X, Y > DPLerpXY
Definition Lerp.h:178
static constexpr Y mapValueSPXY(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:145
static constexpr SPLerpXY< X, Y > mapRangeSPXY(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh) noexcept
Convenient shortcut for single precision.
Definition Lerp.h:129
Lerp< double, double, double > DPLerp
Definition Lerp.h:186
static constexpr Y mapValueSPY(float iValue, float iFromLow, float iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:153
constexpr auto mapRangeDPY
Definition Lerp.h:197
static constexpr T clamp(const U &iValue, const T &iLower, const T &iUpper)
Make sure that the value remains within its bounds.
Definition Misc.h:34
constexpr auto mapRangeSPX
Definition Lerp.h:138
Lerp< float, X, float > SPLerpX
Definition Lerp.h:119
Lerp< float, float, float > SPLerp
Definition Lerp.h:124
Lerp< float, float, Y > SPLerpY
Definition Lerp.h:122
static constexpr Y mapValueDPXY(X iValue, X iFromLow, X iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:207
static constexpr Y mapValueDPY(double iValue, double iFromLow, double iFromHigh, Y iToLow, Y iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:215
static constexpr T clampRange(const U &iValue, const T &iFrom, const T &iTo)
Make sure that the value remains within its bounds.
Definition Misc.h:45
constexpr auto mapRangeDPX
Definition Lerp.h:200
constexpr auto mapRangeSPY
Definition Lerp.h:135
static constexpr DPLerpXY< X, Y > mapRangeDPXY(X iFromLow, X iFromHigh, Y iToLow, Y iToHigh)
Convenient shortcut for double precision.
Definition Lerp.h:191
Lerp< double, double, Y > DPLerpY
Definition Lerp.h:184
static constexpr float mapValueSPX(X iValue, X iFromLow, X iFromHigh, float iToLow, float iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:161
constexpr auto mapRangeDP
Definition Lerp.h:202
constexpr auto mapRangeSP
Definition Lerp.h:140
static constexpr double mapValueDPX(X iValue, X iFromLow, X iFromHigh, double iToLow, double iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:223
static constexpr double mapValueDP(double iValue, double iFromLow, double iFromHigh, double iToLow, double iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:230
static constexpr float mapValueSP(float iValue, float iFromLow, float iFromHigh, float iToLow, float iToHigh, bool iClamp=true)
Convenient shortcut for single precision.
Definition Lerp.h:168
constexpr bool isSingleValue() const
Definition Lerp.h:255
constexpr Range()=default
constexpr Range< U > mapRange(Range< U > const &iRange) const
Map this range to the other range.
Definition Lerp.h:306
constexpr Range(T iValue) noexcept
Definition Lerp.h:249
CCoord fFrom
Definition Lerp.h:350
bool operator!=(const Range &rhs) const
Definition Lerp.h:344
T fTo
Definition Lerp.h:351
constexpr 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:294
bool operator==(const Range &rhs) const
Definition Lerp.h:338
constexpr 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:321
constexpr Range< U > cast() const
Cast this range to another one.
Definition Lerp.h:332
constexpr 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:267
constexpr Range(T iFrom, T iTo) noexcept
Definition Lerp.h:252
constexpr T clamp(T iValue) const
Clamp the value to this range.
Definition Lerp.h:280
T value_type
Gives access to the type of elements in the range.
Definition Lerp.h:243