衝突検出は常にO(n ^ 2)ですか?


14

物理エンジンは、たとえば、互いに近くにあるオブジェクトをグループ化し、すべてのオブジェクトではなくこのグループ内の衝突をチェックすることにより、その複雑さを軽減できますか?(たとえば、他のオブジェクトからの速度と距離を調べることにより、遠いオブジェクトをグループから削除できます)。

そうでない場合、球体(3d)またはディスク(2d)の衝突は簡単になりますか?ダブルループを作成するか、代わりにペアの配列を作成する必要がありますか?

編集:弾丸やbox2dのような物理エンジンの場合、衝突検出はまだO(N ^ 2)ですか?


12
2つの単語:空間分割
MichaelHouse


1
あなたは賭けます。私は両方ともO(n log(n))アルゴリズムであるSAP(SweepとPrune)(とりわけ)の実装を持っていると信じています。詳細については、「ブロードフェーズ衝突検出」を検索してください。
マイケルハウス

2
@ Byte56 Sweep and Pruneの複雑さは、テストするたびにソートする必要がある場合にのみO(n log(n))になります。オブジェクトのソートされたリストを保持し、リストを追加するたびに正しい場所O(log(n))にソートするだけで、O(log(n)+ n)= O(n)が得られます。ただし、オブジェクトが動き始めると非常に複雑になります!
MartinTeeVarga

1
@ SM4、動きはその後、バブルソートの数回のパスが(そのの世話をすることができますだけで移動するオブジェクトをマークし、それらがソートされるまで、配列内の前方または後方にそれらを動かすだけで、他の移動オブジェクトに気を付ける限定されている場合。
ラチェットフリーク

回答:


14

最悪の場合、空間分割は常にO(N ^ 2)であり、それが情報学の複雑さです。

ただし、線形時間O(N)で機能するアルゴリズムがあります。それらはすべて、ある種のスイープラインに基づいています。

基本的に、オブジェクトを1つの座標でソートする必要があります。Xとしましょう。衝突検出の前に毎回ソートを実行すると、複雑度はO(N * logN)になります。トリックは、オブジェクトをシーンに追加するときと、シーン内の何かが変わったときにのみソートすることです。移動後の並べ替えは簡単ではありません。動きを取りながら線形時間で動作するアルゴリズムについては、以下のリンクされたペーパーを参照してください

次に、左から右にスイープします。スイープラインがオブジェクトの先頭を横切るたびに、一時リスト内に配置します。スイープラインがオブジェクトを出るたびに、リストから削除します。この一時リスト内でのみ衝突を考慮します。

素朴なスイープラインは最悪の場合もO(N ^ 2)です(すべてのオブジェクトをマップ全体に左から右に広げます)が、スマートにすることでO(N)にすることができます(以下のリンクを参照)。本当に良いアルゴリズムは非常に複雑です。

これは、スイープラインの仕組みを示す簡単な図です。

スイープラインアルゴリズム

線は左から右にスイープします。オブジェクトはX座標でソートされます。

  • ケース1:最初の2つのオブジェクトがチェックされます。他には何も関係ありません。
  • ケース2:最初のオブジェクトがチェックされ、リストから削除されました。2と3がチェックされます。
  • ケース3:そのオブジェクトが衝突している場合でも、チェックしません。
  • ケース4:このケースをチェックインしているためです!

このようなアルゴリズムの複雑さはO(C * N)= O(N)です。

出典:2年間の計算幾何学コース。

衝突検出では、これは通常SweepおよびPruneと呼ばれますが、アルゴリズムのスイープラインファミリは他の多くの分野で役立ちます。

私はこの質問の範囲外であると信じていますが、さらにお勧めの読書は興味深いですが:AABBの挿入と削除を使用した効率的な大規模なスイープとプルーニングの方法 -このホワイトペーパーでは、軸に合わせた境界ボックス(AABB )移動を考慮したソートを使用します。論文で紹介されているアルゴリズムは線形時間で機能します。


ここで、これが理論上最高のアルゴリズムであることに注意してください。それが使用されるという意味ではありません。実際には、空間分割を使用したO(N ^ 2)アルゴリズムは、一般的な場合(O(N)に近い)でパフォーマンスが向上し、メモリの追加要件があります。これは、O(C * N)の定数Cが非常に高くなる可能性があるためです!通常、十分なメモリがあり、典型的なケースでは空間にオブジェクトが均等に分散しているため、このようなアルゴリズムはより優れたパフォーマンスを発揮します。しかし、O(N)は元の質問に対する答えです。


box2d / bulletはこれを使用しますか?
jokoon

3
「スイープとプルーン」は、これが通常物理学と呼ばれるものです。良いことは、シミュレーションが進むにつれてソートを最新に保つことができることです。また、グラフィックのスイープラインは実装に関して少しずれています(ただし、理論上は良い)-ボックスの開始/終了を反復するだけなので、実際の潜在的な衝突のみをチェックすることになります。この方法は、直接使用するのではなく、より機能的な空間分割ツリーを生成するためにも使用されます。
ショーンミドルディッチ

3
技術的にはO(N ^ 2)ペアワイズ衝突が実際に発生する可能性があるため、スイープアンドプルーンが常にO(N)であると言うのは完全に真実ではありません。むしろ、アルゴリズムの中核となる複雑さはO(N + c)です。ここで、cはアルゴリズムによって検出された衝突の数です。多くの凸包アルゴリズムと同様に、出力依存です。(参照:en.wikipedia.org/wiki/Output-sensitive_algorithm
スティーブンスタドニッキ

1
いくつかの出版物または少なくともアルゴリズム名で主張を支持すべきです。
サムホセバー

1
@SamHocevar私は、定数の詳細な内訳で線形時間で動作する非常に高度なSweep and Pruneアルゴリズムへのリンクを追加しました。アルゴリズムが「Sweep and Prune」と呼ばれているという事実は、私がそれを扱ったことがないので、私にとって新しいものでした。私はこれらのアルゴリズムをマップ選択(他のオブジェクトとの1点の衝突のようなもの)で使用しているので、知識を適用しました。
MartinTeeVarga

8

いいえ。衝突検出は常にO(N ^ 2)と限りません

たとえば、サイズが10x10のオブジェクトを含む100x100のスペースがあるとします。このスペースをグリッドで10x10のセルに分割できます。

各オブジェクトは、最大4つのグリッドセルに入れることができます(ブロック内に収まるか、「間に」セルを配置できます)。各セルにオブジェクトのリストを保持できます。

それらのセルで衝突をチェックするだけです。グリッドセルごとに最大数のオブジェクトがある場合(たとえば、同じブロックに4つを超えるオブジェクトが存在しない場合)、各オブジェクトの衝突検出はO(1)であり、すべてのオブジェクトの衝突検出はO(N)です。

これはO(N ^ 2)の複雑さを回避する唯一の方法ではありません。他のユースケースに適した他の方法があります-多くの場合、ツリーベースのデータ構造を使用します。

説明したアルゴリズムは、スペース分割の一種ですが、他にもスペース分割アルゴリズムがあります。O(N ^ 2)時間的複雑さを回避するアルゴリズムについては、スペースパーティションデータ構造の種類をご覧ください。

Box2DとBulletは、チェックペアの数を減らすメカニズムをサポートしています。

マニュアル、セクション4.15:

物理ステップでの衝突処理は、狭相と広相に分けることができます。狭位相では、形状のペア間の接点を計算します。N個の図形があるとします。ブルートフォースを使用して、N * N / 2ペアの狭位相を実行する必要があります。

b2BroadPhaseクラスは、ペア管理に動的ツリーを使用することにより、この負荷を軽減します。これにより、狭位相呼び出しの数が大幅に削減されます。

通常、ブロードフェーズと直接対話することはありません。代わりに、Box2Dは広範なフェーズを内部的に作成および管理します。また、b2BroadPhaseはBox2Dのシミュレーションループを念頭に置いて設計されているため、他のユースケースには適していません。

Bullet Wikiから:

ペアの完全なリストを返す単純なO(n ^ 2)アルゴリズムを改良するさまざまな種類のブロードフェーズアルゴリズムがあります。これらの最適化されたブロードフェーズでは、衝突しないペアがさらに導入される場合がありますが、これは一般的に実行時間が改善されることで相殺されます。それらは異なるパフォーマンス特性を持ち、すべての状況で他のものより優れているものはありません。

ダイナミックAABBツリー

これは、BulletのbtDbvtBroadphaseによって実装されます。

名前が示すように、これは動的なAABBツリーです。このブロードフェーズの便利な機能の1つは、構造が世界とそのコンテンツの次元に動的に適応することです。非常に最適化されており、非常に優れた汎用ブロードフェーズです。多くのオブジェクトが動いている動的な世界を処理し、オブジェクトの追加と削除はSAPよりも高速です。

スイープとプルーニング(SAP)

Bulletでは、これはAxisSweepのクラスの範囲です。これは、汎用の大規模なフェーズでもあり、事前に知られている固定されたワールドサイズを必要とするという制限があります。このブロードフェーズは、ほとんどのオブジェクトがほとんどまたはまったく動きを持たない典型的なダイナミクスの世界で最高のパフォーマンスを発揮します。btAxisSweep3とbt32AxisSweep3は、パフォーマンスを向上させるために、各軸の開始点と終了点を浮動小数点数ではなく整数として量子化します。

次のリンクは、ブロードフェーズの一般的な紹介と、スイープとプルーンのアルゴリズムの説明です(ただし、「ソートとスイープ」と呼ばれます)。

http://www.ziggyware.com/readarticle.php?article_id=128

また、ウィキペディアのページもご覧ください。

http://en.wikipedia.org/wiki/Sweep_and_prune


同様の質問や外部リソースへのリンクがあれば、これは素晴らしい答えになります。
マイケルハウス

3
これは間違っています。あなたはまだO(N ^ 2)を得ています。N ^ 2/100のような高速ですが、それでもN ^ 2です。証拠として、すべてのオブジェクトがたまたま1つのセルにあることを考慮してください。
MartinTeeVarga

4
@ sm4これは最悪の場合のO(N ^ 2)です。これは、すべてのオブジェクトが1つのセルにある場合に実際に起こることです。ただし、物理エンジンでは、オブジェクトは通常1つのセルにはありません。私の例では、オブジェクトが3つ以上の他のオブジェクトと同じセルを共有することはできません。これは、「通常の」オブジェクトの物理エンジンで発生することです(「通常の」とは、「センサーだけでなく」を意味します)。
ルイスキューバル

アルゴリズムでは、4つのセルだけでなく、周囲の8つのセルをチェックインする必要があると思います。
jokoon

6
@luiscubal Complexityは常に「最悪のケース」です。理論的には、「保証された」複雑さを探しています。クイックソート(O(N ^ 2))とマージソート(O(N * logN))でも同じです。クイックソートは実際のデータでパフォーマンスが向上し、空間要件が低くなります。しかし、マージソートはより優れた複雑さを保証しています。何かを証明する必要がある場合は、mergesortを使用します。何かをソートする必要がある場合は、クイックソートを使用してください。
MartinTeeVarga

2

O(N ^ 2)は、N個のオブジェクトがある場合、何が何と衝突しているのか、最悪の場合、N ^ 2衝突の計算を行うという事実を指します。3つのオブジェクトがあるとします。「誰が誰を攻撃しているか」を見つけるには、以下を見つける必要があります。

o1 hitting o2?  o1 hitting o3?
o2 hitting o1?  o2 hitting o3?
o3 hitting o1?  o3 hitting o2?

それは衝突の6つのチェック、またはN *(N-1)チェックです。漸近解析では、多項式を展開し、O(N ^ 2)として近似します。100個のオブジェクトがある場合、それは100 * 99になり、100 * 100に十分近くなります。

したがって、たとえばオクトツリーを使用してスペースを分割すると、ボディ間の比較の平均回数が減少します。すべてのオブジェクトが非常に小さな領域に集まる可能性がある場合(たとえば、粒子が同じ領域に集まるような粒子流シミュレーションを行う場合)、O(N ^ 2)はまだ発生する可能性がありますシミュレーション内のポイント(スローダウンが発生するポイント)。

したがって、O(N ^ 2)のポイントは、シーン内の他のすべてのボディをチェックする各ボディの性質のためです。それが計算の性質です。しかし、多くのことがこれを安くするのに役立ちます。シーングラフ(同じ部屋内のオブジェクト間のみを検出するなど)でも、実行される衝突計算の数は大幅に削減されますが、O(M ^ 2)(Mは部屋内のオブジェクトの数です)衝突が検出されます)。球形の境界ボリュームにより、初期チェックが非常に高速になります(if( distance( myCenter, hisCenter ) > (myRadius+hisRadius) ) then MISS)。したがって、衝突検出がO(N ^ 2)であっても、境界球の計算は非常に高速に行われる可能性があります。


総当たりチェックを参照する必要はありません:巧妙なアルゴリズムに関係なく、N個のオブジェクトはそれぞれ他のすべてのオブジェクトと衝突し、O(N ^ 2)の処理を必要とするO(N ^ 2)衝突を与えます。優れたアルゴリズムは、衝突が少ない場合にのみうまく機能します。
ロレンツォガッティ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.