計算機応用講義メモ(秋)
hこれは計算機応用の授業の覚え書きです。i
目 次
I 計算機応用(秋学期)の概要 3
1 授業の受けかた . . . . 3
2 (計算機応用のデモンストレーション) . . . . 3
3 環境設定 . . . . 3
4 変更点 . . . . 4
5 注意 . . . . 4
6 Startup . . . . 4
II Unix 5 1 用語 . . . . 5
2 操作法のおさらい . . . . 5
III Cのまとめ—1 7 1 ソースプログラムと実行ファイル . . . . 7
2 変数 . . . . 7
3 基本的な型 . . . . 8
4 演算子 . . . . 8
IV Cのまとめ—2 10 1 文 . . . . 10
2 繰り返し文 . . . . 10
3 関数の利用 . . . . 10
4 関数定義 . . . . 11
5 main関数の引数と返り値 . . . . 12
V レイトレーシングの体験 13 1 準備 . . . . 13
2 コンパイルの練習 . . . . 13
3 最も単純なシーンを作る . . . . 14
VI Fortranの体験 15
1 テキスト . . . . 15
2 準備 . . . . 15
3 プログラムの完成 . . . . 15
4 サブルーチンと変数の理解 . . . . 15
VIICとPovrayの組合せの例 16
VIIIシェルスクリプトによる簡易GUIの作り方 19
I 計算機応用(秋学期)の概要
1 授業の受けかた
• 以下のオンラインテキストを使用
1. C言語入門. . .簡単なグラフィックスと数値計算でC言語入門を完了する。(C言語を少
しは知っている。)
2. シーン記述言語. . .レイトレーシングシステムで3次元画像を作って遊ぶ。(プログラ ミング学習の下地を作りたい。)
3. 数値計算言語入門. . .高級な数値処理システムで計算機応用力を磨く。(実践的なコン ピュータ利用に興味がある。)
4. Fortranによるプログラミング超入門(追加) . . .数値計算の基本(早く数値計算プログラ ミングができるようになりたい。)
• 計算機の設定と操作練習,および,各テキストの概要説明と体験の後,課題を決め,作業ス ケジュールを自分で調整し,学習をすすめる。オンラインテキストの内容を踏まえ,独自に いろいろと試して理解を深めるように努力する。
• プログラムの実行結果などをノートに記録し整理する。練習問題もやって,ノートに記録す る。実行画面の画像もノートの中に保存しておく。ノートはワープロかhtmlエディターで 作る(提出はしない)。
• 11月と1月にレポートを作成して提出する。レポートの内容はオンラインテキストの内容 を踏まえたものでなければならない。
2 (計算機応用のデモンストレーション)
• デモの起動: 端末で/NF/class0/tanigawa/bin/k-oyoと打つ
• C言語プログラミング#3, #4と レイトレーシングのデモを試す。
3 環境設定
教材のプログラムなどを正しく動作させるために,コンピューターの個人設定を変更する。ま ず,シェルの設定を行おう。新しい端末を起動し,そこで次のように打つ。
cp -p .cshrc .cshrc.old emacs -q .cshrc &
(設定ファイル .cshrcのコピーを作り,テキストエディターで設定ファイルを開いた。-qはエ ラーを避けるため。).cshrcの中に次の1行が書かれているかどうかを調べる。
if ( -e ˜/mysetting ) source ˜/mysetting
まだ書かれていなければこれを書き込み,最後に改行が入っていること(カーソルを次の行に移動 することができること)を確かめ,<Ctrl>x <Ctrl>sで保存する。端末で
ln -sf /NF/class0/tanigawa/etc/mysetting
と打つ。新しい端末を起動し,エラーが出ないことを確かめる。もしエラーになったら,.cshrcの 中をよく調べて修正して<Ctrl>x <Ctrl>sで保存し,端末を起動してみる。どうしてもだめな
ら,emacsを終了してから,端末で
mv .cshrc.old .cshrc
と打って元に戻す。始めからやり直す。
次に,Emacsエディターの設定を修正する。端末を開けて,次のように入力する。
cp -p .emacs .emacs.old emacs -q .emacs &
(設定ファイル.emacsをバックアップコピーしてからテキストエディターで開いた。).emacsに (load "/NF/class0/tanigawa/etc/dot_emacs")
という行を追加する。他の行にはすべて左端にセミコロン;を付けて無効化する。ただし,自分 で行った設定がある場合はそれを無効化しないように。
端末で
emacs xxx.txt &
と打ってemacsを立ち上げ,正常に起動することを確かめる。何かエラーになったら,.emacsの
中をよく調べて直す。どうしてもうまくいかない場合は,
mv .emacs.old .emacs で元に戻し,始めからやり直す。
4 変更点
1. PostScriptファイルの表示を行うコマンドとしてgvやggvではなく,evinceを使うこと。
2. 各種のファイルが置かれていたディレクトリー/NF/common/class0/tanigawaと /NF/home/class0/tanigawaは無くなった。かわりに,/NF/class0/tanigawaを使う。
3. 講義要項には無いが,Fortranのテキストが加わった。FortranはCより易しい。「数値計算 言語」のかわりにFortranを勉強してもよい。ソースファイル添付済。自習に使うこともで きる。
5 注意
レポートの書き方について,計算機応用Aの講義ノートの16–18ページ,および,8–9ページ を参照すること。
6 Startup
レポートのネタを保存する場所として,たとえば,デスクトップ(˜/Desktop)にkoyobという 名前のディレクトリーを作る。今後,文書や画像をここに入れる。いろいろな作業ディレクトリー もここに作るとよい。
II Unix
1 用語
コマンド コマンドはコマンド名、スイッチ、パラメーター を1行に並べて作る。コマンド名は 必須で先頭に来る。コマンド名と他の要素との間は空白で区切る。普通、スイッチはハイフ ン-で始まる。
シェル ktermのような端末画面の一つ一つで別々の対話シェルが動く。シェルスクリプト(シェ
ルプログラム)はシェルが自動実行する。
プロンプト 普通にコマンドでプログラムを起動すると、シェルはプログラムが終了するまで待っ てから、次のコマンドを受け付ける。この状態を示すためにプロンプトが表示される。
ファイル ひとかたまりのデータに名前を付けてディスク(2次記憶装置)に保存したもの。データ の中身と名前以外に、日付、所有者名、パーミッションなどの情報も記録される。
カレントディレクトリー 特に指定しない場合に使われるファイルの場所。cdコマンドでカレン トディレクトリーを変えることができる。あるシェルでカレントディレクトリーを変えて も、他のシェルのカレントディレクトリーは変らない。記号は./
ホームディレクトリー ユーザー毎に割り当てられたディレクトリー。通常、対話シェルの起動時 にはホームディレクトリーがカレントディレクトリーになる。記号は˜/
ディレクトリーの木構造 ディレクトリーはファイルを保存する以外にサブディレクトリーを持つ ことができる。逆にディレクトリーは別のディレクトリーを親として持つ。ただし、すべて の祖先であるルートディレクトリーがひとつだけある。ルートディレクトリーは/、親ディ レクトリーは../とあらわす。
パス名 ファイルやディレクトリーの絶対的位置を絶対パスという。スラッシュ/で切りながら、
ルートディレクトリー、そのサブディレクトリー、さらにそのサブディレクトリーという順 に指定する。相対パス指定はカレントディレクトリーを基準にした位置を指定する。スラッ シュ/が先頭に付かない場合は相対パス指定になる。
標準入出力 通常、プログラムへの入力はキーボードからとられ、プログラムからの出力はディス プレイ画面に表示される。これらを切り替えて、ファイルから入力したり、ファイルへ出力 することができる(リダイレクション、記号は<、>)。他のプログラムの出力を入力として 使うこともできるし、出力を他のプログラムの入力として使うこともできる(パイプ、記号 は|)。
2 操作法のおさらい
間違いをしなくなるまで繰り返し練習すること。 はスペースキーで空白をあけることを意味す る。基本的なコマンドについては,コマンドの書き方を思い出すか調べるか訊く。
1. ディレクトリー/usr/includeにcdコマンドで移動し、移動できたことをpwdコマンドで 確認しなさい。
2. ここにファイルstdio.hがあることをlsコマンドで確認しなさい。
3. このファイルの内容をlessコマンドで表示し、上下にスクロールしなさい。lessをqコ マンドで終了しなさい。
4. このファイルをemacsで開き、なにか書き加えようとしてみなさい。書き加えることがで きましたか。
5. emacsを終了し、cdと打ってホームディレクトリーに移動してから、cpコマンドを使って
ファイル/usr/include/stdio.hをホームディレクトリーにコピーしなさい。ファイル名
はstdio.hのままにしておきなさい。コピーができたことをlsコマンドで確かめなさい。
6. ホームディレクトリーのstdio.hをemacsで開いて適当に書き加えてから保存、終了しな さい。
7. /usr/include/stdio.hとホームディレクトリーのstdio.hの詳細情報をlsで表示して、
左端に表示されるパーミッションを比較しなさい。
8. rmコマンドでホームディレクトリーのstdio.hとstdio.h˜を消しなさい。消えたことを lsコマンドで確かめなさい。
9. ホームディレクトリーにmkdirコマンドでbuuhuuuuというサブディレクトリーを作り、cd コマンドでそこに移動し、lsコマンドでここが空であることを確かめなさい。
10. calコマンドのマニュアルをmanまたはjmanで表示し、自分が生まれた年の1年分のカレ ンダーを表示する方法を調べて実行しなさい。
11. calコマンドとリダイレクション(>)を使って、生まれた年のカレンダーをcalender.txt というファイルに保存し、lsでその存在を、catでその内容を確認しなさい。
12. a2ps -p calender.txt >calender.psと打ってポストスクリプトに変換し、calender.ps
をevinceコマンドで表示しなさい。
13. cd .. と打ってホームディレクトリーに戻りpwdコマンドで確認した後、サブディレクト
リーbuuhuuuuの中をlsコマンドで見なさい。
14. rmdirでbuuhuuuuを消すことを試み、エラーメッセージを見なさい。
15. 再びbuuhuuuuに移ってpwdとlsで厳重に確認し、rm *と打ちなさい。lsでここが
空になったのを確認しなさい。*はここにある「すべて」という意味! 16. ホームディレクトリーに戻り、rmdirを使ってbuuhuuuuを消しなさい。
もしUNIXの操作方法をほとんど憶えていないことが判明した場合は、テキスト /NF/class0/tanigawa/materials/oyo/text/Unix-setting の1、2および4または、ごくやさしい入門用の本をみつけて読むとよい。
III Cのまとめ—1
C言語のテキストを読むのに必要な基礎知識を以下にまとめる。春学期にC言語を勉強した人 はこれをざっと見て復習を行なってほしい。そうでない人は練習問題を解きながら少し時間をか けて読むとよい。
1 ソースプログラムと実行ファイル
C++のソースプログラムをテキストエディター(たとえばemacs)で書いてファイルに収め、こ れをコンパイルすると実行ファイルが作られる。ソースファイルの名前は実行ファイルの名前に
拡張子“.cc”を付けたものにする。簡単なプログラムの場合はmakeコマンドでコンパイルを行
なうことができる。実行するには実行ファイルをディレクトリーを含めて指定する。
たとえば、カレントディレクトリーにxyz.ccというソースファイルを作り、シェルで make xyz
と打つと、xyzという実行ファイルができる。これを実行するには ./xyz
と打つ。./はカレントディレクトリー。コマンドラインパラメーターが必要なプログラムでは、
たとえば
./xyz 123 456 というように実行する。
練習問題III 下のソースプログラムから(内容は考えず)上の説明のようにしてyesterdayという 名前の実行ファイルを生成してそれを実行してみなさい。次に、クォーテーションマークで囲ん である英文を書き換えて保存し直し、実行ファイルも作り直してから再度実行してみなさい。次 に、もう一度書き換えを行い、保存しないで作り直して実行してみなさい。次に、保存を行い、
作り直しをしないで実行してみなさい。最後に、作り直しを行い、実行してみなさい。
#include <iostream>
using namespace std;
int main() {
cout << "Yesterday is the day next before today." << endl;
}
2 変数
変数は計算結果を後で使うために憶えておく仕組み。各変数は不変の名前と型および、変化する 内容を持つ。変数を始めて使うところで「宣言」を行ない名前と型と初期値を与える。たとえば、
int order_number = 10;
double weight(15.6);
は、整数型でorder_numberという名前の変数を用意して始めの値を10とし、実数型でweight という名前の変数を用意して始めの値を15.6としている。初期値の設定にはイコールを使っても よいし括弧を使ってもよい。
なお、Cでは変数宣言を置くことのできる位置に関する制限があって、C++ほど自由ではない。
また、括弧を使う初期化の構文は無い。
変数には寿命があり、遅くともプログラムの実行が終るまでにはそのプログラム中で使ってい た変数はすべて消滅する。
練習問題III 次のソースプログラムからhensuuという名前の実行プログラムを生成して実行し てみなさい。また、変数の初期値を変えたり、名前や型を変えたりして実行してみなさい。
#include <iostream>
using namespace std;
int main() {
int order_number = 199;
cout << order_number << endl;
}
3 基本的な型
int n; 標準的な整数型。32ビットCPUでは−231=−2,147,483,648から231−1=2,147,483,647 まで。値に限界があることを考慮して使う必要がある。
double x; 標準的実数型。64ビット。精度は10進15桁程度。精度が有限であることを考慮して
使う必要がある。
char c; 8ビットの符合付き整数型。ASCII文字をあらわすのに使う。
float y; 32 ビットの実数型。短いのでメモリーの節約になるが、精度が低いのであまり使わ
ない。
char s[]="abcdefg"; char s[10]; char ss[]; char* sss; 文字配列。はじめの2つは文 字列の記憶領域を確保する。後の2つは記憶領域を確保せず関数の仮引数などで記憶領域の 位置指定に使う。char以外の型でも同様にして配列を作ることができる。
void 空。関数の返り値が無いことを示す場合などに使われる。
練習問題III-a 次のプログラムを参考にして、実数型の精度の違いを確かめてみなさい。
#include <iostream>
using namespace std;
int main() {
float f = 0.1;
double d = 0.1;
cout << "float precision: " << (f * 10 - 1) << endl;
cout << "double precision: " << (d * 10 - 1) << endl;
}
練習問題III-b 次のプログラムをいろいろに変更して、値の範囲の問題について考えなさい。
#include <iostream>
using namespace std;
int main() {
double x = 8.0e9; // 8000000000.0 in other word int n;
n = x;
cout << x << " is converted to " << n << endl;
}
4 演算子
括弧:
( )
部分式をくくる括弧。計算の順序を変えるためだけではなく、計算の順序が一見してはっきりわ かるようにするためにも使う。多重にくくる場合でも括弧の種類は一種類だけである。
算術演算子:
- x, x * y, x / y, n % m, x + y, x - y
整数どうしの演算の結果は整数になる。割算では切捨てが強制的に行なわれる。実数どうしの場 合は結果は実数になる。整数と実数の演算では整数が実数に変換されてから計算が行なわれ、結 果は実数になる。割算の余りを求める演算子%は整数のみが対象。
関係演算子:
x < y, x > y, x <= y, x >= y, x == y, x != y,
これらの比較式の値は、比較の結果が真であるか偽であるかによって、1か0になる。
代入演算子:
a = x, a += x, a -= x, a *= x, ...
これら代入式の左辺は変数であり、その値は変更される。代入式自体も代入されたのと同じ値を 持つ。そこで、x = y = 1;のような多重代入が可能である(右側の方から処理される)。
自動インクリメント演算子と自動デクリメント演算子:
++n, n++, --n, n--
自動インクリメントと自動デクリメントは変数に対して作用し、値を1増やしたり減らしたりす る。後置形式の式の値は計算前の変数の値になる。そのため、x = 0; y = x++;では、xは1に なるがyは0になる。
練習問題III-a 次のプログラムを参考にして、割算の結果が型によってどう変わるかを調べな
さい。
#include <iostream>
using namespace std;
int main() {
cout << ( 10 / 3 ) << endl;
cout << ( 10.0 / 3.0 ) << endl;
cout << ( 10.0 / 3 ) << endl;
cout << ( 10 / 3.0 ) << endl;
cout << ( (10 + 0) / 3 ) << endl;
cout << ( (10 + 0.0) / 3 ) << endl;
}
練習問題III-b 自動インクリメント演算子の働きを次のプログラムで確認しなさい。
#include <iostream>
using namespace std;
int main() {
int n = 10;
cout << "n equals " << n << endl;
cout << "n++ equals " << n++ << endl;
cout << "n equals " << n << endl;
cout << "n++ equals " << ++n << endl;
cout << "n equals " << n << endl;
}
IV Cのまとめ —2
1 文
代入式や関数呼び出しのような式は、後ろにセミコロンを付けることによって一つの単純文に なる。複数の文を中括弧{ }で囲んだものは一つの文になる。これは複文という。他に、条件文、
スイッチ文、繰り返し文もそれぞれ一つの文である。
2 繰り返し文
for文は配列の中身を操作するのによく使われる。次のプログラムでは、文字列"ABCD"で初期 化された文字配列sの始めの要素から終りの要素までの値を調べている。sizeof(s)は配列sの 大きさを得るものである。配列のインデックス(要素番号)は0からsizeof(s)-1までであるこ とに注意。
#include <iostream>
using namespace std;
int main() {
char s[] = "ABCD";
for (int i = 0 ; i < sizeof(s) ; i++) {
int code = s[i];
cout << i << "---" << code << "---" << s[i] << endl;
} }
同じプログラムをfor文のかわりにwhile文を用いて書くと次のようになる。変数iの初期化 と更新を記述する位置がfor文の場合と異なる。
#include <iostream>
using namespace std;
int main() {
char s[] = "ABCD";
int i = 0;
while ( i < sizeof(s) ) {
int code = s[i];
cout << i << "---" << code << "---" << s[i] << endl;
i++;
} }
練習問題IV 上の2つのプログラムの内どれか一つを実行してみなさい。文字配列 sの初期値
"ABCD"をいろいろに変えてプログラムを実行し、配列の中に文字列がどのように記憶されている
かを調べなさい。
3 関数の利用
ライブラリー関数を使うには、その関数を記述したヘッダーファイルを#include命令で読み込 んだ上で、関数をその仕様に従って呼び出す。標準的ライブラリー関数の仕様と必要なヘッダー ファイル名についてはmanページで調べることができる。普通のライブラリー関数についてはセ クション3にまとめられている。
関数atan2のmanページの始めを見ると 書式
#include <math.h>
double atan2(double y, double x);
とあり、「y/xの逆正接を計算 」 と書いてあるので、たとえばatan2(3.0, 4.0)で3/4のアーク タンジェントが得られるだろう。しかし、atan2(1.0, -1.0)とatan2(-1.0, 1.0)は同じだろう か?また、atan2(-1.0, -1.0)とatan2(1.0, 1.0)は同じだろうか?さらに、atan2(1.0, 0.0) はどうなるだろうか?それを調べるには簡単なプログラムで実際に試してみればよい。たとえば、
次のようなプログラムでよいだろう。
#include <math.h>
#include <iostream>
using namespace std;
int main() {
cout << "atan2( 1/ 1) = " << atan2(1.0, 1.0) << endl;
cout << "atan2(-1/-1) = " << atan2(-1.0, -1.0) << endl;
cout << "atan2(-1/ 1) = " << atan2(-1.0, 1.0) << endl;
cout << "atan2( 1/-1) = " << atan2(1.0, -1.0) << endl;
cout << "atan2( 1/ 0) = " << atan2(1.0, 0.0) << endl;
}
ヘッダーファイルを#includeで指定し、引数の数、順序、型、および返り値の有無と型に矛盾し ないように呼び出す必要がある。ただし変換が一意的に可能なら、型は一致しなくてもよい。引 数が無くても括弧は必要。返り値はもしあっても無視して使わないこともできる。
練習問題IV floorという関数についてmanページで調べ、その機能をテストするために簡単な
プログラムを作りなさい。(計算結果を表示するためにcoutを使うなら、iostreamを#include しusing namespace std;を指定すること。)
4 関数定義
関数の定義の例を下に示す。これは引数として与えられた2つの整数の最大公約数を計算して 返り値として返す関数である(この計算法は「ユークリッドの互除法」という。しかし内容は考え なくてもよい)。関数定義の構成上、最初の3つの要素(返り値の型、関数名、引数)が必須要素。
またreturn命令で返り値を指定。
int // 返り値の型
get_gcd // 関数名
( int x, int y ) // 引数の型 仮引数名 ...
{
if ( y > 0 )
return get_gcd( y, x % y );
else
return x;
}
呼び出した関数の返り値を使うには関数呼び出しを式の中に書く。たとえばget_gcdを使って12 と244の最小公倍数を求めるなら、
int lcm = 244 / get_gcd(12, 244) * 12;
返り値が無い関数を定義する場合、返り値の型としてvoidを使い、return命令には返り値を指 定しない。
練習問題IV 2つの整数272205と42435の最大公約数と最小公倍数を計算して表示するプログ
ラムを上で示した関数get_gcdを使って作りなさい。関数の定義はint main()の行の上に入 れる。
5 main関数の引数と返り値
プログラムの実行とはmain関数の実行であり、他の関数はmain関数から直接または間接に呼 び出されなければ実行されない。なお、main関数が定義されていなければ、コンパイルの時にエ ラーになる。
main関数はint型の返り値を持つように作らなければならない。プログラムが正常に終了した 場合にはゼロ,異常終了した場合にはゼロ以外の値をmain関数が返すようにする。返り値はreturn 命令で指定することができるが、return命令を省略すると、ゼロを帰したものとみなされる。こ の返り値は$?というシェル変数に反映される。なお、異常終了の場合はプログラムを終了する前 にエラーメッセージや使い方の説明を表示するのがよい。
main関数は2つの引数を取るように作ることができる。始めの引数はint型で、コマンドライ ンで与えたパラメーターの数に1を加えた値がセットされる。2番目の引数は 文字列の配列で、
コマンドラインで与えたパラメーター文字列を要素とする配列がセットされる。パラメーター文 字列を数値として利用するには、文字列を数値に変換する関数を使う必要がある。
#include <iostream>
#include <cstdlib>
using namespace std;
int main (int argc, char* argv[]) {
if(argc > 2) //パラメーターの数をチェック
{
int x = atoi(argv[1]); //第1引数を整数に変換 int y = atoi(argv[2]); //第2引数を整数に変換 cout << x + y << endl;
return 0; //正常終了
}
else //パラメーター不足時のエラー処理
{
cerr << "Two integers required." << endl;
return 1; //異常終了
} }
下のように、異常終了の場合にexit関数で終了するようにすることもできる。関数の最後に達 して終了する場合は自動的にゼロが返される。
int main (int argc, char* argv[]) {
if (argc <= 2) {
cerr << "Two integers required." << endl;
exit( 1 );
}
cout << atoi(argv[1]) + atoi(argv[2]) << endl;
}
練習問題IV get_gcd関数の定義を使い、コマンドラインから与えられた2つの整数の最大公約
数を計算して表示するプログラムを作りなさい。ただし、2つの正の整数が与えられなければ、計 算をするかわりに正しい使い方を表示するようにすること。(最初から完全な機能を実装するので はなく、簡単な部分から始めて少しずつ完全なものにしていくのがよい。たとえば、まず、2つの コマンドラインパラメーターをそのまま表示するプログラムを作ってみる。次に、パラメーター の数をチェックする機能を付け加える。次に、パラメーターを数値データーに変換してそれを表 示するようにする。それらの和を計算して表示してみてもよい。最後に最大公約数を計算する機 能を追加する。)
V レイトレーシングの体験
1 準備
レイトレーシングプログラムpovrayの設定ファイルを用意しよう。設定ファイルは˜/.povray/3.6/povray.ini である。すなわち、ホームディレクトリーの中の.povrayサブディレクトリーの中の3.6サブ
ディレクトリーの中のpovray.iniファイル。
まず、サブディレクトリーが無ければ mkdirコマンドを使うかファイルマネージャーを操作 して作る。ファイルはemacsで編集して作る。内容は以下のとおり。
————————————————————————
;; 出力画像サイズ(ピクセル) +W320 +H240 Width=320
Height=240
;; 出力品質(処理精度) +Q9 Quality=9
;; プレビュー画像を表示しながら処理 +D +P Display=On
Pause_When_Done=On
;; モザイクプレビューから始める。
Preview_Start_Size = 4
;; ファイルへ出力する。 T:Targa-24, P:UNIX PPM, N:PNG Output_to_File=true
Output_File_Type=N
;; モニターのガンマ値 Display_Gamma=2.2
;; 標準ライブラリーのありか
Library_Path=/usr/local/share/povray-3.6/include
————————————————————————
次に、作業用ディレクトリー(たとえば˜/koyob/raytracing)を作り、端末でそこへ移る。
cd ## ホームディレクトリーに行く
cd koyob ## 計算機応用Bのディレクトリーに行く
mkdir raytracing ## raytracingディレクトリーを作る cd raytracing ## raytracingディレクトリーに行く
次に、基本的な立体形のサンプルシーンをディレクトリーごとraytracingディレクトリーにコピー する。サンプルシーンがあるディレクトリーは
/usr/local/share/povray-3.6/scenes/objects
である。ディレクトリーごとコピーするには、cpコマンドにコマンドラインスイッチとして-rを 付けて使う(cp -r /usr/local/share/povray-3.6/scenes/objects .)か、ファイルマネー ジャーでドラッグ&ドロップする。
2 コンパイルの練習
コピーしたサンプルシーンのディレクトリーにcdして、lsでどんなファイルがあるかを見る。
box.povというファイルがあることを確認し、その内容をcatで見る。カメラ(camera)の設定、
球(sphere)と箱(box)の定義、光源(light source)の設定が書いてあるのがわかる。
povray box.pov
でコンパイルすると、画像が表示される。もっと大きな画像を得るには、
povray -w600 -h450 box.pov wtorus.pov
3 最も単純なシーンを作る
raytracingディレクトリーに移り、テキストRaytracingの
「5. 簡単なシーンの書き方」
に従って、シーンを書いて画像にしてみる。
VI Fortranの体験
1 テキスト
Intro_fortran.pdfを開くとテキストを読むことができる。プログラム例のソースファイルは
Intro_fortran.pdfに添付してある。添付されたファイルの取り出し方も書いてある。
2 準備
1. Fortranコンパイラーとしてgfortranが使用可能であることを確かめる。また,gfortranの バージョンを見る。
2. emacsの機能を確認する(テキストp4)。
3. gnuplotとdisplayがあることを確認(テキストp4)。
4. 計算機応用のディレクトリーの中にFortran用作業ディレクトリーを作る。
5. テキストp6のはじめのプログラムを入力し,コンパイルする。
6. Makefileを作ってテストする(テキストp7)。 7. プログラムを走らせる。
3 プログラムの完成
完成形を作ってテストする(テキストp8,練習問題まで)。
4 サブルーチンと変数の理解
テキストp8からp10を参照。添付からソースファイルを取り出して使用する。
VII CとPovrayの組合せの例
Povrayのheight fieldオブジェクトは指定した画像データから曲面を生成するものである。画
像の各点の明るさを地図上の各点の高さとみなすことによって、曲面(地形)が定義される。画像 データは有限個のピクセルの色を有限な数値であらわすものであるので、滑らかな曲面を得るに は、十分なピクセル数と色数が必要である。
点(x,y)の明るさが2変数関数 f(x,y)で決まるようなモノクロ画像を作って、それからPovray のheight fieldオブジェクトを作ってみる。関数は次のような形とし,x,yの範囲は共に-5 .. 5と する。
f(x,y)=g(x−y)+g(x+y), ただしg(t)= sinht cosh 2t
-10 -5
0 5
10-10 -5
0 5
10
-0.5 0 0.5
-10 -5
0 5
f(x,y)のグラフ
Povrayが読み込むことのできる画像ファイル形式のうち,ここでは作るのが簡単なPGMテキ
スト形式を使う。この形式のファイルのはじめの方は次のようになっている。
P2 400 400 32768
16382 16954 17521 18081 18629 19163 19678 20173 22264 22596 22899 23173 23417 23633 23822 23984
1行目はファイル形式をあらわすので,いつも同じである。2行目は縦横のピクセル数をあらわ す10進数,3行目は色数をあらわす10進数である。4行目から各ピクセルの明るさをあらわす10 進数が並ぶ。明るさは0から 色数-1の整数であらわされる。
ピクセル数は縦横とも400とし、x,yの原点は画像の中心(200,200)に持っていく。色数つまり 明るさのレベルの数は32768 (215)にする。次のような関係で,x,y及び関数値zをピクセル位置 X,Y及び明るさZに線形にマップする。
x= 10
200(X−200), y= 10
200(Y−200), Z = 32768
z1−z0(z−z0)
ただしzの範囲はz0からz1である。以上に基づいて画像データを作成する。C言語でやるなら次 のようなプログラムでOKである。
#include <stdio.h>
#include <math.h>
double pulse(double x) {
return 0.7 * sinh(x) / cosh(2*x) + 0.25; // 0 .. 0.5 の範囲に調整 }
int main() {
printf("P2\n400 400\n32768\n");
int n = 0; //出力値の数
for(int Y=0 ; Y < 400 ; Y++) //ピクセルの縦位置
for(int X=0 ; X < 400 ; X++){ //ピクセルの横位置
double x = (5.0/200)*(X-200);
double y = (5.0/200)*(Y-200);
double z = pulse(x-y) + pulse(x+y); // 範囲は 0 .. 1.0 printf(" %5d", int(pow(z,1) * 32768));
if (++n >= 12)
n = 0, printf("\n");
} }
このプログラムは画像データを画面出力するので,シェルのリダイレクション機能を使ってそれ をファイルに保存すればよい。ファイル名をwaveimage.pgmとしよう。Povrayのシーンは次の ように作ればよい。
camera{ location <-1, 5, -2> look_at <0, -1, 0> } light_source{ <0,100,-50> rgb<1,1,1> }
height_field {
pgm "waveimage.pgm" // read from pgm file translate <-0.5, -0.5, -0.5> scale <10, 3, 10>
pigment { rgb <1,0.95,0.85> } normal { bumps 0.4 scale 0.02 } }
plane { y, -0.0
pigment { rgb<0.03,0.5,0.15> transmit 0.8 } normal { wrinkles 1 scale .2 }
finish { specular 0.3 roughness 0.1 metallic } }
height fieldは1×1×1の立方体に収まる大きさになるので,scaleで必要な大きさに引き延ばす。
また,真ん中を原点に持ってくるためにtranslateを使う。
高さゼロの面をあらわす半透明な平面を付け加えてみた。左は画像ファイルwaveimage.pgm, 右はレンダリングの結果である。
height fieldは複雑な地形を数学的に計算して作るのによく使われる。左は/NF/home/class0/tanigawa/materials/oyo/examples/Povray にあるmandel1.ccで探索して保存したフラクタル画像(ファイル名darkpond1.pgm)。 右は同じ
場所にあるシーンファイルfract1.povでこの画像を取り込んで作った3次元シーン。
この場合はコンピューター画面に表示される画像をファイルに取り込んで利用している。普通 のコンピューターではモノクロ画像の画面表示は最大256階調でしかない。あるために,滑らか な曲面を作るのは難しい。そこで,画像処理でぼかすことによって質を向上させている。
VIII シェルスクリプトによる簡易GUIの作り方
Xdialogというunixコマンドはボタンやダイアログボックスを表示してユーザーの反応を捉え
たり入力データを収集することができる。単純な対話ならTcl/Tkのような本格的な言語の代りに 使用し、容易にGUIを作ることができる。ユーザーの指示や入力されたデータはXdialogの終了 コードや標準出力などとして出てくるので、それを他のプログラムに与えて使用すればよい。 文 字端末を使ってボタンやダイアログボックスを表示するdialogというコマンドもあり、Xdialogと ほぼ同じ使い方ができる。
Xdialogとやると“Usage for Xdialog”というウィンドウが開いて簡潔な説明が表示される。次 のURIも参考になる。
http://xdialog.dyns.net/
Xdialogの使い方
端末で次のコマンドを実行してみよう。
Xdialog --stdout --inputbox "Input something" 10 50
入力欄のあるウィンドウが表示されたら、たとえばhttp://www.w3.orgと入力してOKボタン を押すと、入力した文字列が端末に表示される。コマンドラインスイッチ--inputboxの後の3 つのパラメーターは順に、説明文、縦幅、横幅をあらわす(単位は文字の大きさ)。これらのパラ メーターをいろいろ変えて試してみよ。
Xdialogで入力した文字列は標準出力から表示される。この標準出力はコマンド置換を使って他
のコマンドのパラメーターにしたり変数に代入したりすることができる。たとえば、
mozilla ‘Xdialog --stdout --inputbox "Input address" 10 50‘
このコマンドでは、まずバッククォートで囲まれたXdialogコマンドが実行され、その結果表示さ れるはずの内容がmozillaコマンドのパラメーターになる。そのため、ダイアログボックスでweb ページのアドレスを入力すると、それがmozillaコマンドに渡されて、そのページが表示される。
次のように、変数を使うと便利なことが多い(=の両側にスペースを入れないこと)。
set ADDR=‘Xdialog --stdout --inputbox "Input address" 10 50‘; mozilla $ADDR ダイアログでCancelボタンを押した場合にmozillaが動かないようにするには、コマンドの区切 りをセミコロン;から2つのアンパサンド&&に変える。&&の左側が異常終了すると右側は実行 されない。Cancelボタンを押すとXdialogコマンドは異常終了になるので &&によりmozillaは 実行されない。
これをgnomeパネルにランチャーとして登録し、ワンクリックで起動できるようにしてみよう。
ランチャーで起動できるようにするため、次のように修正する。
sh -c ’ADDR=‘Xdialog --stdout --inputbox "Input address" 10 50‘ && mozilla $ADDR’
‘sh -c’はコマンドを実行するシェルを指定するものであり、通常shシェルを使う。shでは、csh
系とは代入の構文が異なり、setが不要。シェルが実行するコマンドの全体はシングルクォートで 囲んである。端末上で動作チェックをしてから、ランチャーとして登録するとよい。
シェルスクリプトの利用
もっと複雑なダイアログボックスを作ったり、複数のダイアログボックスを使おうすると、1行 に収まらなくなる。こういう場合はファイルに入れてシェルスクリプトにするのがよい。シェル のコマンドを必要なだけ並べてファイル名を付けて保存し、そのファイルを実行可能にすればシェ ルスクリプトができる。
シェルの種類によって文法が微妙に異なるが、どのシェルで実行するのかをシェルスクリプト 中で指定することができるので、好きなシェルの文法を使うことができる。端末 では普段tcshを 使用しているかも知れないが、シェルスクリプトは伝統的なBourneシェル(sh)の文法で書くこ とが多いので、ここでもそれで行く。
次のシェルスクリプトから始めよう。“Usage for Xdialog”を開いておいて参照するとよい。emacs で下を入力し適当な名前のファイルに保存する。ここではファイル名をxdialogtestとしよう。
#! /bin/sh
INPUTS=‘Xdialog --stdout --separator " " \ --2rangesbox "Input two values" 15 50 \
"Value 1" 0 100 50 \
"Value 2" -10 10 0 ‘ echo $INPUTS
スクリプトの第1行はこのスクリプトをshシェルで実行するよう指定している。これはshシェ ルの実行ファイルがあるディレクトリー/binも含めて指定する必要がある。これは最初の行に左 端から書かなければ認識されない。行の右端にあるバックスラッシュ\は、次の行をつなげて1 行として扱うように指示するもので、これを使うと、本来は1行であるものを分けて書いて見易 くすることができる。2行目から始まり、バックスラッシュで区切られながら5行目まで続くコ マンドラインは、コマンド置換を使ってXdialogコマンドの出力をシェル変数INPUTSに代入す る。shでは変数への代入にはsetコマンドは必要ない。6行目のechoコマンドはこの変数に代入 された内容を表示する。
Xdialogコマンドでは、--2rangesboxというオプションを使うことで、2つのスライドバー
で数値を入力するダイアログボックスを表示している。このオプションには、ダイアログボック スのラベル文字列と縦の大きさおよび横の大きさ、第1のスライドバーのラベル文字列、下限値、
上限値および初期値、第2のスライドバーのラベル文字列、下限値、上限値および初期値が続く。
--separatorオプションは、2つの数値を表示するときに、それらの間に挿入される文字を指定
する。上ではスペースを間に入れるよう指定している。--stdoutオプションは、結果を標準出力 に送るよう指定している。これはコマンド置換を行う場合に必要。
このシェルスクリプトを実行可能にするため、端末で chmod +x xdialogtest
と打つ。実行するには./xdialogtestと打てばよい。
区切り文字をコンマにしたり、各スライドバーの上限、下限、初期値を変えるなどしてテスト を行ってみよう。さらに、スライドバーを3つに増やし、結果をファイルに保存するように変更 しよう。3つに増やすのは--3rangesboxオプションで可能である。ファイルへの保存はechoコ マンドでリダイレクションを使うとできる。Cancelボタンを押した場合に停止させるため&&を 使う。
#! /bin/sh
INPUTS=‘Xdialog --stdout --separator " " \ --3rangesbox "Input three values" 20 50 \
"Value 1" 0 100 50 "Value 2" 0 100 50 "Value 3" 0 100 50 ‘ &&
echo $INPUTS > xdialogout