はじめてのVB

以前からずっと使っている(かのB. DeMarco*1の手になるらしい)CCDカメラ制御&画像解析プログラムの一部をPCI用にちょっと修正した.これがなんとVisual Basic 6.0で書かれている.勘弁してくれ! (CCDカメラに付属のメーカー謹製制御ソフトをCOM経由で動かしているので,自分の好きな言語で再実装... とはやり難い)
Visual Basic 6.0にはArcCosがないらしい.ググってそれっぽいコードを拾ってきたが,定義域がどうなってるかは完全スルー:

There is no ArcSin and ArcCos functions in Visual Basic, but there is ArcTan function, and you can use it to calculate both ArcSin and ArcCos.

ということで以下のコードをコピペ:

Function ArcCos(X As Double) As Double
    ArcCos = Atn(-X / Sqr(-X * X + 1)) + 2 * Atn(1)
End Function

しかしプログラムを実行してみるとエラー → 強制終了を連発.VB 6.0のエラーはスタック・トレースを吐かないのだが,どうやらこのArcCosに渡る引数(CCD信号の強度の比みたいなもの)がSqrAtn (ArcTan)の定義域に違反しているらしい.そこで禁術 On Error ... を使ってみた.

Function ArcCos(X As Double) As Double
    On Error GoTo ErrorHandler
    ArcCos = Atn(-X / Sqr(-X * X + 1)) + 2 * Atn(1)
ErrorHandler:
    ArcCos = 0
End Function

すると結果の画像が0で塗りつぶされてしまった.どうやら上のように書くとエラーが出ないときも ArcCos = 0 が実行されてしまうようだ.そこで次のように修正したらOKだった:

Function ArcCos(X As Double) As Double
    On Error GoTo ErrorHandler
    ArcCos = 0
    ArcCos = Atn(-X / Sqr(-X * X + 1)) + 2 * Atn(1)
ErrorHandler:
End Function

関数の返り値を表す ArcCos にまず0を代入し,そこに欲しい値を代入する行で,右辺の計算途中にエラーが出たら0から書き換わらないままに関数が終了する.
ちなみに 2 * Atn(1) のようにArcTanを経由して円周率を表現するのは,円周率が定数として用意されてないシステムでは常套手段である.まぁ日本人は円周率をよく暗記しているので手で3.14159265くらいまで書けば十分だろうけど.

*1:http://www.physics.uiuc.edu/People/DeMarco/ Brian L. DeMarco, Department of Physics at the University of Illinois at Urbana-Champaign