p5.jsで伝統模様「七宝」を描く

こんにちは．ふじえもんです．

# p5.jsを学び始めた
最近，p5.jsを触れるようになりました．
その経緯や学びを備忘録として記録してみたいと思います．

実は，音声や音楽を可視化するプロダクト作成に興味を持ち，ChatGPTに相談したところ，いくつかの方法を提案されました．


<img width="15px" alt="ふじえもんのアイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2686406/ca3ab555-fea3-4a70-458d-7cd48b5c9f88.png">
Webブラウザ上で音の響きのようすをグラフィカルに表現します．
音や波の描画などが扱いやすい言語だと助かります．どうしましょうか

すると，Web Audio APIやp5.js,Three.jsなどを提案してくれました．

:computer:　
1. Web Audio API: Web Audio APIは、Web上で高度なオーディオ処理を行うための強力なAPIです．JavaScriptで簡単に扱うことができ、波形や周波数などを可視化することも可能です．

2. p5.js: p5.jsはJavaScriptのライブラリで、視覚的なプログラミングを簡単に行えます．p5.jsにはオーディオの可視化に特化した関数も多く、初心者にも扱いやすいです．

3. Three.js: もし3Dで音の響きを表現したい場合には、Three.jsがおすすめです．WebGLを簡単に扱えるように設計されていますが、一定の学習コストは必要です．

4. D3.js: データ駆動型の文書作成を支援するJavaScriptライブラリです．複雑なデータビジュアライゼーションが可能ですが、やはり一定の学習コストが必要です．

Web Audio APIは，とあるアプリをつくるときに使っていたので，今回はp5.jsを使うことにしてみました．

調べてみると，[p5.js](https://p5js.org/)はProcessingをJavascriptで扱えるようにしたもののようです．
> p5.js is an interpretation of Processing for today’s web. We hold events and operate with support from the Processing Foundation.

(https://p5js.org/ Communityより引用)


# 余談
Processingは講義で使ったことがあり，**400*400px**のキャンバス上でランダムな色の10*10pxの正方形を生成し，繰り返し表示するプログラムを作成したことがあります．

実行すると以下のような画像が繰り返し表示されます．
<img width="200px" alt="画像" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2686406/950b8f59-48b4-ab3f-4c4b-1850300f0c63.png">

当時書いたProcessingのコードをp5.jsで書くと以下のようになります．
```js
function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(0);

  for (let i = 0; i < 40; i += 1) {
    for (let j = 0; j < 40; j += 1) {
      let R = int(random(256));
      let G = int(random(256));
      let B = int(random(256));
      fill(R, G, B);
      rect(i * 10, j * 10, 10, 10);
    }
  }
}
```


# まず伝統模様を描いてみた
いきなり音の可視化をやるのは難しいだろうってことで，簡単な画像処理から始めました．

画像処理といえば[GIMP](https://www.gimp.org/)でいくつか伝統模様を作っていたことを思い出し，これってプログラムで再帰的に書けるよねってことでやってみました．

<img width="300px" alt="七宝１枚目" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2686406/ceeed04e-bb45-a40d-fe10-0243abf92962.png">
<img width="300px" alt="七宝２枚目" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2686406/588efdac-54ee-f06e-9c5b-aef28b02f00f.png">

そこで探して見つけたのはこちらのブログ「七宝模様を描く．【p5.jsで和柄】」です．

https://gin-graphic.hatenablog.com/entry/2021/04/21/191000

こちらの記事にあったコードを参考に自分が好きな色に変えて書いてみました．
こんな感じ．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2686406/e34979ff-b231-662f-5323-daaeb5220bd3.png)


で，ちょっと色を変えてあげるとこんな感じで，２つの重なる円を繰り返し描画していることがわかります．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2686406/1ac558d7-4b1c-3d9d-9665-595dd044c40c.png)


```js
const w=720;
const N=10;
const d=w/N;
const setcol=[]
setcol[0]=["#5F6427", "#DE3B23"];
setcol[1]=["#21C4DC", "#A09BD8", "#4B0082"];
setcol[2]=["#4B0082", "#0000DC", "#DE3B23"];

function setup() {
   createCanvas(w, w);
   ellipseMode(CORNER);
   noFill();
   strokeWeight(d/20);
   col = random(setcol);
   noLoop();
}

function draw() {
   background(col[0])
	 
   for(let i=0;i<N;i++){
      const x = d*i;
      for(let j=0;j<N;j++){
         const y = d*j;
         push();
         stroke(col[1]);
         translate(x, y);
         circle(0, 0, d);
         pop();
      }
   }

   for(let i=0;i<N+1;i++){
      const x = d*(i-0.5);
      for(let j=0;j<N+1;j++){
         const y = d*(j-0.5);
         push();
         stroke(col[2]);
         translate(x, y);
         circle(0, 0, d);
         pop();
      }
   }
}
```


コメントをいただき，いくつか修正しました．（2023/11/01）
- setcol[0]の要素を追記．(ついでに四季のイメージに合わせて，setcol[]を４つ用意しました．)
- pop,pushは一時的にスタイルや変換の設定を変更し，その後で元に戻すときに使われますが，今回のプログラムではずっと同じスタイルで描画していることと，stroke()を使用して明示的に色を設定しているため削除．参考[Reference push()](https://p5js.org/reference/#/p5/push)
- for文の中でx,yの計算を行う．(座標の計算過程がわかりやすくなった．)
- circle(0,0,d)に描画座標(x,y)を指定する(よってtranslate()は不要)
以上です．コメントいただきありがとうございました😃
```js
const w=720;
const N=10;
const d=w/N;
const setcol=[]
setcol[0]=["#FFD700", "#32CD32", "#FF69B4"];
setcol[1]=["#00CED1", "#20B2AA", "#FF4500"];
setcol[2]=["#8B4513", "#FF6347", "#FFDEAD"];
setcol[3]=["#ADD8E6", "#FFFFFF", "#4682B4"];


function setup() {
  createCanvas(w, w);
  ellipseMode(CORNER);
  noFill();
  strokeWeight(d/20);
  col = random(setcol);
	noLoop();
}

function draw() {
	background(col[0])
	stroke(col[1]); 
	for (let x = 0; x < d * N; x += d) {
		for (let y = 0; y < d * N; y += d) {
			circle(x, y, d);
		}
	}
	stroke(col[2]);
	for(let x = -d/2; x < d * (N + 1); x += d){
		for(let y = -d/2; y < d * (N + 1); y += d){
    	circle(x, y, d);	
		}
	}
}
```

また，```const setcol=[]```でいくつかの色を用意しているので実行するたびに模様の配色が変わります．

縦と横で走査するために二重ループを使っているのがポイントで，１つの模様を繰り返し表示するように書けば簡単にいくらでも描画できるんですね．
先の余談で書いたプログラムもそうでした．

GIMPでも，１つの模様を小さく作ってそれをひたすらコピペしていたことを思い出しました．


# さいごに
というわけで，p5.jsを使って伝統模様を描いてみた話でした．
あと何個か違う模様を描画してみつつ，音の可視化についても書いてみようと思います．

プログラムを使って絵を描くというのは面白いですね．今回は幾何模様を扱いましたが，一見ルールがないように見られるような模様の描画もやってみたいです．

以上．
ここまで読んでいただきありがとうございました．ふじえもん．<img width="15px" alt="ふじえもんのアイコン" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2686406/ca3ab555-fea3-4a70-458d-7cd48b5c9f88.png">