読者です 読者をやめる 読者になる 読者になる

TeX Alchemist Online

TeX を使って化学のお仕事をしています。

☃ゆきだるまで素因数分解を可視化しよう!☃

TikZ TeX 数学

この記事は TeX & LaTeX Advent Calendar 2015 の23日目の記事です。16日目に次いで2回目のエントリーとなります。 22日目はu_riboさんでした。 24日目はgolden_luckyさんです。

本記事では,ゆきだるま☃を用いて素因数分解を次のように可視化する方法を解説します。

f:id:doraTeX:20151223163106g:plain

目次

元ネタ

元ネタは,以下の記事で作られた素因数分解ダイアグラムです。

次の記事では,それがカラフルに着色されるとともに,デジタル時計のようなインタラクティブなダンスアニメーションが実現されています。

本記事では,これを TeX + TikZ + ゆきだるま☃ で実現します。

実現に向けての課題

このアニメーションを作成するための課題を,次のように5つのステップに分割して考えましょう。

  1. TeX による素因数分解の実行
  2. ゆきだるま☃の配置の決定
  3. ゆきだるま☃の描画
  4. ゆきだるま☃の色の決定
  5. アニメーションの生成

ステップ1: TeX による素因数分解の実行

「TeX による素因数分解の実行」というのは,定番のネタでありましょう。3年前には,次のような詳細な作り方の解説記事がありました。

d.hatena.ne.jp

最近では,昨年末に次のような「素数デマ」を検証するために TeX が活躍した事例がありました。

この事件のとき,「素数デマから身を守る方法」として様々な方法が挙げられましたが,その中に TeX による防御策も含まれていました。

今回は,

  • 2から順に割ってゆき,最小の素因数を探す
  • 商が1でない場合は,その商に対して再帰的に同じ手順を繰り返す

という素朴な方法で実装することにしました。→ 実装例

\Factorize{20141231}
\Factorize{20150101}

f:id:doraTeX:20151223121317p:plain

ちなみに,一昨日は素数デーでした。今日は,素数ではありませんが比較的大きな素因数2個だけの積になっています。

\Factorize{20151221}
\Factorize{20151223}

f:id:doraTeX:20151223121427p:plain

今年の年末年始は,比較的小さな素因数を持ってしまっています。

\Factorize{20151231}
\Factorize{20160101}

f:id:doraTeX:20151223121435p:plain

ステップ2: ゆきだるま☃の配置の決定

$n$が与えられたときのゆきだるま☃を配置する座標は,次のように決定します。

  1. $n$ の最大の素因数を $p$,大円の半径を $R$ とし,$\theta = \frac{\pi}{p}$ とする。
  2. $\sin\theta = \frac{r}{R-r}$ なる $r$ をとる。つまり $r= \frac{\sin\theta}{1+\sin\theta} R$ とする。
  3. 半径 $R$ の大円の中に,半径 $r$ の小円 $p$ 個を内接させる。
  4. $n$ を $p$ で割った商 $q$ が 1 であれば,各小円の中心にゆきだるま☃を置く。
  5. $q$ が 1 でない場合は,各小円に対して $q$ を与えて,以上の手順を再帰的に繰り返す。

例えば,$n=11$ の場合はこのような形になります。

f:id:doraTeX:20151223134745p:plain

$n=75=5\times 5\times 3$ の場合はこのような形になります。

f:id:doraTeX:20151223135141p:plain

ステップ3: ゆきだるま☃の描画

TeX によるゆきだるま☃の描画と言えば,TeX & LaTeX Advent Calendar 2015 の13日目に発表された,scsnowman パッケージが決定版ですね!

ステップ4: ゆきだるま☃の色の決定

出力される多量のゆきだるま☃に,綺麗なグラデーションで色づけましょう。全部で n 体のゆきだるま☃が丸く出力されるので,色相環を n 等分して,各ゆきだるま☃にそれらの色を割り当てるとよいでしょう。

TeX & LaTeX Advent Calendar 2015 の10日目に解説があった xcolor パッケージであれば,HSBカラーモデルをサポートしています。

そこで,k番目のゆきだるま☃の色は,

\definecolor{k番目の色}{hsb}{0〜1をn等分したときのk番目の値,1,1}

のように定義すればよいでしょう。指定色によるゆきだるま☃の着色は,scsnowman パッケージにその機能があるので利用します。

仕上げ ― パラパラ漫画状PDFの完成

こうして完成したのが次のソースです。*1

www.overleaf.com

ステップ5: アニメーションの生成

TeX で作ったパラパラ漫画状のPDFをアニメーションにするには,いくつかの選択肢があります。

  • アニメーションGIF
  • SMIL を利用したSVGによるベクターグラフィックスアニメーション
  • PDFから動画ファイルを生成する

拙作の TeX2img は,TeXソースまたはPDFから,アニメーションGIFやアニメーションSVGを生成する機能を持っています。TeX2img を使って生成したものがこちらです。

アニメーションGIF

f:id:doraTeX:20151223144707g:plain

いかがでしょう。賑やかでクリスマスっぽいですね……!

このアニメーションは,TeX2img によってPDFからアニメーションGIFに変換したものです。GUI版ならば,

  • 外部ファイル入力機能で,上記ソースで生成したPDFを指定する。
  • 出力ファイルの拡張子を gif に指定。
  • 背景色を白に指定し,「透過」のチェックを解除。
  • 「元のページサイズを維持する」にチェック。
  • 「単一ファイルまたはアニメを生成」にチェック。

とすればよいでしょう。

f:id:doraTeX:20151223144541p:plain

ここでは,CUI版の TeX2img(Mac版 Ver. 2.1.4)を用いて,次のパラメータで変換しました。

$ tex2img --resolution 5 \
    --keep-page-size \
    --no-transparent \
    --merge-output-files \
    --animation-delay 1 \
    snowmen.pdf snowmen.gif

アニメーションSVG

次に,TeX2img によってアニメーションSVGを生成した例です。

アニメーションSVGの場合,ベクターグラフィックスなので,拡大してもどこまでも綺麗なゆきだるま☃が出力されて美しいです。

これは,CUI版の TeX2img(Mac版 Ver. 2.1.4)を用いて,次のパラメータで変換しました。

$ tex2img --keep-page-size \
    --no-transparent \
    --delete-display-size \
    --merge-output-files \
    --animation-delay 1 \
    snowmen.pdf snowmen.svg

その後,gzip で圧縮をかけてSVGZ形式に変換してあります。

$ gzip -cfq9 snowmen.svg > snowmen.svgz

できあがったSVGZファイルをHTML文書中に貼り込むには,次のようなHTMLを書くのがお勧めです。

<div style="position:relative; padding-bottom:100%; padding-top:0; height:0; overflow:hidden;">
<embed src="SVGZファイルのURL" type="image/svg+xml" style="position:absolute; top:0; left:0; width:100%; height:100%;" />
</div>

このCSSは,SVGZ画像を横幅いっぱいにスケールして表示するためのものです。例えばこのはてなブログの場合,PCから閲覧する場合とスマートフォンから閲覧する場合で横幅が異なるレスポンシブデザインになっていますが,そのような場合にも対応できます。

なお,SVGZファイルを設置するサーバについては,SVGZファイルが次のHTTPヘッダを伴って送信されるように設定されていなければなりません。

Content-Type: image/svg+xml
Content-Encoding: gzip

Webサーバに Apache を使っているレンタルサーバで,.htaccess を自分で設置できる場合は,.htaccess に次のように書いておくことで,そのように設定できます。

AddType image/svg+xml svg svgz
AddEncoding gzip svgz

SVGZ形式のサーバ設定の詳細はこちらのサイトが参考になります。

動画

以前の連成振動アニメ-ションのときと同様に,次のように ImageMagick と FFmpeg を用いることで,mp4動画を生成できます。

$ convert -debug all -alpha deactivate \
    -density 300x300 -resize 800x \
    snowmen.pdf snowmen.png
$ ffmpeg -r 1 -i snowmen-%d.png \
    -c:v libx264 -pix_fmt yuv420p \
    snowmen.mp4

これを YouTube に投稿するとこのようになります。


おわりに

Merry Christmas! Happy TeXing!

*1:素因数 $p=2$ の描画が単調な直線状になってしまうのを防ぐため,実際の実装では素因数 $p=2$ の場合の描画だけ例外扱いして90度回しています。