2009年4月9日木曜日

moebiusの帯

今回もコンピュータ作図の話題である.

以前の小田急の社章は「小」の文字の縦の線を線路の断面の「エ」のような形にし, 両側の点を円弧にして囲み, 円に縦棒が通っているような形と記憶している. 最近の車体にはMoebiusの帯のような図案の後に, Odakyuと書いてある. それを見ているうちに, またMoebiusの帯をプログラムで描いてみたくなった.

moebiusの帯では, Escherの版画にアリが歩いている有名な絵がある. 例えばこれ.
アリが動いている動画もあった.

それほど芸術的には出来ないが, とりあえず

のような書き方を考えた. まず上の図は, 平行四辺形ABCDが, くっきりと折り目をつけたmoebiusの帯である. 外周が六角形になる. 帯の長さ方向の辺ABの長さをaとし, 短い方の辺BCの長さをbとする. この平行四辺形を120度ずつ回転して3回書くわけだ. 回転の中心をOとし, 辺ABの中心HからOまでの長さをcとする. またOHとCDの交点をG. DGの長さをd, OGの長さをfとする.

d=(a-b)/2 c=(a/2+b)tan 30 f=d tan 30

である. 従ってOを原点とすれば, dだけ左, fだけ下のDへ行き, b/2だけ左, c-fだけ下へ移動してA, aだけ右へ移動してB, b/2だけ右, c-fだけ上へ移動してC, そして線を閉じる.

d neg f neg moveto %D
b -2 div f c sub rlineto %A
a 0 rlineto %B
b 2 div c f sub rlineto %D
closepath stroke

で描ける. このサブルーチンを例えばpと定義すると, p 120 rotate p 120 rotate p 120 rotate でくっきり線のmoebiusの帯が出来る.

でもやはりゆるやかに曲がった帯が描きたい. しかしそう大変でもないことが分かる. 上の図で, A,B,Cの角を円弧にすればよい. PostScriptの関数arcは円弧の中心のx,y座標, 円の半径r, 反時計まわりに中心から見た出発の角度と到着の角度をパラメータにし, 前に描き終った点から, この出発点までを直線で結び, その後に到着点までの円弧を描いてくれる. 時計回りにしたければarcnを使う.

上のプログラムでは rlineto で相対的な位置までの直線を描いたが, 今度は, translateを使い, 座標をA,B,Cに移動しながら描くことにする.

d neg f neg translate 0 0 moveto
b -2 div f c sub translate e r r 150 270 arc
a 0 translate e neg r r 270 330 arc
b 2 div c f sub translate e neg r r 330 270 arcn
closepath stroke a neg 0 translate d f translate} def

最初の行は, Dへ原点を移し, 0,0へペンを置いた.
次の行は, Aへ原点を移し, e,rを中心, 半径rで150度から270度まで円弧を描いた.
次の行は, Bへ原点を移し, -e,rを中心, 半径rで270度から330度まで円弧を描いた.
次の行は, Cへ原点を移し, -e,rを中心, 半径rで330度から270度まで時計まわりに円弧を描いた.
次の行のclosepathで0,0へ線を引き, 続く2つのtranslateで原点をOへ戻している.

最後にtranslateで戻す代りに, 描画環境をスタックに保存してくれる, gsaveとgrestoreを使う方が簡単であろう.

0 件のコメント: