Öncelikle, eksen hizalı dikdörtgenler söz konusu olduğunda Kevin Reid'in cevabı en iyisi ve algoritması en hızlısı.
İkinci olarak, basit şekiller için, çarpışma tespiti için nispi hızları (aşağıda görüldüğü gibi) ve ayırma ekseni teoremini kullanın. Bu olacak bir çarpışma doğrusal hareket (devir yok) durumunda olur olmadığını bildirir. Ve rotasyon varsa, hassas olması için küçük bir zaman adımına ihtiyacınız vardır. Şimdi soruyu cevaplamak için:
Genel durumda, iki dışbükey şeklin kesiştiği nasıl anlaşılır?
Size sadece altıgenler için değil tüm dışbükey şekiller için çalışan bir algoritma vereceğim.
X ve Y'nin iki dışbükey şekil olduğunu varsayalım . Bunlar ortak bir nokta vardır, ancak ve ancak bir nokta vardır, yani, kesişen x ∈ X ve nokta y ∈ Y , örneğin , X = Y . Eğer boşluğu bir vektör boşluğu olarak görürseniz, bu x - y = 0 demek anlamına gelir . Ve şimdi bu Minkowski işine gidelim:
Minkowsky toplamı ve X ve Y her kümesidir , x + y için x ∈ X ve y ∈ Y .
X ve Y için bir örnek
X, Y ve Minkowski toplamı, X + Y
Diyelim (= Y) her bir grubu olduğu -y için y ∈ Y , bir önceki paragrafa verilen X ve Y, kesiştiği ancak ve ancak X + (= Y) içeren 0 , kökenli, .
Yan açıklama: neden X - Y yerine X + (-Y) yazıyorum ? Çünkü matematikte, bazen X - Y yazılı olan A ve B'nin Minkowski farkı olarak adlandırılan bir işlem var, ancak x - X ve y ∈ Y için tüm x - y kümeleriyle hiçbir ilgisi yoktur (gerçek Minkowski) fark biraz daha karmaşıktır).
Bu yüzden Minkowski'nin X ve -Y toplamlarını hesaplamak ve bunun kökenini içerip içermediğini bulmak istiyoruz. Köken, herhangi bir noktaya kıyasla özel değildir, bu nedenle orijinin belirli bir etki alanı içinde olup olmadığını bulmak için, bize verilen herhangi bir noktanın o etki alanına ait olup olmadığını söyleyebilecek bir algoritma kullanırız.
Minkowski toplamı X ve Y ise ki serin özelliğine sahiptir X ve Y, konveks, daha sonra X + Y too. Ve bir noktanın dışbükey bir kümeye ait olup olmadığını bulmak, o kümenin dışbükey olmadığından çok daha kolaydır.
X - X ve y ∈ Y için tüm x - y değerlerini hesaplayamayız çünkü x ve y noktalarının sonsuzluğu vardır, umarım, X , Y ve X + Y dışbükey olduğundan, sadece kullanabiliriz "en dıştaki" , köşeleri olan X ve Y biçimlerini tanımlayan noktaları gösterir ve X + Y'nin en dıştaki noktalarını ve ayrıca bazılarını da alırız .
Bu ek noktalar, X + Y'nin en dıştakileri tarafından "çevrelenmiştir", böylece yeni elde edilen dışbükey şeklinin tanımlanmasına katkıda bulunmazlar. Nokta kümesinin " dışbükey kabuğunu " tanımlamadıklarını söylüyoruz . Öyleyse yaptığımız şey, kökenin dışbükey gövde içinde olup olmadığını söyleyen son algoritmaya hazırlık olarak onlardan kurtulmamız.
X + Y'nin dışbükey gövdesi. "İç" köşelerini kaldırdık.
Biz bu nedenle almak
İlk, saf bir algoritma
boolean intersect(Shape X, Shape Y) {
SetOfVertices minkowski = new SetOfVertices();
for (Vertice x in X) {
for (Vertice y in Y) {
minkowski.addVertice(x-y);
}
}
return contains(convexHull(minkowski), Vector2D(0,0));
}
Döngüler açık bir şekilde karmaşıklığa sahiptir O (mn) ki burada m ve n her şeklin köşeleridir. minkoswki
Seti içeren mn en fazla unsurları. convexHull
Algoritma bağlı olan bir karmaşıklığa sahiptir kullandığınız algoritma ve için amaç olabilir O (k günlüğüne (k)) k noktalarının kümesinin boyutu, yani bizim durumumuzda biz almak O (mn log (mn) ) . contains
Algoritma gerçekten sizin başlangıç şekilleri bağlıdır, böylece (2D) kenarları veya dışbükey kabuğun (3D) yüz sayısı ile doğrusal bir karmaşıklık var, ama daha büyük olmayacak O (mn) .
contains
Dışbükey şekiller için algoritma google size izin vereceğim , oldukça yaygın olanı. Vaktim varsa buraya koyabilirim.
Ama yaptığımız çarpışma tespiti, bunu çok daha iyi hale getirebiliriz
Başlangıçta zamanaşımı dt sırasında (resimlerinize bakarak söyleyebileceklerimden) iki gövdesi A ve B döndürmeden hareket ediyorduk . Let çağrısı v A ve v B ilgili hızları A ve B süresi bizim timestep sırasında sabit olan, dt . Aşağıdakileri alıyoruz:
ve, resimlerinizde işaret ettiğiniz gibi, bu gövdeler hareket ettikçe alanları (veya hacimleri, 3B) tararlar:
ve zaman aşımından sonra A ' ve B' olarak bitiyorlar.
Burada naif algoritmamızı uygulamak için sadece süpürülmüş hacimleri hesaplamamız gerekirdi. Ama bunu yapmıyoruz.
Referans çerçevesinde B , B (yaa!) Hareket etmez. Ve A , v A - v B'yi hesaplayarak elde ettiğiniz B'ye göre belirli bir hıza sahiptir (dönüştürmeyi yapabilirsiniz , A'nın referans çerçevesinde B'nin nispi hızını hesaplayabilirsiniz ).
Soldan sağa: temel referans çerçevesindeki hızlar; bağıl hızlar; hesaplamalı göreceli hızlar.
İlgili olarak B kendi referans çerçevesinde hareketsiz olarak, Sadece sesi hesaplamak zorunda olduğunu bir o sırasında hareket ederken aracılığıyla temizleyicileri dt göreceli hız ile v A - v B .
Bu, Minkowski toplamı hesaplamasında kullanılacak köşe noktalarının sayısını azaltır (bazen büyük ölçüde).
Bir başka olası optimizasyon ise, gövdelerden birinin süpürdüğü hacmi hesapladığınız noktadadır. Diyelim ki, A. Diyelim ki bütün oluşturan köşeleri çevirmek zorunda değilsiniz. dış normal "yüz" süpürme yönü. Elbette, kareler için süpürülmüş alanlarınızı hesaplarken zaten bunu fark etmişsinizdir. Nokta ürününü, pozitif olması gereken süpürme yönü ile kullanarak normalin süpürme yönüne doğru olup olmadığını anlayabilirsiniz.
Kavşaklarla ilgili sorunuzla ilgisi olmayan son optimizasyon durumumuzda gerçekten yararlıdır. Bahsettiğimiz göreceli hızları ve sözde ayırma ekseni yöntemini kullanır. Elbette zaten biliyorsunuz.
Bildiğiniz varsayalım yarıçapları arasında A ve B kendi açısından kütle merkezleri bu gibi (söylemek kütle merkezinden ve ondan tepe uzak arasındaki mesafedir):
Bir çarpışma mümkün olması halinde ortaya çıkabilir Bunun sınırlayıcı daire A buluştuğu bu B . Burada görmeyeceğimizi ve bilgisayara aşağıdaki resimdeki C B ile I arasındaki mesafeyi hesaplamanın ve A ve B yarıçaplarının toplamından daha büyük olduğundan emin olmanın yolunu anlamanın yolunu görüyoruz . Daha büyükse, çarpışma olmaz. Daha küçükse, çarpışma.
Bu, uzun olan şekillerle çok iyi çalışmaz, ancak kareler veya bu tür başka şekiller söz konusu olduğunda, çarpışmayı dışlamak çok iyi bir sezgiseldir .
Bununla birlikte, B'ye uygulanan ayırma ekseni teorisi ve A tarafından kaydırılan hacim , çarpışmanın olup olmadığını size söyler. İlişkili algoritmanın karmaşıklığı, her dışbükey şeklin köşelerinin sayısının toplamı ile doğrusaldır, ancak çarpışmayı ele alma zamanı geldiğinde daha az büyülüdür.
Çarpışmaları algılamaya yardımcı olmak için kesişimleri kullanan yeni, daha iyi algoritmamız , ancak aslında bir çarpışmanın gerçekleşip gerçekleşmeyeceğini anlatmak için ayırma ekseni teoremi kadar iyi değil
boolean mayCollide(Body A, Body B) {
Vector2D relativeVelocity = A.velocity - B.velocity;
if (radiiHeuristic(A, B, relativeVelocity)) {
return false; // there is a separating axis between them
}
Volume sweptA = sweptVolume(A, relativeVelocity);
return contains(convexHull(minkowskiMinus(sweptA, B)), Vector2D(0,0));
}
boolean radiiHeuristic(A, B, relativeVelocity)) {
// the code here
}
Volume convexHull(SetOfVertices s) {
// the code here
}
boolean contains(Volume v, Vector2D p) {
// the code here
}
SetOfVertices minkowskiMinus(Body X, Body Y) {
SetOfVertices result = new SetOfVertices();
for (Vertice x in X) {
for (Vertice y in Y) {
result.addVertice(x-y);
}
}
return result;
}