1. ホーム
  2. 錯視アート
  3. 拡大パンジー

この記事では書籍「世界一美しい錯視アート」に掲載されている「拡大パンジー」という作品をProcessingを使って再現してみます。

拡大パンジー

今回作成した錯視アート「拡大パンジー」です。

拡大パンジー

書籍では「花が拡大して見える。」と解説されています。実際、自分には面白いほど(気持ち悪いほど?)花が拡大して見えます。

描き方のポイント

花びらをどう表現していくか

この作品では、花びらをどう形づくっていくかということがポイントになってくると思います。いろいろと試行錯誤した結果、ベジエ曲線を使って下記のような設定で描くのが一番しっくりきました。

花びらの作成
  1. まず、花びらは花の中心に向かって縮小していきますので、別記事「縮小していく線分を描く」で解説した要領で、花びらのポイントとなる点(ベジエ曲線の始点、終点となる点)を取ります。上図で\((x_1,y_1)\)と\((x_1,-y_1)\)、\((x_2,y_2)\)と\((x_2,-y_2)\)、\((x_3,y_3)\)と\((x_3,-y_3)\)がそれぞれベジエ曲線の始点と終点となります。
  2. 次に、ベジエ曲線を描きます。今回、試行錯誤の結果、制御点を\[ a_1 = (x_1+\frac{y_1}{2}) \cos(\frac{\theta}{2}), \ \ b_1 = (x_1+\frac{y_1}{2}) \sin(\frac{\theta}{2}), \\ a_2 = (x_2+\frac{y_2}{2}) \cos(\frac{\theta}{2}), \ \ b_2 = (x_2+\frac{y_2}{2}) \sin(\frac{\theta}{2}) \]と取って、外側のベジエ曲線を\((x_2,y_2)\)と\((x_2,-y_2)\)を始点と終点、\((a_1,b_1)\)と\((a_1,-b_1)\)を制御点として描き、内側のベジエ曲線を\((x_3,y_3)\)と\((x_3,-y_3)\)を始点と終点、\((a_2,b_2)\)と\((a_2,-b_2)\)を制御点として描くことで、花びらの形としてしっくりくるものを描くことができました。
  3. あとは、花びらを花の中心に向かって色を交互に変えながら縮小して描いていき、この花びらの列を円形に並べて行けば、1つの花が完成します。その花をまず3×3に並べ、さらに花をそれらの上に4×4に並べていくことでこの作品「拡大パンジー」は完成します。

プログラムコード

今回作成した錯視アート「拡大パンジー」のプログラムコードを載せておきます。

void setup() {
  size(1000, 1000);
  background(255,255,255);

  float pansy_size = width/2.0/4.0+4; // 1つのパンジーの大きさ(半径):キャンパスサイズの4分の1より少し大き目に設定
  float petel_size = pansy_size / 5.0; // 一番外側の花びらのサイズ
  float ratio = 1.0 - petel_size / pansy_size; // 花びらの縮小比率

  noStroke();
  // 描画キャンパスの中央に3×3でパンジーを描く
  translate(width/4.0, height/4.0);
  for(int j=0; j<3; j++){
    for(int i=0; i<3; i++){
      drawPansies(pansy_size, petel_size, ratio);
      translate(width/4.0,0.0);
    }
    translate(-width*3.0/4.0, height/4.0);
  } 
  // 描画キャンパスの中央に4×4でパンジーを描く
  translate(-width/8.0, -height+height/8.0);
  for(int j=0; j<4; j++){
    for(int i=0; i<4; i++){
      drawPansies(pansy_size, petel_size, ratio);
      translate(width/4.0,0.0);
    }
    translate(-width, height/4.0);
  }
}

// パンジーを描く関数
void drawPansies(
  float pansy_size, // パンジーの大きさ(半径)
  float petel_size, // 一番外側の花びらの大きさ
  float ratio // 花びらの縮小比率
){
  int line_num = 12;
  float theta = radians(360.0/line_num); // 花びらの幅を調整するための角度
  rotate(theta/2.0); 
  for(int i=0; i<line_num; i++){
    rotate(theta);  
    drawPetels(pansy_size, petel_size, ratio, theta);
  }
  rotate(-theta/2.0);
}

void drawPetels(
  float pansy_size, // パンジーの大きさ(半径)
  float petel_size, // 一番外側の花びらの大きさ
  float ratio, // 花びらの縮小比率
  float theta // 花びらの幅を調整するための角度
){
  int i = 0;
  float r, a;
  color col_out, col_in;
  float[] x = new float[100];
  float[] y = new float[100];
  
  r = pansy_size;
  a = petel_size;

  x[0] = r * cos(theta/2.0);
  y[0] = r * sin(theta/2.0);  

  while(i<99){
    i++;
    r = r - a;
    x[i] = r * cos(theta/2.0);
    y[i] = r * sin(theta/2.0);
    a = a * ratio;
  }
  
  i=0;
  while(i<100-2){  
    noStroke();
    if (i % 2 == 0){
      col_out = color(#FF0370);
      col_in = color(#90003F);
    } else {
      col_out = color(#C8CB00);
      col_in = color(#FAFF00);
    }
    
    // グラデーションを伴う花びらを描く
    grdPetel(x[i], y[i], x[i+1], y[i+1], x[i+2], y[i+2], 1.0, theta, col_out, col_in);
    i++;
  }
}

// グラデーションを伴う花びらを描く関数
void grdPetel(
  float x1, // 花びらの大きさの基準のx座標
  float y1, // 花びらの大きさの基準のy座標
  float x2, // 花びらの外側のベジエ曲線の始点、終点のx座標
  float y2, // 花びらの外側のベジエ曲線の始点、終点のy座標
  float x3, // 花びらの内側のベジエ曲線の始点、終点のx座標
  float y3, // 花びらの内側のベジエ曲線の始点、終点のy座標 
  float alpha, // ベジエ曲線の始点、終点を調整するパラメータ
  float theta, // 花びらの幅を調整するための角度
  color col_out, // グラデーションの一番外側の色
  color col_in // グラデーションの一番内側の色
){
  float anchor1_x, anchor1_y, anchor2_x, anchor2_y;
  float mean1_x, mean1_y, mean2_x, mean2_y;
  
  mean1_x = (1.0-alpha)*x1+alpha*x2;
  mean1_y = (1.0-alpha)*y1+alpha*y2;  
  mean2_x = (1.0-alpha)*x2+alpha*x3;
  mean2_y = (1.0-alpha)*y2+alpha*y3;  
 
  anchor1_x = (x1+y1/2.0) * cos(theta/2);
  anchor1_y = (x1+y1/2.0) * sin(theta/2);
  anchor2_x = (x2+y2/2.0) * cos(theta/2);
  anchor2_y = (x2+y2/2.0) * sin(theta/2);
  
  float c = 100;
  for (int i=0; i<c; i++) {
    color col = lerpColor(col_out, col_in, i/c);
    float dd_x = lerp(mean1_x, mean2_x, i/c);
    float dd_y = lerp(mean1_y, mean2_y, i/c);
    float dd_anchor_x = lerp(anchor1_x, anchor2_x, i/c);
    float dd_anchor_y = lerp(anchor1_y, anchor2_y, i/c);
    
    noStroke();
    fill(col);
    beginShape();
    vertex(dd_x,dd_y);
    bezierVertex(dd_anchor_x, dd_anchor_y, dd_anchor_x, -dd_anchor_y, dd_x,-dd_y);
    vertex(mean2_x, -mean2_y);
    bezierVertex(anchor2_x, -anchor2_y, anchor2_x, anchor2_y, mean2_x, mean2_y);
    endShape(CLOSE);
  }
}

青い拡大パンジー

書籍「世界一美しい錯視アート」 には、花びらの色が青色とオレンジ色の「青い拡大パンジー」も掲載されていましたので、それも再現してみました。

青い拡大パンジー

コメントを残す