三角形
三角形是图形程序的基本建模单元. 诸如颜色之类信息,通常被标记到三角形顶点上,需要通过该三角形插值. 插值过程在称为重心坐标系(barycenric coordinates)的坐标系统上进行.
2D三角形
2D空间下,默认直角标架\(Ⅰ[O;e_1,e_2]\). 点a,b,c是三角形3顶点,坐标分别为\((x_a,y_a)_Ⅰ,(x_b,y_b)_Ⅰ,(x_c,y_c)_Ⅰ,\),那么三角形的有向面积:
\[\tag{1}
\begin{aligned}
S&=\frac{1}{2}\overrightarrow{ab}\times \overrightarrow{ac}\\
&=\frac{1}{2}(x_b-x_a,y_b-y_a)\times (x_c-x_a,y_c-y_a)\\
&=\frac{1}{2}(a_1,a_2)\times (b_1,b_2)\\
&=\frac{1}{2}(a_1e_1+a_2e_2)\times (b_1e_1+b_2e_2)\\
&=\frac{1}{2}(a_1b_1-a_2b_1)e_3,(e_3=e_1e_2)\\
&=\frac{1}{2}\begin{vmatrix}a_1&b_1\\a_2&b_2\end{vmatrix}\\
&=\frac{1}{2}\begin{vmatrix}
x_b-x_a & x_c-x_a\\
y_b-y_a & y_c-y_a
\end{vmatrix}\\
&=\frac{1}{2}(x_ay_b+x_by_c+x_cy_a-x_ay_c-x_by_a-x_cy_b)
\end{aligned}
\]
当a,b,c逆时针顺序时,S方向为正;否则,S方向为负.
重心空间
点到直线的距离
这部分作为引理,为后续推导重心插值公式.
以直线\(L:f(x,y)=Ax+By+C=0\)梯度方向作向量\((A,B)\),那么\((A,B)⊥L\).
证明:
∵直线L经过\((x_0,y_0)\)
∴
\[\begin{cases}
Ax_0+By_0+C=0\\
Ax_1+By_1+C=0
\end{cases}\\
\]
∴\(A(x_1-x_0)+B(y_1-y_0)=0\)
∵\((x_1-x_0,y_1-y_0)\cdot (A,B)=A(x_1-x_0)+B(y_1-y_0)=0\)
∴\((A,B)⊥(x_1-x_0,y_1-y_0)\)
而\((x_1-x_0,y_1-y_0)//L\)
∴\((A,B)⊥L\)
在直线L上任取一点\(P_0=(x,y)\),从该点沿着向量\((A,B)\)方向确定另一点\(P=(x,y)+k(A,B), k\in R\)
那么,求点\(P\)到直线L的距离,可转化为求\(|P_0P|\).
\[|P_0P|=|k(A,B)|=k\sqrt{A^2+B^2}, k\in R
\]
其中,k为常数,代表沿着\((A,B)\)的方向(同向 or 反向).
实际应用中,往往已知P点坐标\((a,b)\),如何求P到L距离?或者说,如何确定k值?
\[P=(a,b)\implies P_0=(a,b)-k(A,B)=(a-kA,b-kB)
\]
∵\(P_0\)在直线L上
∴\(f(a-kA,b-kB)=A(a-kA)+B(b-kB)+C=0\)
∴
\[k=\frac{Aa+Bb+C}{A^2+B^2}=\frac{f(a,b)}{A^2+B^2}
\]
∴点\(P(a,b)\)到直线\(f(x,y):Ax+By+C=0\)的距离:
\[d_p=|P_0P|=\frac{f(a,b)}{\sqrt{A^2+B^2}}
\]
重心坐标插值
有时,我们希望为三角形顶点赋予属性,如颜色,并在三角形上平滑插值. 用重心坐标(barycentric coordinates)是最简单的办法.
重心坐标系是仿射坐标系,而非正交坐标系. 仿射坐标系参见解析几何笔记:仿射坐标系.
如上图,以三角形a点为原点、两边\(\overrightarrow{ab},\overrightarrow{ac}\)为基向量(不平行),建立仿射标架\(Ⅱ[a;\overrightarrow{ab},\overrightarrow{ac}]\),任一点p在\(Ⅰ\)中坐标:\((x_p,y_p)_Ⅰ\),在\(Ⅱ\)中坐标\((β,γ)_Ⅱ\).
有
\[\tag{2}
\begin{aligned}
\bm{p-a}&=β(\bm{b}-\bm{a})+γ(\bm{c}-\bm{a})\\
\bm{p}&=\bm{a}+β(\bm{b}-\bm{a})+γ(\bm{c}-\bm{a})\\
\bm{p}&=(1-β-γ)\bm{a}+β\bm{b}+γ\bm{c}
\end{aligned}
\]
令\(α=1-β-γ\),则
\[\tag{3}
\bm{p}(α,β,γ)=α\bm{a}+β\bm{b}+γ\bm{c},α+β+γ=1
\]
这样,p点坐标用三角形顶点a,b,c表示. 式(3)就是重心坐标插值公式.
- p在三角形abc内部,当且仅当\(0<α<1,0<β<1,0<γ<1\)
- 如果\(α,β,γ\)中有1项为0,另2项(0,1),则p在三角形边界时;
- 如果有2项为0,另1项为1,则p在三角形顶点.
式(3)不仅用于坐标混合,也可用于其他属性混合.
将式(2)写成坐标形式:
\[\tag{4}
\begin{aligned}
\bm{p-a}&=β(\bm{b}-\bm{a})+γ(\bm{c}-\bm{a})\\
\begin{pmatrix}x_p-x_a\\y_p-y_a
\end{pmatrix}&=\begin{pmatrix}x_b-x_a&x_c-x_a\\y_b-y_a&y_c-y_a\end{pmatrix}
\begin{pmatrix}β\\ γ\end{pmatrix}
\end{aligned}
\]
如何确定参数\(α,β,γ\)值?
∵\(α=1-β-γ\)
∴求出\(β,γ\)即可.
P到直线ac距离\(d_p\)与P在Ⅱ下坐标满足:
\[\frac{β}{1}=\frac{d_{ac,p}}{d_{ac,b}}
\]
而平面上任一点\(P(x_p,y_p)\)到直线\(ac:f_{ac}(x,y)=Ax+By+C=0\)距离:
\[d_{ac,p}=\frac{f_{ac}(x_p,y_p)}{\sqrt{A^2+B^2}}
\]
因此,
\[β=\frac{d_{ac,p}}{d_{ac,b}}=\frac{f_{ac}(x_p,y_p)}{f_{ac}(x_b,y_b)}
=\frac{Ax_p+By_p+C}{Ax_b+By_b+C}
\]
问题转化为求A、B、C,即求直线ac方程.
∵\(f_{ac}(x,y)=0\)过a,c点
∴
\[\begin{aligned}
Ax_a+By_a+C=0\\
Ax_c+By_c+C=0
\end{aligned}
\]
∴
\[A(x_c-x_a)+B(y_c-y_a)=0
\]
∴向量\((A,B)⊥(x_c-x_a,y_c-y_a)\)
不妨取\((A,B)=(y_a-y_c,x_c-x_a)\). 又直线过点\(a(x_a,y_a)\),可得
\[\begin{aligned}
f_{ac}(x_a,y_a)&=Ax_a+By_a+C\\
&=(y_a-y_c)x_a+(x_c-x_a)y_a+C=0\\
\implies C &=(y_c-y_a)x_a+(x_a-x_c)y_a=x_ay_c-x_cy_a
\end{aligned}
\]
因此,直线ac方程:
\[(y_a-y_c)x+(x_c-x_a)y+x_ay_c-x_cy_a=0
\]
∴
\[β=\frac{(y_a-y_c)x_p+(x_c-x_a)y_p+x_ay_c-x_cy_a}{(y_a-y_c)x_b+(x_c-x_a)y_b+x_ay_c-x_cy_a}
\]
注意:b、P都不在直线ac上.
同理,
\[\begin{aligned}
γ&=\frac{d_{ab,p}}{d_{ab,c}}\\
&=\frac{f_{ab}(x_p,y_p)}{f_{ab}(x_c,y_c)}\\
&=...\\
&=\frac{(y_a-y_b)x_p+(x_b-x_a)y_p+x_ay_b-x_by_a}{(y_a-y_b)x_c+(x_b-x_a)y_c+x_ay_b-x_by_a}\\
α&=1-β-γ
\end{aligned}
\]
重心插值参数\(α,β,γ\),还有另一种计算方式.
\(P、c\)到直线\(ab\)距离,可看作\(△abP、△abc\)的高,底边都是ab,那么
\[γ=\frac{d_{ab,p}}{d_{ab,c}}=\frac{A_c}{A}
\]
这里,\(A,A_a,A_b,A_c\)分别表示\(△abc,△bcP,△acP,△abP\)的面积.
同理,
\[\begin{aligned}
α=\frac{A_a}{A}\\
β=\frac{A_b}{A}
\end{aligned}
\]
参考
[1] Shirley P .Fundamentals of Computer Graphics[M]. 2015.