ライフゲーム #13

さて、ノードのpos属性をピン留めする方向に進むか否かについて考えてみよう。
ピン留めしていない現在のグラフでは各ノードのpos属性の値は1単位で整数値を与えられている。
ピン留めされていないため、neatoのオプションで、

neato ...snip... -Nwidth=.2 -Nheight=.2 ...snip... -Elen=.3 ...snip

のようにノードの幅や高さ、エッジの長さなどにpos属性の値とは整合しない実際のサイズが指定されると、
それに合わせてノードの位置を調整してくれる。つまり、pos属性は相対的な参考値として使われることになる。
しかし、pos属性をピン留めすると話は変わる。
以下は、#10でサイズを小さめにする前の第0世代の画像を作成するときに、
pos属性の値に!を付けてピン留めを指示した場合である。
vis_alive.gでpos属性を付加したものを、さらにgvprでフィルタして!を付加してから画像化している。

c:\foo> gvpr -cf vis_alive.g glider_0.gv | gvpr -c "N{pos=sprintf('%s!',pos);}" | neato -Gsize=5.40625 -Nlabel="" -Nshape=box -Nwidth=.2 -Nheight=.2 -Ncolor=slategrey -Nfillcolor=blue -Estyle=invis -T png -o glider_0.png

neatoに与えるオプションは#10と基本的に同じである。
ただし、エッジ長を与える-Elen=.3はノード位置に影響を与えないし、
スタイルがinvisなのでどう描画されるかを気にしなくていいので指定していない。
もちろん、指定しても結果は変わらない。
また、できあがる画像のサイズがとても大きくなるので-Gsize=5.40625でサイズを#10のものに合わせてある。

ノードの大きさが極端に小さくなっているのは、
pos属性でのノード位置が1単位なのに対してノードの大きさが0.2になっているからである。
つまりピン留めによって、しなかった時のような適宜調整などというものはしてくれなくなる。
ただし、ノードの配置は#10の場合と異なり、歪みなくきちんと格子状になっていることが分かる。
もし、位置とサイズの整合性を取ろうとするなら、ノードサイズに合わせてpos属性の値を変更するか、
逆にノードサイズの方をposに合わせて変更するかする必要がある。
pos属性を1単位の整数値のままにするなら画像サイズがかなり大きいものとなるので、
最終的な画像化の際、もしくは画像化後にサイズ調整を行う必要があるだろう。
ここでは、pos属性の方をノードサイズに合わせてみる。

c:\foo> gvpr -cf vis_alive.g glider_0.gv | gvpr -c "N{pos=sprintf('%f,%f!',xOf(pos)*0.27,yOf(pos)*0.27);}" | neato -Nlabel="" -Nshape=box -Nwidth=.2 -Nheight=.2 -Ncolor=slategrey -Nfillcolor=blue -Estyle=invis -T png -o glider_0.png

"x,y"の形式の文字列からxとyを取り出すにはxOf(), yOf()という便利組み込み関数が用意されている。
pos属性の方を合わせたのでneatoの方の-Gsizeは不要になる。

歪みがなくノード間距離とノードサイズとのアンマッチもないものが得られた。
こういう結果が得られると、メッシュサイズ次第でどういう風に歪みが現れるか分からないピン留め無しよりも、
pos属性をきちんとピン留めしたほうがいいのかもしれない。

以上の議論のうち、cmdとbashとの表現の差で注意する点がある。
gvprのワンライナを打つ時に、bashでは'%s!''%f,%f!'はコマンド履歴機能が働くので、
'%s\!''%f,%f\!'のように!をエスケープしてやらないと、そんな履歴は無いと怒られる*1

*1:もしくはそんな実在の履歴に置き換えられ思ってもみない動作を…