点線で楕円を描く

[追記] この記事には誤りが含まれています。訂正した記事はこちらです。




今日は 1 つネタをもらったので, ガチな数学をやろうと思います.


お題は「点線で楕円を描く」です.

円の場合は, 等角度ごとに区切って点線を書いていけば良いので簡単です.
たいていの場合, 三角関数は標準ライブラリにあるのであまり苦労しません.

しかし楕円の場合となると, 円がつぶれた形をしているので一筋縄ではいきません.


話の流れを追いつつ, どう解決していったか見ていきましょう.

発端

募集:PIL で点線の楕円を描画するのが得意な人。つーか、arc (円弧描画)関数だけで点線が書ける人。

http://twitter.com/#!/tk0miya/status/26986376482267136

楕円の場合は角度あたりの弧の長さが均等にならないよね。つまり点線を描画するにはどうすればいいんだ? 平面幾何なんてさっぱり分からないんだから、こんなん解決できないよ!

http://twitter.com/#!/tk0miya/status/26987619082571776

@tk0miya 楕円の弧長の話ですよね? その計算は楕円積分と言って, 数学で有名な積分計算です. 円もそうですが初等関数にならないので, きっちり計算する以上に楽な方法はありません. 計算式書きましょうか?

http://twitter.com/#!/cocoatomo/status/26991426927599616

実は, この楕円の弧長を求めるという問題は数学でも大きな問題でした.
いったいこれはどんな性質を持っているのか? 三角関数のようなものなのか?

数学のはなし

これを研究していた人たちにヤコビやワイエルシュトラスがいます.
彼らは
\begin{align*}\begin{cases}x = a \cos \varphi \\ y = b \sin \varphi\end{cases}\end{align*}
という楕円の周を (a, 0) から左回りにたどったときの長さを求める積分
\begin{align*}E(k,\quad \varphi) = \int_0^{\varphi} \sqrt{1 - k^2 \sin^2 \varphi} d \varphi \\ (k^2 = \frac{a^2 - b^2}{a^2}) \end{align*}
の逆関数に着目し, その性質を調べ数学的な業績を挙げました.

その逆関数を \varphi(k,\quad u) とするとその微分は以下のように求まります. (みなさん高校でやりましたね!?)
\begin{align*}\frac{d \varphi}{du}(k,\quad u) &= \frac{1}{E'(k,\quad \varphi)} \\ &= \frac{1}{\sqrt{1 - k^2 \sin^2 \varphi}} \\ (u = E(k,\quad \varphi)) \end{align*}

これを微分の形から差分の形に直して
\begin{align*} \Delta \varphi &= \frac{\Delta u}{\sqrt{1 - k^2 \sin^2 \varphi}}\end{align*}
これをさらに総和の形に直すと
\begin{align*}\varphi_0 &= 0 \\ \varphi_n &= \varphi_{n-1} + \Delta \varphi_{n-1} \\ &= \varphi_{n-1} + \frac{\Delta u}{\sqrt{1 - k^2 \sin^2 \varphi_{n-1}}} \\ (\varphi_n \approx \varphi(n * \Delta u) \) \end{align*}
となる.

なので, \varphi (k,\quad u) の値を求めるときは n を十分大きく (つまり \Delta u = u/n 十分小さく) とれば \varphi の値が差分の総和を計算することで求まり,  x = a \cos \varphi,\quad y = b \sin \varphi という計算で座標の値に戻せる.

誤差評価を行ってないので収束あたりがまだあやしいけれど, 一応目処は立った.
これからは誤差が出てしまったときの対処が残っているかな.

あとがき

こんなんでどうでしょう, tk0miya さん.