CGプログラミング演習
2 変数、繰り返し、乱数

前回講義では、Processing を用いたグラフィックの描画の基本を学びました。
今回は、これにコンピュータの計算能力を組み合わせます。

1 コンピュータの計算能力を生かす

  • 前回講義では、Processing でできることとして、いくつかの Processing を用いた作品を見てみました。
  • もうひとつ実例を見てみます。
  • このようなグラフィックを描画するためには、コンピュータの計算能力を活用することがぜひとも必要になってきます。
  • その際に必要になるのが、ここで学ぶ「変数」と「繰り返し」の概念・技術です。

2 前回学んだ関数(おさらい)

2.1 キャンバスサイズの指定と図形の描画

// キャンバスサイズの指定
// 幅400ピクセル、高さ200ピクセルのウインドウを開く
size(400, 200);

// 点
// 座業(200, 100)に点を描きます
point(200, 100);

// 線
// 座標(25, 175)から(175, 175)に線を描きます
line(25, 175, 175, 175);

// 長方形
// 左上の座標を(225, 25)として、150ピクセルの幅と 75ピクセルの高さを持つ長方形を描きます
rect(225, 25, 150, 75);

// 三角形
// みっつの頂点がそれぞれ(300, 125)(225, 175)(375, 175)の三角形を描きます
triangle(300, 125, 225, 175, 375, 175);

// 円、楕円
// 中心の座標を(100, 90)として、幅 140ピクセル、高さ 140ピクセルの円を描きます
ellipse(100, 90, 140, 140);

2.1 色の指定

// 背景色の指定
// background([Rの値],[Gの値],[Bの値]);
background(255, 255, 255);

// 線の色の指定
// stroke([Rの値],[Gの値],[Bの値]);
stroke(255, 0, 0);

// 塗りの色の指定
// fill([Rの値],[Gの値],[Bの値]);
fill(255, 255, 0);

// 線を描画しない
noStroke();

// 塗りを描画しない
noFill();

3 変数

3.1 クイズ

  • 幅と高さが 100 ピクセルのキャンバスの上端にキャンバスを横ぎる直線を描くには?

  • さらに10ピクセル下に同じように直線を描くには?

  • キャンバスの下端に達するまで、同じ作業を繰り返してみてください

3.2 クイズの答え

size(100,100);

line(0,0,100,0);
line(0,10,100,10);
line(0,20,100,20);
line(0,30,100,30);
line(0,40,100,40);
line(0,50,100,50);
line(0,60,100,60);
line(0,70,100,70);
line(0,80,100,80);
line(0,90,100,90);

3.3 変数の利用

  • 10ピクセルずつ下げていくという部分を、結局のところ自分自身で計算している。
  • せっかくコンピュータを利用しているのだから、こうした計算は、コンピュータにやってもらいたい。
  • そこで、作業内容を考えてみると、次の作業を繰り返していることが分かる「(1)線を描く、(2)Y 軸方向を 10 ピクセルずらす」。
  • まずは、現在のY軸方向の値(位置)を記録できないものか?
  • 「値を記録する」には「変数」を利用する。

3.3.1 変数とは?

  • 一時的に値(文字、文字列、数字など)を記憶しておく場所
  • データを入れておく「箱」のようなもの

プログラマーは、プログラムする際に、変数の箱を想像いるようにおもいます。

3.3.2 データの型(変数の種類)

  • Processingでよく用いられるデータ型
  • int:整数 (-1, 0, 1, 2, 3....)
  • float:少数 (-0.01, 3.14, 21.314)
  • boolean:ブール値、真か偽か、(true, false)
  • char:1文字分のデータ(a, b, c, d...)
  • color:色の情報を保存

型が異なる変数は、異なる箱に入れるイメージ。

3.4 変数の利用方法

// 宣言……使用する変数の名前の箱を準備する
int hoo;
// 複数の宣言を一度に行うこともできる
int hoo, bar;

// 代入……変数の箱に値を入れる
hoo = 100;

// 演算……変数の値を計算する(ここでの = は「代入」の意味なので注意すること)
// 足し算
hoo = hoo + 1;
// 引き算
hoo = hoo - 1;
// かけ算
hoo = hoo * 2;
// 割り算
hoo = hoo / 2;

// 演算の規則は、数学で学んだのと同じ順序(かけ算、割り算が先)
// 以下の三つは、どれも同じ順序で計算される。
hoo = hoo * 2 + 4;
hoo = 4 + hoo * 2;
hoo = (hoo * 2) + 4;

3.5 変数を用いたグラフィックの描画

  • さきほどの例を変数を用いると次のようになる
size(100, 100);

float y = 0;

line(0, y, 100, y);
y = 10;
line(0, y, 100, y);
y = 20;
line(0, y, 100, y);
y = 30;
line(0, y, 100, y);
y = 40;
line(0, y, 100, y);
y = 50;
line(0, y, 100, y);
y = 60;
line(0, y, 100, y);
y = 70;
line(0, y, 100, y);
y = 80;
line(0, y, 100, y);
y = 90;
line(0, y, 100, y);
  • 上記は、y 自身に 10 を足す作業の繰り返しなので、さらに単純にできる。
size(100, 100);

float y = 0;

line(0, y, 100, y);
y = y + 10;
line(0, y, 100, y);
y = y + 10;
line(0, y, 100, y);
y = y + 10;
line(0, y, 100, y);
y = y + 10;
line(0, y, 100, y);
y = y + 10;
line(0, y, 100, y);
y = y + 10;
line(0, y, 100, y);
y = y + 10;
line(0, y, 100, y);
y = y + 10;
line(0, y, 100, y);
y = y + 10;
line(0, y, 100, y);

より単純なプログラムで、同じ結果を得られた。
複雑なものをより複雑にすることは困難だが、単純なものをより複雑なものにすることは簡単。
単純さは、プログラミングにおいて、とても重要な要素です。

3.6 変数を用いたグラフィック描画を実験してみる

変数を用いれば、面倒な計算せず、正確に、複雑な描画を得ることができます。

  • 同心円を描画する
size(400, 400);
float x = 200, y = 200, diameter = 400;

noFill();

diameter = diameter - 40;
ellipse(x, y, diameter, diameter);

diameter = diameter - 40;
ellipse(x, y, diameter, diameter);

diameter = diameter - 40;
ellipse(x, y, diameter, diameter);

diameter = diameter - 40;
ellipse(x, y, diameter, diameter);

diameter = diameter - 40;
ellipse(x, y, diameter, diameter);

diameter = diameter - 40;
ellipse(x, y, diameter, diameter);

diameter = diameter - 40;
ellipse(x, y, diameter, diameter);

diameter = diameter - 40;
ellipse(x, y, diameter, diameter);

diameter = diameter - 40;
ellipse(x, y, diameter, diameter);

diameter = diameter - 40;
ellipse(x, y, diameter, diameter);

3.7 演習 変数を用いた色の演算

  • 上の同心円を描画するプログラムをもとにして、変数を利用した色の加工処理を導入してください。
float r = 255, g = 255, b = 255;
stroke(r, g, b);
fill(r, g, b);

4 繰り返し

4.1 同じ処理を見いだす

  • さきほどの同心円のプログラムを、もう一度見てください。
  • 途中から同じ命令が繰り返されています。
diameter = diameter - 40;
ellipse(x, y, diameter, diameter);

diameter = diameter - 40;
ellipse(x, y, diameter, diameter);

diameter = diameter - 40;
ellipse(x, y, diameter, diameter);

...
  • 繰り返しの部分を何度も書かずに一気に指定するには、どうすればよいでしょう?
diameter = diameter - 40;
ellipse(x, y, diameter, diameter);
  • つまり、この処理を10回くりかえしたい。
  • それには、for 文を書きます。

4.2 for文の書きかた

for (初期化式; 継続条件式; 再初期化式) {
    文;
}
  • 初期化式:初期化の際の条件式
  • 継続条件式:繰り返しを継続する条件式
  • 再初期化式:繰り返されるたびに実行される式
/*
    for 文を用いた繰り返しの例 1
    100回「+」の文字を出力する
 */
int i;
for (i = 0; i < 100; i = i + 1) {
    // print 関数を利用すると、メインウインドウの下に、変数の内容が出力されます
    print("+"); 
}
/*
    for 文を用いた繰り返しの例 2
    0から99までの数を出力する
 */
int i;
for (i = 0; i < 100; i = i + 1) {
    print(i + ", ");
}

4.3 さきほどの同心円を for文を用いて描画する

  • それでは、さきほどの同心円のプログラムを for 文を用いたものに変更してみてください。
  • この下にプログラム内容が書かれていますが、ぜひ、自力で!

この例は、さきほどのサンプルに色を変化させる処理を追加したものです。

// 初期条件の設定
size(400, 400);
background(0, 0, 0);

// smooth 関数を利用すると、描画結果をアンチエイリアシングできる。
smooth();

// stroke, fill などの関数に 4番目の引数として 0〜100 までの値を与えると、
// 与えた数値に応じて、0〜100% までの透明度を設定できる。
// ここでは、10% の白を設定している。
stroke(255, 255, 255, 10);

// 描画処理に用いる変数の宣言
float x = 200, y = 200, diameter = 400;
float r = 255, g = 255, b = 255;
int i = 0;

// 同心円を描いていく
for (i = 0; i < 10; i++)
{
  // 以下の 3 行は色の調整部分
  g = g * 0.9;
  b = b * 0.9;
  fill(255 - r, 255 - g, 255 - b);  

  diameter = diameter - 40;
  ellipse(x, y, diameter, diameter);
}

5 色の指定方法の補足 HSB による指定

5.1 HSB とは

  • Processing では、RGB による色の指定のほか、HSB による色の指定ができる。
    • 色相(Hue)……色の種類
    • 彩度(Saturation)……色の鮮かさ
    • 明度(Brightness)……色の明かるさ
  • プログラミングしながら色を指定する場合、HSBの方が直感的に望みの色を指定しやすいことが多い

Adobe Photoshop の HSBカラーパレット

5.2 Processing における HSB の利用方法

  • colorMode 関数を使用して、色指定方式を変更する。
  • それぞれのパラメータの範囲も同時に指定
  • 例:
    • 色相:360階調(度数)
    • 彩度:100階調(%)
    • 明度:100階調(%)
colorMode(HSB, 360, 100, 100);

5.3 HSB と繰り返しを使用した表現

HSBを利用すると、このような虹色の表現が容易にできる。

// 初期設定
size(360, 360);
colorMode(HSB, 360, 100, 100);  // ここで HSB を指定

// 変数の宣言
int w = width, h = height, i;

// 色相を変化させながら線を描いていく
for (i = 0; i < w; i++) {
	stroke(i, 100, 100);
	line(i, 0, i, h);
}

6 乱数

6.1 乱数とは

  • プログラムは、設定された手続きを何度でも、飽きることなく繰り返しつづける。
  • そのままでは、予想外の挙動はしない。
  • 一方で、完全に全てをコントロールするのではなく、偶然性、意外性をとり入れたい要求がある。
  • ほとんどのプログラミング言語には、実行する度に毎回異なる値を出力する仕組みが備わっている。
  • 乱数とは、法則性、規則性のない、ランダムな値の集合のこと。
  • Processing では、乱数を出力するために random 関数を使用する。

6.2 Processing における乱数の使用方法

  • Processingで乱数を生成するには、random 関数を使用する。
  • その際、乱数の範囲を指定することができる。
// 例:0から100の乱数を生成
random(100);

// 例:100から1000の乱数を生成
random(100, 1000);

6.3 乱数を用いた色の指定

色相をランダムに変化させた描画結果

// 初期設定
size(360, 360);
colorMode(HSB, 360, 100, 100);  // ここで HSB を指定

// 変数の宣言
int w = width, h = height, i;

// 色相を変化させながら線を描いていく
for (i = 0; i < w; i++) {
	stroke(random(0, 360), 100, 100);
	line(i, 0, i, h);
}
  • 色相だけでなく、彩度、明度もランダムに変化させるにはどうしたらよいか、考えてみてください。

色相、彩度、明度をランダムに変化させた描画結果

  • さらに、色相、彩度、明度のうち、色相を、似た値に限定してランダムに描画するには、どうしたらよいでしょうか?

色相を似た値に限定してランダムに変化させた描画結果

7 乱数と繰り返し

  • 乱数と繰り返しの力を用いれば、複雑なグラフィックをおどろくほど簡単に描画することができます。

7.1 ランダムな点の描画

  • 乱数と形態のくみあわせの最初の例として、「点」を利用してみます。

ランダムな点の描画。これは、点の描画数を少しずつ増やしていった例。

// 初期設定
size(200, 200);

// HSBモードの指定
colorMode(HSB, 100, 100, 100);

// 変数の宣言
int w = width, h = height, i;

// ランダムに点を描画する
for (i = 0; i < (w * h) / 4; i++)
{
    stroke(random(0, 100), random(0, 100), random(0, 100));
    point(random(w), random(h));
}
  • 上のプログラム中の for 文の「継続条件式」部分を下記のように変更。
    • for (i = 0; i < (width * height) / 20; i++)
    • for (i = 0; i < (width * height) / 10; i++)
    • for (i = 0; i < (width * height) / 5; i++)
    • for (i = 0; i < (width * height) / 4; i++)
    • for (i = 0; i < (width * height) / 2; i++)
    • for (i = 0; i < (width * height); i++)

7.2 ランダムな線の描画

  • 続いて「線」でも同じことをしてみましょう。

ランダムな線の描画。これは、彩度の範囲を少しずつ減らし、0に近づけていった例。

// 初期設定
size(200, 200);

// HSBモードの指定
colorMode(HSB, 100, 100, 100);

// 変数の宣言
int w = width, h = height, i;

// ランダムに線を描画する
for (i = 0; i < (w * h) / 4; i++)
{
    stroke(random(0, 100), random(0, 100), random(0, 100));
    line(random(w), random(h), random(w), random(h));
}
  • 上のプログラム中の stroke 関数の色指定部分のうち彩度を下記のように変更。
    • stroke(random(0, 100), random(0, 100), random(0, 100));
    • stroke(random(0, 100), random(0, 80), random(0, 100));
    • stroke(random(0, 100), random(0, 60), random(0, 100));
    • stroke(random(0, 100), random(0, 40), random(0, 100));
    • stroke(random(0, 100), random(0, 20), random(0, 100));
    • stroke(random(0, 100), 0, random(0, 100));

8 演習

  • 「点」「線」とくれば、続いて「面」がきます(ワシリー・カンディンスキー『点と線から面へ』バウハウス叢書、美術出版社、1995)。
  • 本日学んだ「変数」「繰り返し」と「乱数」を利用し、「面」を描画するプログラムを作成してください。
  • 条件は下記の通りです:
    • 面=円/四角形/三角形の描画が含まれること(点や線の描画が含まれていてももちろんOKです)
    • 提出期限は、次回木曜日(10月6日)の授業開始時とします

8 提出作品(20110507更新)

012 岩見啓子

038 川島歩

040 北村昭美

079 長嶋茜

102 増田飛鳥

112 山川幸子