らんだむな記憶

blogというものを体験してみようか!的なー

Bézier曲線と曲率

曲率の式なんか忘れたのでパクる。曲率と曲率半径 [物理のかぎしっぽ]より、 $x=x(t),\ y=x(t)$ なパラメトリックな曲線に対して以下が曲率 $\kappa$ となる。ここで曲線は2回連続微分可能とする、っと。
\begin{equation}
\kappa =
\frac{\left|
\begin{array}{cc}
x^\prime & y^\prime \\
x^{\prime\prime} & y^{\prime\prime}
\end{array}
\right|}{\left( {x^{\prime}}^2 + {y^{\prime}}^2 \right)^{3/2}}
\end{equation}

大雑把には分子の行列式は曲線の方向ベクトルとその微分(つまり車で言えばどっちにハンドルを切っていくかの動き)とのベクトル積の形になっている。左にハンドルを切っているケースで正の値になり、右にハンドルを切っているケースで負になる。そしてハンドルがニュートラルな状態で0だ。
でこの分子の行列式だけ見たら曲率が0になるとことか分かるんだけど、
\begin{equation}
P(t) = (1-t)^3 P_0 + 3(1-t)^2 t P_1 + 3(1-t)t P_2 + t^3 P_3
\end{equation}

に対して、1階の導函数は2次式で、2階の導函数は1次式で、これをぶっこんで行列式を計算したら3次式になるからCardanoの公式の出番じゃないですかーという気持ちになった。
ところが実際には2次式に落ち込む様子。要は計算をサボったのだが、ios - How to determine curvature of a cubic bezier path at an end point - Stack Overflowにあるように、 $t$ について整理しながら適当に変数を設定して計算するととても綺麗になる。
\begin{align}
& a = P_1 - P_0, \\
& b = P_2 - 2 P_1 + P_0 = P_2 - P_1 - a, \\
& c = P_3 - 3 P_2 + 3 P_1 - P_0 = P_3 - P_2 - 2 b - a
\end{align}

と置くと、先ほどの行列式の部分は、
\begin{equation}
18\left[ a \times b + (a \times c)\,t + (a \times c)\,t^2 \right] \quad\quad\quad (1)
\end{equation}

になるというのだ。多少の確認の後にこの2次方程式の根を求めることで曲率が0となる点、即ち変曲点が見つかることになる。凄いぞBézier曲線!本当に色んな計算が簡単になる魔法のようなパラメトリック曲線だなぁ。
なお、GitHub - mekkablue/InsertInflections: Glyphs Filter to insert nodes at path inflectionsでは InsertInflections.py にて(1)式を解く形で実装されている。

まぢめにベンキョーするなら小林昭七先生の曲線と曲面の微分幾何とかで曲率について調べたらいいと思う。