Need help with some errors in my bilinear interpolation function

Started by
11 comments, last by iMalc 14 years, 6 months ago
Quote: +---0,0---+---1,0---+ |? ? ? ? ?|? ? ? ? ?|... |? ? ? ? ?|? ? ? ? ?|... |? ? A ? ?|? ? B ? ?|... |? ? ? ? ?|? ? ? ? ?|... |? ? ? ? ?|? ? ? ? ?|... +---0,1---+---1,1---+ |? ? ? ? ?|? ? ? ? ?|... |? ? ? ? ?|? ? ? ? ?|... |? ? C ? ?|? ? D ? ?|... |? ? ? ? ?|? ? ? ? ?|... |? ? ? ? ?|? ? ? ? ?|... +---------+---------+ | ... | ... |...
I know the values of A, B, C & D and I want to interpolate between those values to fill in the rest of the ?'s Below is the source code as I currently have it, but I am doing something wrong somewhere and I can't figure it out. In the code below the NW quadrant == 0 NE quadrant == 1 SW quadrant == 2 SE quadrant == 3

	for(int pix = 0; pix < RMAP_X; pix++)
	{
		for(int piy = 0; piy < RMAP_Y; piy++)
		{
			quadrant = -1;
			if(pix < (halfRMAP_X) && piy <(halfRMAP_Y))
			{
				quadrant = 0;
			}
			else if(pix >= (halfRMAP_X) && piy < (halfRMAP_Y))
			{
				quadrant = 1;
			}
			else if(pix < (halfRMAP_X) && piy >= (halfRMAP_Y))
			{
				quadrant = 2;
			}
			else if(pix >= (halfRMAP_X) && piy >= (halfRMAP_Y))
			{
				quadrant = 3;
			}


			if(quadrant == 0)
			{
				//nw quadrant - 
				//pix < halfRMAP_X
				//piy < halfRMAP_Y

				float nwDist = 0;
				float nDist = 0;
				float wDist = 0;
				float centDist = 0;
				nDist = 1 / linearDist(pix,piy,pix + (halfRMAP_X - pix),piy - (halfRMAP_Y + piy));
				wDist = 1 / linearDist(pix,piy,pix - (halfRMAP_X + pix),piy + (halfRMAP_Y - piy));
				nwDist = 1 / linearDist(pix,piy, pix - (halfRMAP_X + pix), piy - (halfRMAP_Y - piy));
				centDist = 1 / linearDist(pix,piy, pix + (halfRMAP_X - pix), piy + (halfRMAP_Y - piy));
				
				float sum = nDist + wDist + nwDist + centDist;

				nDist = nDist / sum;
				wDist = wDist / sum;
				nwDist = nwDist / sum;
				centDist = centDist / sum;
				
				world.wMap[wX][wY].area.aMap[aX][aY].region.rMap[pix][piy].elevation = nw*nwDist + n*nDist + w*wDist + world.wMap[wX][wY].area.aMap[aX][aY].region.baseHt*centDist;

			}
			else if(quadrant == 1)
			{
				//ne quadrant
				//pix >= halfRMAP_X
				//piy < halfRMAP_Y

				float neDist = 0;
				float nDist = 0;
				float eDist = 0;
				float centDist = 0;
				nDist = 1 / linearDist(pix,piy, pix - (pix - halfRMAP_X), piy - (halfRMAP_Y + piy));
				eDist = 1 / linearDist(pix,piy, pix + (halfRMAP_X + (RMAP_X - pix)), piy + (halfRMAP_Y - piy));
				neDist = 1 / linearDist(pix,piy, pix + (halfRMAP_X + (RMAP_X - pix)), piy - (halfRMAP_Y + piy));
				centDist = 1 / linearDist(pix,piy, pix - (pix - halfRMAP_X), piy + (halfRMAP_Y - piy));

				float sum = nDist + eDist + neDist + centDist;

				nDist = nDist / sum;
				eDist = eDist / sum;
				neDist = neDist / sum;
				centDist = centDist / sum;

				world.wMap[wX][wY].area.aMap[aX][aY].region.rMap[pix][piy].elevation = ne*neDist + n*nDist + e*eDist + world.wMap[wX][wY].area.aMap[aX][aY].region.baseHt*centDist;

			}
			else if(quadrant == 2)
			{
				//sw quadrant
				//pix < halfRMAP_X
				//piy >= halfRMAP_Y

				float swDist = 0;
				float sDist = 0;
				float wDist = 0;
				float centDist = 0;

				wDist = 1 / linearDist(pix,piy,pix - (halfRMAP_X + pix), piy - (piy - halfRMAP_Y));
				sDist = 1 / linearDist(pix,piy, pix + (halfRMAP_X - pix), piy + (halfRMAP_Y + (RMAP_Y - piy)));
				swDist = 1 / linearDist(pix,piy, pix - (halfRMAP_X + pix), piy + (halfRMAP_Y + (RMAP_Y - piy)));
				centDist = 1 / linearDist(pix,piy, pix + (halfRMAP_X - pix), piy - (piy - halfRMAP_Y));

				float sum = sDist + wDist + swDist + centDist;

				sDist = sDist / sum;
				wDist = wDist / sum;
				swDist = swDist / sum;
				centDist = centDist / sum;


				world.wMap[wX][wY].area.aMap[aX][aY].region.rMap[pix][piy].elevation = sw*swDist + s*sDist + w*wDist + world.wMap[wX][wY].area.aMap[aX][aY].region.baseHt*centDist;

			}
			else if(quadrant == 3)
			{
				//se quadrant
				//pix >= halfRMAP_X
				//piy >= halfRMAP_Y

				float seDist = 0;
				float sDist = 0;
				float eDist = 0;
				float centDist = 0;

				eDist = 1 / linearDist(pix,piy, pix + (halfRMAP_X + (RMAP_X - pix)), piy - (piy - halfRMAP_Y));
				sDist = 1 / linearDist(pix,piy, pix - (pix - halfRMAP_X), piy + (halfRMAP_Y + (RMAP_Y - piy)));
				seDist = 1 / linearDist(pix,piy, pix + (halfRMAP_X + (RMAP_X - pix)), piy + (halfRMAP_Y + (RMAP_Y - piy)));
				centDist = 1 / linearDist(pix,piy, pix - (pix - halfRMAP_X), piy - (piy - halfRMAP_Y));

				float sum = sDist + eDist + seDist + centDist;

				sDist = sDist / sum;
				eDist = eDist / sum;
				seDist = seDist / sum;
				centDist = centDist / sum;



				world.wMap[wX][wY].area.aMap[aX][aY].region.rMap[pix][piy].elevation = se*seDist + s*sDist + e*eDist + world.wMap[wX][wY].area.aMap[aX][aY].region.baseHt*centDist;

			}
		}
	}



My results are below: as you can see, things don't line up correctly and some other stuff isn't working out correctly. It looks like it is something with the se quadrant, because it seems from the shore in the 2nd picture that the sw & ne quadrants will line up, but I'm not sure. [Edited by - polpoint on September 28, 2009 7:08:48 PM]
Advertisement
The code seems to be interpolating correctly within each quadrant, but the 4 quadrants don't line up correctly. And there are those little low elevation squares (the little blue squares evenly spaced around) that mark the exact center of each square.

if I take into account all 8 of the surrounding elevation levels (as opposed to how I am doing it now and only taking into account the three closest) will that make everything smooth inbetween the 4 quadrants?
First thing you need to know is that your diagram and description of the interpolation is incorrect (apart from the missing [code][/code] tags). Bilinear interpolation only provides the values from between the samples. Also, one strip is usually left for calculation by the interpolation of the next "source pixel" in the row or column (to save duplication). Usually a diagram would represent the values takes the values from the "source pixel" corners. Here is your diagram modified to put X's in the values that are not calculated from an bilerp of A, B, C & D. Only the ?'s are calculated via interpolation of A, B, C & D.
+---0,0---+---1,0---+-|X X X X X|X X X X X|...|X X X X X|X X X X X|...|X X A ? ?|? ? B X X|...|X X ? ? ?|? ? X X X|...|X X ? ? ?|? ? X X X|...+---0,1---+---1,1---+-|X X ? ? ?|? ? X X X|...|X X ? ? ?|? ? X X X|...|X X C X X|X X D X X|...|X X X X X|X X X X X|...|X X X X X|X X X X X|...+---------+---------+-| ....... | ....... |
Now as you can see, the actual amount of samples taken from the one interpolation actually only covers an area the size of one logical "source pixel". Thus the more typical diagram would be:
+---0,0---+---1,0|A ? ? ? ?|B ...|? ? ? ? ?|X ...|? ? ? ? ?|X ...|? ? ? ? ?|X ...|? ? ? ? ?|X ...+---0,1---+---1,1|C X X X X|D ...| ....... | ....
Note now how you sample each "source pixel" from the top-left corner and use those four values to fill in an area corresponding to exactly one "source pixel". You may also notice that this also means you actually need one more row and one more column of source data than you have already. (Unless you scale your sampling across the entire row etc such that you sample each "source pixel" from a slightly different spot)

Sure it can be done without an extra sample by using extrapolation around the edges, but that's actually a lot more work and certainly not a good idea if you're already running into difficulties.

In light of this I think you unfortunately need to totally rewrite what you have. Having written plenty of bilerps myself, I don't even recognise this code as a bilerp of any kind. The whole thing with the quadrants has no place here IMHO.

Note that I use the terms "source pixel" and "destination pixel" very losely here. It only refers to the sampling frequencies of the source and desintation.

I'm trying to look up a useful source of the algorithm for you to start from...
Edit: I found this which might help.
Here's another link that might be useful.

[Edited by - iMalc on September 29, 2009 1:37:30 PM]
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Thanks for the thorough description iMalc!

I don't think I explained the specifics of my problem very well or else I am not completely understanding your explanation.

I am not doing anything with graphics, I let openGL handle all of the resampling of my graphics. I am trying to smooth out the elevation of my heightmap after zooming in to a different "magnification" (but it seems that you understand that with the very loose usage of source and destination pixel)


I start out with this:
+-+-+-+
|5|1|4|
+-+-+-+
|9|5|2|
+-+-+-+
|3|8|7|
+-+-+-+

Then increase my magnification to this:
+---+---+---+
|555|111|444|
|555|111|444|
|555|111|444|
+---+---+---+
|999|555|222|
|999|555|222|
|999|555|222|
+---+---+---+
|333|888|777|
|333|888|777|
|333|888|777|
+---+---+---+

At this point I only have the center 5-value square loaded in memory for the new magnification and all of the squares at the previous magnification loaded in memory, so I basically know what the "base" surrounding values are supposed to be.

Then I want to smooth out the values so I get something close to this (the values in the center square are a close enough approximation for this example):
+---+---+---+
|555|111|444|
|555|111|444|
|555|111|444|
+---+---+---+
|999|635|222|
|999|754|222|
|999|566|222|
+---+---+---+
|333|888|777|
|333|888|777|
|333|888|777|
+---+---+---+


So I am coming close to figuring it out, but I don't have access to the extra row & column and it seems like, from your example, I need a specific "start position," which would be the upper-left-most square (or whichever corner). I am using this to smooth out the elevation of a heightmap for a huge area that is divided up into smaller chunks.

So the code that I posted above (minus the stupid method I utilized to figure the coordinates for the surrounding center squares) works, but only within one quadrant and the surrounding square's bordering quadrants. I edited one of the pictures above to highlight this.


The arrows point to the center of the big squares (the values of that specific tile are messed up because I divided by 0 distance from the center) and the black square is outlining the se, sw, ne, and nw quadrant of 4 adjoining big squares.



As you can see everything is lining up within the black square, but it does not line up with that same big square's other 3 quadrants. I tried doing the same thing utilizing all 8 surrounding big square's values along with the central big square that I am modifying but that doesn't work either.

Ah! problems that I can not solve are frustrating!
Good, more diagrams, and you got the code tags - excellent![smile]
What I thought you might not fully understand is that bilinear interpolation of images is exactly the same process as it is for generating smoothed map data.
This is known as point sampling:
+---+---+---+|555|111|444||555|111|444||555|111|444|+---+---+---+|999|555|222||999|555|222||999|555|222|+---+---+---+|333|888|777||333|888|777||333|888|777|+---+---+---+
All well and good.

Here is the sample as you probably imagine it, without any of the interpolated pixels calculated:
+---+---+---+|???|???|???||?5?|?1?|?4?||???|???|???|+---+---+---+|???|???|???||?9?|?5?|?2?||???|???|???|+---+---+---+|???|???|???||?3?|?8?|?7?||???|???|???|+---+---+---+
Now, if you expect those grid points with numbers in them to be exactly as shown with the interpolation, how would you plan to calculate the numbers in say the position of the top-left question mark? It's not located between the 5 and the 1 horizontally, nor is it located between the 5 and the 9 vertically. You'd need to calculate it via extrapolation if this is how you imagined it. This is the difficult way, and it really doesn't work nicely for what you want.

On the other hand you can start out like:
+---+---+---+|5??|?1?|??4||???|???|???||???|???|???|+---+---+---+|???|???|???||9??|?5?|??2||???|???|???|+---+---+---+|???|???|???||???|???|???||3??|?8?|??7|+---+---+---+
What I've done here is stretch the source image out by almost one "source pixel". The numbers at the positions shown are the final values. Now you can clearly calculate the values for all of the question marks because they are all located between known values. For example the first three question marks on the top row would be 4, 3, and 2, correct?
Okay, if this is how you want to do it it's easy:
Iterate over every "destination pixel" (ahem grid tile or whatever) and calculate the exact fractional position that that position refers to on the source "image". when performing lookups. For the question mark in the sixth row and the second column it's source coordinates are 1.25 and 0.25. You use the whole numbers to look up the source pixels, and the whole numbers plus one. So that's source positions (1, 0) (1, 1) (2, 0) and (2, 1).
Now you perform the interpolation using the fractional parts. In this case it's 0.25 of the lower two samples and 0.75 of the upper two. Ditto for the horizontal interpolation.
("1"*0.75 + "4"*0.25)*0.75 + ("5"*0.75 + "2"*0.25)*0.25 = Bingo!

Or you can start with one extra row and column of data like this:
+---+---+---+|5??|1??|4??|8|???|???|???|X|???|???|???|X+---+---+---+-|9??|5??|2??|2|???|???|???|X|???|???|???|X+---+---+---+-|3??|8??|7??|6|???|???|???|X|???|???|???|X+---+---+---+-|0XX|3XX|2XX|5
Again you can calculate the value for every question mark square because it is actually between known values. This method puts each nown value in the same place and makes the interpolation potentially faster, but requires an extra row and column of data.
For the question mark in the sixth row and the second column it's source coordinates are now 1.667 and 0.333. The integer portions are the same here so you still read the values 1, 4, 5 and 2, but now you take slightly different portions of each to fill in that grid position.
Note that the easy way to get one extra row and column is to make it wrap around for the rightmost column such that it actually reads the value from the leftmost column again. I.e:
+---+---+---+|5??|1??|4??|5|???|???|???|X|???|???|???|X+---+---+---+-|9??|5??|2??|9|???|???|???|X|???|???|???|X+---+---+---+-|3??|8??|7??|3|???|???|???|X|???|???|???|X+---+---+---+-|5XX|1XX|4XX|5

This also makes the resulting map tileable, and it's the method usually used in texture bilinear filtering.
Hmm well that's all I have time for right now. I'll let you digest all that for now as you probably need to adjust your thinking somewhat. I suspect that you're either not sure which one of these methods your using, which has led the the problem, or you're trying the method that would require extrapolation.

Edit: Oh one last thing I just realised, it looks like you might be trying to interpolate the values in one destination pixel from the values of the source pixels above, below, left, and right of the desintation pixel. If so, that is definitely wrong and although it makes some sense to someone who is new to interpolation, it will not work and probably explains why you're getting what you're getting.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
I've thought about your actual some more and I really can't tell what you ar actually doing, but it definitely isn't bilinear interpolation.
				nDist = 1 / linearDist(pix,piy,pix + (halfRMAP_X - pix),piy - (halfRMAP_Y + piy));				wDist = 1 / linearDist(pix,piy,pix - (halfRMAP_X + pix),piy + (halfRMAP_Y - piy));				nwDist = 1 / linearDist(pix,piy, pix - (halfRMAP_X + pix), piy - (halfRMAP_Y - piy));				centDist = 1 / linearDist(pix,piy, pix + (halfRMAP_X - pix), piy + (halfRMAP_Y - piy));//All of these can be simplified to just				nDist = 1 / linearDist(pix, piy, halfRMAP_X, -halfRMAP_Y));				wDist = 1 / linearDist(pix, piy, -halfRMAP_X, halfRMAP_Y);				nwDist = 1 / linearDist(pix, piy, -halfRMAP_X, -halfRMAP_Y);				centDist = 1 / linearDist(pix, piy, halfRMAP_X, halfRMAP_Y);
What does linearDist do?
I don't know where n, w, and nw come from. Are those samples form the corner of the map or something?
world.wMap[wX][wY].area.aMap[aX][aY].region.rMap[pix][piy].elevation = sw*swDist + s*sDist + w*wDist + world.wMap[wX][wY].area.aMap[aX][aY].region.baseHt*centDist;
This monstrosity screams to me "breaking encapsulation"!. Use a reference to the part that doesn't change during the loop.
Anyway, one thing remains clear here. Your code does not resemble bilinear interpolation at all. Bilinear interpolation would mean that every "destination pixel" is a weighted average of exactly four source pixels. There is normally no floating point used, no divisions, and nothing to do with quadrants.
If you could show me where the sample data comes from and where it is to go to, I can write the bilerp for you to try out.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
I don't really understand -

so if I do something like your diagram to calculate only the central 5-value square:
+---+---+---+|5??|?1?|??4||???|???|???||???|???|???|+---+---+---+|???|???|???||9??|?5?|??2||???|???|???|+---+---+---+|???|???|???||???|???|???||3??|?8?|??7|+---+---+---+


Then if I move one square to the north and calculate the 1-value square like this:
+---+---+---+|7??|?2?|??3||???|???|???||???|???|???|+---+---+---+|???|???|???||5??|?1?|??4||???|???|???|+---+---+---+|???|???|???||???|???|???||9??|?5?|??2|+---+---+---+

will it line up with the calculated values for the 5-value square?

It doesn't seem like it would - it seems like it would be missing one row (the three ?'s that are right between the 5 and the 1)
Yeah, that code is pretty funked up -
the lowercase n, ne, e, se, s, sw, w & nw are the surrounding big square's base elevation values (or the A, B & D in the example where we try to calculate the values for the C square - the A would be n, the B would be ne and the D would be e)



	CORD N, NE, E, SE, S, SW, W, NW;	N.X = halfRMAP_X;	N.Y = -halfRMAP_Y;		NE.X = halfRMAP_X + RMAP_X;	NE.Y = -halfRMAP_Y;	E.X = halfRMAP_X + RMAP_X;	E.Y = halfRMAP_Y;	SE.X = halfRMAP_X + RMAP_X;	SE.Y = halfRMAP_Y + RMAP_Y;	S.X = halfRMAP_X;	S.Y = halfRMAP_Y + RMAP_Y;	SW.X = -halfRMAP_X;	SW.Y = halfRMAP_Y + RMAP_Y;	W.X = -halfRMAP_X;	W.Y = halfRMAP_Y;		NW.X = -halfRMAP_X;	NW.Y = -halfRMAP_Y;			//quadrants go:	//	0  1	//	2  3	for(int pix = 0; pix < RMAP_X; pix++)	{		for(int piy = 0; piy < RMAP_Y; piy++)		{			quadrant = -1;			if(pix < (halfRMAP_X) && piy <(halfRMAP_Y))			{				quadrant = 0;			}			else if(pix >= (halfRMAP_X) && piy < (halfRMAP_Y))			{				quadrant = 1;			}			else if(pix < (halfRMAP_X) && piy >= (halfRMAP_Y))			{				quadrant = 2;			}			else if(pix >= (halfRMAP_X) && piy >= (halfRMAP_Y))			{				quadrant = 3;			}			if(quadrant == 0)			{				float wDist = 1 / linearDist(pix,piy,W.X,W.Y);				float nwDist = 1 / linearDist(pix,piy,NW.X,NW.Y);				float nDist = 1 / linearDist(pix,piy,N.X,N.Y);				float centDist = 1 / linearDist(pix,piy,halfRMAP_X,halfRMAP_Y);				float sum = nDist + wDist + nwDist + centDist;				nDist = nDist / sum;				wDist = wDist / sum;				nwDist = nwDist / sum;				centDist = centDist / sum;				world.wMap[wX][wY].area.aMap[aX][aY].region.rMap[pix][piy].elevation = n*nDist + w*wDist + nw*nwDist + world.wMap[wX][wY].area.aMap[aX][aY].region.baseHt*centDist;							}			else if(quadrant == 1)			{				float nDist = 1 / linearDist(pix,piy,N.X,N.Y);				float neDist = 1 / linearDist(pix,piy,NE.X,NE.Y);				float eDist = 1 / linearDist(pix,piy,E.X,E.Y);				float centDist = 1 / linearDist(pix,piy,halfRMAP_X,halfRMAP_Y);				float sum = nDist + eDist + neDist + centDist;				nDist = nDist / sum;				eDist = eDist / sum;				neDist = neDist / sum;				centDist = centDist / sum;				world.wMap[wX][wY].area.aMap[aX][aY].region.rMap[pix][piy].elevation = n*nDist + e*eDist + ne*neDist + world.wMap[wX][wY].area.aMap[aX][aY].region.baseHt*centDist;							}			else if(quadrant == 2)			{				float sDist = 1 / linearDist(pix,piy,S.X,S.Y);				float swDist = 1 / linearDist(pix,piy,SW.X,SW.Y);				float wDist = 1 / linearDist(pix,piy,W.X,W.Y);					float centDist = 1 / linearDist(pix,piy,halfRMAP_X,halfRMAP_Y);				float sum = sDist + wDist + swDist + centDist;				sDist = sDist / sum;				wDist = wDist / sum;				swDist = swDist / sum;				centDist = centDist / sum;				world.wMap[wX][wY].area.aMap[aX][aY].region.rMap[pix][piy].elevation = s*sDist + w*wDist + sw*swDist + world.wMap[wX][wY].area.aMap[aX][aY].region.baseHt*centDist;							}			else if(quadrant == 3)			{				float eDist = linearDist(pix,piy,E.X,E.Y);				float seDist = linearDist(pix,piy,SE.X,SE.Y);				float sDist =  linearDist(pix,piy,S.X,S.Y);				float centDist = linearDist(pix,piy,halfRMAP_X,halfRMAP_Y);								eDist = 1 / eDist;				seDist = 1 / seDist;				sDist = 1 / sDist;				if(centDist != 0)				{					centDist = 1 / centDist;				}				else				{					eDist = 0;					seDist = 0;					sDist = 0;					centDist = 1;				}													float sum = sDist + eDist + seDist + centDist;				sDist = sDist / sum;				eDist = eDist / sum;				seDist = seDist / sum;				centDist = centDist / sum; 				world.wMap[wX][wY].area.aMap[aX][aY].region.rMap[pix][piy].elevation = s*sDist + e*eDist + se*seDist + world.wMap[wX][wY].area.aMap[aX][aY].region.baseHt*centDist;							}                }         }


float linearDist(float x1,float y1,float x2,float y2) {  float dx = x2 - x1;  float dy = y2 - y1;  dx = dx * dx + dy * dy;  if(dx != 0)  {	return sqrt(dx);  }  else  {	return 0;  }}
I think I am just missing some minor step in my function somewhere -

I need 'e' to only take into account 5 & 2, because at that point, both 4 & 7 and 1 & 8 should have 0% influence on the value

I only have odd sized maps at this magnification so I think it might produce the results I want if I calculate the 8 cardinal directions first and then interpolate inbetween those values to fill in the remainder. I'll have to write that up when I get the chance & test it out.


+---+---+---+|???|???|???||?5?|?1?|?4?||???|???|???|+---+---+---+|???|abc|???||?9?|d5e|?2?||???|fgh|???|+---+---+---+|???|???|???||?3?|?8?|?7?||???|???|???|+---+---+---+

Quote:Original post by polpoint
I don't really understand -

so if I do something like your diagram to calculate only the central 5-value square:
+---+---+---+|5??|?1?|??4||???|???|???||???|???|???|+---+---+---+|???|???|???||9??|?5?|??2||???|???|???|+---+---+---+|???|???|???||???|???|???||3??|?8?|??7|+---+---+---+


Then if I move one square to the north and calculate the 1-value square like this:
+---+---+---+|7??|?2?|??3||???|???|???||???|???|???|+---+---+---+|???|???|???||5??|?1?|??4||???|???|???|+---+---+---+|???|???|???||???|???|???||9??|?5?|??2|+---+---+---+

will it line up with the calculated values for the 5-value square?

It doesn't seem like it would - it seems like it would be missing one row (the three ?'s that are right between the 5 and the 1)
Ah, that's because for that example I was assuming that the entire source board was 3x3, i.e. you don't scroll that part at all. I wasn't aware that you were not calculating the entire interpolated board at once, beforehand. (excuse the double-negation there)
From the extra code posted it seems that you're not actually interpolating the source data at all, as I suspected. Your code is only sampling from one spot and is creating all the point values in the "big square" based solely on that.
I think I have enough to have a shot at implementing actual bilinear interpolation now so I'll give it a go...
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms

This topic is closed to new replies.

Advertisement