| 
  
    | 技術解説 |  
    | 陰関数の高速描画 |  
    | 最終更新日:2007/05/11     
      新規 |  ●概要   従来Tipsで紹介していた方法は、時間が掛かり、ユーザのインタラクティブな処理に対応できない。今回、これを高速化したので紹介する。●原理  z = f(x, y) とすると、z = 0 
となる点の集合がその陰関数のグラフとなる。但し、多価関数になることが多いので、順序を持った点集合(つまり、曲線)としては認識できない。陽関数や、媒介変数関数に展開できない場合、闇雲に 
x, y を与えても、z = 0 
となるのは奇跡なので、うまい方法が必要となる。  極値でない場合、 z = 0 の前後では、z 
は、符号を変化している。例えば、  z > 0 at f(x, y)z = 0 at f(xt, y)
 z < 0 at f(x + dx, y)
  である。xt 
は、0になる真値で不明とする。しかし、dxで走査し、符号の反転があれば、少なくとも、x 
と x + dx の間に z = 0 となる、xt があることになる。dx 
が、例えば表示系のピクセル幅以下のような十分に小さければ、x 
= xt とできる。y 方向も同様な処理を行えば良い。 ●高速化  従来はビットマップで描画しており、サイズも固定で、処理時間が掛かっていたが、今回は、可変サイズでオンライン処理とした。以下のようである。 
  x、y の任意の範囲が外部より与えられる。その範囲を、1200分割して走査する。1200 
    は、最大の画面の幅を考慮した値。関数値の符号を求め、一行分を保存。直前行と現在行の二行分を持つ。x、y方向で符号の反転点を検出する。検出したら、その点の、関数座標(x, 
    y) を記録する。全範囲を処理する。  この方法であれば、範囲の変化に対応して、曲線の再演算がほぼリアルタイムで可能となる。 ・コード例 dx = (m_VRange.VMax - m_VRange.VMin) / 1200      '関数の変数刻みdy = (m_FRange.VMax - m_FRange.VMin) / 1200
 pp = 0
 Dim CMap(1200) As Integer       '現在行符号バッファ
 Dim PMap(1200) As Integer        '直前行符号バッファ
 For i = 0 To 1200
 Y = m_FRange.VMin + i * dy
 Array.Clear(CMap, 0, 1201)
 For j = 0 To 1200
 X = m_VRange.VMin + j * dx
 d = m_FuncXY(X, 
Y)             '関数値
 CMap(j) = 
Sign(d)                
'その符号を保存
 Z = 0
 If CMap(j) = 0 Then
 Z = 
1                      
'関数0点
 Else
 If i > 0 Then
 If CMap(j) 
<> PMap(j) Then
 Z = 
1                
'X方向0クロス点
 End If
 End If
 If j > 0 Then
 If CMap(j) 
<> CMap(j - 1) Then
 Z = 
1                
'Y方向0クロス点
 End If
 End If
 End If
 If Z = 1 Then
 ReDim Preserve m_PD(pp)
 m_PD(pp).X = X
 m_PD(pp).Y = 
Y            '座標点を保存(DoubleによるPoint構造体)
 pp = pp + 1
 End If
 Next
 PMap = 
CMap.Clone            '現在行を直前行にする
 Next
 ・表示  座標点 m_PD() 
があれば、プロットすべき点のみの処理となり、高速に描画できる(元の座標点が100万点あっても、実際に描画すべき点は高々数千程度となる)。座標値は関数での値なので、描画時に、表示領域の物理座標に変換する。   |