はじめに
いくつかの連結されたベジェ曲線に沿って一定の速さで移動したときの、各単位時間あたりの座標を所得する方法について解説します。ここでは実用できな2次元の3次ベジェ曲線のみを扱いますが、$n$次の場合も同様に計算できると思います。
準備
まずは制御点 $\mathbf{B} _ 1, \mathbf{B} _ 2, \mathbf{B} _ 3, \mathbf{B} _ 4$ によって表されるベジェ曲線 $\mathbf{P}(t)$ を次式で定義しておきます。 $$\mathbf{P}(t) = (1 - t)^3 \mathbf{B} _ 1 + 3t(1-t)^2 \mathbf{B} _ 2 + 3t^2(1-t) \mathbf{B} _ 3 + t^3 \mathbf{B} _ 4\ \ \ (0 \leq t \leq 1)$$
$t = 0$ で始点、$t = 1$ で終点の座標を取ります。
またベジェ曲線を複数連結したものをベジェ曲線ズと呼ぶことにし、これを構成する各ベジェ曲線により表される曲線をセグメントと呼ぶことにします。具体的な式でベジェ曲線ズ $\mathbf{P}(t)$ を定義しておきます。
$$ \mathbf{P}(t) = \begin{cases} \mathbf{P} _ {1}(0) & if\ t = 0\\ \mathbf{P} _ {1}(t) & if\ 0 < t \leq 1\\ \mathbf{P} _ {2}(t - 1) & if \ 1 < \leq 2\\ \vdots & \vdots \\ \mathbf{P} _ {n}(t - n + 1) & if\ n - 1 < t \leq n\\ \end{cases} $$
ただし $\mathbf{P} _ i$ は $i$ 番目のセグメントのベジェ曲線を表し、$\mathbf{P} _ i(1) = \mathbf{P} _ {i + 1}(0)\ \ (1 \leq i < n)$ を満たすものとします。
ベジェ曲線を長さの関数で表す
まずベジェ曲線 $\mathbf{P}(t)$ を曲線に沿った長さ $s$ を使って $\mathbf{Q}(s)\ \ 0 \leq s \leq l$ と表すことを考えます。ただし $l$ はベジェ曲線の孤長とします。
連鎖律から
$$ \left| \dfrac{d\mathbf{P}}{dt}\right| = \left| \dfrac{d\mathbf{Q}}{ds} \dfrac{ds}{dt} \right| = \left| \dfrac{d\mathbf{Q}}{ds}\right| \left| \dfrac{ds}{dt}\right| = \dfrac{ds}{dt}$$
よって微分と積分の関係から
$$ s = f(t) = \int ^ {t} _ {0} \left| \dfrac{d\mathbf{P}}{dt} \right| dt$$
これを使えば $t$ が次のように表せます。
$$ t = f^{-1}(s) $$
したがって
$$\mathbf{Q}(s) = (\mathbf{P} \circ f^{-1})(s)$$
となります。一応ですがベジェ曲線の導関数は
$$\dfrac{d\mathbf{P}}{dt} = 3t^2(-\mathbf{B} _ 1 + 3 \mathbf{B} _ 2 - 3\mathbf{B} _ 3 + \mathbf{B} _ 4) + 6t(\mathbf{B} _ 1 - 2\mathbf{B} _ 2 + \mathbf{B} _ 3) + 3(-\mathbf{B} _ 1 + \mathbf{B} _ 2)$$
です。
ベジェ曲線ズ
改めてベジェ曲線ズ $\mathbf{P}(t),\ \ (0 \leq t \leq n)$ を長さ $s$ を使って $\mathbf{Q}(s),\ \ (0 \leq s \leq L)$ と表すことを考えます。ここでの $L$ はベジェ曲線ズ全体の弧長で、$i$ 番目のセグメントの長さは $l _ i$ と表すことにします。
また、$i$ 番目のセグメント $\mathbf{P} _ i$ に対応した $s$ による関数を $\mathbf{Q} _ i (s)$ と表すことにします。この場合でも先ほどと同様に
$$f _ i (t) = \int ^ t _ 0 \left| \dfrac{d \mathbf{P} _ i}{dt} \right| dt$$
とし、ベジェ曲線ズの始点から長さ $s$ の地点を含むセグメントの番号を $m$ とすれば
$$ \begin{aligned} s = f(t) &= \sum^{m-1} _ {k=1} \int^1 _ 0 \left| \dfrac{d\mathbf{P} _ k}{dt}\right| dt + \int^t _ 0 \left| \dfrac{d\mathbf{P} _ m}{dt} \right| dt \\ &= \sum^{m-1} _ {k=1} l _ k + f _ m (t) \end{aligned} $$
と表せます。
したがって $f^{-1} _ i (l _ i) = 1$ より
$$t = f^{-1}(s) = m - 1 + f^{-1} _ m (s)$$
なので
$$\mathbf{Q}(s) = (\mathbf{P} \circ f^{-1})(s)$$
となります。
ソースコード
|
|
main関数にあるように、beziersにベジェ曲線ズを登録しその他変数を初期化すれば動きます。calctが肝心の関数で、sを渡すことでそれに対応したベジェ曲線ズのtを計算してくれます。main関数内のコードは速さ10でのbeziers上の等速度運動における変位を計算し表示するものになっています。
弧長は台形公式を用いて積分を禁じ、fの逆関数はニュートン法と二分法を用いて近似しています。