web-dev-qa-db-ja.com

3次元空間で凸包を見つける方法

一連の点S (x, y, z)が与えられます。それらのポイントのconvex hullを見つける方法は?

here からアルゴリズムを理解しようとしましたが、あまり理解できませんでした。

それは言う:

最初にすべてのポイントをxy平面に投影し、y座標が最も高いポイントを選択し、ギフトラッピングを1回繰り返してエッジのもう一方の端点を決定することにより、船体上にあるエッジを見つけます。これは不完全な船体の最初の部分です。次に、船体を繰り返し作成します。この最初のエッジについて考えてみましょう。次に、船体の最初の三角形の面を形成するために別の点を見つけます。他のすべてのポイントが右側に配置されるようにエッジを選択したギフトラッピングアルゴリズムと同様に、他のすべてのポイントがこの三角形の右側にあるようにポイントを選択することにより、これを行いますそのエッジ)。これで、船体に3つのエッジがあります。続行するには、そのうちの1つを任意に選択し、すべてのポイントをもう一度スキャンして別のポイントを見つけ、このEdgeで新しい三角形を作成し、エッジがなくなるまでこれを繰り返します。 (新しい三角形の面を作成するとき、2つのエッジをプールに追加します。ただし、最初にそれらが船体に既に追加されているかどうかを確認する必要があります。その場合、それらを無視します。)O(n)面。残りのすべての点をスキャンしてO(n2)を与える必要があるため、各反復にはO(n)時間かかります。

誰かがそれをより明確な方法で説明したり、より簡単な代替アプローチを提案したりできます。

18
Ninja420

3D凸包の実装は簡単ではありませんが、多くのアルゴリズムが実装されており、コードは広く利用可能です。品質と時間の上限で使用する投資は [〜#〜] cgal [〜#〜] です。両方のメジャーの下端は 自分のCコード です。
DCG Cover
中間には QuickHullのこの実装 を含む、Web全体のコードがあります。

18
Joseph O'Rourke

まず、クイックハルのような簡単な方法を試すことをお勧めします。 (ところで、ギフトラッピングの順序はO(nh) O(n2)ではありません。ここで、hは船体上のポイントで、クイックハルの順序はO(n log n)です)。

平均的な状況では、クイックハルは非常に適切に機能しますが、対称性が高い場合や、円の円周上にある点の場合、処理は通常遅くなります。クイックハルは、次の手順に分類できます。

  1. 最小と最大のx座標を持つポイントを見つけます。これらは凸の一部になるようにバインドされています。

  2. 2つのポイントによって形成される線を使用して、セットをポイントの2つのサブセットに分割します。これは再帰的に処理されます。 enter image description here

  3. 線の片側で、線からの最大距離でポイントを決定します。これまでに見つかった2つの点は、この1つとともに三角形を形成します。

  4. その三角形の内側にある点は、凸包の一部にすることはできないため、次の手順では無視できます。

  5. 三角形によって形成された2本の線(最初の線ではない)で前の2つの手順を繰り返します。 enter image description here

  6. ポイントがなくなるまで再帰を続け、再帰が終了し、選択されたポイントが凸包を構成します。 enter image description here

クイックハルアルゴリズムを使用した3D凸包については、 this 実装と説明を参照してください。

ギフト包装アルゴリズム:

Jarvisの一致アルゴリズムは、文字列の一部をポイントで囲むようなものです。左端の点は凸包の頂点でなければならないことがわかっているので、左端の点lを計算することから始めます。このプロセスには線形時間がかかります。次に、アルゴリズムは一連のピボットステップを実行して、次のlまで連続する各凸包の頂点を見つけます。頂点は、元の左端のポイントです。

アルゴリズムは、次のように連続する凸包の頂点を見つけます。点pの直後の頂点は、pに立っていて他の点を見ている人にとって、右端にあるように見える点です。つまり、qがpに続く頂点であり、rが他の入力ポイントである場合、トリプルp、q、rは反時計回りの順序になります。一連のO(n)反時計回りのテストを実行することにより、線形時間で連続する各頂点を見つけることができます。

アルゴリズムはO(n)の時間を各凸包頂点に費やしているため、最悪の場合の実行時間はO(n2)です。ただし、凸包の頂点が非常に少ない場合、ジャービスの行進は次のようになります。非常に高速です。実行時間を記述するより良い方法はO(nh)です。ここで、hは凸包の頂点の数です。最悪の場合、h = nであり、古いO(n2)時間制限がありますが、最良の場合はh = 3であり、アルゴリズムはO(n)時間のみを必要とします。これはいわゆる出力依存アルゴリズムであり、出力が小さいほど、アルゴリズムが高速です。

次の画像はあなたにもっとアイデアを与えるでしょう enter image description here

14
Aditya

3D凸包を見つけるためのGPL C++コードは http://www.newtonapples.net/code/NewtonAppleWrapper_11Feb2016.tar.gz で入手でき、O(n log(n))アルゴリズムの説明は http://www.newtonapples.net/NewtonAppleWrapper.html

4
David