dragon.jpg


ドラゴン曲線を描画する

 自己相似図形(フラクタル)にドラゴン曲線と呼ばれるものがあります。今回は、ドラゴン曲線を描画してみたいと思います。

ドラゴン曲線

 ドラゴン曲線のジェネレータをご覧に入れます。

dragon_1.png

 赤い矢印が1本と、青い矢印が2本描かれています。本来は、ただの「線分」であるべきなので、矢印の矢の部分は無いものと思ってください。ただ、説明文中では、矢印の方向が重要な意味を持っていますので、注目しておいてください。
 まず最初に、赤い線分が1本描いてあったとします。そうしたら、その赤い線分を消して、代わりに青い線分を描きます。次は、いま描いた青い線分を赤い線分に見立て、同様に赤い線分を消して青い線分を描きます。この時、赤い矢印と青い矢印の向きが、上図で示した位置関係になるように描きます。すると、下図の様になります。

dragon_2.png

 後はこの繰り返し。また青い線分を赤い線分と見なして、……。

dragon_3.png

dragon_4.png

dragon_5.png

 このままlevel=12まで描画すると、以下の様になります。

dragon_12.png

 ものすごく単純なルールによって描かれていることがわかりました。
 なお、説明の都合上、前後2つの再帰レベルで描画すべき線分(赤い線と青い線)を1枚の図に収めてしまっていますが、実際には、どちらか一方だけが残った状態が「ドラゴン曲線」ですので、お間違いなく。

C曲線

 ドラゴン曲線のジェネレータをご覧に入れた時、「矢印の方向が重要」だと述べました。下図左側のジェネレータを使うと、C曲線と呼ばれる自己相似図形を描画することができます。

ccurve_1.png

 再帰レベル2〜5まで。

ccurve_2.png

ccurve_3.png

ccurve_4.png

ccurve_5.png

 一気にlevel=12まで飛びます。

ccurve_12.png

 この向きだとピンときませんが、時計回りに90°回転してみると、アルファベットの「C」に似ています。それで、C曲線と呼ばれています。
 ドラゴン曲線とC曲線は、矢印の向きが違っただけの兄弟みたいな自己相似図形でした。

残りの矢印の向き

 さて、赤い矢印(線分)は共通なので良いとして、青い矢印が2本×それぞれの矢印の向きが2種類、とすると、全部で4通りの組み合わせがあるわけです。その内の2通りがドラゴン曲線とC曲線でした。残りの組み合わせはどうなるでしょうか?

variation.png

 1つは左右が反転したドラゴン曲線でした。もう1つはあんまり面白味のない三角形が描画されました。


3D化してレイトレーシングする

 ドラゴン曲線は二次元のグラフィックになりましたが、これを三次元に拡張するとどうなるのかしら?と思いました。2Dの直線(線分)は、3Dになると平面(三角ポリゴンとか?)になるんでしょうか?でも、そこから先、何だか思考が回っていきませんでした(1x_x;)。
 と、言うことで、単純に、「2Dのまま、3D化」する方法に落着しましたorz。線分を、円柱面を切り取った棒(rod)に置き換えてみます。

rod.png

 完成したデータでは、円柱面の両端に、同じ半径で球面を配置して丸みを持たせ、頂点を共有する線分と線分が滑らかにつながって見えるようにしてあります。

  procedure rod a.x,a.y,a.z, b.x,b.y,b.z, rr
  {
    // a→bへ棒を描画する
    // 棒の太さ:rr
    b.x=b.x - a.x;
    b.y=b.y - a.y;
    b.z=b.z - a.z;
    var len=sqrt (sq (b.x) + sq (b.y) + sq (b.z));
    para a.x,a.y,a.z;
    lever 0,len,0, b.x,b.y,b.z;
    boundary cuboid 0,len/2,0, rr,len/2 + rr,rr
    {
      sphere 0,0,0, rr;
      sphere 0,len,0, rr;
      and
      {
        cylind 0,0,0, 0,1,0, rr;
        plane 0,0,0, 0,-1,0;
        plane 0,len,0, 0,1,0;
      }
    }
  }


 この手続きは「金魚鉢」を作った時にも使っていますが、作りやすい位置(原点からy軸正方向にまっすぐ伸びる円柱面)でサイズ(長さ、太さ)を作り込んだ後、一次変換を使って始点と終点が指定した座標に来るように調整しています。面倒で複雑な計算をすることなく、簡単な計算と一次変換にお任せで楽をしています。

動きを付ける

 ドラゴン曲線は完成した形状も面白いですが、再帰しながら描画していく過程も面白くて飽きないので、時間の経過とともに、だんだんドラゴン曲線が出来上がっていく様子を動画にしてみます。

 まず、データを見ていただくと、dragonと言う名前の手続きを作成し、後は描画レベルを1づつ変化させながら、再帰させて描画しています。実際に線分を定義するところで、今描画した線分がいくつ目の線分なのか?をn_linと言う変数にカウントするようにしました。
 では、ドラゴン曲線全体では、何本の線分が発生するのでしょうか?最初にご覧に入れたジェネレータを見直していただくと、最初に赤い線分が1本あって、次の再帰レベルに進む時に青い線分が2本になります。よって、再帰レベルnの場合の線分の数は、2本(2のn乗)です。
 動画を生成するフレーム番号を0〜fn_allとして、その途中のfn番目のフレームでは、k=(2)×fn/fn_all番目の線分まで描画していれば良いことになります。線分を描画する手続きrodにて、n_linを使った判定を実施し、時系列で描画が進むような記述にしました。kの値は実数(浮動小数)値で計算されるので、小数部分を使って棒の長さも調整するようにしました。
 ただし、再帰レベルnの時の線分数は2本ですから、仮に1フレームで1本の線分を描画したとして、30フレーム/秒で再生したとすると、(2)÷30秒かかるわけです。nが小さいうちは良いですが、n=12では(212)÷30=136.5秒、2分超の動画になります。その場合でも、1フレームで1本の線分がパッと現れるだけで、線が伸びていく様子を見るためには、もっと時間をかけないとなりません。ドラゴン曲線が出来上がっていくだけで2分超の動画では、さすがに退屈しますよね?
 と、いうことで、線分が伸びていく様子を動画にする場合には、十分に小さなnを使う必要があるようです。


完成動画

 完成したデータと動画です。

Xi-TRACEデータ dragon_curve_2d.xitr
Xi-TRACEデータ dragon_curve.xitr

 dragon_curve_2d.xitrの方は、このページで使った図の作成に使用したスクリプトです。レイトレーシングはしません。"_2d"のついていない方でレイトレーシングした動画がこちら(↓)。



 再帰レベル5と再帰レベル12のドラゴン曲線が、ニョロニョロと完成していく様子を2本つなげてあります。

 動画データを計算させるとき、最初の方のフレームでは、線分数(物体数)が少ないので高速に演算終了しますが、最後の方のフレームになると、物体数が増加するため計算時間が多くかかるようになります。全体の計算時間を見積もる場合にはお気を付けください。


home

download

gallery