2015.10.14

線分の描画

二次元図形のデジタル画像への変換処理を効率的に実行しよう. 今回は線分を対象とする.


走査変換

現代のコンピュータスクリーン(LCD や CRT)を利用する場合, 三次元の図形を CG 画像として表示するためには, まず,図形の構成要素(ポリゴンなど)を二次元に投影し, 更に,その二次元図形をディジタル画像(画素の集合) へ変換する必要がある. この画像化処理が 走査変換(scan-conversion,rasterize)である.

走査変換による CG は ラスタグラフィックスと呼ばれている. ラスタとは,昔のCRT(ブラウン管)の水平走査線のことだ.

実用的な CG では,膨大な量の図形要素を取り扱うことになるので, 走査変換の高速化が非常に重要な技術となっている. そこで今回は,走査変換について, 次の2通りの方法でプログラミングしてみよう.


問題の設定(線分の描画)

次のような仮定のもとで, Fig.1 のような線分(有限長の直線)を描くことにする:

Fig.1. 線分

直接解法および DDA による線分描画プログラムの実装例を示しておく:

なお,表示される画像中の y 軸の正方向は, 上向きではなく下向きであることに注意. (IT 界のスクリーン座標系では,歴史的な慣例で,y 軸は下向き. 数学界のグラフ座標系とは異なる.)

低速アルゴリズム(直接解法)

もっとも単純な線分描画アルゴリズムは次の通り:

プログラムを実装する際には, x1 = 0,y1 = 0 とみなして, 方程式 ydy x / dx の計算について, x を 0 から dx まで変化させて繰り返し, 画素(xx1yy1) を点灯する方が簡単

また,計算式自体は実数演算だが, 画面上の座標 xy は整数値であることに注意.

このアルゴリズムでは, 1画素についての計算はさほど複雑ではないが, 同じような結果をもたらす乗算・除算を何度も繰り返すことになるので, 線分全体として見ると,効率が悪い.


高速アルゴリズム(インクリメンタル解法)

以下,ブレゼンハムのアルゴリズムについて解説する. DDA については,サンプルソースコードを参照せよ.

直線の方程式を変形すると:

この左辺を 2 倍し,誤差関数 fxy)を定義しておく:

なぜ 2 倍するのか? 後述のアルゴリズムの実行中,関数値を常に整数に保つためだ.

座標値は基本的には整数なのだが, 四捨五入のために 1/2 刻みの実数と考える場面もある. しかし,その場面でも,係数 2 によって, 関数値は 1 刻みの整数のままにできる.

この関数の値は:

なお,ここではまだスクリーン座標系ではない. Fig.1 のように,左=+x 方向,上=+y 方向, として説明していることに注意.

となる. したがって,誤差関数が 0 となるようなすべての画素を 探し出して点灯すれば直線が描かれることになる.

しかし,ディジタル画像(各画素の座標値は整数のみ)なので, 誤差がぴったり 0.0 になるような画素はほとんど存在しない. つまり,誤差 0 の画素だけを点灯するだけでは, 直線のつもりが点線になってしまうだろう. そこで実際には,誤差関数の値が 0 に近い画素の集合を探索することになる.

なお,現在画素(xy)に対して, 隣接画素の候補は2個 {(x+1,y)と(x+1,y+1)}存在するが, Bresenham のアルゴリズムでは, それらの中間地点(x+1,y+1/2)1箇所の誤差関数を検査するだけで, 正しい隣接画素を合理的に決定する. さらに,この処理をインクリメンタルに (実数や乗除算を使わず,整数の加減算のみで高速に)実行する:

プログラムを実装する際には, x1 = 0,y1 = 0 とみなして... 画素(x+x1yy1)を点灯... DDA 等のソースコードを参考にせよ.

Fig.2 は,このアルゴリズムの説明図である. 判定点(×印)と直線の位置関係に応じて, 画素 P,Q,R が順次点灯されて行く. (Fig.2 では,格子点が画素の中心点を表わしている.四角形が画素ではない.)

Fig.2. ブレゼンハムのアルゴリズムによる線分の描画


本日の課題

サンプルソースファイル line.c の中に, ブレゼンハムのアルゴリズムによる高速線分描画関数 FastDrawLineBA( ) を定義せよ.

また,処理時間を測定し,他の手法の結果と比較せよ. (処理時間は一定ではない.3回程度ずつ測定せよ.)

このとき,純粋に計算時間だけを比較するために, 画面描き込み Off の状態で測定すること. なお,あたり前だが...速度比較の前に, 描画結果が正しいことを確認すること!

ソースコードのありがちなまちがい:

上級者向け:

レポート提出

描画結果のスクリーンショット画像を作るには, import コマンドを使えばよい.

# 対象のウィンドウを前面に出しておき...
$ import  画像ファイル.png
# 対象をクリック

# 画像の確認には...
$ display 画像ファイル.png &

(c) 2015, KY