not good but great

プログラミング、アート、映画・本の感想について書きます。

Canvasで着物の柄である「毘沙門亀甲」を描画する

Canvasで遊ぶことが多いのだけれど、もう少し数学を使って描画やアニメーションをつくればおもしろいものができると考えていた。そこで図書館で見つけたこの紋様の本を借りた。これは昔の家紋や着物の模様を数学で説明している。その説明が難解で、結局読んだ意味はなかったのだけれど、いろいろ紋様が紹介されていて、参考にはなった。

See the Pen Bishamon-Kikko Pattern by naoyashiga (@naoyashiga) on CodePen

そのなかで「毘沙門亀甲」の紋様が目に止まり、描画することにした。

・参考
毘沙門亀甲 - Google 検索

毘沙門亀甲の一つのパーツを描画する

最初は六角形隙間なく並べて、いらない辺を消去しようとしたけど、辺を消去する条件を分けるのが煩雑になりやめた。だから一つのパーツを描画する関数を作って、それの並べ方を工夫する手法をとった。

f:id:naoyashiga:20131113150958p:plain
一つのパーツとは上の下手くそな絵にある、3つの六角形を合体させたものだ。赤い点線は本来、描画される線だけど、消去している。

毘沙門オブジェクトを用意

bishamon = {
	    size: 20,
	    xCenter: 0,
	    yCenter: 0,
	    lineWidth: 10,
	    arrowWidth: 8,
	    arrowColor: "#080808"
},
プロパティ名 内容
size 六角形の一辺の長さ
xCenter パーツの中心のx座標
yCenter パーツの中心のy座標
lineWidth 辺の太さ
arrowWidth パーツ内部の線の太さ
arrowColor パーツ内部の線の色

f:id:naoyashiga:20131113151912p:plain
青い線がパーツ内部の線(arrow)。ピンクの点がパーツの中心だ。

f:id:naoyashiga:20131113152502p:plain

bishamon.xMargin = bishamon.size * Math.cos(2 * Math.PI / 12);

xMarginというプロパティも用意する。これは緑の線の長さ。

上の六角形を描画する

//move to top side hexagon center
ctx.moveTo(bishamon.xCenter, bishamon.yCenter - bishamon.size);

上の六角形の中心に移動

//line top side hexagon
for(var k = 0;k <= 6;k++){
	theta = (k * 2 * Math.PI / 6) - 2 * Math.PI / 12;
	ctx.lineTo(bishamon.xCenter + bishamon.size * Math.cos(theta),
		bishamon.yCenter + bishamon.size * Math.sin(theta));
}

右下、左下の六角形も同様に、各六角形の中心に移動して描画する。

必要のない線を消去する

CanvasにclearLineはないので、clearRectするしかない。しかしこれは透明になって後から、背景色で描画しないといけないので面倒くさい。それに斜めに四角を描画するのは回転を考えないといけないので大変。だから背景色の線を重ねることにした。

    //clear inside three lines
	    ctx.save();
	    ctx.beginPath();
	    bishamon.xCenter += bishamon.xMargin;
	    bishamon.yCenter -= bishamon.size / 2;
	    ctx.moveTo(bishamon.xCenter, bishamon.yCenter);
	    ctx.lineTo(bishamon.xCenter, bishamon.yCenter + bishamon.size);

	    ctx.moveTo(bishamon.xCenter, bishamon.yCenter);
	    ctx.lineTo(bishamon.xCenter - bishamon.xMargin, bishamon.yCenter - bishamon.size / 2);

	    ctx.moveTo(bishamon.xCenter, bishamon.yCenter);
	    ctx.lineTo(bishamon.xCenter + bishamon.xMargin, bishamon.yCenter - bishamon.size / 2);


	    ctx.strokeStyle = backgroundColor;
	    ctx.lineWidth = line.w * 1.5;
	    ctx.stroke();
	    ctx.closePath();
	    ctx.restore();

lineCapに三角はない

内部の線の先端を、六角形と同様に120度の角の三角形で描画したかった。三角形の塗りつぶしは線で囲って、fillする。上部の六角形の内部の線はそれで実装できた。しかし右下、左下は線に角度が着いており、計算がややこしく挫折したw

だから妥協案として、先端は四角にすることにした。



他の詳しい処理はソースを見てほしい。煩雑な処理が多くて、Canvasでゴリゴリ幾何の計算をするのはもう嫌だ・・・。