Pages

2011年12月4日日曜日

[Processing] 折り紙を折り続ける

前回の続き。1回しか折らない折り紙は哀しいので、折り続けさせてみた。

問題は、折った紙を新たに操作するときに、その座標とか折る方向とかをどのように計算するか。
あらゆる状況を想定する描写関数を用意するとか、再帰処理するかと考えたが、座標変換を利用してみることにした。

利用した関数は、
      transpate(x, y) --- 現在の座標をベクトル(x, y)分だけ座標を移動させる。
                          つまり過去の座標(x, y)が、新たな(0,0)となる。
      rotate( r )     --- 同様に r ラジアンだけ、軸を回転させ、あらたな座標にする  

期待した動きは、折りおわったら、translate し rotate(90度) して、新たな折り紙を左から右に折ることだった。

しかし、ここで落とし穴が。draw()関数は、座標をリセットする。何で? まだ信じられないのだが。
しかたないので、描写の度に translate , rotate を折り返しの数 実施させた。そのため、折りすぎると描写が遅くなってしまった。

でき上がったのは、以下のアプレット。
折り続ける折り紙

以下、ソースコードの解説
  1. int cnt = 0;   // 折り返し回数  
  2. float rad = 270// 折る角度  
  3.   
  4. void setup(){  
  5.   size(200200);  
  6.   color(RGB,256);  
  7.   background(255);  
  8.   frameRate(30);  
  9. }  
  10.   
  11. void draw(){  
  12.   // 折り紙の左上に座標を移動  
  13.   translate(50,50);  
  14.   float rr = 40;  // 折り紙の横の半分 (折りの半径になる)   
  15.   float hh = 80;  // 折り紙の高さ  
  16.   // 折り回数分だけ、座標と半径、高さを計算し直す  
  17.   for(int i=0;i<cnt;i++){  
  18.     translate(rr, hh);      // 次の折り紙の左上  
  19.     rotate(radians(-90));  // 折りの方向を90度回転  
  20.     // 新たな折り紙の高さと半径(横の半分)  
  21.     float temp = hh;  
  22.     hh = rr;  
  23.     rr = temp / 2;  
  24.   }  
  25.     
  26.   background(255);  
  27.   stroke(0);  
  28.   page(rr, hh, 90);  // 折り紙の右半分  
  29.   page(rr, hh, rad); // 折り紙の左半分 radは折り角度  
  30.   
  31.   // 折り曲げたら折り角度radを戻し、1回カウント  
  32.   if(--rad == 90){  
  33.     rad = 270;  
  34.     if(++cnt > 5)cnt = 0// 5回折ったら元に戻す  
  35.   }  
  36. }  
  37.   
  38. // 開いた状態の折り紙の左上を 座標( 0,0 ) として  
  39. // 折り紙の左半分を描く  
  40. void page(float r, float h, float rd){  
  41.   // 折りの軸の上座標は(r, 0)  
  42.   float x = r + r * sin(radians(rd)); // 左上位置 X座標  
  43.   float y = 0 + r * cos(radians(rd)); // 左上位置 Y座標  
  44.   line(x, y, r, 0);         // 上辺  
  45.   line(x, y, x, y + h);     // 左辺  
  46.   line(x, y + h, r, 0 + h); // 下辺  
  47.   line(r, 0 + h, r, 0);     // 右辺  
  48. }  
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 件のコメント:

コメントを投稿