2010年4月6日火曜日

カオスメモ理論

どうも、最近制御論が面白いQです、こんちには。

前の日記はカオスだったが、要するにLinux用のプラネタリウムソフトを作ったのである。プラットホームはCとX window。
まだ改善点は大量にあるが、家の微妙なPCでもマウスでそこそこインタラクティブに視点変更ができるので、それなりに面白いものができたんじゃないかと思っている。もちろんメガモードも持ってます。最もメガモードだとそれなりに天の川とか映るけど、とてもインタラクティブとは言いがたい操作性。

まあちょっとマシンパワー当たりに手を加える必要があるかもしれない・・・。まだこういった機能付けたいといったものがあるので余裕をみて少しずつ改善していく予定です。将来的にはは実機のプラネタリウムと連携とかも考えてはいるのですが。

で、実装に完全にかまけていたのでメモ。まじカオス。

1.KDevelop
デバッグ環境が欲しかったので、KDevelop使ってみた。gdbとかで頑張るのもまあぶっちゃけ馬鹿馬鹿しいだけなので、この際一つ何か使えるようになっておこうかと。
普段Linuxではemacsでプログラム書いてるので、プログラム書くときにctrl-cとか押してしまうのに参った。というわけでショートカットボタンを変更。良く使うコマンドはemacs仕様に変更。setting->configureナンチャラとかで色々設定できる。

ちょっとハマッたのがプロジェクト管理。本家のQ&Aによると、画面の右側にAutomake Managerというのがあるので、ここで既存ファイルをプロジェクトに追加したり、特定のファイルをプロジェクトから外すことができる。



2.mallocとかcallocとか
Cの仕様として、保証される最大サイズは64KByte。これ以上確保する場合はエラーが発生する可能性がある。まあ今のPCのメモリは普通にGByte程度は有るので、よっぽどのことをやらない限り問題にはならない気がするけど。



3.feof()
現在ファイルポインタが指している文字がEOFかどうかを判定する。ただし、
12345\nEOF
見たいなファイルでfgets()を使っていると、ファイルポインタの中身?は\nで止まってしまうので、
while(feof(fp) == 0){
fgets(fp);
}
というコードを組んでいると、EOFを一行として余計に読み込んでしまう。
詳しい実装は知らんが、おそらくファイルポインタから読み込まれたストリームの最後の文字がEOFかどうかを調べているんだと思う。従ってEOF前の\nでストリームの最後の文字が止まるため、whileの判定文をすり抜けてしまう.



4.XWindowのディスプレイとスクリーンの意味。
スクリーンはいわゆるマルチディスプレイ環境におけるどのディスプレイか?を示す。デュアルディスプレイとか言うときのディスプレイの概念はこっちに当てはまる。一方ディスプレイは凄い怪しい説明が多いのだが、最も明解な説明は、「ユーザーに提供されるマウスやキーボード、モニタ等の、インターフェースのセット」。現代のPCのイメージだと想像し難いが、昔のハイスペックなPCを皆で共有していた時代の概念だと思う。インターフェースのセットなんて考え方は一人にPC一台の時代には不要な概念だし。



5.Xにおけるマウスのボタン。
右手系において、
左ボタン:Button1
ホイールをコチってする:Button2
右ボタン:Button3
ホイール前回転:Button4
ホイール後回転:Button5
に相当。



6.構造体を型として定義
typedef struct{
short suzuki;
long watanabe;
char *tsukishima;
int kobayashi;
double iwaki;
} zannen;
ど忘れした。こんな感じで定義する。



7.キーボードからの入力を受け取る
KeyPressMaskをイベントして許可する.
通常のウィンドウの場合、フォーカスが有ればキーボードの入力は普通に認識されるが、override_redirectが設定されてたりするとキーボードの入力が認識されない。認識されるようにすることをgrabとXでは表現しているようだが、キーボードの入力をgrabするためには、ウィンドウをmapした後に、
XGrabKeyboard
という関数を使う。
さらに入力された文字が何かを知るためには
XLookupString(
XKeyEvent*,
char*,
int,
KeySim*,
XComposeStatus*)
という関数を使う。最後の二個の引数はNULLで良い。char*にアスキーコードが返され、intに数が返される。



8.Pixmapのクリア
XClearWindowはWindowに対して定義されている関数で、Pixmapには使えない。代用として、drawableに対して使うことができるXFillRectanbleを用いた。



9.イベントのqueueingと圧縮
ExposeやMotionNotifyのイベントは大量に発生するので、逐次対応していたのでは描画に時間がかかったりして非効率である。そこで、同じ種類のイベントがあったら一つにまとめて対応することが良く行われ、これをイベントの圧縮という。
Bool XCheckMaskEvent(
display *,
long,
XEvent*)
Bool XCheckTypedEvent(
display *,
int,
XEvent *)
queueingされているイベントのうち、同種のイベントが有るかどうかをチェックし、有ればそのイベントをqueueから削除してXEvent構造体に格納、Trueをreturnする関数。



10.日周運動と緯度
diurnal motion
latitude
latitudeってD○LLのPCってイメージだが緯度って意味だったのね・・・。



11.マルチスレッドのプログラム
コンパイル時に-lpthreadを付ける。忘れてはまった。



12.意図的にイベントを起こす
マルチスレッドなんかやってると意図的にイベントを起こしたくなる。
XSendEventという関数を使う。
使いかたが意外と面倒なのだが、基本的にはXEvent型の変数を定義して、内部のメンバの値を色々偽装する。そして、XSendEvent関数で当該のDisplayのイベントqueueに送り込むことになる。Exposeイベントなんかでは使うことも有るのではないかと思う。
ちなみにExposeイベントとかのメンバにはcountというのがあって、本来は同様のイベントが少なくともあと何回くるか?を表す。イベントの圧縮の手法にこっちを使うことも有るようだが、XSendEventで送られたイベントはこの処理は行ってくれない。従って自分で調べて偽装するか、これに頼らない実装を採用することになる.



13.sprintf
printf関数の何が便利って%dとかだと思う。double-char変換を簡単に行う方法として、
sprintf(配列的なもの,"%f",double型の何か);
で代入できる。



しばらくメモをサボってただけ長文メモになってしまった・・・




眠いけど
いつかは見るさ
このメモも

0 件のコメント:

コメントを投稿