1.线性插值简介
线性插值是采用一次多项式上进行的插值计算,任意给定两个值A和B,那么在A和B之间的任意值可以定义为
P(t) = A * (1 - t) + B * t,0 <= t <= 1。
t从0逐渐增大到1,就是P(t)的值就是从值A开始,逐渐变化为值B的过程。
如果A、B定义为在实数轴上的两个点,那么P(t)就是线段AB上的任意点,
t从0逐渐增大到1,就是P(t)从A点逐渐滑向B点的过程。
我们也可以把A、B定义在二维平面,或者三维空间中,这时A和B代表平面或控件中的点,包含多维坐标数值。
例如任意指定平面上的两个点A和B,A = (Ax, Ay),B = (Bx, By),
那么
P(t) = A * (1 - t) + B * t
= (Ax, Ay) * (1 - t) + (Bx, By) * t
= (Ax * (1 - t) + Bx * t, Ay * (1 - t) + By * t)
= (Px(t), Py(t)),
其中
Px(t) = Ax * (1 - t) + Bx * t
Py(t) = Ay * (1 - t) + By * t,0 <= t <= 1
类似的,我们也可以把A、B定义在RGB颜色空间中,那么A和B代表的两个颜色,分别包含R、G、B三分量值。
那么这时P(t)就可以表示在颜色A过渡到颜色B的任意颜色。
A = (Ar, Ag, Ab),B = (Br, Bg, Bb),
那么P(t) = A * (1 - t) + B * t = (Pr(t), Pg(t), Pb(t)),
其中
Pr(t) = Ar * (1 - t) + Br * t
Pg(t) = Ag * (1 - t) + Bg * t
Pb(t) = Ab * (1 - t) + Bb * t, 0 <= t <= 1
我们再把以上两个例子组合起来,就可以构建出一个彩色的线段。
知道端点A、B的位置(Ax, Ay)、(Bx, By),
也知道端点A、B的颜色(Ar, Ag, Ab)、(Br, Bg, Bb),
那么线段AB上任意点P(t)的位置和颜色,就均可以通过线性插值计算得出。
2.从线性插值到二阶贝赛尔曲线
线性插值可以定义为点P(t)从点A到点B的直线运动过程,那么如何描述曲线运动呢?
例如t=0->1,P(t)从三角形ABC的端点A出发,经过靠近端点B的曲线,运动到端点C。
根据线性插值定义,我们定义点D(t)从端点A运动到端点B,点E(t)从端点B运动到端点C,其中
D(t) = A * (1 - t) + B * t
E(t) = B * (1 - t) + C * t, 0 <= t <= 1
然后我们递归的定义点P(t)线性的从点D(t)运动到点E(t),也即
P(t) = D(t) * (1 - t) + E(t) * t
= [A * (1 - t) + B * t] * (1 - t) + [B * (1 - t) + C * t] * t
= A * (1 - t) * (1 - t) + B * 2 * (1 - t) * t + C * t * t, 0 <= t <= 1
我们将A、B、C定义在平面直角坐标系上,三个点的坐标分别为(Ax, Ay),(Bx, By),(Cx, Cy),
那么类似的可以定义出P(t) = (Px(t), Py(t))。
其中,
Px(t) = Ax * (1 - t) * (1 - t) + Bx * 2 * (1 - t) * t + Cx * t * t
Py(t) = Ax * (1 - t) * (1 - t) + By * 2 * (1 - t) * t + Cy * t * t, 0 <= t <= 1
以相似的方式,我们还可以定义更高阶的贝塞尔曲线。
例如三阶贝赛尔曲线,P(t)从四边形ABCD的端点A出发,经过靠近端点B、端点C的曲线,运动到端点D。
可以推导出,
P(t) = A * (1 - t) * (1 - t) * (1 - t) + B * 3 * (1 - t) * (1 - t) * t + C * 3 * (1 - t) * t * t + D * t * t * t, 0 <= t <= 1
3.从线性插值到双线性插值
针对端点A、B的位置和颜色值,我们就可以根据线性插值方式,计算出端点A过渡到端点B的任意颜色值。
矩形的四个端点A、B、C和D,分别绑定一个颜色,那么能否根据线性插值方式,定义出面上的任一点的颜色值呢?
C D
+--------+
| |
+--------+
A B
因为单变量t,只能定义直线或曲线上的位置,我们要定义面上的位置,就引入双变量u,v。
其中u定义端点A到端点B方向,v定义端点A到端点C方向。
根据线性插值定义,我们定义点E(u)从端点A运动到端点B,点F(u)从端点C运动到端点D。
E(u) = A * (1 - u) + B * u
F(u) = C * (1 - u) + D * u, 0 <= u <= 1
然后递归的定义P(u, v)从端点E(u)运动到端点F(u),那么
P(u, v) = E(u) * (1 - v) + F(u) * v
= [A * (1 - u) + B * u] * (1 - v) + [C * (1 - u) + D * u] * v
= A * (1 - u) * (1 - v) + B * u * (1 - v) + C * (1 - u) * v + D * u * v, 0 <= u <= 1, 0 <= v <= 1
这样,我们就定义出了P(u, v)和A、B、C和D四个端点的关系。位置和颜色,都可以作为点的属性,进行计算求解。
做一下扩展:
A、B、C和D四个端点,如果定义为平面上任意四边形的端点,也还是可以通过参数u,v得到中间任意点。
A、B、C和D四个端点,如果定义在三维空间中的不共面的点,这样还可以定义出了空间曲面的每个点的位置和颜色。
做一下扩展2:
如果立方体的八个顶点有不同颜色,那么怎么能否根据立方体的顶点,定义立方体的表面和内部每个点的颜色呢?
这样就可以变成三线性插值,但还是定义位置和定义颜色的关系。
4.总结
采用线性插值方式,可以定义出空间的位置和颜色。
空间位置的变化可以构建直线、曲线,也可以构建曲面、体。
颜色的过渡呢,应该也不只是对直线、曲线、面、体进行着色吧。