こんにちは。NUMです。
最近はChatGPTが世間を賑わせていますね。
もしかするとWEBブラウザを使用して検索するという行為自体が無くなってかもしれない中、ブログを書いているのはなんだか笑えてきます。
もし誰にも読まれない記事になったとしても、僕はブログを書くことは今後もやめないと思います。
理由は単純で、Processingが楽しいし、ブログを書くと作れる作品の幅が広がっていくからです。
ブログを書いていると、内容を噛み砕いていくので難しい概念が自分の頭の中にすんなり入っていきます。分からないことが理解できると、どこを変えれば形、動きが変わるかが分かるようになってきます。基礎ができれば応用もできると言うことですね。
まあ、こんな感じでこれからも気まぐれにブログを書いていく予定です。
このブログをきっかけにProcessingの楽しさに目覚める人が増えたら嬉しい限りです。
目次
10PRINTとは
今回は歴史あるジェネラティブアート「10PRINT」の実装をしていきます。
10PRINTは、1980年代初頭に作成された短いプログラムです。1行のコードで「/」と「\」の2つの文字で構成されるランダムな迷路のような模様を作成するものです。短いコードで複雑な模様を作り出すことができるので、多くのメディアアーティストが応用した作品を作っています。
図1
このサイトで10PRINTについてのランダム性、形など考察についてPDFでダウンロードできます。たった1行のプログラムについて膨大なページ数の考察があります。興味ある方は読んでみてはいかがでしょうか。
概要
10PRINTのプログラムの概要は以下です。
「/」と「\」の2つの文字は使用せず、Processingのline関数を使用
キャンバスを指定の数値で分割し、グリッドを作成
グリッド毎に「斜め上」もしくは「斜め下」の線をランダムに引く
線を引いた際、四角形ができるパターンを判定し、四角形で塗りつぶす
10PRINTのプログラムは非常に単純なので、応用として下線部の実装もしていきます。
プログラム
setup()
void setup() {
size(850, 850);
background(255);
pixelDensity(displayDensity());
int divNum = int(random(10, 100));
tenPrint(divNum, divNum);
}
tenPrint()
/**
* 10PRINT作成
* @param1 int キャンバス分割値(横)
* @param2 int キャンバス分割値(縦)
*/
void tenPrint(int divW, int divH) {
boolean[][] states = create10PrintPattern(divW, divH);
draw10Print(states, divW, divH);
}
create10PrintPattern()
/**
* 10PRINTパターン2次元配列作成
* @param1 int 2次元配列サイズ(行)
* @param2 int 2次元配列サイズ(縦)
* @return boolean[][] 10PRINTパターン2次元配列
*/
boolean[][] create10PrintPattern(int rows, int cols) {
int adjust = 10;//配列のサイズを余分に作成
boolean[][] states = new boolean[rows+adjust][cols+adjust];
int rowsLen = states.length;
int colsLen = states[1].length;
for (int row = 0; row<rowsLen; row++) {
for (int col = 0; col<colsLen; col++) {
if (int(random(0, 100))>50) {
states[row][col] = true;//右斜め下線
} else {
states[row][col] = false;//右斜め上線
}
}
}
return states;
}
draw10Print()
/**
* 10PRINTの線と四角形をパターン2次元配列を使用して描画
* @param1 boolean[][] 10PRINTパターン2次元配列
* @param2 int キャンバス分割値(横)
* @param3 int キャンバス分割値(縦)
*/
void draw10Print(boolean[][] states, int divW, int divH) {
int lenW = width/divW;//グリッド横幅
int lenH = height/divH;//グリッド縦幅
int rowsLen = states.length-1;//配列サイズ(行)
int colsLen = states[1].length-1;//配列サイズ(列)
for (int row = 0; row<rowsLen; row++) {
for (int col = 0; col<colsLen; col++) {
int x = col*lenW;
int y = row*lenH;
stroke(0);
strokeWeight(1);
draw10PrintLine(x, y, lenW, lenH, states[row][col]);//線描画
//四角形のパターン判定
if (checkRect(states, row, col)) {
noStroke();
fill(0);
draw10PrintRect(x+lenW, y+lenH, lenW, lenH);//四角形描画
}
}
}
}
checkRect()
/**
* 10PRINTの四角形の形を判定
* @param1 boolean[][] 10PRINTパターン2次元配列
* @param2 int 2次元配列Index(行)
* @param3 int 2次元配列Index(列)
* @return boolean 四角形の場合:true
*/
boolean checkRect(boolean[][] states, int rowIndex, int colIndex) {
boolean checkResult = false;
if (!states[rowIndex][colIndex] &&
states[rowIndex][colIndex+1] &&
states[rowIndex+1][colIndex] &&
!states[rowIndex+1][colIndex+1]) {
checkResult = true;
}
return checkResult;
}
draw10PrintLine()
/**
* 10PRINTの四角形の形を判定
* @param1 int line関数のx1座標
* @param2 int line関数のy1座標
* @param3 int line関数のx2座標
* @param4 int line関数のy2座標
*/
void draw10PrintLine(int x, int y, int lineLenW, int lineLenH, boolean state) {
pushMatrix();
translate(x, y);
if (state) {
line(0, 0, lineLenW, lineLenH);//右斜め下線
} else {
line(0, lineLenH, lineLenW, 0);//右斜め上線
}
popMatrix();
}
draw10PrintRect()
/**
* 10PRINTの四角形の形を判定
* @param1 int rect関数のx座標
* @param2 int rect関数のy座標
* @param3 int rect関数の横幅
* @param4 int rect関数の縦幅
*/
void draw10PrintRect(int x, int y, int rectLenW, int rectLenH) {
rectMode(CENTER);
pushMatrix();
translate(x, y);
rotate(radians(45));
rect(0, 0, rectLenW, rectLenH);
popMatrix();
}
解説
create10PrintPattern()
四角形ができる線のパターンを判定するためのboolean型2次元配列を作成
trueの場合「斜め上」falseの場合「斜め下」という仕様とする
draw10Print()
create10PrintPatternで作成したパターン配列の要素数-1だけ線を描画
checkRect関数で四角形パターンを判定し、四角形を描画
checkRect()
四角形になるパターンを判定
四角形になる条件は以下です。
配列[row][col] = false (右斜め上)
配列[row][col+1] = true (右斜め下)
配列[row+1][col] = true (右斜め下)
配列[row+1][col+1] = false (右斜め上)
以下キャプチャは四角形ができるパターンを図示したものです。
AB,BC,AG,GCが四角形になっています。
同じ行の線が「右斜め上」「右斜め下」、1つ下の行の線が「右斜め下」「右斜め上」となっている場合のみ四角形が出来上がります。
図2
draw10PrintRect()
rectMode(CENTER)でrectの基点座標を中央に指定
10PRINTで出来る四角形は四角形を45°回転させたものになる
まとめ
今回は10PRINTの実装と応用について解説してみました。
1~10まで解説したわけではないですが、重要な部分は解説できたかなと思います。
もし、ブログを読んでいて分からないところがあれば、コメント等で質問していただけるとありがたいです。
こちらは今回のプログラムを応用して作った作品です。
規則正しい形を荒い質感で表現することで、コンピュータらしさと人間味の両方を表現できている気がします。
ただ眺めているだけでも心地よい形ですね。他にも10PRINTを応用した作品を見てみたいです。
最後まで記事を読んでいただきありがとうございました。
ぜひ皆さんも自分だけの10PRINTを作ってみて見せてほしいです!
Comments