Linear Interpolation

We can use linear interpolation to blend between two values using a floating point scalar value which ranges from 0-1

The basic formula given two values

**a**and

**b**and a real number

*t*is \(

p=a+(b-a)*t \text{ where } 0\leq t\leq1 \). If we overload operators for our vector class so that we can subtract a vector from a vector, add a vector to a vector and multiply by a floating point scalar we can implement a Lerp function as

def Lerp(self, _a, _b, _t) : return _a+(_b-_a)*_t

In C++ it makes sense to make this a template function and the ngl:: library contains this template

/// @brief a simple template function for Linear Interpolation requires that any classes have /// + - and * scalar (i.e. Real) overloaded operators /// In the graphics lib this will work for Vector and Colour /// @param [in] _a the template value for the first parameter /// @param [in] _b the template value for the first parameter /// @param [in] _t the value for the blend between _a and _b must be between 0 - 1 template <class T> T lerp( T _a, T _b, ngl::Real _t ) { T p; p=_a+(_b-_a)*_t; return p; }And the C++ version can be used by including Util.h as follows

#include "ngl/Util.h" ngl::Colour c1(0.0,0.0,0.0); ngl::Colour c2(1.0,0.0,0.0); ngl::Colour c3=Lerp(c1,c2,0.3); ngl::Vector v1(1.0,2.0,1.0); ngl::Vector v2(1.0,0.0,2.0); ngl::Colour v3=Lerp(v1,v2,0.3);Trigonometric Interpolation

A Linear interpolant ensures that equal steps in the parameter t give rise to equal steps in the interpolated values. However it is often required that equal steps in t give rise to unequal steps in the interpolated values. We can achieve this using a variety of mathematical techniques.

From the basic trigonometric ratios we know that \(\sin^2\beta+\cos^2\beta=1\) This satisfies one of the requirements of an interpolant that the terms must sum to 1. If \(\beta\) varies between 0 and \(\frac{\pi}{2}\) then \(\cos^2\beta\) varies between 1 and \(\sin^2\beta\) varies between 0 and 1 which can be used to modify the interpolated values. We can write this as

$$n=n_1\cos^2t+n_2\sin^2t \text{ where } \left[0 \leq t \leq \frac{\pi}{2} \right] $$

plotting these values we get the following curves

If we calculate this for a point starting at (1,1) and ending at (4,3) we get the following graph

def TrigInterp(self, _a,_b,_t) : angle=math.radians(self.Lerp(0.0,90.0,_t)) return _a*math.cos(angle)*math.cos(angle)+_b*math.sin(angle)*math.sin(angle)Cubic Interpolation

In cubic interpolation we need to develop a cubic function to do our blending.

In mathematics a cubic function is one of the form

$$f(x)=ax^3+bx^2+cx+d$$

Applying this to our interpolant we get

$$v_{1}=at^3+bt^2+ct+d$$

or in Matrix form

$$n=\left[ v_{1} v_{2}\right]\left[\begin{array}{c} n_{1} \\ n_{2}\end{array}\right]$$

The task is to find the values of the constants associated with the polynomials v1 and v2

The requirements are

- The cubic function v2 must grow from 0 to 1 for
- The slope at point t must equal the slope at the point (1-t) this ensures the slope symmetry over the range of the function
- The value v2 at any point t must also produce (1-v2) at (1-t) this ensures curve symmetry

To satisfy the first requirement :

$$v_{2}=at^3+bt^2+ct+d$$and when \(t=0\), \(v_2=0\) and \(d=0\). Similarly, when \(t=1\), \(v_2=a+b+c\).

To satisfy the second requirement, we differentiate \(v_2\) to obtain the slope

$$ \frac{dv_2}{dt}=3at^2+2bt+c=3a(1-t)^2+2b(1-t)+c $$

equating the constants we discover \(c=0\) and \(0=3a+2b\)

To satisfy the third requirement

$$a^3+bt^2=1-\left[a(1-t)^3+b(1-t)^2\right]$$

where we can compute \(1=a+0\). But \(0=3a+2b\), therefore \(a=2\) and \(b=3\) and we get

$$v_2=-2t^3+3t^2$$

We must now find the previous curve's mirror, which starts at 1 and collapses to 0 as \(t\) moves from 0 to 1. To do this we subtract the previous equation from 1 and get

$$v_1=2t^3-3t^2+1$$

These can be used as the interpolants

$$n=v_1n_1+v_2n_2$$

$$n=\left[ \begin{array}{cc} 2t^3-3t^2+1 & -2t^3+3t^2\end{array}\right]

\left[\begin{array}{c} n_1\\n_2\end{array}\right]$$

expanded in matrix form to

$$n=\left[ \begin{array}{cccc} t^3 & t^2 & t &1 \end{array}\right]

\left[\begin{array}{cc}

2 & -2 \\

-3 & 3 \\

0 & 0 \\

1 & 0 \\

\end{array}\right]

\left[\begin{array}{c} n_1\\n_2 \end{array}\right]$$

Plotting the two sets of polynomials gives us the following curves

applying this to the points (1,1) to (4,3) over a range 0-1 we get the following point spread

We can write a function to do this as follows

def Cubic(self, _a,_b,_t) : v1=(2.0*_t*_t*_t)-3.0*(_t*_t)+1.0 v2=-(2.0*_t*_t*_t)+3*(_t*_t) return (_a*v1)+(_b*v2)

The following movie shows all 3 functions in action on a teapot, the top one is Trigonometric interpolation, the middle linear interpolation and the bottom one Cubic

You can see the ease in / out effect of the two non-linear interpolants and the linear one moving at a constant rate.

References

Vince, John (2010). Mathematics for Computer Graphics. 2nd. ed. London: Springr Verlag.

and for the title http://en.wikipedia.org/wiki/Pigs_(Three_Different_Ones)

Linear Interpolation, app for fast, easy and safe calculation of Linear Interpolation

ReplyDeletehttps://play.google.com/store/apps/details?id=com.fjapps.juank.linearinterpolation&hl=en