Reputation: 47945
I have a range a
(starting range) and a range b
(target range), and I need to scale a value aX
from range a
to range b
. Code is a basic linear interpolation:
double LinearInterpolation(double a0, double a1, double b0, double b1, double aX) {
return b0 + (b1 - b0) * (aX - a0) / (a1 - a0);
}
The fact is: range b can be 0-length from 1.0 to 1.0. But when I reach that range, I got a value that is "trap", and can't go back. Here's an example:
int main ()
{
double a0 = 0.4;
double a1 = 1.0;
double b0 = 0.6;
double b1 = 1.0;
double aX = 0.58;
aX = LinearInterpolation(a0, a1, b0, b1, aX);
std::cout << aX << std::endl;
b0 = 1.0;
aX = LinearInterpolation(a0, a1, b0, b1, aX);
std::cout << aX << std::endl;
b0 = 0.6;
aX = LinearInterpolation(a0, a1, b0, b1, aX);
std::cout << aX << std::endl;
}
Until b0
is 0, it scales correctly the aX
value. When I reach b0 = b1 = 1.0
, I can't go back (aX
is always 1.0, because aX = a1
, thus is always b0 + (b1 - b0) => b1
).
How can I avoid this?
Upvotes: 1
Views: 130
Reputation: 16156
How can I avoid this?
Don't store the actual value, but rather the relative position within a range:
struct value_in_range {
double normalized_offset;
double in_range (double from, double to) const {
return from + (to - from) * normalized_offset;
}
};
value_in_range make_value_in_range (double from, double value, double to) {
// Add assertions to avoid misuse
return {(value - from) / (to - from)};
}
With your example:
int main ()
{
double a0 = 0.4;
double a1 = 1.0;
double b0 = 0.6;
double b1 = 1.0;
double aX = 0.58;
value_in_range X = make_value_in_range (a0, aX, a1);
std::cout << X.in_range(b0, b1) << std::endl;
b0 = 1.0;
std::cout << X.in_range(b0, b1) << std::endl;
b0 = 0.6;
std::cout << X.in_range(b0, b1) << std::endl;
}
You could also set aX
as in your original code.
Upvotes: 1