Loading article…
コンピュータグラフィックスにおいて、Liang–Barskyアルゴリズム( You-Dong LiangとBrian A. Barskyにちなんで命名)は、 1984年初頭に初めて発表された線分クリッピングアルゴリズムです。Liang–Barskyアルゴリズムは、線分の媒介変数表示とクリッピングウィンドウの範囲を表す不等式を用いて、線分とクリッピングウィンドウの交点を決定します。これらの交点によって、線分のどの部分を描画すべきかが分かります。そのため、このアルゴリズムはCohen–Sutherlandアルゴリズムよりもはるかに効率的です。Liang–Barskyクリッピングアルゴリズムの基本的な考え方は、線分の交点を計算する前に、できるだけ多くのテストを行うことです。
このアルゴリズムは直線のパラメトリック表現を使用します。
ポイントがクリップウィンドウ内にある場合、
そして
これは4つの不等式として表現できる。
どこ
最終的な線分を計算するには:
// Liang–Barsky 線切りアルゴリズム#include <iostream> #include <graphics.h> #include <math.h>using namespace std ;// この関数は最大値を返しますfloat maxi ( float arr [], int n ) { float m = 0 ; for ( int i = 0 ; i < n ; ++ i ) if ( m < arr [ i ]) m = arr [ i ]; return m ; }// この関数は最小のfloat mini ( float arr [], int n ) { float m = 1 ; for ( int i = 0 ; i < n ; ++ i ) if ( m > arr [ i ]) m = arr [ i ]; return m ; }void liang_barsky_clipper ( float xmin , float ymin , float xmax , float ymax , float x1 , float y1 , float x2 , float y2 ) { // 変数の定義float p1 = - ( x2 - x1 ); float p2 = - p1 ; float p3 = - ( y2 - y1 ); float p4 = - p3 ;float q1 = x1 - xmin ; float q2 = xmax - x1 ; float q3 = y1 - ymin ; float q4 = ymax - y1 ;float exitParams [ 5 ], entryParams [ 5 ]; int exitIndex = 1 , entryIndex = 1 ; exitParams [ 0 ] = 1 ; entryParams [ 0 ] = 0 ;rectangle ( xmin , ymin , xmax , ymax ); // クリッピングウィンドウを描画if (( p1 == 0 && q1 < 0 ) || ( p2 == 0 && q2 < 0 ) || ( p3 == 0 && q3 < 0 ) || ( p4 == 0 && q4 < 0 )) { outtextxy ( 80 , 80 , "Line is parallel to clipping window!" ); return ; } if ( p1 != 0 ) { float r1 = q1 / p1 ; float r2 = q2 / p2 ; if ( p1 < 0 ) { entryParams [ entryIndex ++ ] = r1 ; exitParams [ exitIndex ++ ] = r2 ; } else { entryParams [ entryIndex ++ ] = r2 ; exitParams [ exitIndex ++ ] = r1 ; } } if ( p3 != 0 ) { float r3 = q3 / p3 ; float r4 = q4 / p4 ; if ( p3 < 0 ) { entryParams [ entryIndex ++ ] = r3 ; exitParams [ exitIndex ++ ] = r4 ; } else { entryParams [ entryIndex ++ ] = r4 ; exitParams [ exitIndex ++ ] = r3 ; } }float clippedX1 , clippedY1 , clippedX2 , clippedY2 ; float u1 , u2 ; u1 = maxi ( entryParams , entryIndex ); // エントリーポイントの最大値u2 = mini ( exitParams , exitIndex ); // 出口ポイントの最小値if ( u1 > u2 ) { outtextxy ( 80 , 80 , "線がクリッピングウィンドウの外にあります!" ); return ; }clippedX1 = x1 + ( x2 - x1 ) * u1 ; clippedY1 = y1 + ( y2 - y1 ) * u1 ; clippedX2 = x1 + ( x2 - x1 ) * u2 ; clippedY2 = y1 + ( y2 - y1 ) * u2 ;setcolor ( CYAN ); line ( clippedX1 , clippedY1 , clippedX2 , clippedY2 ); // 切り取られたセグメントを描画setlinestyle ( 1 , 1 , 0 ); line ( x1 , y1 , clippedX1 , clippedY1 ); // 元の開始位置からクリップされた開始位置までline ( x2 , y2 , clippedX2 , clippedY2 ); // 元終了位置からクリップされた終了位置まで}int main () { cout << " \n Liang-Barsky ライン クリッピング" ; cout << " \nシステム ウィンドウのレイアウトは、左下が (0,0)、右上が (631, 467) です" ; cout << " \nウィンドウの座標 (xmin, ymin, xmax, ymax) を入力してください: " ; float xmin , ymin , xmax , ymax ; cin >> xmin >> ymin >> xmax >> ymax ;cout << " \n線分 (x1, y1) と (x2, y2) の端点を入力してください: " ; float x1 , y1 , x2 , y2 ; cin >> x1 >> y1 >> x2 >> y2 ;int gd = DETECT , gm ; initgraph ( & gd , & gm , "" ); // winbgimを使用liang_barsky_clipper ( xmin , ymin , xmax , ymax , x1 , y1 , x2 , y2 ); getch (); closegraph (); }同じ目的で使用されるアルゴリズム: