情報システム基礎I(スクーリング後半)
情報システム基礎Iのスクーリング後半に参加しました。
後半は2日間ですが、半分近くは作品作りと講評会でした。
1日目
描画の基本的な部分のほか、応用的な部分も勉強しました。
- 楕円(ellipse)
- 自由曲線(curveVertex)
- 文字の描画
- グレースケール
- 色彩(RGB / HSB / 透明度)
- noise関数(パーリンノイズ)
- 反復による配置(簡単な作品作り)
- 平行移動(translate)
- 回転(rotate)
- 拡大縮小(scale)
- クラスとオブジェクト
- pushMatrix / popMatrix
2日目
2日目はほとんど作品作りでした。最初に今までの作例を見たり、途中で通信課題の説明があり、最後に講評会があり、全員がそれぞれ作品を紹介し、講師の方からコメントをいただきました。
後半は勉強になったことがたくさんあったので、詳しくまとめておきます。
変換
translateやrotate、scaleは使う機会が無かったので使い方がよくわかっていませんでしたが、今回の説明で理解することができました。
translate
translateは描画した図形を平行移動させるもので、原点を変える関数です。
processingは通常であれば左上が原点(x:0 , y:0)になりますが、その原点の位置を変えます。
下の例では、最初に(x:0 , y:0)に点を描いているので左上に欠けた丸があります。そのあとにtranslate(300, 200);としているので、原点が(300, 200)の位置に変わりました。そこで同じように(0, 0)と点を描いているので、その時点での原点(300, 200)に点が掛かれます。
影響を与える範囲は、translateを使った時点から、draw関数が終わるまでです。
- 原点の位置を変える
- translateを使ったところからdrawが終わるまでの範囲に影響する
void setup() { size(600, 400); background(255); stroke(0); strokeWeight(10); } void draw() { point(0, 0); translate(300, 200); //中心を原点にしたい場合はこの書き方も可能 //translate(width / 2, height / 2); point(0, 0); }
rotate
rotateは内容を理解せずに使うと書いた図形がどこかに行ってしまいます。 原点を中心に回転するので、rotateだけ使うと原点の初期位置である(x:0 , y:0)を基準に回ります。
- 原点を中心に回転する
- ラジアンで指定する必要があるので、角度を使う場合はradians()を使う
- rotateを使ったところからdrawが終わるまでの範囲に影響する
void setup() { size(600, 400); background(255); stroke(0); strokeWeight(10); } void draw() { point(300, 200); rotate(radians(10)); point(300, 200); }
原点を中心にするので、図形自体を回転したい場合はtranslateと組み合わせる必要があります。 translateで原点が変わっているので、そのあとの描画は(0, 0)の位置を指定します。
void setup() { size(600, 400); background(255); stroke(0); strokeWeight(1); rectMode(CENTER); } void draw() { translate(300, 200); rotate(radians(45)); rect(0, 0, 50, 50); }
scale
scaleも基本的な考え方は同じで原点を基準にサイズを変えます。 引数の基準は1で、2にすると2倍、0.5にすると半分(0.5倍)の大きさになります。
- サイズは1(1倍)が基準
- 原点を基準に拡大縮小する
- scaleを使ったところからdrawが終わるまでの範囲に影響する
void setup() { size(600, 400); background(255); stroke(0); strokeWeight(1); rectMode(CENTER); } void draw() { translate(300, 200); scale(2); rect(0, 0, 50, 50); }
変換系の動きがわかるプログラムを作ってみました。
- Tキーを押してからドラッグすると、基準点が動きます(translate)
- Rキーを押してからドラッグすると、基準点を中心に回転します(rotate)
- Sキーを押してからドラッグすると、基準点を中心に拡大縮小します(scale)
真ん中に図形を配置しているので、原点の位置によって回転や拡大縮小の仕方が違うこと、図形の位置を変えずに変換したい場合には原点が図形の中心になければいけないということがわかるかと思います。
float x = 0; float y = 0; float angle = 0; float scale = 1.0; void setup() { size(400, 400); stroke(0); rectMode(CENTER); keyCode = 't'; } void draw() { background(255); translate(x, y); rotate(angle); scale(scale); strokeWeight(10); point(0, 0); strokeWeight(0.5); for (int i = - 32; i < 32; i++) { strokeWeight(0.5); if (i == 0) { strokeWeight(2); } line(-width, i * 25, width * 2, i * 25); line(i * 25, -height, i * 25, height * 2); } strokeWeight(1); fill(100, 200, 250, 100); rect(width / 2 - x, height /2 - y , 50, 50); } void mousePressed() { save("translate.jpg"); } void mouseDragged() { if (keyCode == 't' || keyCode == 'T') { x += mouseX - pmouseX; y += mouseY - pmouseY; println("translate(" + x + ", " + y + ");"); } else if (keyCode == 'r' || keyCode == 'R') { angle += atan2(mouseY - 0, mouseX - 0) - atan2(pmouseY - 0, pmouseX - 0); println("rotate(radians(" + angle * 180 / PI + "));"); } else if (keyCode == 's' || keyCode == 'S') { scale += ((mouseX + mouseY) - (pmouseX + pmouseY)) * 0.005; if (scale < 0) { scale = 0; } println("scale(" + scale + ");"); } }
またコンソール画面に、その時にどのようなコードを実行したか表示されるようになっています。
pushMatrix / popMatrix
pushMatrixとpopMatrixは変換とは少し異なり、他の変換関数と組み合わせて使うものです。 pushとpopとなってることからわかるように、スタックというデータ領域に座標データをしまったり取り出したりするものです。 スタックのデータは、先入れ後出しで扱われます。
スタックの他に先入れ先出しのキューがありますが、Matrixでの使用には向いていないのか用意されていません。
詳しい内容を知らなくても、変換の関数が影響する範囲を狭めると考えるとわかりやすいと思います。 変換を行うとdraw関数の終わりまで影響しますが、pushMatrixとpopMatrixの間で行う変換は、それ以外の部分に影響しません。
- pushMatrixで現在の座標を保存する
- popMatrixで保存した座標を取り出す
例えば、下記のような3つの図形を描くプログラムがあります。
void setup() { size(600, 400); noFill(); stroke(0); strokeWeight(1); rectMode(CENTER); } void draw() { background(255); rect(150, 100, 50, 50); triangle(300, 175, 325, 225, 275, 225); rect(450, 300, 50, 80); }
これらの図形をそれぞれ別の角度に回転し、サイズも変えたい場合は、それぞれの図形で変形を行った後に一度座標を戻す必要があります。
void setup() { size(600, 400); noFill(); stroke(0); strokeWeight(1); rectMode(CENTER); } void draw() { background(255); translate(150, 100); rotate(radians(45)); scale(0.8); rect(0, 0, 50, 50); scale(1.2); rotate(radians(-45)); translate(-150, -100); translate(300, 200); rotate(radians(180)); scale(2); triangle(0, -25, 25, 25, -25, 25); scale(0.5); rotate(radians(-180)); translate(-300, -200); translate(450, 300); rotate(radians(30)); scale(1.2); rect(0, 0, 50, 80); }
変換を行うときは初めの基準ではなく、現在を基準にしなければいけません。そのため、translate(150, 100);をもとに戻すためにはtranslate(-150, -100);とする必要があります。rotateやscaleも同じです。
このように行った変換の逆の数値を逆の順番で行わなければいけないため、変換が多くなるほどコードが複雑になってしまいます。
そこでpushMatrixとpopMatrixを使うことで、このコードを簡単にできます。
void setup() { size(600, 400); noFill(); stroke(0); strokeWeight(1); rectMode(CENTER); } void draw() { background(255); pushMatrix(); translate(150, 100); rotate(radians(45)); scale(0.8); rect(0, 0, 50, 50); popMatrix(); pushMatrix(); translate(300, 200); rotate(radians(180)); scale(2); triangle(0, -25, 25, 25, -25, 25); popMatrix(); pushMatrix(); translate(450, 300); rotate(radians(30)); scale(1.2); rect(0, 0, 50, 80); popMatrix(); }
pushMatrixで座標データを保存しておき、変換を行った後にpopMatrixを行うことで、最初の座標データを取り出して元に戻しています。
このような仕組みなのでpushMatrixとpopMatrixは入れ子にすることもできます。
注意点として、pushMatrixとpopMatrixは同じ数だけコード内に書かれていないととエラーになります。
長くなってしまったのでオブジェクト指向はまた別にまとめたいと思います。
制作した作品は、作っているうちに方向を見失ってしまい、アート感が薄れてしまいました。
他の皆さんの作品はいろいろなアイディアのものがあり、もっとアートを学ばないといけないと感じました。
でもせっかく作った作品なので、どこかで内容をまとめたいと思います。
今回のスクーリングは大変な部分もありましたが、多くのことを学ぶことができました。