Skip to main content
gamedev.net
🔒 Locked

Linear interpolation help

Started by EvilNando Dec 27, 2008 at 3:35 PM 7 replies 950+ views
Original Post
EvilNando
EvilNando
Im trying to figure out how to calculate mid-values between two numbers point A: 0 point B: 10 the number of points to calculate are 25 my problem is that I need these points to be of an Int32 type, I tried calculating an increment amount by dividing the end value by the number of points needed but this gives me wrong data. Any ideas on how to approach this?
Palidine
Palidine
int32 means whole numbers. there are not 25 whole (integer) numbers between 0 and 10 (there are 9 not counting 0 and 10). Use a float

If you're really bound by int32, I suppose you could also make 0 == 0 and 10 == 1000 and treat the 2 least significant digits as decimal points (thus, 1.5 would become 150, 2.3 -> 230, etc).

-me
swiftcoder
swiftcoder
Quote:
Original post by EvilNando
Im trying to figure out how to calculate mid-values between two numbers

point A: 0
point B: 10

the number of points to calculate are 25. my problem is that I need these points to be of an Int32 type.
Well, an obvious problem is that there are not 25 unique integers between 0 and 10, instead there are only 9. Something like this might do the trick:
def interpolate(points, start, end, count):	diff = end - start # take the difference	if count > diff: # clamp the count to the distance		count = diff	step = diff / count # calculate a step increment		for i in range(count): # loop over count		start += step # generate point		points.append(start)
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]
EvilNando
EvilNando
there is no need to have each point unique

values can (and should) repeat in cases like these
Ignifex
Ignifex
Well I'm not exactly sure of how you want to divide the 25 numbers in that range, but wouldn't integer arithmetic suffice?
Something along the lines of:
for i from 1 to 25 do  midpoint := 0 + 10 * i / 25end

Note that this is uses integer division, which usually rounds the result down to the nearest integer. This means you will get more low numbers and only one 10. Sticking to integer division, a way to make this a little better would be something like:
midpoint := 0 + ((10 * i) + 25 / 2) / 25

You mentioned your resulting data was wrong. What was wrong with it?
EvilNando
EvilNando
nevermind got it working

A : 0;
B : 10;

numpoints = 25;

increment = B - A / numpoints;

for (numpoints)
point = (Int32)(A + increment * idx);

thank you for the ideas! :)
HappyCoder
HappyCoder
I would just interpolate with floats, then cast them to integers.

double inc = (pointB - pointA) / pointCount;double currentPoint = pointA;for (int i = 0; i <= pointCount, currentPoint += inc; i++){     int point = (int)floor(currentPoint + 0.5); // round to the nearest int     // store the point or use it, whatever you need to do here}

This version will also have the interpolated points as part of the end points. (see below)
Point A             Point B  .                    .  .  .  .  .  .  .  .  .  <- interpolated points


If you absolutely need to keep them as int use fixed point.
int inc = ((pointB - pointA) << 16) / pointCount;int currentPoint = pointA << 16;for (int i = 0; i <= pointCount, currentPoint += inc; i++){     int point = (currentPoint + 0x8000) >> 16; // round to the nearest int     // store the point or use it, whatever you need to do here}


As long as the pointA and pointB don't exceed 65535 and pointCount doesn't get close to that same number this should work fairly well. If you will reach those numbers you will have to change the integers to long longs, double the 16s to 32s and change 0x8000 to 0x80000000. Unless you are looking to squeeze out extra speed because this is a critical routine, I would just go with the float version.
My current game project Platform RPG
EvilNando
EvilNando
Awesome! thanks a lot!
Zahlman
Zahlman
Try to consider how you might adapt this to your problem.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.