Linear interpolation
Whie thinking about another topic to write about at my still new blog, I came across some basic mathematical or geometrical concepts where I was not sure whether I need to introduce these before going straight into the topic.
That’s why I come up with this post about a basic concept in computer graphics which is linear interpolation. If this is to basic for you, watch out for more complex blog posts of mine.
Lerp»
lerp()
ist a contraction of “linear interpolation”
and often the name of a function frequently used in computer graphics.
Sometimes it is called by a different name, e.g. mix()
const lerp = (s, e, t) => (1 - t) * s + t * e;
This function interpolates a value between a start value (s) and an end value (e). Assuming a linear course, this function calculates a value of this line at a time (tvalue).
Linear function»
Maybe you remember linear functions back from school. A function is linear if it increases evenly over time.
So for every change along the horizontal axis by one (Δt = 1
) the slope m constantly is e minus s.
The vertical axis f(t) is intercepted at n which is s.
So when calculating a value between s and e we can simply insert the values read from the diagram. Everything else is just a mathematical transformation of the equation.
f(t) = m * t + n
value = (e - s) * tvalue + s
Examples»
In practice there are a lot of use-cases for lerp()
. But remember: all it does is to calculate a value betwenn two others. What you do with the result is up to you and your code.
Here are a few practical examples. In addition to a number, you could also search for the value for a hue, an angle or a coordinate, in each case between two known values. You can use the slider to manually select a value.
To interpolate between two points, you can use plerp()
.
const point = (x, y) => ({x, y});
const plerp = (s, e, t) => point(
lerp(s.x, e.x, t),
lerp(s.y, e.y, t),
);
Clamp»
I would like to point out the clamp()' method. With this one can ensure that the result of
lerp()` is between 0 and 1.
const clamp = (v, min = 0, max = 1) => Math.min(max, Math.max(min, v));
This is an interpolation because we find a value on a line between two points. If we assume the line continues straight outside the two points and we are looking for a value outside this range, we speak of extrapolation.
Inverse Lerp»
Of course, there can also be cases where we are interested in exactly the opposite of lerp()
.
If we want to know where we are between two points, we can simply rearrange the equation for t.
tvalue = (value - s) / (e - s)
const invLerp = (s, e, v) => (v - s) / (e - s);
An example of this would be to output the scroll position of the page as a value between 0 and 1.
We pass the method 0 and the page height minus the height of the browser window as our range of interest
and determine the inverseLerp()
result for the scrollY
position.
Remap»
While the text in the slider above shows the value between 0 and 1, the bar itself has a width between 0 and 160 pixels.
This can be calculated using remap()
which combines lerp()
and inverseLerp()
.
const remap = (min1, max1, min2, max2, v) =>
lerp(min2, max2, invLerp(min1, max1, v));
Curryied lerp»
And last but not least a reminder to use ES6 currying syntax. So you can memoize recurring function arguments as a new function.
const clerp = (s) => (e) => (t) => lerp(s, e, t);
For example, if you want to determine several values between 0 and 2Π, you can come up with a shortcut function angle like this:
// angle between 0 and 2π
const angle = clerp(0)(2 * Math.PI);
angle(0.25); // 1.5707963267948966
angle(0.5); // 3.141592653589793
angle(1.0); // 6.283185307179586