Reputation: 8239
I have 2 double values which can go from let's say start value 62.243
to end value 79.495
. I have another 2 double values which can go from let's say start value 4.456
to end value 7.687
.
double start_1 = 62.243;
double end_1 = 79.495;
double start_2 = 4.456;
double end_2 = 7.687;
Now if I a value picked between start_1
and end_1
, I want to interpolate the same value to a value between start_2
and end_2
.
Question:
How do implement the below function in C++ which can do what I described above?
double InterpolateAValue(const double start_1, const double end_1, const double start_2, const double end_2, double value_between_start_1_and_end_1) {
// How to get a value between start_2 and end_2 which matches the position of value_between_start_1_and_end_1 in the range of `start_1` and `end_1`
};
I think above function should pass the following unit test.
EXPECT_DOUBLE_EQ(40.0, InterpolateAValue(10.0, 20.0, 30.0, 50.0, 15.0));
std::lerp seems to be doing something like what I need but not exactly. I am on C++11. I have taken double
as the type here. I could have chosen float
s as well but a wish to see how doubles affect the math is also a part of the question.
Upvotes: 2
Views: 5047
Reputation: 122460
Since C++20 there is std::lerp
.
Computes a+t(b−a), i.e. the linear interpolation between a and b for the parameter t (or extrapolation, when t is outside the range [0,1]).
It does half of what you want. Your t
is t = ( value - start_1) / (end_1 - start_1)
. Hence you can do
#include <cmath>
double InterpolateAValue(double start_1,double end_1,double start_2, const double end_2, double value) {
return std::lerp(start_2, end_2, (value - start1) / (end_1 - start_1));
}
Upvotes: 6
Reputation: 234695
For a number value_between_start_1_and_end_1
,
lambda = (value_between_start_1_and_end_1 - start_1) / (end_1 - start_1)
tells you how far you are along the 1
-line. 0 means you're at start_1
, 1 means you're at end_1
.
Then use
start_2 + lambda * (end_2 - start_2)
to get the corresponding position along the 2
-line. I've separated the computation into two stages, but aside from giving up ease of debugging, you could combine in one step.
Personally I'd always use double
s for this. A float
could even be slower on modern systems due to unexpected type conversions. Of course you need to check that start_1
and end_1
are different.
Upvotes: 4