気を散らすノート

色々と散った気をまとめておくところ.論文読んだり自分で遊んだりする.たぶん.

2019年の年賀状

じぶん advent calendar 2019, 7日目の記事です.

そろそろ年末ですね.未だに紙の年賀状を送るのがやっぱり好きで,ちょくちょく友人などに送りつけて年一度の友誼をつないだりしています.とはいえ絵心などはもとよりなくて,最近は幾何学的な方向にシフト中.今年(昨年に作った)のはこれ.

f:id:lesguillemets:20191206235159j:plain:h400
謹賀新年 印刷すると端の印刷幅の関係でもうちょっとバランスが整う

亀甲柄に松葉という趣向なのですが,これは旅行でいった輪島で塗り物の柄として見かけたのを参考にしたものです.お重(ひゃくまんえんくらいする)でしたが,黒字に沈金で松葉をあしらっててめちゃくちゃきれい.輪島は手の届きうるものからお宝まで,最近の売り物から蔵から出てきた江戸時代の品で非売品だけど展示だけしてるってものまで,たくさんの塗りが店頭に並んでいて本当に良かった.萩に比べるとごはん屋さんとかが充実してて観光客に優しいのもポイント高いです.

閑話休題.昨年は年末にちょっとばたばたしてたのもあって,vanilla の javascriptcanvas に絵を描いて,それを .png として上に字とかを足すという形で作成しました.ごく単純なお絵かきをするには,案外シンプルで使いやすいのです.1 はじめは黄色で松の実をいくつか描き添えていたのですが,手描きだと出せる揺れの味を出すのが難しくて,結局そこはコードで書くのは断念して,印刷後のはがきにペンで書き足す形になりました(上の画像に入ってるのはここに上げる用に gimp で描いたもの.)

方針として非自明なのは (i) 松葉を置くところと空白にするところの選び方 と (ii) 六角形の中の松葉のちらし方 です.前者は単にいろいろ試して手で選び,後者はなにか賢いやり方を考えようと思ったら単に角度についてランダム(0-2π の一様乱数)で試したところうまく行ってしまったのでそのまま,というので, clever なところは何もなく作ってしまったものです.

昨年末にぱっと書いたコードのリファクタをいまさらするのもアレなのでそのまま載せてしまいます.

var rBase = 200;
var leaves =  64;
var hexaWidth = rBase * Math.sqrt(3);

// starting point
var x0 = rBase*1.8;
var y0 = rBase*1.1;
var matsuba = "#1b3303";
var lighter_matsuba = "#53772f";
var weak = "#edda90";
var lighter_weak = "#f8ff93";
// この辺は,松の実を書こうとしてたのの名残(結局手書きにした)
var seed = "#845607";
var seed_distance = rBase * 0.3;
var seed_size = rBase * 0.1;

/// x, y : int
function centreAt(x, y) {
    var shift = (y % 2 === 0) ? 0 : -hexaWidth / 2;
    return [x0 + x * hexaWidth + shift,  y0+ y* (rBase * 3 / 2 )];
}


function draw_pine_at( x, y, ctx ){
    var centre = centreAt(x,y);
    // ctx.strokeStyle = matsuba;
    ctx.lineWidth = 5;
    ctx.beginPath();
    for (var t=0; t < leaves; t++) {
        var θ = 2 * Math.PI * Math.random(); // radian
        var r = hexaWidth  / (2* Math. cos( Math.PI / 6 - ( θ % (Math.PI / 3) ) ) );
        ctx.moveTo( centre[0], centre[1] );
        ctx.lineTo( centre[0] + r* Math.sin(θ),
                    centre[1] + r* Math.cos(θ)
                    );
    }
    ctx.stroke();
    ctx.closePath();
}


function main() {
    var cnv = document.getElementById('world');
    var ctx = cnv.getContext('2d');
    var points = [
        [0,0], [0,1], [0,2], [0,3], [0,4], [0,5],
        [1,1], [1,2], [1,3], [1,4], [1,5], [1,6],
        [2,0], [2,1], [2,2],               [2,5],
        [3,1], [3,2],
        [4,0], [4,1],
                                           [5,6],
                                           [6,5],
                                    [7,5], [7,6],
                             [8,3], [8,4], [8,5],
                             [9,2], [9,3], [9,4],
    ];
    var vacants = [
                             [2,3], [2,4],
                             [3,3], [3,4],[3,5],
                      [4,2], [4,3], [4,4],[4,5],
               [5,1], [5,2], [5,3], [5,4],[5,5], 
        [6,0], [6,1], [6,2], [6,3], [6,4],
               [7,1], [7,2], [7,3], [7,4],
        [8,1], [8,2],
    ];
    ctx.strokeStyle = lighter_matsuba;
    for (point of points) {
        draw_pine_at( point[1], point[0], ctx );
    }
}
window.addEventListener('load', main);
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <script src="./main.js"></script>
  <link rel="stylesheet" href="./common.css">
</head>
<body>
  <canvas id="world" width=3000 height=3000></canvas>
</body>
</html>

というわけで年賀状の柄の話でした.今年はどうしようかな(まだ何も思いついていない).

ちなみに,その一つ前 2018年の年賀状は,気分転換の必要があったのと時間があったので(国家試験を控えてましたが) Clojure+quil (processing.js 的な)で作成しました.この柄については年明けに,当時その速さで話題をさらった dev.to で記事にしてます


  1. 本来 Haskell+Diagrams とかがこういうのには強いはずなんだけど,どうもあのライブラリのAPIに馴染めないままでいる.