
コンピュータグラフィックスにおいて、線描画アルゴリズムとは、ピクセルベースのディスプレイやプリンタなどの離散的なグラフィック媒体上で線分を近似するためのアルゴリズムである。このような媒体では、線描画には(非自明な場合)近似が必要となる。基本的なアルゴリズムでは、線を単一の色でラスタライズする。複数の色のグラデーションを用いたより正確な表現には、空間アンチエイリアシングという高度な処理が必要となる。
一方、連続媒体では、線を描画するためにアルゴリズムは必要ありません。例えば、陰極線オシロスコープはアナログ回路を用いて線や曲線を描画します。高速CPUが登場する以前は、このようなモニターは、ワイヤーフレーム図面を用いた自動車設計などの高度なCAD/CAMアプリケーション分野で使用されていました。これらのシステムは、コンピュータから少数の(x,y)ベクトルを受け取るだけで、すぐに線画像を描画できました。ピクセルの強度しか受け付けないディスプレイ上で視覚化するには、デジタルアルゴリズムを開発する必要がありました。

単色線描画アルゴリズムは、背景色に対して単一の前景色で線を描画するものです。モノクロディスプレイでの使用に適しています。
目的とする直線の始点と終点は通常、整数座標で指定されるため、アルゴリズムが考慮する点と直接重なります。そのため、ほとんどのアルゴリズムは、このような始点と終点のみを対象として設計されています。
線を引く最も簡単な方法は、線方程式からピクセル位置を直接計算することです。開始点が与えられた場合そして終点直線上の点は方程式を満たす、 とこれは直線の傾きです。直線は、次の擬似コードに示すように、単純なループを使用してこの方程式を評価することによって描画できます。
dx = x2 − x1 dy = y2 − y1 m = dy/dx x1からx2までxについて y = m × (x − x1) + y1 plot(x, y)
ここでは、ポイントはすでに次のように順序付けられています。。
このアルゴリズムは、ループに乗算が含まれているため、不必要に遅くなっています。乗算は、ほとんどのデバイスで加算や減算よりも大幅に遅いためです。より高速な方法は、連続する2つのステップ間の差分を見ることで実現できます。
したがって、単にその地点から始めるだけで十分ですそして、によるループの各反復で一度だけ実行されます。このアルゴリズムはデジタル微分解析器として知られています。
丸め処理のため最も近い整数に丸めることは、四捨五入することと同じです。下方向への丸めを回避するには、0.5で初期化された追加の制御変数を使用します。は、各反復でこの変数に追加されます。次に、この変数が 1.0 を超えると、は1ずつ増加し、制御変数は1ずつ減少します。これにより、アルゴリズムは丸めを回避し、整数演算のみを使用できます。ただし、短い行の場合、この高速なループは、コストのかかる除算を補うものではありません。これは、初期段階では依然として必要である。
これらのアルゴリズムは、(つまり、傾きが1以下である場合)(つまり、傾きが 1 より大きい場合)、線は多くのギャップで非常に疎になり、極限の場合、ゼロ除算例外が発生します。
特定の状況下では、単色線描画アルゴリズムは次のような問題に直面する。
同じ長さでも傾きが異なる線を描画する場合、描画されるピクセル数は異なります。そのため、同じ長さの線でも、傾きの急な線は傾きの緩やかな線よりもピクセル数が少なくなり、結果として傾きの急な線の方が明るく表示されます。この問題は、モノクロ表示のデバイスでは避けられません。
クリッピングとは、ラスタライズ処理を限られた領域(通常は長方形)に限定する操作です。これは、指定された線の始点と終点が領域の外側にある場合、それらをその領域の境界に移動させることによって行われます。一般的に、この操作によってこれらの点の座標は整数ではなくなります。これらの座標を単純に丸めると、結果として得られる線の傾きが意図したものと異なってしまいます。この問題を回避するには、クリッピング後に追加のテストを行う必要があります。
単色線描画アルゴリズムの最大の問題点は、線が粗くギザギザした外観になってしまうことです。複数の輝度レベルを表示できるデバイスでは、アンチエイリアシングによってこの問題を回避できます。アンチエイリアシングでは、線は通常、所望の太さの長方形として2次元的に表現されます。これらの線を描画するには、この長方形の近くにある点を考慮する必要があります。
Gupta -SproullアルゴリズムはBresenhamの線アルゴリズムに基づいているが、アンチエイリアシングを追加している。
Gupta-Sproullアルゴリズムの最適化されたバリアントは、擬似コードで次のように記述できます。
DrawLine(x1, x2, y1, y2) { x = x1; y = y1; dx = x2 − x1; dy = y2 − y1; d = 2 * dy − dx; // 判別器 // 点(x,y)から直線(符号付き)までのユークリッド距離 D = 0; // 点 (x1, y1) と (x2, y2) 間のユークリッド距離 長さ = sqrt(dx * dx + dy * dy); sin = dy / length; cos = dx / 長さ; while (x <= x2) { IntensifyPixels(x, y − 1, D + cos); IntensifyPixels(x, y, D); IntensifyPixels(x, y + 1, D − cos); x = x + 1 if (d <= 0) { D = D + sin; d = d + 2 * dy; }それ以外{ D = D + sin − cos; d = d + 2 * (dy − dx); y = y + 1; } } }IntensifyPixels(x,y,r) 関数は、放射状の線変換を受け取り、ピクセル (x,y) の強度を、線からピクセルまでの距離 r に依存する 3 次多項式の値で設定します。
線描画アルゴリズムは、近似法、ハードウェアによる直接実装、および並列化によって効率化できる。このような最適化は、多数の線をリアルタイムで描画する場合に必要となる。
BoyerとBourdinは、理想的な直線の真下にあるピクセルに色を付ける近似アルゴリズムを導入しました。[ 1 ]このようにレンダリングされた直線は、利用できる特別な特性をいくつか示します。たとえば、このような場合、直線のセクションは周期的です。これにより、特に長い直線の場合、正確なバリアントよりも大幅に高速なアルゴリズムが実現します。品質の低下は、傾斜が非常に小さい直線でのみ見られます。
単色線ラスタライズを並列化する簡単な方法は、複数の線描画アルゴリズムに、互いに一定の距離だけ離れたオフセットピクセルを描画させることです。[ 2 ]別の方法としては、線をほぼ等しい長さの複数のセクションに分割し、それらを異なるプロセッサに割り当ててラスタライズする方法があります。主な問題は、これらのセクションの正しい開始点と終了点を見つけることです。
数千個のプロセッサを備えた大規模並列プロセッサアーキテクチャ向けのアルゴリズムも存在する。これらのアルゴリズムでは、ピクセルのグリッドから各ピクセルが単一のプロセッサに割り当てられ、そのプロセッサが与えられたピクセルに色を付けるかどうかを決定する。[ 3 ]
ラスタライズ中のメモリアクセスを高速化するために、特別なメモリ階層が開発されました。たとえば、メモリを複数のセルに分割し、各セルが独立してラインの一部をレンダリングします。[ 4 ] アンチエイリアシングを伴うラスタライズは、専用ハードウェアによってもサポートできます。[ 5 ]
線は8連結だけでなく4連結でも描画できます。4連結とは、水平方向と垂直方向のステップのみが許可され、斜め方向のステップは禁止されていることを意味します。正方形ピクセルのラスタが与えられた場合、これにより、線の一部を含むすべての正方形が着色されます。4連結線描画方法を3次元に一般化したものが、例えば最適化されたレイトレーシングのように、ボクセルグリッドを扱う際に使用され、特定のレイが通過するボクセルを特定できます。
線描画アルゴリズムは、対角線上のステップをほぼ均等に分配します。したがって、線描画アルゴリズムは、与えられた区間内の整数座標を持つ点を均等に分配するためにも使用できます。[ 6 ] この方法の応用例としては、信号処理における線形補間やダウンサンプリングなどが挙げられます。また、ユークリッドアルゴリズムやファレイ数列、その他多くの関連する数学的構成とも類似点があります。 [ 7 ]