1 /**
2  * Inclusive scalar value ranges for interpolating and remapping values.
3  */
4 module bettercmath.valuerange;
5 
6 /// Remap `value` from the range [inputStart, inputEnd] to [outputStart, outputEnd].
7 T remap(T)(const T value, const T inputStart, const T inputEnd, const T outputStart, const T outputEnd)
8 {
9     return (value - inputStart) / (inputEnd - inputStart) * (outputEnd - outputStart) + outputStart;
10 }
11 
12 /// Remap `value` from the `input` range to `output` range.
13 T remap(T)(const T value, const ValueRange!T input, const ValueRange!T output)
14 {
15     return remap(value, input.from, input.to, output.from, output.to);
16 }
17 
18 /**
19  * Range of scalar values, for more easily interpolating and remapping them.
20  */
21 struct ValueRange(T)
22 {
23     /// Alias for ValueRange element type.
24     alias ElementType = T;
25     /// Value that starts the range.
26     T from = 0;
27     /// Value that ends the range.
28     T to = 1;
29 
30     /// Construct from both values.
31     this(const T from, const T to)
32     {
33         this.from = from;
34         this.to = to;
35     }
36     /// Construct from array of values.
37     this(const T[2] values)
38     {
39         from = values[0];
40         to = values[1];
41     }
42 
43     /// Invert ValueRange inplace.
44     ref ValueRange invert() return
45     {
46         import std.algorithm : swap;
47         swap(from, to);
48         return this;
49     }
50 
51     /// Returns an inverted copy of ValueRange, the range [to, from].
52     ValueRange inverted() const
53     {
54         typeof(return) r = this;
55         return r.invert();
56     }
57 
58     /// Linearly interpolates range by `amount`.
59     T lerp(U)(const U amount) const
60     {
61         import bettercmath.misc : lerp;
62         return lerp(from, to, amount);
63     }
64 
65     /// Remap `value` from this range to `newRange`.
66     T remap(const T value, const ValueRange newRange) const
67     {
68         return .remap(value, this, newRange);
69     }
70 
71     /// Return `value` normalized by this range, so that 0 represents the start of the range and 1 represents the end of it.
72     T normalize(const T value) const
73     {
74         return (value - from) / (to - from);
75     }
76 
77     /// Returns the distance between the range start and end.
78     T distance() const
79     {
80         return to - from;
81     }
82 }