クリッピングアルゴリズム

コンピュータの処理能力の向上に伴い、ますます多くの人々がグラフィックを使用しようとしています。 一見、多くのアルゴリズムは直観的に見えますが、アプリケーションを許容可能な速度で動作させるには、古典的なアルゴリズムを勉強する必要があります。



この投稿は、同じタスク、つまりセグメントを切り離すタスクを目的としたいくつかのアルゴリズムの分析に当てられています。 画像を生成するときに、任意の形状とサイズの形状を取得できます。 多くの場合、モニターは生成された画像全体を表示できません。 また、画面上の画像の領域を設定し、この領域内にのみ画像を表示する必要がある場合もあります。 これらの問題を解決するために、クリッピングアルゴリズムが考案されました。



セグメントの切断



最も単純なクリッピングタスクは、セグメントを切り取ることです。 具体例で定式化します。 出力領域は長方形ABCDによって定義されると仮定します。 例を考えて、三角形PRQをカットオフ図として取ります。







クリッピング処理は完全に自動化される必要があります。 つまり PRQの三角形を描画するには、PQ; PP '; Q' Qの線描画コマンドのみを実行する必要があります。また、点P '; Q'の座標は事前にわかりません。

実際には、セグメントのポイントと出力領域の多数の相対位置が可能です。 この多様性により、アルゴリズムの観点からクリッピング操作が非常に重要になります。 これらの問題を解決するために、クリッピングアルゴリズムが作成されました。



Sutherland-Cohenアルゴリズム


SutherlandとCohenが提案したクリッピングアルゴリズムは非常に興味深いものです。 アルゴリズムの本質は、4ビットコードがセグメントの両端に割り当てられることです:b 0 、b 1 、b 2 、b 3 。 この4ビットコードには、出力領域に相対的なポイントの位置に関する情報が含まれています。 実際には、9つの組み合わせが可能です。



これらのコードを説明してください:

これらのコードを説明してください:





コードを受け取った後、次のオプションが可能です。

  1. コードには0のみが含まれます。これは、セグメント全体がウィンドウ内にあり、全体を描画する必要があることを意味します。
  2. コードには同じ位置に1ビットが含まれています。つまり、セグメントはウィンドウの外側にあり、描画されません。
  3. 他のすべての場合、セグメントの一部のみがウィンドウ内にあり、これはクリッピングが必要であることを意味します。


最初の2つのケースは、ビットごとの論理演算を使用して簡単に検証できます。 3番目のケースは最大の関心事です。 小さな具体的な例で考えてみましょう。







どちらかの端のコードに単一ビットが含まれている場合、P 1またはP 2のいずれかがウィンドウの外側からその境界の1つ(またはその継続)に移動します。 つまり ポイントP 1はポイントRに移動し、P 2はポイントUに移動します。新しいポイントについては、4ビットコードを再度計算します。 私たちの場合、セグメントの両端はまだウィンドウの外側にあります。 もう1つの移動が必要です。ポイントRがポイントSに移動し、ポイントUがポイントTに移動します。クリッピングプロセスは反復的であることがわかります。 各ステップでセグメントの両端間の距離が減少するため、アルゴリズムは収束していると言えます。 その結果、セグメントが取得されます(この例では(S; T)、表示する必要があります)。

別の例を使用して、このアルゴリズムの動作を考えてみましょう。







セグメントの位置(P 1 ; P 2 )は、完全な可視性の条件または完全な不可視性の条件のいずれにも対応しないため、この場合、ポイントの移動操作にも頼ります。



転送の実行後、セグメントの両端のコードは2番目の条件を満たします。 セグメント全体は画面に表示されません。

中間点アルゴリズム


Sutherland-Cohenアルゴリズムでは、線分とウィンドウの境界との交点を見つけるには、いくつかの反復が必要になる場合があります。 これは、バイナリ検索を使用して交差点の検索を実装する場合は回避できます。 このアイデアはSprullとSutherlandによって提案されました。 このアルゴリズムのソフトウェア実装は、Sutherland-Cohenアルゴリズムよりも遅くなりますが、アルゴリズムの基本操作はハードウェアで非常に効率的に実装されるため、ハードウェア実装は高速です。





このメソッドは、上記の4ビットコードも使用します。 これらのコードの助けを借りて、些細な可視性(a)と些細な不可視性(b)のケースが簡単に検出されます。 残りの(重要な)セグメントは2つの等しい部分に分割され、2つの新しく取得されたセグメントに対してチェックが実行されます。 分割とチェックは、ウィンドウの側面との交差が検出されるまで、または線がポイントに縮退するまで実行されます。 セグメントが縮退した後、その可視性を判断し、結果に応じて、現在に描画するかどうかを決定します。

セグメントcについて考えます。 明らかに、このセグメントは完全にウィンドウの外側にありますが、すぐに拒否することはできません。 そのため、半分の除算を実行し、セグメントの一部を除外します。 分割は、セグメントがポイントに変わった瞬間に終了します。 結果のポイントが不可視であることを確認した後、セグメント全体を描画すべきではないと結論付けます。

セグメントdも簡単に定義されていません。 2つの半分に分割すると(ポイント3)、両方の半分で同じ結果になります。 セグメント(3; 2)はポイント4で半分に分割されます。理論的には、セグメント(3; 4)をすでに描画できますが、これはあまり効果的ではありません。 ポイント4をポイント1から最も遠い可視ポイントとして記憶し、ウィンドウの下部境界と交差するまでセグメント(4; 2)を分割し続けることがより正確です。 結果のポイントは、ポイント1から最も遠い可視ポイントと見なされます。 セグメント3; 1も同様に処理され、可視ポイントがポイント2から最も遠い位置に配置されます。次に、これら2つのポイント間で描画が実行されます。

タイプdのセグメントの場合、セグメントの端から最も遠い可視ポイントの2つのバイナリ検索を実行する必要があります。 タイプeのセグメントの場合、バイナリ検索のいずれかは不要になりました。



Kirus-Beckアルゴリズム


Kirus-Beckアルゴリズムの作業では、区間のパラメトリック表現が使用されます:P s (t)= P 1 +(P 2 -P 1 )* t;t∈[0; 1]。 このアルゴリズムにより、長方形のウィンドウだけでなく、凸多角形によるクリッピングも可能になります。

切断ポリゴンの別のエッジE iを考えます。 このエッジの法線を切断ポリゴンの外側に向けます。 また、切断ポリゴンは反時計回りに回避されると想定しています。 次に、エッジがベクトルP (E (i 1 P E i 2の場合、法線N E iは比例します(y E i 2 -y E i 1 ; x E i 1 -x E i 2 )。

エッジが存在する線をL iで示します。 次に、直線L iで切り取られた領域は、ベクトル(PP E i )とN E iのスカラー積が0より大きい点Pに対応します(P E iはエッジE i上の任意の点です)。 セグメントが存在する直線とカットオフラインL iの交点は、方程式((P s (t)-P E i 、N E i = 0.この方程式を解くと、tが見つかります。

説明したアルゴリズムでは、P 1からP 2にセグメントに沿って移動するときにポイントが通過する方向(ウィンドウの内側または外側)が重要です。 これは符号((P 2 -P 1 )、N E iによって決定されます。次のような交差点を示します。







線L iとのすべての交点について座標tが計算された後、潜在的に着信する最大座標と潜在的に発信する最小座標を選択する必要があります(t VxMax ; t OutMin )。 セグメントP 1 P 2が位置するラインがカットオフポリゴンと交差する場合、t BxMax <t OutMinになります。 この場合、交点[t 1 、t 2 ] = [t BxMax 、t OutMin ]∩[0,1]が空でない場合、P s (t 1 )P s (t 2 )が望ましいカットオフセグメントになります。この場合、セグメントはカットオフ領域の完全に外側にあります。



もちろん、クリッピングのトピックはこれらのアルゴリズムで終わりではありません。 別の問題は、ポリゴンクリッピングアルゴリズムです。 トピックがhabrasocietyにとって興味深いものである場合、私は間違いなくこのトピックを明らかにします。



All Articles