markzzz
markzzz

Reputation: 47945

How to avoid "trap" with linear interpolation?

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

Answers (1)

Daniel Jour
Daniel Jour

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

Related Questions