はじめに
これは POV-Rayによる数学お絵かき入門 Advent Calendar 2017 の13日目の記事です.
povrayでは外部ファイルを読み込むためのコマンドが用意されています.
これによって他の言語で計算した結果を取り込んでPOV-Rayで可視化させる事が可能になります.
この具体例は第15回で見る予定です.
公式ドキュメントでは以下に相当しますが, 具体例に乏しいので今回に限ってはあまり参考にならないかもしれません.
http://www.povray.org/documentation/3.7.0/r3_3.html#r3_3_2_3
使い方
他の殆どのプログラミング言語のそれとは異なり, POV-Rayでは特定の形式のテキストファイルしか扱えません.
換言すれば, あまり自由度は高くないです.
読み込み可能な形式
次に外部ファイルに必要な要件を箇条書きで示します.
- ファイルはテキストファイルでカンマ
,
区切りされている必要があります. - 各要素は 数値 / ベクトル / 文字列 の何れかである必要があります.
- カンマ前後に改行やスペースなどの空白文字が含まれていても構いません.
- ただし次のような通常のcsvファイルは正常に読み込めません. これは行末にカンマが入っていないためです.
2,<4,0,0>,"hoge"
3,<8,0,0>,"fuga"
5,<0,1,1>,"piyo"
- 行末がカンマで終わるような形式であればこれは可能です.
2,<4,0,0>,"hoge",
3,<8,0,0>,"fuga",
5,<0,1,1>,"piyo"
- 拡張子は任意です.
構文
以下で#fopen
, #read
, defined
の使い方を説明します.
ファイルを開く
ファイルを開くには次のように#fopen
を使います.
ここでFILE_HANDLE_IDENTIFIER
にはファイルを扱うための識別子が, FILE_NAME
にはファイル名が入ります.
#fopen FILE_HANDLE_IDENTIFIER FILE_NAME read
最後のread
はファイルを読むための宣言です.
要素を読み込む
ファイルの要素を読み込むためには次のように#read
を使います.
ここでFILE_HANDLE_IDENTIFIER
は先程宣言したファイル識別子で, DATA_IDENTIFIER
には要素の読み込み先となる識別子が入ります.
#read(FILE_HANDLE_IDENTIFIER, DATA_IDENTIFIER1, ... , DATA_IDENTIFIERn)
POV-Rayでは最初の#read
でファイルの先頭の要素が読み込まれ, 続いて読み込まれる度に要素の読み込み位置が一つずつ下がっていきます.
つまり, 最初に#fopen
でファイルを開いた後は#read
を繰り返せば順々に要素が読み込まれていきます.
関数definedについて
さて, POV-Rayには識別子が定義されているかを調べるための関数defined
が用意されています.
このdefined
は識別子が宣言されていればtrue
を, 宣言されていなければfalse
を返します.
(第四回に見たように, POV-Rayでは真偽値は数値で表現されていたのでした)
ファイル識別子にこの関数を使えば, 読み込む要素が残っている場合にtrue
を, 残っていない場合にfalse
を返します.
これの有用性は後述の具体例で見ます.
ファイルを閉じる
レンダリング処理が終われば(正確には構文解析が終われば)ファイルは自動的に閉じられます.
#fclose
でファイルを閉じることも可能ですが, 基本的には使う必要はありません.
具体例
最初の例
次のコードを最初の例とします.
2,<4,0,0>,"hoge",
3,<8,0,0>,"fuga",
5,<0,1,1>,"piyo"
#fopen fuga "hoge.txt" read
#read(fuga,val1,vec1,str1)
#read(fuga,val2,vec2,str2)
#read(fuga,val3,vec3,str3)
この宣言によってval1
, val2
, val3
にそれぞれ2
, 3
, 5
が入ります.
ベクトル, 文字列についても同様です.
点列の描画
外部ファイルに書かれた複数の座標から, それらを中心とする複数の球面を描くには次のようにします.
<1,0,0>,<2,0,0>,<3,0,0>,<4,0,0>,<5,0,0>,
<0,1,0>,<0,2,0>,<0,3,0>,<0,4,0>,<0,5,0>,
<0,0,1>,<0,0,2>,<0,0,3>,<0,0,4>,<0,0,5>
#fopen fuga "hoge.txt" read
#while(defined(fuga))
#read(fuga,vec)
sphere{vec,0.1 pigment{rgb<1,0,0>}}
#end
このように, defined
を使うことで, 座標の書かれたテキストファイルから点列を描くことが出来ます.
これを応用すれば次のアニメーションを描くことが出来ます.
これはLorentzアトラクターのアニメーションで, 色々の初期条件からアトラクターに近づく様子を表しています.
注意点など
配列
#read
で読み込む際に配列の要素に書き込む, つまり次のように書くことは出来ません.
#read(fuga,ary[1])
配列に入れたい状況では, 次のように一時変数を利用します.
#read(fuga,tmp)
#declare ary[1]=tmp;
書き込み
書き込みのための#write
も用意されていますが, あまり使わないため今回は省略しました.
詳しくは上記の公式ドキュメントを参照して下さい.
(ひょっとすると改めて書くかもしれません)
ファイル読み込み vs インクルードファイル
筆者の場合はファイル読み込みの使用頻度が低く毎度のように構文を忘れるので, インクルードファイル(第19回予定)を直接他のプログラミング言語から出力する方が使い易く感じる事もあります.