問題は、折った紙を新たに操作するときに、その座標とか折る方向とかをどのように計算するか。
あらゆる状況を想定する描写関数を用意するとか、再帰処理するかと考えたが、座標変換を利用してみることにした。
利用した関数は、
transpate(x, y) --- 現在の座標をベクトル(x, y)分だけ座標を移動させる。 つまり過去の座標(x, y)が、新たな(0,0)となる。 rotate( r ) --- 同様に r ラジアンだけ、軸を回転させ、あらたな座標にする
期待した動きは、折りおわったら、translate し rotate(90度) して、新たな折り紙を左から右に折ることだった。
しかし、ここで落とし穴が。draw()関数は、座標をリセットする。何で? まだ信じられないのだが。
しかたないので、描写の度に translate , rotate を折り返しの数 実施させた。そのため、折りすぎると描写が遅くなってしまった。
でき上がったのは、以下のアプレット。
折り続ける折り紙
以下、ソースコードの解説
- int cnt = 0; // 折り返し回数
- float rad = 270; // 折る角度
- void setup(){
- size(200, 200);
- color(RGB,256);
- background(255);
- frameRate(30);
- }
- void draw(){
- // 折り紙の左上に座標を移動
- translate(50,50);
- float rr = 40; // 折り紙の横の半分 (折りの半径になる)
- float hh = 80; // 折り紙の高さ
- // 折り回数分だけ、座標と半径、高さを計算し直す
- for(int i=0;i<cnt;i++){
- translate(rr, hh); // 次の折り紙の左上
- rotate(radians(-90)); // 折りの方向を90度回転
- // 新たな折り紙の高さと半径(横の半分)
- float temp = hh;
- hh = rr;
- rr = temp / 2;
- }
- background(255);
- stroke(0);
- page(rr, hh, 90); // 折り紙の右半分
- page(rr, hh, rad); // 折り紙の左半分 radは折り角度
- // 折り曲げたら折り角度radを戻し、1回カウント
- if(--rad == 90){
- rad = 270;
- if(++cnt > 5)cnt = 0; // 5回折ったら元に戻す
- }
- }
- // 開いた状態の折り紙の左上を 座標( 0,0 ) として
- // 折り紙の左半分を描く
- void page(float r, float h, float rd){
- // 折りの軸の上座標は(r, 0)
- float x = r + r * sin(radians(rd)); // 左上位置 X座標
- float y = 0 + r * cos(radians(rd)); // 左上位置 Y座標
- line(x, y, r, 0); // 上辺
- line(x, y, x, y + h); // 左辺
- line(x, y + h, r, 0 + h); // 下辺
- line(r, 0 + h, r, 0); // 右辺
- }
どうも、ロジックの正解は、
* 再帰関数を行う
* draw関数を使わない
のではないかと思う。もう少し調べてみる必要があるな。
0 件のコメント:
コメントを投稿