ホーム ] TIPS ウィンドウズ系 ] TIPS グラフィックス系 ] TIPS メルチメディア系 ] TIPS 理数系 ] TIPS 総覧 ]

上へ
G0001 色名一覧
G0002 アルファブレンド
G0003 カラーマップを作る
G0101 曲線の数値化
G0102 曲線長を測る
G0103 曲線の接線・法線
G0104 曲線のスムージング
G0201 図形の回転
G0202 領域の認識
G0301 文字の線形変換
G0302 文字の自由変形
G0303 文字の極座標変換
G0304 曲線に沿った文字列
G0305 飾文字-中抜き
G0306 飾文字-縁取り
G0307 飾文字-ドロップダウンシャドウ
G0501 画像の線形変換
G0502 画像の透明化
G0503 画像の任意形状切出し
G0504 画像の回転
G0505 画像の高速処理化

VB.NET2005 TIPS / グラフィックス系

G0104 曲線のスムージング

最終更新:2006/11/12 新規

●解説

  マウスドローなどで描かれた曲線は、必要以上に点数が多い、曲線が細かく振れているなどの弊害が見受けられる。下図参照。ここでは、曲線を構成する点を再構成し、点数を適正化し、同時に曲線に滑らかさを得るような方法を紹介する。 

ドローで作成した曲線
(赤点が発生した点)

法線を描くと方向が乱れている
(細かく震えていることを示す)
スムージング結果、法線は揃っている
(緑の点がリサンプル点)

●原理 

 単純に点を間引いても良さそうであるが、点密度が偏ってしまう可能性があり、何らかのアルゴリズムが必要となる。ここでは、得られた曲線を有効な距離分解能で再構成し、点を振り直し、改めてスプライン補間すると言うアルゴリズムを採用する。有効な距離分解能は、見た目で(全長、最小の意味のある曲がり具合など考慮)単位となる距離を指定するものとする。結果として、点の進行方向の点密度が一定となる。但し、曲線の曲率に応じた点密度の変化はない。

 上図のように、オリジナルの点を距離を計算しながら辿り、ΔLづつ新しい点(新しい点間の直線距離がΔLではない)を決めてゆく。新しい点で、スプライン補間すると、結局スムージングされ、点数も減る。 

●方法 

  1. 適当な単位距離dLを決める。

  2. 始点から全長以内をdLづつたどり、新しい点を作成してゆく。

  3. 新しいPoint配列でスプライン曲線を描いたり、得たりする。

●実例 

○例1:一次線形補間

この場合、不要な凹凸が全くなくなったり、不自然なピーク点が採用される可能性がある。 

CL()は元の曲線(fps())の線長テーブル 

    Dim i, LM, n As Integer
    Dim dL, L, X, Y, A As Single
    Dim nfp() As PointF                      
新しい点配列
    LM = CL.Length - 1
    dL = (適当な値)
    L = 0
    n = 0
    While L <= CL(LM)
        GetCurveParam(fps, CL, L, X, Y, A)     
距離Lの点を見つける
        ReDim Preserve nfp(n)
        nfp(n).X = X : nfp(n).Y = Y
        g.FillEllipse(Brushes.Red, New RectangleF(X - 3, Y - 3, 7, 7))
        L = L + dL
        n = n + 1
    End While
   g.DrawCurve(Pens.DarkGreen, nfp) 

GetCurveParamここを参照。 

○例2:近傍2〜4点から求める

新しい点を近傍2〜4点から求める方法もある。この場合は、不要な凹凸を全体として減少させる方向となる。不自然なピークは減少する方向となる。 

ksは近傍点の始まり、keはその終わり

距離に対応する点の位置によって、近傍点数が変わる 

   For i = 1 To c - 1
        Select Case i
            Case 1
                ks = 0 : ke = 2                  
始め:最初の3点
            Case c - 1
                ks = c - 2 : ke = c
1         終わり:最後の2点
            Case Else
                ks = i - 2 : ke = i + 1          
中間:前後の4点
        End Select
        Xa = 0.0F : Ya = 0.0F
        For k = ks To ke
            Xa = Xa + po(k).X
            Ya = Ya + po(k).Y
        Next
        Xa = Xa / (ke - ks + 1)
        Ya = Ya / (ke - ks + 1)

  ・・・・・・・・・・・・・・・・・・・・・・・・
    Next