Friday 5 April 2013

gnuplot (5)


現実逃避が捗りすぎて基本的に何見てもつらい.(?)

今回のお題は animated gif です.
gnuplot を使って直接 animated gif を作ることができるらしいので,では,ということで.
印刷はできないのが残念ですが,見てて楽しいものができそう.
というわけでanimated gif 自体の作り方と, gnuplot で繰り返しを扱う1つの方法の一端について.

今回は主に Gnuplot surprising: Creating gif animation using gnuplotを参照しました.
僕のに今入ってるのは gnuplot 4.4 patchlevel 3 なので,
リンク先で紹介されている「新しいやり方」は使えません.

--1-- gif

gif:

 Syntax:
       set terminal gif 
              {{no}transparent} {rounded|butt}
              {linewidth <lw>} {dashlength <dl>}
              {tiny | small | medium | large | giant}
              {font "<face> {,<pointsize>}"} {{no}enhanced}
              {size <x>,<y>} {{no}crop}
              {animate {delay <d>} {loop <n>} {{no}optimize}}
              {<background_color>}

今回関係するのは animate の部分.説明を抜粋すると

 The `animate` option is available only if your local gd library supports the creation of animated gifs. The default delay between display of successive images may be specified in units of 1/100 second (default 5).
 The actual delay may vary depending on the program used as a viewer.
 Number of animation loops can be specified, default 0 means infinity.
 An animation sequence is terminated by the next `set output` or `set term` command.  The `optimize` option has two effects on the animation.
 1) A single color map is used for the entire animation. This requires
 that all colors used in any frame of the animation are already
 defined in the first frame.
 2) If possible, only the portions of a frame that differ from the
 previous frame are stored in the animation file.  This space saving
 may not be possible if the animation uses transparency.
 要するに
  • animate オプションはお使いのPCに入ってるものによっては使えへんこともあるよ
  • フレームの間の時間は 1/100 秒刻みで指定できるよ (delay n で指定)
    • デフォルトは 5 (5/100 秒)だよ
    • まあいうて実際どう表示されるかは viewer によって決まるよ
  • ループ回数も指定できるよ
    • デフォルトは 0 で無限回っていう意味だよ
  • 次に set output とか set term(inal) とかした時にアニメーションの生成は終わるよ
  •  optimize っていうオプションがあってこれをつけると
    • アニメーション全体で color map を1種類しか使わないよ:その後出てくる色は全部一枚目に出てこないといけないよ
    • 可能なら差分だけデータとして保存するよ.透明色があるとうまく行かないかもしれない 
という感じですね.set term gif animate で指定すると
delay 10 loop 0 nooptimize size 640,480  というオプションがついてきます.
たとえば

gnuplot> set term gif animate delay 50
gnuplot> set output "foo.gif"
gnuplot> set xrange [0:1]
gnuplot> set yrange [0:1]
gnuplot> plot x
gnuplot> replot x**2
gnuplot> replot x**3 
  ....
gnuplot> replot x**8
gnuplot> set term wxt

としてできたのがこちら.のはずだったのですが少しでも鬱陶しさがましかと思って

gnuplot> set term gif animate delay 50
gnuplot> replot x**8
gnuplot> plot x, x**2, x**3, x**4, x**5, x**6, x**7
gnuplot> plot x, x**2, x**3, x**4, x**5, x**6
    ...
gnuplot> plot x

としたものがこちら.
gif アニメーションは大体において鬱陶しくてあまり好きではないのです.
firefox ならページが読み込まれた状態で esc で止まるはず.他はよく知らない.
あと xrange, yrange (plot する範囲) の指定はちゃんとやらないと
コマごとに座標が動いて大変なことになったりします.


--2-- if, load, reread

gnuplot 自身に if 文は備わっているらしい.

if (<condition>) <command-line> [; else if (<condition>) ...; else ...]

ここで else if とか入れるなら最初の if と同じ行に書かないと別の塊と認識されて
  else without if
と怒られます.行末に \ を入れると次の行までつなげて解釈してくれます.

そして load と reread.
 load "file_name"  で指定のファイルを読み込み,そこに書かれたコマンドを順に実行してくれ,
reread はそのファイルをもう一度読み込むという命令になります.
というわけでGnuplot surprising: Creating gif animation using gnuplotに紹介されているように,
命令実行→条件(例えばステップ回数)がまだ満たされていないならもう一回
を繰り返してgif アニメーションが出来上がる,というわけ.


今回,カオスラボ 神話の翼を描く【カオスでCG】で紹介されているものを題材に
少し作ってみます.
(リンク先,たまに page not found になるみたい. fc2 blog なのですが,時々そういうことがあるみたいです.
表題でググると最初に出てくるのでその場合はそちらをご利用ください.)

これは,ある時点の点の座標 (x_{n}, y{n}) から次の時点の座標 (x_{n+1},y_{n+1})が与えられ,
それが動いていった点をプロットする,というかんじで(最終的な画像は)出来上がる.
というわけで,その点を順番に打っていくようにしてみましょう.
とはいえ数が多いので,
  • 100個くらいまでは1個づつ打っていく.
  • それ以降は画像に出てくる点の総数が直前の 1.1 倍とかになるようにいっぺんに打つ
    • 100 - 10000  では直前の1.1倍,それ以降は直前の 1.2 倍にしました.なんとなく.
ということにします.以下実際の工程

____

1. カオスラボで紹介されていたコードをそのままお借りして tsubasa.dat を作る.

2. tsubasa.plt を用意

k = int(i) # 1.1 倍とかにすると一般に i が整数にならないので
plot "./tsubasa.dat" every ::::k w dots lc rgb "blue"
if (i<100) i = i+1; else if (i<10000) i = i*1.1; else i = i * 1.2
if (i<n) reread

every のあたりはデータのどこを使うかの指定です.GNUPLOT memo の「間引いて plot」を参照.
every ::::k で k行目までを使え,ということ.(らしい.)
あと dots の色も lc (linecolor) で設定ってのが字面的に意外な感じがした.


3. plot
gnuplot を立ち上げて

gnuplot> set term gif dalay 2 optimize
gnuplot> set output "tsubasa.gif"
gnuplot> i = 0 
gnuplot> n = 100000 #全部で何個まで plot するか
gnuplot> set xrange[ : ] #事前に plot しておいて丁度いい値に.何使ったか忘れた
gnuplot> set yrange [ : ] 
gnuplot> load "./tsubasa.plt" #このあと少しかかる
gnuplot> set term wxt

で,できたのがこちら.綺麗.真っ白やん,と思ったら少し待ってください.



ちなみに optimize を付けないと 900kB 以上になってたのが,
optimize つけたら 254kB に収まりました.

再帰とかをうまく使うと gnuplot 単体でフラクタル図形がサクっとかけるようで,
やってみたいところですね.

No comments:

Post a Comment