In response to `clamp`

, a commenter unerringly pointed out another function whose common name I didn't know: `lerp`

, for linear interpolation. You know the operation - you have two points and you want a line:

`lerp :: (Num a, Num b) ⇒ (a, b) → (a, b) → a → b lerp (x1,y1) (x2,y2) x = y1 + (x - x1) * (y2 - y1) / (x2 - x1)`

?`foo = lerp (1,1) (10,4)`

?`foo 4`

2 ?`foo -5`

-1

What if you have more than two points? The obvious generalization is to interpolate between successive pairs of points:

```
polylerp :: (Num a, Num b) ⇒ [(a, b)] → a → b
polylerp [] _ = error "domain"
polylerp ((x1, _):ps) x | x1 > x = error "domain"
polylerp ((x1, y1):ps) x | x1 == x = y1
polylerp ((x1, y1):(x2, y2):_) x | x2 > x = lerp (x1, y1) (x2, y2) x
polylerp (_:ps) x = polylerp ps x
```

(Apologies for the explicit recursion. I wanted to write this with combinators to more closely resemble the natural-language description, but even with made-to-order combinators, I can't find anything clearer. This sort of iteration - a fold that operates on more than one element at once - is often awkward to express.)

The commenter mentioned that `lerp`

, like `clamp`

, is used a lot in graphics. This use is more specific than interpolating arbitrary functions between points: it's used to mix two pixels, for applications like antialiasing or transparency. This doesn't require arbitrary X-coordinates, so a simpler variant of `lerp`

is common:

```
lerp :: (Num a, Num b) ⇒ b → b → a → b
lerp y1 y2 s = y1 + s * (y2 - y1)
```

As with `clamp`

, I've used this form of `lerp`

before, but didn't know its standard name - I called it `mix`

. Can you tell I'm not a graphics person?

Now for a question. The examples above are in (untested) Haskell, but the type signatures are not the real ones, since Haskell requires in all of them that `a == b`

. I wrote them this way to make the distinction between X and Y coordinates clear, since the types would be unreadable otherwise. Is this a good idea?

Well, lerp presumably stands for Linear IntERPolation, or LinEar InteRPolation. But that's only obvious in hindsight.

ReplyDeleteThe former, I think: Linear intERPolation.

ReplyDelete