lecture:design_with_prototyping:p5.js編:14.繰返しの再構成

繰返しの再構成

繰返しと言われて皆さんなにを思い浮かべるでしょうか?一般的には同じことを何度もすることを意味しているわけですが、朝昼夜、春夏秋冬、デザイン思考等など、 繰返しとは様々なプロセスにおいて一般的に語られるプロトコルであり私達の身の回りにあふれる概念です。このページでは繰返し処理をテーマにいくつかの視覚的な表現に関するコードをスケッチしてみたいと思います。

ピエト・モンドリアンの作品の中で最も有名とも言える,Compositionという作品群があります.

ピエト・モンドリアン(ピート・モンドリアン、Piet Mondrian、本名ピーテル・コルネーリス・モンドリアーン Pieter Cornelis Mondriaan 1872年3月7日 - 1944年2月1日)は19世紀末-20世紀のオランダ出身の画家。ワシリー・カンディンスキー、カジミール・マレーヴィチらと並び、本格的な抽象絵画を描いた最初期の画家とされる。 出典: フリー百科事典『ウィキペディア(Wikipedia)』

Piet Mondriaan, 1930 - Mondrian Composition II in Red, Blue, and Yellow. Lisenced by Public Domain.

上記作品はその中の一つです.青,白,黄色,赤の四色をカンバスに引かれた線を基準にそれぞれの四角を塗りつぶしています.従来絵画とは,自然界における対象物を綿密に観察し,それらを模写または再構成することが多かった中.このような抽象画は描き方そのものに大きな変化がありました.絵画というよりは工業製品や設計物に近い,手続き的な技法となっています.今回の絵画の特徴は,上下左右に引かれた線及び,それを基準にした四角になります. このような四角を引くための基準となる線のことをグリッドと呼びます.グリッドは様々な視覚的コンテンツにおいて基礎的に用いられる手法です.基本となる縦及び横の線を引き,その線を基準に様々なものをレイアウトします.例えばポスターやウェブデザイン,アプリケーションGUIなどにコンテンツを配置する場合,このようなグリッドを基準にしてコンテンツを視覚的に揃えることが行われています.

グラフィックデザインなどでは,このようなグリッドが無意識的に利用されており,私達はこのグリッドを通じてポスターなどに載せられたコンテンツや情報を受け取っているわけです.もちろん絵画においてもこのような考え方は構図と呼ばれ,例えばセザンヌの構図等は良く練られた構図としてしばしば紹介されています.

絵画の発展とともに構図の様式が定式化され,様式にとらわれる技法を皮肉ったとも考えることができますし,対象物の抽象化を図る過程において,このようなグリッドだけを残した絵画が描かれるのも納得が行くのではないでしょうか.抽象的であるからこそ,鑑賞者に対して解釈の余白を多く提示してくれています.

下記に示す手順は,アルゴリズムにおける再帰呼び出しと呼ばれるものです.具体的にいうと,例えば func()という関数があったとします.このfunc()という関数をfun()関数の中でさらに呼び出すことです.

  1. 四角を描く
  2. その四角の中から,一点を選択する
  3. その点を境界として4つの四角形を新たに描く.
  4. 2,3を繰り返す.

sketch.js
/*
  Reference: https://makezine.com/2011/05/11/codebox-explore-recursion-with-processing/
*/
 
let number = 3;  // Number of recursive steps
 
//Draw the first image
function setup() {
  createCanvas(500, 500);
  piet(1, 1, 500, 500, number);
}
 
// Draw a Mondarian-inspired image using recursion
function piet(x0, y0, x1, y1, N) {
  if (N == 0) {
    // Base case -- draw a colorful rectangle with a thick black border 
    let sw = 10; //this is the stroke width for the rectangle's border
    let c = ['#ff0000', '#0000ff', '#ffff00', '#ffffff']; //Mondarian color palatte    
    fill(c[int(random(c.length))]);
    stroke(0);
    strokeWeight(sw);
    rect (x0, y0, x1-x0, y1-y0);
    return;
  } else {
    //Recursive step -- recursively break the current rectangle into 4 new random rectangles
    let i = int(random(x0, x1)); //Pick a random x coordinate inside the current rectangle
    let j = int(random(y0, y1)); //Pick a random y coordinate inside the current rectangle
    piet(x0, y0, i, j, N-1); // Recurse on upper left rectangle
    piet(i, y0, x1, j, N-1); // Recurse on upper right rectangle
    piet(x0, j, i, y1, N-1); // Recurse on lower left rectangle
    piet(i, j, x1, y1, N-1); // Recurse on lower right rectangle
    return;
  }  
  //save("mondorian.png");
}
 
// keep draw() here to continue looping while waiting for keys
function draw() {
}
 
//Draw a new image each time a key is pressed
function keyPressed() {
  background(0);
  piet(1, 1, 500, 500, number);
}
 

上記プログラムを参考にして,様々なCompositionを作成してみましょう.

さて、このような再帰関数的生成手法は近代的な絵画だけではなく、自然界にも多く存在していると言われています。このような考え方はフラクタルやカオスなどと呼ばれ、繰り返し決まった処理を行いつつも、繰り返す中で微妙なパラメータが変化し、結果として興味深い出力結果になるといったものです。その中でも有名なフラクタル図形の木を実際にコーディングしてみましょう。上図に描いているようなプログラムを目指します。手続きは次のとおりです。

  1. 任意の座標から直線を描く
  2. 直線の一端で、2つの方向に角度を決定する。任意の座標はその一端のx,y座標に変更する
  3. 上記を繰り返す

上記流れを理解した上で、プログラムを記述するために必要な具体的な部分も決めて、実際の流れを以下のようにします。

  1. 座標(width/2, height-10)の一から、真上に向かって直線を100pxだけ描画する
  2. 描いた直線の一端座標(width/2 + 100*cos(PI/2), height-10 - 100*sin(PI/2))の位置から任意の角度PI/4だけそれぞれ右と左にずらした直線を描く
  3. 上記を繰り返す

では実際に記述してみます。

sketch.jg
function setup() {
  createCanvas(500, 500);
  background(250);
  drawBar(width / 2, height - 10, 100, PI / 2, 8);
}
 
function drawBar(x0, y0, length, theta, N) {
  if (N > 0) {
    let x = x0 + length * cos(theta);
    let y = y0 - length * sin(theta);
    line(x0, y0, x, y);
    drawBar(x, y, length * 0.8, theta + PI / 8, N - 1);
    drawBar(x, y, length * 0.8, theta - PI / 8, N - 1);
  }
}

html上のUIを利用して、反復回数や、lengthの減衰値、角度などを動的に変化させて生成される木の種類を観察してみましょう。

以下はこのページのトップにある画像を生成するコードです。上記のサンプルプログラムと見比べてみてもなにか発見があるかもしれません。

トップの画像を生成するコード.js
let number = 25;
 
 
function setup() {
  createCanvas(1280, 720);
  background(0);
  stroke(121, 84, 56, 150);
  strokeWeight(1);
  drawBar(width / 2, height - 10, 100, PI / 2, number);
}
 
function drawBar(x0, y0, length, theta, N) {
 
  if (N > 0) {
    let x = x0 + length * cos(theta);
    let y = y0 - length * sin(theta);
 
    line(x0, y0, x, y);
 
    if (N < number / 2) {
      stroke(49, 226, 22, 150 - 150 * (N / number));
      if (random(0.0, 1.0) < 0.8) {
        stroke(49, 226, 22, 20);
        drawBar(x, y, length * random(0.6, 1.0), theta + random(PI / 8, PI / 7), N - 1);
      }
      if (random(0.0, 1.0) < 0.8) {
        stroke(49, 226, 22, 20);
        drawBar(x, y, length * random(0.6, 1.0), theta - random(PI / 8, PI / 7), N - 1);
      }
    }
    else {
      //stroke(121, 84, 56, 150 * (N / number));
 
      if (random(0.0, 1.0) < 0.8) {
        stroke(121, 84, 56, 150 * (N / number));
        drawBar(x, y, length * random(0.6, 1.0), theta + random(PI / 8, PI / 7), N - 1);
      }
      if (random(0.0, 1.0) < 0.8) {
        stroke(121, 84, 56, 150 * (N / number));
        drawBar(x, y, length * random(0.6, 1.0), theta - random(PI / 8, PI / 7), N - 1);
      }
    }
 
 
  }
 
}
 
function keyPressed() {
  if (key == 's') {
    save('fractal_tree_simple.png');
  }
}

Reference

  • /home/users/2/lolipop.jp-4404d470cd64c603/web/ws/data/pages/lecture/design_with_prototyping/p5.js編/14.繰返しの再構成.txt
  • 最終更新: 2021/03/10 18:12
  • by baba