SSブログ

Bezier曲線による関数の近似 - その4 [レンズ形状をBezierで描く]

スプラインと似たやりかたで補間ではなく関数近似にBezier曲線を使おうという話の続き。前回端点での1階と2階の微係数が一致するBezier曲線を決定する方法をまとめた。実装して確認する前に、その予備として単一のBezier曲線をふたつに分割する方法を整理する....

7  Bezier曲線の分割

実装の前にひとつのBezier曲線を途中の点でふたつに分割する方法を考える。ふたつのBezer曲線をひとつの接合するのは一般には不可能だけど、分割はそれほど難しくない。

媒介変数$t$に関して区間$(0,\alpha)$と区間$(\alpha,1)$に分割$(1<\alpha <1)$したとして、制御点がどう変わればいいかを考える。まず前半の区間で、$\boldsymbol{B}(\alpha t)$が改めて$\hat{\boldsymbol{B}}( t)$と一致するように$\hat{\boldsymbol{P}}_i,i=0\dots 3$をとりなおせばいい。

分割前の$\boldsymbol{B}(\alpha t)$を$t$に関して整理して \begin{align} &\alpha \boldsymbol{P}_0+3(-\alpha \boldsymbol{P}_0+\alpha \boldsymbol{P}_1)t+3(\alpha^2 \boldsymbol{P}_0-2\alpha^2 \boldsymbol{P}_1+\alpha^2 \boldsymbol{P}_2)t^2 \nonumber \\ &\hspace{25mm}+(-\alpha^3 \boldsymbol{P}_0+3\alpha ^3\boldsymbol{P}_1-3\alpha^3 \boldsymbol{P}_2+\alpha^3 \boldsymbol{P}_3)t^3 \end{align} これが分割後の \begin{align} &\hat{\boldsymbol{P}}_0+3(- \hat{\boldsymbol{P}}_0+ \hat{\boldsymbol{P}}_1)t+3(^2 \hat{\boldsymbol{P}}_0-2^2 \hat{\boldsymbol{P}}_1+^2 \hat{\boldsymbol{P}}_2)t^2 \nonumber \\ &\hspace{25mm}+(-^3 \hat{\boldsymbol{P}}_0+3 ^3\hat{\boldsymbol{P}}_1-3^3 \hat{\boldsymbol{P}}_2+^3 \hat{\boldsymbol{P}}_3)t^3 \end{align} と一致すればいいので、$t$のベキごとの係数に関して比較して \begin{equation} \begin{array}{rl} \hat{\boldsymbol{P}}_0 =& \boldsymbol{P}_0 \\ -\hat{\boldsymbol{P}}_0+\hat{\boldsymbol{P}}_1 =& -\alpha \boldsymbol{P}_0+\alpha \boldsymbol{P}_1 \\ \hat{\boldsymbol{P}}_0-2\hat{\boldsymbol{P}}_1+\hat{\boldsymbol{P}}_2 =& \alpha^2 \boldsymbol{P}_0-2\alpha^2 \boldsymbol{P}_1+\alpha^2 \boldsymbol{P}_2 \\ -\hat{\boldsymbol{P}}_0+3\hat{\boldsymbol{P}}_1-3\hat{\boldsymbol{P}}_2+\hat{\boldsymbol{P}}_3 =& -\alpha^3 \boldsymbol{P}_0+3\alpha ^3\boldsymbol{P}_1-3\alpha^3 \boldsymbol{P}_2+\alpha^3 \boldsymbol{P}_3 \end{array} \end{equation} を$\hat{\boldsymbol{P}}_i,i=0\dots 3$について解けばよくて、これは一次の連立方程式なのですなおに書けて \begin{equation} \begin{array}{rl} \hat{\boldsymbol{P}}_0&= \boldsymbol{P}_0 \\ \hat{\boldsymbol{P}}_1&= \alpha \boldsymbol{P}_1-(\alpha -1) \boldsymbol{P}_0 \\ \hat{\boldsymbol{P}}_2&= (\alpha -1)^2 \boldsymbol{P}_0+\alpha \left(\alpha \boldsymbol{P}_2-2 (\alpha -1)\boldsymbol{P}_1\right) \\ \hat{\boldsymbol{P}}_3&= \alpha \left(3 (\alpha -1)^2 \boldsymbol{P}_1+\alpha \left(\alpha \boldsymbol{P}_3-3 (\alpha -1)\boldsymbol{P}_2\right)\right)-(\alpha -1)^3 \boldsymbol{P}_0\end{array} \end{equation} となる。

同じように残りの分割前の$\boldsymbol{B}(\alpha +(1-\alpha)t)$に対して \begin{equation} \begin{array}{rl} \hat{\boldsymbol{P}}_0 &= \alpha \left(3 ( \alpha-1)^2 \boldsymbol{P}_1+ \alpha \left( \alpha \boldsymbol{P}_3-3 ( \alpha-1) \boldsymbol{P}_2\right)\right)-( \alpha-1)^3 \boldsymbol{P}_0 \\ \hat{\boldsymbol{P}}_1 &= ( \alpha-1)^2 \boldsymbol{P}_1+ \alpha \left( \alpha \boldsymbol{P}_3-2 ( \alpha-1) \boldsymbol{P}_2\right) \\ \hat{\boldsymbol{P}}_2 &= \alpha \boldsymbol{P}_3-( \alpha-1) \boldsymbol{P}_2 \\ \hat{\boldsymbol{P}}_3 &= \boldsymbol{P}_3 \end{array} \end{equation} となる。これはめんどくさいけどわりと簡単。

しかし媒介変数$t$ではなく、座標で分割しようとすると、例えば$x_m$となる$t_m$を解く必要がある。これは当然3次方程式を解くということになる。これはかなり煩わしいけど、解の公式があるので可能である。たかが3次でもかなりめんどくさいけど。

実数係数の3次方程式は少なくともひとつ実数解があるので、それ決め打ちで良さそうに思えるけど、一般にはそうとはいかない。例えば分割したい位置を$x_m$だけ指定した場合、$t<0$や$1<t$でたまたま実数解がある場合も十分ある。今回のような制限をつけたとき($x$の陽に書ける)は$0 \le t \le 1$にある解だけを取ればいいけど、その制限を外すと$(x_m,y_m)$の両方を指定しないと分割できない場合がある。

Illustratorなんかではユーザが直接曲線の近傍の点を指定できるし、またそれほど厳密に分割できなくても結果に影響はないので問題ないんだろうな。
nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。