Wizard Notes

Python, JavaScript を使った音楽信号分析の技術録、作曲活動に関する雑記

魔法円の自動生成プログラム:概要と基本概形の生成

開発の動機と方針

魔術に関連する創作の際に、音源用アートワークやWebサイトや動画の素材として、様々なデザインの魔法円を一瞬で大量生成したいと思ってました。
また、魔法円を制作する際に、事前にどんな図形を使ってデザインするのがいいのか検討する材料(制作支援)できるツールがあれば便利だと思い、開発を行っています。

最近はディープラーニングでの深層生成モデルによる画像の自動生成が流行ってますが、魔法円のような幾何学的な作品(図形と記号・テキストの組み合わせ)ならば古典的なルールベースのほうが開発が楽・生成処理が高速であり、開発者・利用者ともに制御しやすいと思い、processing.jsを使って実装してみました。

先行事例

https://codepen.io/SomnusHermeticus/pen/zngtJcodepen.io

CSSの属性を操作し、特定の図形やテキスト、記号をある程度決められた位置にランダムに表示しているようです。
具体的には、以下の要素の組み合わせで魔法円を自動生成しています。

  • 図形:円、正方形、正三角形
  • テキスト:ラテン語テキスト、3カテゴリ用意(長いテキスト、短いテキスト、単語)
  • 記号:Unicodeの錬金術記号を利用 (コメントの"symbols goes from 128768 to 128883"より)

f:id:Kurene:20181021172220p:plain
Magic Circles Generator - A PEN BY Didier

開発方針

いきなり複雑な魔法円の生成は難しいので、実際に魔法円を作成する工程を大まかにモデル化し、以下の3段階に分けます。

  1. 基本概形の生成
    • 基礎的な図形(円、星型多角形など)の組み合わせ生成
  2. 意味の付加および多様化
    • テキスト・記号、複雑な図形の追加
  3. 装飾
    • シェーダーなどの画像効果
    • 細かい書き込み(テクスチャ)の追加

以下では、魔法円生成の基礎となる1.の部分の概要を記載します。
この辺は、次の紹介記事を読んでモデル化してみました。

www.pixivision.net

魔法円の基本概形の自動生成

基本的なデザインの決定

基礎的な図形の組み合わせといえども、そのパターンは無数にあります。
そのため、あらかじめ魔法円の概形を少数パラメタでモデル化します。つまり、単純にランダムに図形を表示するのではなく、あらかじめ表示する形状・位置を限定すると魔法円らしいものが生成されます。

今回は以下のようにモデル化しました。

  • 大きさの異なる2つの輪から成り立ち、中心に円を備える。
    • 直径Outer ring, Inner ringの大きい順に、, Center circleと呼ぶことにする
  • Outer ringの円周上、Inner ringの内側には小さなRingが生成される。
    • それぞれOuter child-ring, Inner child-ringと呼ぶことにする。
    • このRingは0個~N個ランダムに生成される。
  • これら4つのRingの内部には、星型多角形などの星っぽい図形がランダムに生成される。これをStar-shapeと呼ぶ。

CircleではなくRingとしたのは、後の工程でテキストを書きこむスペースを作るためです。Ring自体は少しだけ直径差が円を2つ描くことで実現しています。

なお、Inner Ringの内部を塗り潰しをするか否かでも見た目の印象は結構変わります
f:id:Kurene:20181021172828p:plain

描写手順

  1. Outer ringと、その内部のStar-shapeを描写する
  2. Outer child-ringと、その内部のStar-shapeを描写する
  3. Inner ringと、その内部のStar-shapeを描写する
  4. Inner child-ringと、その内部のStar-shapeを描写する
  5. Center circle (Ring)を描写する

以上のモデル化の嬉しいところは、以下の2つの関数の組み合わせで魔法円を描画できるところです。

  • draw_ring(中心座標,直径)
  • draw_star_shape(中心座標,直径)

ランダム要素の追加

六芒星だったり八芒星だったり、多様な魔法円を生成するには上の2つの関数にパラメタを追加する必要があります。

今回の実装では以下のパラメタを導入しました。

  • Ring
    • 内部塗りつぶしのOn/Off
  • Child-ring
    • 個数
  • Star-shape
    • 頂点数
    • 形状(頂点間に線を引くか、楕円を描くか)

乱数はMath.random()でもいいのですが、ランダム要素によっては乱数のデザインとして正規分布や片側正規分布べき分布を使うと何となく良くなります。

今回は、Star-shapeは頂点数が多いほど出現頻度を下げてたかったため、片側正規分布を用いております。
正規分布についてはボックスミュラーなどで実装してもよいのですが、(Math.random()+Math.random()+Math.random())/3.0のような方法で十分です。

togetter.com

まとめ

魔法円の自動生成に関する開発方針と、基本概形の自動生成についての概要について説明しました

後日、テキストの埋め込みと複雑な図形の生成か、具体的なProcessing.jsのコード解説をしたいと思ってます。

おまけ

カラフルにするとお祭りの夜の屋台感があります。
f:id:Kurene:20181021174033p:plain

※2018/10/21にBloggerより転載