ホーム ] コンポーネント開発 ] グリッドコントロール ] レギュラープレーヤ ] 数学関数表示コントロール ]

上へ
関数引継ぎ
陰関数の高速描画
陰関数の高速描画U
曲線解析
導関数
描画領域

技術解説

陰関数の高速描画

最終更新日: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 方向も同様な処理を行えば良い。

●高速化

 従来はビットマップで描画しており、サイズも固定で、処理時間が掛かっていたが、今回は、可変サイズでオンライン処理とした。以下のようである。

  1. x、y の任意の範囲が外部より与えられる。
  2. その範囲を、1200分割して走査する。1200 は、最大の画面の幅を考慮した値。
  3. 関数値の符号を求め、一行分を保存。直前行と現在行の二行分を持つ。
  4. x、y方向で符号の反転点を検出する。検出したら、その点の、関数座標(x, y) を記録する。
  5. 全範囲を処理する。

 この方法であれば、範囲の変化に対応して、曲線の再演算がほぼリアルタイムで可能となる。

・コード例

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万点あっても、実際に描画すべき点は高々数千程度となる)。座標値は関数での値なので、描画時に、表示領域の物理座標に変換する。