충돌 감지는 항상 O (n ^ 2)입니까?


14

물리 엔진은 예를 들어 서로 가까이있는 객체를 그룹화하여 모든 객체 대신이 그룹 내에서 충돌을 확인하는 등 복잡성을 줄일 수 있습니까? 예를 들어, 원거리 객체는 다른 객체와의 속도와 거리를보고 그룹에서 제거 할 수 있습니다.

그렇지 않은 경우, 구 (3d) 또는 디스크 (2d)에 대해 충돌이 사소한가? 이중 루프를 만들거나 대신 쌍의 배열을 만들어야합니까?

편집 : 글 머리 기호 및 box2d와 같은 물리 엔진의 경우 충돌 감지가 여전히 O (N ^ 2)입니까?


12
두 단어 : 공간 분할
MichaelHouse


1
물론이지. 둘 다 O (n log (n)) 알고리즘 인 SAP ( Sweep 및 Prune ) (다른 것들 중에서)를 구현했다고 생각합니다 . 자세한 내용은 "광역 충돌 감지"를 검색하십시오.
MichaelHouse

2
@ Byte56 Sweep 및 Prune은 테스트 할 때마다 정렬해야하는 경우에만 복잡도 O (n log (n))를 갖습니다. 정렬 된 객체 목록을 유지하고 싶을 때마다 올바른 위치에 정렬하면 O (log (n)) O (log (n) + n) = O (n)이됩니다. 객체가 움직이기 시작하면 매우 복잡해집니다!
MartinTeeVarga 2016 년

1
@ SM4, 운동 후 거품 종류의 몇 패스 (즉 돌볼 수 바로 이동 객체를 표시하고 정렬 될 때까지 배열의 전방 또는 후방으로 이동 다만 다른 이동 물체에 대한 조심 제한됩니다.
래칫 괴물

답변:


14

공간 분할은 최악의 경우 항상 O (N ^ 2)이며 정보학의 복잡성에 관한 것입니다.

그러나 선형 시간 O (N)에서 작동하는 알고리즘이 있습니다 . 그들 모두는 일종의 스윕 라인을 기반으로합니다.

기본적으로 객체를 하나의 좌표로 정렬해야합니다. X라고 가정 해 봅시다. 충돌 감지 전에 매번 정렬을 수행하면 복잡도는 O (N * logN)입니다. 트릭은 장면에 객체를 추가 할 때와 나중에 장면의 무언가가 변경 될 때만 정렬하는 것입니다. 이동 후 정렬이 간단하지 않습니다. 움직임을 취하고 여전히 선형 시간으로 작동하는 알고리즘에 대해서는 아래 링크 된 문서를 참조하십시오 .

그런 다음 왼쪽에서 오른쪽으로 스윕합니다. 스윕 선이 객체의 시작 부분을 지나갈 때마다 임시 목록에 배치합니다. 스윕 라인이 객체를 빠져 나갈 때마다리스트에서 꺼냅니다. 이 임시 목록 내에서만 충돌을 고려합니다.

순진한 스윕 라인은 최악의 경우에도 O (N ^ 2)입니다 (모든 객체를 왼쪽에서 오른쪽으로 전체 맵으로 확장). 그러나 더 똑똑하게 만들어 O (N)로 만들 수 있습니다 (아래 링크 참조). 정말 좋은 알고리즘은 매우 복잡합니다.

다음은 스윕 라인 작동 방식에 대한 간단한 다이어그램입니다.

스윕 라인 알고리즘

선이 왼쪽에서 오른쪽으로 스윕됩니다. 개체는 X 좌표로 정렬됩니다.

  • 사례 1 : 처음 두 개체가 검사됩니다. 다른 것은 중요하지 않습니다.
  • 사례 2 : 첫 번째 개체가 확인되었고 목록에서 사라졌습니다. 둘과 셋이 확인됩니다.
  • 사례 3 : 해당 개체가 충돌하더라도 검사하지 않습니다.
  • 사례 4 : 우리는이 경우를 확인하기 때문에!

이와 같은 알고리즘은 복잡도 O (C * N) = O (N)을 갖습니다.

출처 : 2 년간의 계산 기하학 과정.

충돌 감지에서는 일반적으로 Sweep and Prune 이라고 하지만 스위프 라인 알고리즘 계열은 다른 많은 분야에서 유용합니다.

또한 나는이 질문의 범위를 벗어난 생각하지만, 그럼에도 불구하고 흥미로운 독서 권장 : 효율적인 대규모 스윕 및 AABB 삽입과 자두 방법 및 제거 -이 종이 선물 용도가 경계 상자 정렬 축 것을 향상된 스윕와 자두 알고리즘을 (AABB 이동을 고려한 정렬 논문에 제시된 알고리즘은 선형 시간으로 작동합니다.


이제주의 이 이론에서 가장 알고리즘이다 . 그것이 사용된다는 의미는 아닙니다. 실제로, 공간 분할을 갖는 O (N ^ 2) 알고리즘은 전형적인 경우 (O (N)에 가까운) 더 나은 성능 속도와 메모리에 대한 추가 요구 사항을 갖습니다. O (C * N)의 상수 C가 매우 높을 수 있기 때문입니다! 일반적으로 메모리가 충분하고 일반적인 경우 공간에 객체가 고르게 분포되어 있기 때문에 이러한 알고리즘은 더 나은 성능을 발휘합니다. 그러나 O (N)는 원래 질문에 대한 답입니다.


box2d / bullet이 이것을 사용합니까?
jokoon

3
"스윕 및 프룬"은 이것이 일반적으로 물리학에서 요구되는 것입니다. 좋은 점은 시뮬레이션이 진행됨에 따라 정렬을 최신 상태로 유지할 수 있다는 것입니다. 또한 그래픽의 스윕 라인은 구현 측면에서 약간 벗어납니다 (이론에는 적합 함). 상자 시작 / 끝을 반복하기 만하면 실제 충돌 가능성 만 확인하게됩니다. 이 방법은 직접 사용하는 것보다 더 유능한 공간 분할 트리를 생성하는 데 사용됩니다.
Sean Middleditch 2016 년

3
기술적으로 실제로 O (N ^ 2) 페어 충돌이있을 수 있기 때문에, 그렇지 않아 완전히 스윕 앤 자두는 항상 O (N)라고하는 사실. 오히려, 알고리즘의 핵심 복잡도는 O (N + c)이며, 여기서 c는 알고리즘에 의해 발견 된 충돌의 수입니다 . 많은 볼록 껍질 알고리즘과 마찬가지로 출력에 민감 합니다. (참조 : en.wikipedia.org/wiki/Output-sensitive_algorithm )
Steven Stadnicki 2016 년

1
일부 출판물이나 최소한 알고리즘 이름으로 클레임을 뒷받침해야합니다.
sam hocevar

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의 시뮬레이션 루프를 염두에두고 설계되었으므로 다른 사용 사례에는 적합하지 않을 수 있습니다.

로부터 총알 위키 :

전체 쌍 목록을 반환하는 순진 O (n ^ 2) 알고리즘을 개선하는 다양한 종류의 광대역 알고리즘이 있습니다. 이러한 최적화 된 광대역은 때때로 더 많은 비 충돌 쌍을 도입하지만 일반적으로 개선 된 실행 시간으로 상쇄됩니다. 성능 특성이 다르며 모든 상황에서 다른 성능 특성을 능가하지는 않습니다.

동적 AABB 트리

이것은 Bullet의 btDbvtBroadphase에 의해 구현됩니다.

이름에서 알 수 있듯이 이것은 동적 AABB 트리 입니다. 이 넓은 단계의 유용한 기능 중 하나는 구조가 세계의 크기와 내용에 동적으로 적응한다는 것입니다. 그것은 매우 잘 최적화되어 있으며 범용성이 매우 뛰어납니다. 많은 객체가 움직이는 동적 인 세계를 처리하며 SAP보다 객체 추가 및 제거가 더 빠릅니다.

청소 및 정리 (SAP)

Bullet에서는 이것이 AxisSweep 범위의 클래스입니다. 또한 사전에 알려진 고정 월드 크기가 필요하다는 제한이 있지만 좋은 범용 광대역입니다. 이 넓은 단계는 대부분의 물체에 움직임이 거의 없거나 전혀없는 전형적인 역학 세계에서 최고의 성능을 발휘합니다. btAxisSweep3 및 bt32AxisSweep3 모두 성능을 향상시키기 위해 부동 소수점 숫자 대신 정수로 각 축의 시작 및 끝 지점을 양자화합니다.

다음 링크는 broadphase에 대한 일반적인 소개와 Sweep 및 Prune 알고리즘에 대한 설명입니다 ( "Sort and Sweep"이라고 함).

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

또한 wikipedia 페이지를보십시오.

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


비슷한 질문과 외부 리소스에 대한 일부 링크는 이것이 훌륭한 답변이 될 것입니다.
MichaelHouse

3
이것은 잘못이다. 여전히 O (N ^ 2)를 받고 있습니다. N ^ 2 / 100과 같이 훨씬 빠르지 만 여전히 N ^ 2입니다. 증거로 모든 개체가 하나의 셀에있는 것으로 간주하십시오.
MartinTeeVarga

4
@ sm4 이것은 최악의 경우 O (N ^ 2)이며, 모든 개체가 하나의 셀에있는 경우 실제로 발생합니다. 그러나 물리 엔진에서 객체는 일반적으로 하나의 셀에 있지 않습니다 . 내 예에서는 어떤 개체도 같은 셀을 3 개 이상의 다른 개체와 공유 할 수 없습니다. 이것은 "정상적인"물체에 대한 물리 엔진에서 일어나는 일입니다. "정상적인"이란 "단지 센서가 아니라"를 의미합니다.
luiscubal

알고리즘이 4 셀이 아닌 8 셀 주위를 체크인해야한다고 생각합니다.
jokoon

6
@luiscubal Complexity는 항상 "최악의 경우"입니다. 이론적으로는 "보증 된"복잡성을 찾고 있습니다. quicksort (O (N ^ 2))와 mergesort (O (N * logN))와 동일합니다. Quicksort는 실제 데이터에서 더 나은 성능을 제공하며 공간 요구 사항이 더 낮습니다. 그러나 mergesort는 더 나은 복잡성을 보장했습니다. 무언가를 증명해야 할 경우 mergesort를 사용하십시오. 무언가를 정렬해야하는 경우 quicksort를 사용하십시오.
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) 충돌이 발생합니다. 좋은 알고리즘은 충돌이 적은 경우에만 더 잘 수행 할 수 있습니다.
Lorenzo Gatti
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.