Function of the day: lerp

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?

2 comments:

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

    ReplyDelete
  2. The former, I think: Linear intERPolation.

    ReplyDelete

It's OK to comment on old posts.