[Go to “teaching” in Morimoto Lab]
もっと関数について学びます。
再帰関数で木を描画します。
オリジナルの関数を定義するときに、関数の頭についているvoidやintなどは関数の型と言います。(Processingのsetup()にはvoidが付いていますね!それです)
この型は、関数が返す値によって決めます。
返す値のことを返り値や戻り値と言い、関数内でreturnを記述することで返します。
ちなみに、voidはよく関数の頭についていますが、変数の定義に使ったことはありませんでした。
voidは「この関数は何も返しませんよ!」という意味になります。
この場合、return文はいりません。
キーワード(上記のまとめ)
関数の型:関数の定義のとき、頭についているvoid, int, float,…などのこと。
戻り値(返り値とも):関数の処理によって返す値のこと。
return文:戻り値を返すときにreturn a;などと、returnを使って値を返す。return文以降の関数の処理は行われない。
void:関数の型で使われた場合、「この関数は何も返しませんよ」という意味。この場合、関数にreturn文は不要。
以下のプログラムを実行して、説明を読みながら、中身を少しアレンジして挙動を確認してみてください。
int a;
void setup()
{
size(300,300);
a=0;
//↓定義した関数を呼び出しています。setupから呼べばhelloは一回だけprintlnされます。
myFuncVoid();
}
void draw()
{
//↓もしここで呼ぶと怖いくらいたくさんhello!と言われます
//myFuncVoid();
//↓returnがある関数でも代入しなければその値は特に使われません
myFuncInt();
//↓returnのある関数は直接代入に使えます。boolなら直接if文に入れてもOKなど。
float aaa = myFuncFloat(5.0);
}
//↓voidがついた関数は何も返しません
void myFuncVoid()
{
println(“Hello!”);
}
//↓intなどのデータ型が付いた関数は、そのデータ型の変数を返します
int myFuncInt()
{
int a = 0;
return a;//関数の最後にreturnで返したい変数を返します。
}
//↓括弧の中に引数を定義できます。渡したい値があるときに使います。複数定義可能。
float myFuncFloat(float a)
{
return a + 1.5f;
}
Note: 関数の 引数 は以下のように複数に増やすことができます.
float myFuncFloat(int a, float b, color c, PImage img)
Note: 関数を呼び出すときに与える引数は、定義されたデータ型と一致していればOKです。
呼び出し側は、数値でもいいですし、変数で指定する場合も同じ名前を使う必要などはありません。Note: メソッドというのも関数とかなり似た言葉で、関数の一種です。
クラスの中で定義したメンバ関数のことをメソッドと、厳密には言うみたいです。
メンバ関数というのはクラスに属する関数のこと、
クラスはまたのちの講義で説明します(あまり今は気にしなくてよいです)。
Hint: 文字の表示方法は以下のリンクなどを参照
Hint: 配列の要素数は.lengthで取得できます。関数内でここを定数などにしてはいけません。エラーが起こります。参照
再帰関数で描画する対象として、最もポピュラーな「木」を描きましょう。
用意する関数は一本の枝と見立てた「一本の線」を描く関数です。
この関数は描画の「始点・角度・深さ」を引数とする関数であれば、最低限の木が描けます。
[Sample Code F]
void setup(){
size(500,300); //window size
background(255); //background color
strokeWeight(5); //line weight(sen haba)
stroke(50,200,50); //line color RGB
branch(width/2, height, -90, 10);
}
void branch(float sx, float sy, float angle, int depth){
if(depth>0){
float rad = radians(angle);
float radius = depth * 5;
//end point
float ex =sx + cos(rad)* radius;
float ey =sy + sin(rad)* radius;
line(sx, sy, ex, ey);
//branch(ex,ey,angle+20, depth-1);
//branch(ex,ey,angle-20, depth-1);
}
}
上記のプログラムでは枝を描く関数の中で、枝を描く関数を呼び出しています。
これによって再帰的な処理になります。
depthはどんどん小さくなり、0になったらif文でもうbranch()を呼ばないようにすれば終了です。
!終了処理がうまく働かないコードを作ってしまった場合、ソフトウェアを強制終了させる事態になりますので、気を付けてください!
更に枝の太さ、色、長さ、を考慮するために工夫すると、もっとリッチな木が描けます。
枝も線でなく、文字やお花などに変更したり、付け加えたりすれば表現力∞ですね!
以下の課題を通して、オリジナルの木を表現してみてください。
参考URL←何となく絵を眺めてみるだけでも…
風に揺れるさま、爆発するさま…?
ヒント:
HSB色空間
例えば?
シダ植物(Processingじゃないですけど参照)
きれいな模様(曼荼羅?魔法陣?)
プラレール!(参考URL)
再帰なのか微妙ですが、ついでにスピログラフ
シェルピンスキーのギャスケットも係数を変えると面白いそうです
その他:思いつけば研究になるかも!
L-Systemも再帰性があり、自己相似図形やフラクタル図形のような形状を幅広く記述できます。
https://ja.wikipedia.org/wiki/L-system
英語ですが、こちらのテキストが分かりやすく、
Processingのコードもあります。
http://www.erase.net/projects/l-systems/
Processing official web site > Example > Fractals and L-Systems
の
Penrose Snowflake
Penrose Tile
Pentigree
にもサンプルがあります。
色々なパターンを作るためのL-Systemの構成?は以下のページが参考になります。
http://hiiragicompany.net/ls.html
少しプログラムは複雑ですが…。