週に一回は書きますよ 月に4つ記事を書けばノルマは満たされます。
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

前編があります。 前回は gnuplotが出てこないところできってしまいました。 今回はがんがん出てくるのでご安心ください。

画像に出て欲しい情報は次のとおりです。

  1. 鏡の中の人
  2. 鏡の中の鏡
  3. 反射経路、鏡の中の像がどこの像から反転されたかを示す、 鏡によって垂直二等分される線
  4. 視線すなわち像と人とを結ぶ線。視線が所定の鏡の像と交差していれば像は見える。

これらをgnuplotで表示します。gnuplotへはどう情報を渡せばよいでしょうか。 今度はgnuplotの座標指定方法とスタイル一覧を見ます。 gnuplot tipsを参考にしました。以下、このサイトへ多くのリンクを張ります。

まず、目的の絵を描く方法を確認するためにスタイルを決めます。 スタイルは点を打つとか線を引くとかということです。スタイル一覧を参考に。

人と像は点なのでpointsでかまいません。反射経路は折れ線になるので、linesで表現できます。鏡と視線はつながった折れ線にならなかったので、vectorsで対応しました。vectors noheadとすると矢印のない線分がかけるので、これを使いました。

ひとつの図の中に、点や線分など複数の情報を入れる必要があります。複数のグラフを描くならmultiplot と一瞬思いました。しかしこれはフェイクです。 plot (人の座標) w p, (鏡の座標) w vectors, (視線の座標) w vectors のようにplotコマンドに複数の情報を並べて書けば十分です。

データごとにスタイルを変えたいので、逆にスタイルごとにデータを分けました。 一つのファイルに入った複数のデータをプロットするには?を参考に、indexを使うことにしました。そのためデータはそのスタイルごとにまとめて、スタイルの変わるところは改行二つで区切ることにしました。 この方法だと、たとえば像が見えないなどで偶然そのスタイルを使うデータがなかったときに、indexがずれてしまうという欠点が後に見つかりましたが。

以上でgnuplotの情報はすべて確認できました。

使うスタイルを決めると、スタイルの要求する形式に合わせてデータ出力コードを書きます。 像ならx座標 y座標をスペースで区切って一行に並べればよいです。 折れ線も、折れ線の通過する順番に行を並べるほかは、像と同じくx座標 y座標と書いておけばよいです。 鏡のための線分は、x1 y1 x2 y2を空白で区切って一行で出しました。 これらのデータは、入力ケースごとにひとつのファイルに出力することにしました。

最後に、座標データををgnuplotで画像に変換するコードを書きます。この部分はperlに手伝ってもらいました。 複数の入力ケースが存在するため、ケースごとにひとつの画像を作ったほうが便利です。 複数の画像を作るには当然同じ作業を繰り返さないといけませんが、gnuplotは繰り返しが得意でない、正確にはgnuplotに繰り返し作業をさせる方法を私がよく知らないので、ここの部分はperlに手伝ってもらい、入力されたファイルの個数分の長さのスクリプトを作りました。

具体的なperl scriptを載せます。

print "set term post eps enh color\n";
linestyle();
for ($num=1 ; $num<=134 ; ++$num ) {          # # of images is 134
    $f = "graph-$num.dat";                     # coordinate data file name
    $image=sprintf 'eps\\mirror%03d.eps',$num; # output image file name
    hoge();
}
sub linestyle{
print<<"END_OF_HEAD";
set style line 1 lt 1 lw 4
set style line 2 lt 2 lw 4
set style line 3 lt 1 lw 1
set style line 4 lt 2 lw 1
set style line 5 lt 0 lw 1
set style line 6 lt 3 lw 1
set size ratio -1
END_OF_HEAD
}
sub hoge{
print << "END_OF_PLOT";
set out '$image'
plot '$f' index 0 notitle w p pt 1 pointsize 4,\\
'' index 6 notitle w p pt 2 pointsize 2,\\
'' index 1 using 1:2:(\$3-\$1):(\$4-\$2) notitle w vectors nohead ls 1,\\
'' index 2 using 1:2:(\$3-\$1):(\$4-\$2) notitle w vectors nohead ls 2,\\
'' index 3 using 1:2:(\$3-\$1):(\$4-\$2) notitle w vectors nohead ls 3,\\
'' index 4 using 1:2:(\$3-\$1):(\$4-\$2) notitle w vectors nohead ls 4,\\
'' index 5 notitle w l ls 5,\\
'' index 7 using 1:2:(\$3-\$1):(\$4-\$2) notitle w vectors nohead ls 6
END_OF_PLOT
}
こんな感じになります。上のほうは繰り返しとファイル名指定、sub linestyleのところは線や画像のサイズの決定、sub hogeのところがプロットコマンドです。 画像サイズのところで、set size ratio -1とあるのは、xyの縮尺を同じにするという指定です。これをしないと直角が直角に見えなくなるので、ちゃんと反射しているように見えません。 プロットの部分、index ~の部分は実際のデータを見ないと意味不明でしょうが、上から人、見える像、鏡1、鏡2、鏡1の像、鏡2の像、反射の経路を示す線、視線となります。

with vectorsで描画するところには謎のusing指定が入っています。これはvectorsの指定が(x,y,dx,dy)だったのに、私は間違えて(x1,y1,x2,y2)としてしまったので、それを修正するために(x1,y1,x2-x1,y2-x1)と書いたのです。using指定のところは括弧でくくってこのような式を書くことができ、その際$1,$2などと書くことで1,2カラム目の値を参照することができます。ただし$文字はperlの変数開始文字になってしまっているので、バックスラッシュでエスケープしています。

この作業によって、プログラムが何をしているかよくわかるようになりました。 目で確認することによって、どのような位置の像を見逃しているかわかり、 デバッグが驚くほど早くなったのです。

可視化は問題作成に貢献しましたが、それらはほとんどほかの人には見えません。 なんだかもったいないですね。 ということで、解説pptに可視化画像を大量に張り込みました。 解説とかまじめに書いてなくてすみませんね。


追補編を書きました。
スポンサーサイト
コメント
この記事へのコメント
コメントを投稿する
URL:
Comment:
Pass:
秘密: 管理者にだけ表示を許可する
 
トラックバック
この記事のトラックバックURL
http://gusmachine.blog49.fc2.com/tb.php/149-1cb584a7
この記事にトラックバックする(FC2ブログユーザー)
この記事へのトラックバック
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。