上へ
開発メモ2001/07/30 カーニハン本仕事上のプログラムは予算、納期の制限もあり、納得いくまでつきつめられるわけではないので、 一般に汚くなりがちなんですが、「これはひどい」(多分、作者もいくつか書いた(^^;) というものなかにはあるので、教育上良い本を探していました。最近ではオブジェクト指向へのパラダイムシフトに伴うごたごたも一段落して、 一昔前はオブジェクト指向プログラムの作り方だったところが、 オブジェクト指向をつかってどうやって楽をするかということに話題が移ってきて、 仕事用コードを書くための本を探すには良い環境になってきました。 そんな中で、教育上良い本として 「リファクタリング,マーチン ファウラー」 に目をつけていました。プログラムをコンパクトに保つ方法を解説している本なんですが、 最近の本ではよくあるように、オブジェクト指向は常識として特に解説もしていないので、 冷静に考えると、兼業プログラマが多い作者周辺でこの本を読める人はほぼいませんでした。 (いるにはいるけど、そういう人は元々良いコードを書く) もうちょっと敷居の低い本を探して、古典的有名所を中心に GW を利用して いくつか読んでみました。(←いつの話やねん)
次のお勧めも、同じカーニハンのプログラミング作法でした。プログラム書法より厚くて、 空白も少ないのが難点ですが、そのかわり、例題は C で書かれていて、 内容もプログラム書法を発展させた充実の内容でした。 1970年代から2000年代まで一気に読んだことになりましたが、全体として、 構造化プログラミング、オブジェクト指向など、プログラムについて書かれたものは生き残る、 流行が去っても全面否定まではされない。 それに対して、フォーターフォールモデルや、各種オブジェクト指向方法論、 フローチャート、ISO9800のような文書とか方法論についは後の世になると けちょんけちょんにけなされることもある。といった感じでした。 今回読んだ本の中ではCMMは今のところ一定の評価を得ているようですが、今後どうなるでしょ? 2001/07/23 Kylix 対応 I/O ポートアクセスドライバだれが使うんだこんなもの。(^^;2001/07/14 仕事重心演算、データによってはオーバーフローを起こすので、一部 64bit 計算に変更。Kylix 画面更新遅い対策 その2ゲームの画面更新は速いはずだ。ということで、 Simple DirectMedia Layer(SDL) というのを発見、安定供給が期待できるか、環境依存がどの程度か、実際の性能は、・・・ など評価している時間がないため、今回は採用を見送る。画像取り込ボードにコマンドを送って、ハードに描かせる方法もためしてみたが、 これはこれで、ハードアクセスに 70ms 程度(2フレーム?)オーバーヘッドがあって、リスクの割りに 得るものが少ない。 前回からさらに思い付きを試した結果、Kylix 標準の範囲では PaintBox Draw が速いようだ。 これで行く。 Kylix 画面更新遅い対策 その2ScanLine ベースでピクセルセット関数、直線描画、円描画を作る。フォーカス評価スポットが小さくて、強度が強いという条件で適当にフォーカス評価関数を作ってみた。 検出精度がいまいち。google で "focus" "評価関数" で検索する、"Modified Laplacian" とかいうのが引っかかった。もしかして知らないと恥なのか? "Modified Laplacian" でさらに検索・・・引っかかりすぎ・・・。 原理に戻ると、フォーカスの評価で Laplacian を使うのはなんとなく分かる気がするが、 使いたい場面ではエッジの片側がサチっていることが多いので・・・、 そこまで考えて思い付きを実装、どうなるでしょ? 最少二乗円3点以上を二乗誤差最少で通る円を求める必要があるので式をたててみると、 連立1次方程式の形になった、プログラムを作り計算させてみると、 ちゃんと計算できているようだ。(X[1],Y[1])〜(X[n],Y[n])を通る円 (X - A)^2 + (Y - B)^2 = R^2 のパラメータ A, B, R を求める。 | 2*X[1] 2*Y[1] 1| |X[1]^2 + Y[1]^2| | 2*X[2] 2*Y[2] 1||A| |X[2]^2 + Y[2]^2| | 2*X[3] 2*Y[3] 1||B| = |X[3]^2 + Y[3]^2| | ... ||C| | ... | | 2*X[n] 2*Y[n] 1| |X[n]^2 + Y[n]^2| を解いて、R は R = Sqrt(C + A^2 + B^2)しかし、暑さで思考が止まりがちなのはなんも・・・。 2001/07/11 仕事Kylix 画面更新遅い対策画面の更新(Scanline + Invalidate)が 200ms 位と使い物にならないほど遅い (Windows-95 では 10ms位)。調べてみると 100ms が 640 x 480 領域を更新するのにかかる時間で、最初のうちは ScanLine は 10ms 以内で完了して、Invalidate 発行は(イベントのセットだけなので) 0ms で終了 しているが、Canvas を使った後から、ScanLine を使用時と、Invalidate 発行時にそれぞれ 100ms かかるようになっている。とりあえず Canvas は使えないので、ScanLine ベースで描画コマンドを作る必要がある。 ピクセルセット関数を作って、ピクセルセット関数から直線描画を作って、 直線描画で円描画を作って・・・でなんとかなるかな。 これで ScanLine と Invalidate は瞬時(10ms程度)に終わる。 実際の描画は 100ms かかるけど、Xプロトコルを経由していないはずの Windows でも 100ms 弱はかかるので、これは諦めるしかないかな。 Kylix 画面更新ちらつき対策ScanLine で画像をセットして、Invalidate (または Repaint) で画面を更新するときに 画面がちらつく、(Delphi ではダブルバッファプロパティを使うのが定石だが、 Kylix では無くなっている) 調べると、TImage の Invalidate は最終的に、TForm や TPanel の InvalidateRect メソッド を呼び出しているように見える。InvalidateRect の第2引数は、画面更新時の初期化有無を 指定できるはずだが、どうも指定が無視されている。 いろいろやって見たところ、TImage を保有している TForm (または TFrame )の Invalidate メソッドを呼び出すことで、ちらつき無しで更新できるようだ。2001/07/10 仕事重心演算関係とりあえず出来た。Blob.pas(そのうち削除予定) コード行数 200 行で、Celeron 400MHz で 60ms 程度 (1〜2フレーム落ち、画像にもよる)ならまぁ良しとする。ビットマスクを使った探索高速化、効果が10% 程度なら却下しようと思っていたのですが、 20% 程度の効果があったので、微妙な所ですが残しました。 キューのメモリ配置上、スレッドセーフではありませんが、とりあえず自分が 必要になるまでは対応しない予定。 昔持っていた8086-386 のクロック表から、386 以降のプロセッサでは乗算、除算のペナルティは 無視できると思っていたのですが、どうも誤解だったことが発覚。 コンパイラの最適化をOFFにして、適当にループをまわしてみると、 手元の Crusoe (プロセッサがまったく違うけど(笑))では加算、減算、ビット演算を1とすると、 乗算が5、除算、剰余が10程度かかっているようでした。 クロック表は目安程度にしかならない時代ですが、 やっぱり乗算、除算はペナルティと考えていたほうが良さそう。 2001/07/08 仕事画像処理関係のプログラムを、通常は Matrox の画像処理ライブラリ (MIL 50万+ランタイム7万くらい)を使って作っているのですが、 今回は重心演算程度ということや、原価低減の圧力(笑)もあり、 今回は MIL は使わないことにしています。とりあえず http://www.google.co.jp/ で探したのですが、めぼしいものを見つけられなかったので、 自作することにしました。手順としては
必要データとしては
GetMem を使って配列へのポインタ配列を作って(以下概略)クラスで隠蔽が、 MIL とか子バッファが取れる市販画像処理ライブラリでも採用されていそうな形式だけど、 type TByteArray = array [0 .. MAXINT div 2 div SizeOf(Byte)] of Byte; PByteArray = ^TByteArray; var A: PByteArray; P: array of PByteArray; begin SetLength(P, 480); GetMem(A, 640 * 480 div SizeOf(Byte)); // 画像ボードから直接転送可 P[0] := @A[0 * 640]; P[1] := @A[1 * 640]; P[2] := @A[2 * 640]; ...作者はこの分野のニーズをよく把握しているわけでもないので、この状態で大掛かりなものを 作ると、かなりの確率で ”しょうもないもの(*)” を作ってしまうため、 自分のニーズが出てくるまでは当面却下。 (*) クラスを作るとしても型が違う(=インターフェースが違う)から、 アルゴリズムを共用しようと思っても出来ないし、仮想関数呼び出しオーバーヘッドも惜しいし、 クラス使用を強要することになる割りにいまいちメリットが感じられない、 最近 Delphi-ML でテンプレートもどきという技も出ていたし、しばらく様子見。 とりあえずは1次元配列+縦横サイズ形式とする。(ローテク採用) データ格納形式が決まって、ラベリング探索アルゴリズム、楽なのは再帰呼び出しによる、 深さ優先探索だけど・・・、最悪 640 x 480 関数呼び出しがネストするので、スタック的にも 関数呼び出しオーバーヘッド的にも却下、キューを作って幅優先探索を作ることにする、TQueue を 普通に使うとメモリアロケートのオーバーヘッドが毎回出るし、姑息なことをしてもある程度 メモリアロケートは発生するし・・・姑息分を差し引くとキューも自作かな・・・。 というところで、暑さで思考が停止・・・。う〜ん、ピンチなのに。 2001/07/07 InputForms仕事が忙しい・・・というわけで、InputForms を Kylix に対応
EUC コードの同一ソースで、Delphi5 と Kylix の両方のコンパイルは通るけど、 印刷ボタンは化けるので、一応 SJIS 版と EUC 版の2つを配布。 |