web-dev-qa-db-ja.com

2Dポリラインのエッジの周りをトレースするための優れたアルゴリズムは何ですか

任意の数の頂点で構成されるポリラインがある場合、このポリラインの境界の周りをトレースするための効率的なアルゴリズムは何ですか?

考慮すべき4つの状況があります。

  1. ポリラインはそれ自体と交差せず、同一線上のエッジもありません。
  2. ポリラインはそれ自体と交差しませんが、内部または外部のループがあります。
  3. ポリラインには、蝶ネクタイの形をした自己交差があります。
  4. ポリラインには、内部ループを形成する自己交差があります。

それぞれの例(すべて閉じています):

  1. 頂点リスト=(5,3)(10,3)(10,7)(5,7)
  2. 頂点リスト=(0,0)(3,0)(3,3)(1,3)(1,2)(2,2)(2,3)(0,3)
  3. 頂点リスト=(5,3)(10,7)(10,3)(5,7)
  4. 頂点リスト=(0,0)(3,0)(3,4)(1,4)(1,2)(2,2)(2,3)(0,3)

視覚的に:

The shapes to trace the outline of.

この場合、形状の凹みを保持したいので、凸型ハリングアルゴリズムは実際には適切ではありません。

結果:

明確にするために、蝶ネクタイの形状を交差させてはならず、単純な面積計算でこの形状の面積が得られるはずです(つまり、2つの三角形は論理的に同じ方向に巻かれます)。

This is what the resultant shapes should look like

このアルゴリズムは機能する必要があるだけでなく(これが最優先事項です)、数秒で数十万のポリラインで実行するのに十分な速度である必要があります。

さらに、アルゴリズムは4つのケースの任意の組み合わせを処理できる必要があります。

1
Stephen

これはおそらくあなたの問題を解決するかもしれないアルゴリズムの大まかな概要です:

  1. ポリゴンを交差しない線に分解し、 平面グラフ を形成します。

  2. 平面グラフができたら、古典的な ギフトラッピング アルゴリズムをこのグラフに適合させて外側の船体を構築します

ステップ1は、エッジの各ペアに対して交差テストを行うことにより、単純ですが、あまり効率的ではない方法で実装できます(実行時間をO(#Edges²)にします)。より洗練された実装では、 スイープラインアプローチ を利用できます。スイープラインを既存の頂点の座標に移動するだけでなく、交点や平行線などにも注意し、それに応じて既存のラインを分割するように注意する必要があります。この手順を実行すると、線が交差したり重なったりすることはなくなります。

ステップ2は、従来の「凸包」アルゴリズムの単純な変更です。グラフの外側の頂点から開始し、ある頂点から次の隣接する頂点に移動して、「最小角度」で接続エッジを選択します。手順1で、データ構造の平面グラフが渡されることを確認してください。これにより、特定の頂点に接続されているすべてのエッジをすばやく選択できます。

お役に立てれば。

3
Doc Brown