Skip to content

Instantly share code, notes, and snippets.

@Martin-Pitt
Created February 15, 2024 01:16
Show Gist options
  • Save Martin-Pitt/adf0e5d5fc01227b7277f53fdd6b7294 to your computer and use it in GitHub Desktop.
Save Martin-Pitt/adf0e5d5fc01227b7277f53fdd6b7294 to your computer and use it in GitHub Desktop.
Rescale Interpolation
/*
More interesting interpolation functions to make life easier.
Rescale is a function which can interpolate a value between two different ranges.
Say you have a number which represents the position of a slider.
The slider has a start and end as well.
You want the slider to control a box between two locations.
So you could do the following:
boxPosition = rescale(sliderStart, sliderEnd, boxStart, boxEnd, slideValue);
Additionally there is a clamped variation, `rescale.clamped(…)` with the same
function signature that clamps the output value in the `to` range
*/
function rescale(from_min, from_max, to_min, to_max, from) {
return to_min + ((to_max-to_min) * ((from_min-from) / (from_min-from_max)));
}
rescale.clamped = function(from_min, from_max, to_min, to_max, from) {
from = this(from_min, from_max, to_min, to_max, from);
if(to_min < to_max) {
if(from < to_min) return to_min;
else if(from > to_max) return to_max;
} else {
if(from < to_max) return to_max;
else if(from > to_min) return to_min;
}
return from;
}
/// An alternative API, works via two-element arrays: `from` and `to`
// E.g. retarget([0, 1], [0, 100], 0.23) => 23
function retarget(from, to, via) {
if(!Array.isArray(from)) throw new Error('retarget: `from` is not an array');
if(!Array.isArray(to)) throw new Error('retarget: `to` is not an array');
if(from.length < 2) throw new Error('retarget: `from` needs at least 2 entries');
if(to.length < 2) throw new Error('retarget: `to` needs at least 2 entries');
if(via < from[0]) return rescale(from[0], from[1], to[0], to[1], via);
if(via > from[from.length - 1]) return t = rescale(from[from.length - 2], from[from.length - 1], to[to.length - 2], to[to.length - 1], via);
for(var iter = 0, total = from.length; iter < total; ++iter)
if(via <= from[iter]) break;
var a = from[iter - 1], b = from[iter];
var t = (via - a) / (b-a);
t = ((iter - 1 + t) / from.length) * to.length;
var c = to[Math.floor(t)], d = to[Math.ceil(t)];
return rescale(a, b, c, d, via);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment