本文主要是介绍Hermite 三次插值可编辑样条,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。
问题描述
利用三次样条和Hermite插值制作一个类似于ppt里的曲线工作。
基本思路
- 对于给定点,初始生成时用参数化+三次函数插值的方式生成。三次样条函数插值法
- 生成后在各型值点处展示切线信息。
- 编辑时,利用两点两切线的信息,通过hermite三次插值进行分段插值。
切线计算
对曲线参数化后
P ( t ) = { y ( t ) x ( t ) P(t) = \left \{ \begin{array}{l} y(t) \\ x(t) \end{array} \right. P(t)={y(t)x(t)
切线信息就是 P(t)的1阶导
P ′ ( t ) = { y ′ ( t ) x ′ ( t ) P'(t) = \left \{ \begin{array}{l} y'(t) \\ x'(t) \end{array} \right. P′(t)={y′(t)x′(t)
根据三弯矩公式求导,得到导数公式。
S i ′ ( x ) = − M i 2 h i ( x i + 1 − x ) 2 + M i + 1 2 h i ( x − x i ) 2 + ( y i + 1 h i − M i + 1 h i 6 ) + ( M i h i 6 − y i h i ) S_i'(x) = -\frac {M_i}{2h_i}(x_{i+1}-x)^2+\frac {M_{i+1}}{2h_i}(x-x_{i})^2+(\frac{y_{i+1}}{h_i}-\frac{M_{i+1}h_i}{6})+(\frac{M_ih_i}{6}-\frac{y_i}{h_i}) Si′(x)=−2hiMi(xi+1−x)2+2hiMi+1(x−xi)2+(hiyi+1−6Mi+1hi)+(6Mihi−hiyi)
Hermite 插值法
给定两点两切线信息,求出两点之间的曲线方程。
设两端点和导数如下:
P ( 0 ) = p i P ( 1 ) = p i + 1 P ′ ( 0 ) = D p i P ′ ( 1 ) = D p i + 1 \begin{array}{lc}\mathbf P\boldsymbol(\mathbf0\boldsymbol)\boldsymbol={\mathbf p}_{\mathbf i}\\\mathbf P\boldsymbol(\mathbf1\boldsymbol)\boldsymbol={\mathbf p}_{\mathbf i\boldsymbol+\mathbf1}\\\mathbf P\boldsymbol'\boldsymbol(\mathbf0\boldsymbol)\boldsymbol={\mathbf{Dp}}_{\mathbf i}\\\mathbf P\boldsymbol'\boldsymbol(\mathbf1\boldsymbol)\boldsymbol={\mathbf{Dp}}_{\mathbf i\boldsymbol+\mathbf1}\end{array} P(0)=piP(1)=pi+1P′(0)=DpiP′(1)=Dpi+1
可以给出待定式
P ( u ) = a u 3 + b u 2 + c u + d , u ∈ [ 0 , 1 ] \boldsymbol P(u) = \boldsymbol au^3 + \boldsymbol bu^2 +\boldsymbol cu + \boldsymbol d , u \in [0,1] P(u)=au3+bu2+cu+d,u∈[0,1]
我们希望求得a,b,c,d从而得到表达式
分量 P x ( u ) = a x u 3 + b x u 2 + c x u + d x 分量\boldsymbol P_x(u) = \boldsymbol a_xu^3 + \boldsymbol b_xu^2 +\boldsymbol c_xu + \boldsymbol d_x 分量Px(u)=axu3+bxu2+cxu+dx
y, z也有类似的关系。
可以写成矩阵形式
P ( u ) = [ u 3 u 2 u 1 ] [ a b c d ] ( 1 ) \boldsymbol P(u) = \begin{bmatrix} u^3 &u^2&u & 1 \end{bmatrix} \begin{bmatrix} \boldsymbol a\\ \boldsymbol b\\ \boldsymbol c\\ \boldsymbol d \end{bmatrix} (1) P(u)=[u3u2u1] abcd (1)
对P(u) 求导得到
P ′ ( u ) = [ 3 u 2 2 u 1 0 ] [ a b c d ] ( 2 ) \boldsymbol P'(u) = \begin{bmatrix} 3u^2 &2u &1 & 0 \end{bmatrix} \begin{bmatrix} \boldsymbol a\\ \boldsymbol b\\ \boldsymbol c\\ \boldsymbol d \end{bmatrix}(2) P′(u)=[3u22u10] abcd (2)
把u=0, u=1 时的值和一阶导代入式(1),式(2)可以得到方程组
[ P i P i + 1 D p i D p i + 1 ] = [ 0 0 0 1 1 1 1 1 0 0 1 0 3 2 1 0 ] [ a b c d ] \begin{bmatrix} \boldsymbol P_i\\ \boldsymbol P_{i+1}\\ \boldsymbol Dp_i\\ \boldsymbol Dp_{i+1} \end{bmatrix} = \begin{bmatrix} 0&0&0&1 \\ 1&1&1&1\\ 0&0&1&0\\3&2&1&0\end{bmatrix} \begin{bmatrix} \boldsymbol a\\ \boldsymbol b\\ \boldsymbol c\\ \boldsymbol d \end{bmatrix} PiPi+1DpiDpi+1 = 0103010201111100 abcd
[ P i P i + 1 D p i D p i + 1 ] = [ 0 0 0 1 1 1 1 1 0 0 1 0 3 2 1 0 ] [ a b c d ] \begin{bmatrix} \boldsymbol P_i\\ \boldsymbol P_{i+1}\\ \boldsymbol Dp_i\\ \boldsymbol Dp_{i+1} \end{bmatrix} = \begin{bmatrix} 0&0&0&1 \\ 1&1&1&1\\ 0&0&1&0\\3&2&1&0\end{bmatrix} \begin{bmatrix} \boldsymbol a\\ \boldsymbol b\\ \boldsymbol c\\ \boldsymbol d \end{bmatrix} PiPi+1DpiDpi+1 = 0103010201111100 abcd
[ a b c d ] = [ 0 0 0 1 1 1 1 1 0 0 1 0 3 2 1 0 ] − 1 [ P i P i + 1 D p i D p i + 1 ] \begin{bmatrix} \boldsymbol a\\ \boldsymbol b\\ \boldsymbol c\\ \boldsymbol d \end{bmatrix}= \begin{bmatrix} 0&0&0&1 \\ 1&1&1&1\\ 0&0&1&0\\3&2&1&0\end{bmatrix}^{-1} \begin{bmatrix} \boldsymbol P_i\\ \boldsymbol P_{i+1}\\ \boldsymbol Dp_i\\ \boldsymbol Dp_{i+1} \end{bmatrix} abcd = 0103010201111100 −1 PiPi+1DpiDpi+1
= [ 2 − 2 1 1 − 3 3 − 2 − 1 0 0 1 0 1 0 0 0 ] [ P i P i + 1 D p i D p i + 1 ] = \begin{bmatrix} 2&-2&1&1 \\ -3&3&-2&-1\\ 0&0&1&0\\1&0&0&0\end{bmatrix} \begin{bmatrix} \boldsymbol P_i\\ \boldsymbol P_{i+1}\\ \boldsymbol Dp_i\\ \boldsymbol Dp_{i+1} \end{bmatrix} = 2−301−23001−2101−100 PiPi+1DpiDpi+1
令
M H = [ 2 − 2 1 1 − 3 3 − 2 − 1 0 0 1 0 1 0 0 0 ] \boldsymbol M_H= \begin{bmatrix} 2&-2&1&1 \\ -3&3&-2&-1\\ 0&0&1&0\\1&0&0&0\end{bmatrix} MH= 2−301−23001−2101−100
P ( u ) = [ u 3 u 2 u 1 ] M H [ P i P i + 1 D p i D p i + 1 ] \boldsymbol P(u) = \begin{bmatrix} u^3 &u^2&u & 1 \end{bmatrix} \boldsymbol M_H \begin{bmatrix} \boldsymbol P_i\\ \boldsymbol P_{i+1}\\ \boldsymbol Dp_i\\ \boldsymbol Dp_{i+1} \end{bmatrix} P(u)=[u3u2u1]MH PiPi+1DpiDpi+1
这样就可以直接由两点两切线直接得到表达式。
展开得到分段表达式
P i ( u ) = P i ( 2 u 3 − 3 u 2 + 1 ) + P i + 1 ( − 2 u 3 + 3 u 2 ) + D p i ( u 3 − 2 u 2 + u ) + D p i + 1 ( u 3 − u 2 ) \boldsymbol P_i(u) = \boldsymbol P_i(2u^3-3u^2+1)+ \boldsymbol P_{i+1}(-2u^3+3u^2) + \boldsymbol Dp_i(u^3-2u^2+u) +\boldsymbol Dp_{i+1}(u^3-u^2) Pi(u)=Pi(2u3−3u2+1)+Pi+1(−2u3+3u2)+Dpi(u3−2u2+u)+Dpi+1(u3−u2)
实现
代码:
https://gitcode.com/chenbb1989/geometric_model/tree/master/gohw4-1
演示视频
三次样条编辑
本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。创作不易,帮忙点击公众号的链接,帮忙转发,感激不尽。
这篇关于Hermite 三次插值可编辑样条的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!