Messing around with

*bilinear interpolation* ...

Suppose that you have a data-set, provided as a rectangular grid of numeric values.

For example, terrain heights [metres above sea level] are given at kilometre intervals (in the east and north dimensions).

The problem is to estimate the value at any "in-between" point.

Bilinear interpolation is quite appealing. Your point lies somewhere within a rectangle whose corner values are known. Through your point, draw parallels to the grid, making 4 sub-rectangles. Consider any one of these sub-rectangles. The larger its area, the smaller the area of the diagonally opposed sub-rectangle. And that other sub-rectangle contains a corner value whose relevance must therefore increase.

That's about it! The relative areas of the 4 sub-rectangles act as weights (or levities) on the 4 corner values. (Weights or levities, depending on your point of view.)

Using the R language environment, I wrote a routine for bilinear interpolation, and soon had the idea of using color values to display its workings.

unit.square.bilinear <- function (x, y, corner.values) {
X <- c (1 - x, x)
Y <- c (1 - y, y)
sum (corner.values * outer (X, Y))
}
interpolation <- function (corner.values) {
Vectorize (function (x, y) {
unit.square.bilinear (x, y, corner.values)
})
}

But how, exactly? Consider a rectangle with corner values

*< black, red, green, blue >*. That seems particularly straight-forward, given that our screens have red, green, and blue pixels.

Using bilinear interpolation, I calculated the red, green, and blue components. Then I began drawing with R's *image* function. The 3 component bands could be drawn separately (and in any palette), but there was apparently no way of combining them. So I temporarily resorted to writing the bands to an image file ...

Eventually, I found that R's *rasterImage* function provided the intrinsic means. Here is the raster for the black-red-green-blue rectangle:

[,1] [,2] [,3] [,4] [,5]
[1,] "#00ff00" "#00bf40" "#008080" "#0040bf" "#0000ff"
[2,] "#00aa00" "#15802a" "#2b5555" "#402a80" "#5500aa"
[3,] "#005500" "#2b4015" "#552a2a" "#801540" "#aa0055"
[4,] "#000000" "#400000" "#800000" "#bf0000" "#ff0000"

The

*rasterImage* function even offers to perform its own interpolation — look for

**smooth = TRUE** in the image titles.