İki dikdörtgenin kesişimini algılayan algoritma?


143

İki dikdörtgen kesişip kesişmediğini tespit etmek için bir algoritma arıyorum (biri rastgele bir açıda, diğeri sadece dikey / yatay çizgilerle).

Birinin bir köşesinin diğer ALMOST'ta olup olmadığını test etmek işe yarar. Dikdörtgenler çapraz benzeri bir şekil oluşturuyorsa başarısız olur.

Dikey çizgiler için özel durumlar gerektiren çizgilerin eğimlerini kullanmaktan kaçınmak iyi bir fikir gibi görünüyor.


köşe kontrolünüze eklerseniz, ikinci dikdörtgenin açılı dikdörtgenin sınırları içinde (dikdörtgen) olup olmadığını kontrol edin?
Wes P

Bunu hangi dilde yapacaksın? Çünkü Java'da bunu yapmanıza izin veren yerleşik sınıflar vardır.
Martijn

Ben grafik api ve çoğu GUI kütüphaneleri (swing gibi) bunu uyguladı düşünüyorum.
l_39217_l

üst üste geldiği ancak herhangi bir dikdörtgenin içinde köşe olmadığı durumları kaçırabilecek
Florian Bösch

1
Bu soru neredeyse aynı: stackoverflow.com/questions/306316/… . Rağmen, bu özellikle C ++ için bir çözüm arıyor. Kabul edilen cevap da oldukça basit ve anlaşılır.
Silver Gonzales

Yanıtlar:


162

Standart yöntem, ayırma ekseni testi yapmaktır (bu konuda bir google araması yapın).

Kısacası:

  • İki nesneyi ayıran bir çizgi bulabilirseniz, iki nesne kesişmez. örneğin, nesneler / bir nesnenin tüm noktaları çizginin farklı taraflarındadır.

Eğlenceli olan şey, iki dikdörtgenin tüm kenarlarını kontrol etmenin yeterli olmasıdır. Dikdörtgenler üst üste gelmezse kenarlardan biri ayırma ekseni olacaktır.

2B'de bunu eğim kullanmadan yapabilirsiniz. Bir kenar basitçe iki köşe arasındaki fark olarak tanımlanır, ör.

  edge = v(n) - v(n-1)

Buna 90 ° döndürerek buna dikey olarak sahip olabilirsiniz. 2D'de bu kolay:

  rotated.x = -unrotated.y
  rotated.y =  unrotated.x

Dolayısıyla hiçbir trigonometri veya eğim söz konusu değildir. Vektörün ünite uzunluğuna normalleştirilmesi de gerekli değildir.

Bir noktanın çizginin bir veya başka bir tarafında olup olmadığını test etmek istiyorsanız, sadece nokta ürününü kullanabilirsiniz. işaret hangi tarafta olduğunuzu söyleyecektir:

  // rotated: your rotated edge
  // v(n-1) any point from the edge.
  // testpoint: the point you want to find out which side it's on.

  side = sign (rotated.x * (testpoint.x - v(n-1).x) + 
               rotated.y * (testpoint.y - v(n-1).y);

Şimdi A dikdörtgenin tüm noktalarını, dikdörtgenin B kenarlarına karşı test edin. Bir ayırma kenarı bulursanız, nesneler kesişmez (B'deki diğer tüm noktaların test edilen kenarın diğer tarafında olması koşuluyla - aşağıdaki çizime bakın). Ayırma kenarı bulamazsanız, dikdörtgenler kesişir veya bir dikdörtgen diğerinde bulunur.

Test, herhangi bir dışbükey çokgen ile çalışır.

Değişiklik: Bir ayırma kenarını tanımlamak için, bir dikdörtgenin tüm noktalarını diğerinin her kenarına karşı test etmek yeterli değildir. A aday kenarı E (aşağıda), A'daki tüm noktalar E'nin aynı yarım düzleminde olduğu için ayırıcı bir kenar olarak tanımlanır. Ancak, B'nin Vb1 ve Vb2 köşeleri olduğu için ayırıcı bir kenar değildir. bu yarım düzlemde de var. Ancak bu böyle olmasaydı ayırıcı bir avantaj olurdu http://www.iassess.com/collision.png


2
Bu algoritma her durumda çalışmaz. 45 ° döndürülmüş ikinci dikdörtgeni ilk dikdörtgene yerleştirmek ve diyagonal boyunca ofset yapmak mümkündür, böylece yukarıdaki kavşak testlerini yerine getirir, ancak kesişmez.
Skizz

6
Skizz, sekiz kenarı da kontrol et. Nesneler sekiz kenarları olmayan kesiştiği birini yapın edecek ayırın. Neden davanızı gösteren bir resim yayınlamıyorsunuz? Sana eksenini gösterebilirim ..
Nils Pipenbrinck

2
Benim hatam, bu durumla başa çıkıyor.
Skizz

2
Görüntü şimdi öldü (Kasım 2012)
John Dvorak

2
Ben bu görselleştirme bir sürü sorun vardı, bu yüzden referans alınan görüntü gibi görünüyordu ne yeniden oluşturdu. imgur.com/bNwrzsv
Rjdlee

16

Temel olarak aşağıdaki resme bakın:


İki kutu çarpışırsa, A ve B çizgileri çakışır.

Bunun hem X hem de Y ekseninde yapılması gerektiğini ve dikdörtgenlerin çarpışması için her ikisinin de örtüşmesi gerektiğini unutmayın.

Gamasutra.com'da soruyu cevaplayan iyi bir makale var (resim makaleden). 5 yıl önce benzer bir algoritma yaptım ve daha sonra buraya göndermek için kod snippet'imi bulmam gerekiyor

Değişiklik : Ayırma Eksen teoremi iki dışbükey şekil bildiren yok üst üste bir ayırma ekseni varsa (gösterildiği gibi çıkıntılar, yani bir yok üst üste gelir). Yani "Ayırma ekseni var" => "Çakışma yok". Bu iki yönlü bir sonuç değildir, bu yüzden tersi sonuçlandıramazsınız.


1
Açıkçası, iki kare (0,0,1,1) ve (0,3,1,4) üst üste gelmediği halde x ekseni üzerindeki çıkıntıları tamamen örtüşüyor. Her iki test de gereklidir, kombinasyon yeterlidir.
MSalters

18
X ve y projeksiyonlarının çakışması yeterli değildir: örneğin dikdörtgenleri [(0,0), (0,3), (3,3), (3,0)] ve [(2,5) alın, (5,2), (7,4), (4,7)].
Joel, Gö Ocak'ta

4
Gö'deki @Joel ile hemfikirim. Bu yöntem, dikdörtgenlerin üst üste gelmediği, ancak yansıtılan yarıçaplarının hem x hem de y'de yaptığı çok sayıda durumu kaçırır.
Scottie T

5
Bu cevap yanlış değil ama yanıltıcı. Doğru: İki kutu çarpışırsa, A ve B çizgileri çakışacaktır. ancak şu da doğrudur: A ve B çizgileri çakışırsa, iki kutu çarpışabilir veya çarpışmayabilir
matt

7
@floater: Bunun sadece yanlış değil , aynı zamanda yanıltıcı olduğunu söyleyebilirim ki bu daha da kötüdür.
BlueRaja - Danny Pflughoeft

4

m_pGladiator'ın cevabı doğru ve ben bunu tercih ediyorum. Eksen ayırma testi , dikdörtgen çakışmasını tespit etmek için en basit ve standart yöntemdir. Yansıtma aralıklarının üst üste gelmediği bir çizgiye ayırma ekseni diyoruz . Nils Pipenbrinck'in çözümü çok genel. Bir şeklin tamamen diğerinin kenarının bir tarafında olup olmadığını kontrol etmek için nokta ürünü kullanır . Bu çözüm aslında n kenarlı dışbükey çokgenlere neden olabilir. Ancak, iki dikdörtgen için optimize edilmemiştir.

m_pGladiator'ın cevabının kritik noktası, iki dikdörtgenin her iki eksende (x ve y) izdüşümünü kontrol etmemiz gerektiğidir. İki projeksiyon çakışırsa, bu iki dikdörtgenin örtüştüğünü söyleyebiliriz. Yani m_pGladiator'ın cevabına ilişkin yukarıdaki yorumlar yanlış.

basit bir durum için, iki dikdörtgen döndürülmezse, yapısına sahip bir dikdörtgen sunarız:

struct Rect {
    x, // the center in x axis
    y, // the center in y axis
    width,
    height
}

rectA, rectB ile A, B dikdörtgenini adlandırıyoruz.

    if Math.abs(rectA.x - rectB.x) < (Math.abs(rectA.width + rectB.width) / 2) 
&& (Math.abs(rectA.y - rectB.y) < (Math.abs(rectA.height + rectB.height) / 2))
    then
        // A and B collide
    end if

iki dikdörtgenden herhangi biri döndürülmüşse, bunların x ve y eksenlerine izdüşümünü belirlemek için biraz çaba gösterilmesi gerekebilir. RotatedRect yapısını aşağıdaki gibi tanımlayın:

struct RotatedRect : Rect {
    double angle; // the rotating angle oriented to its center
}

fark 'genişliğinin şimdi biraz farklı olması: rectA için Math.sqrt(rectA.width*rectA.width + rectA.height*rectA.height) * Math.cos(rectA.angle) widthA' : rectB için widthB ':Math.sqrt(rectB.width*rectB.width + rectB.height*rectB.height) * Math.cos(rectB.angle)

    if Math.abs(rectA.x - rectB.x) < (Math.abs(widthA' + widthB') / 2) 
&& (Math.abs(rectA.y - rectB.y) < (Math.abs(heightA' + heightB') / 2))
    then
        // A and B collide
    end if

Bir GDC (Oyun Geliştirme Konferansı 2007) PPT'ye başvurabilir www.realtimecollisiondetection.net/pubs/GDC07_Ericson_Physics_Tutorial_SAT.ppt


Negatif genişlikleri işlemek için neden "Math.abs (rectA.width + rectB.width)" öğesinde Math.abs () öğesine ihtiyacınız var?
AlexWien

Ayırma ekseni mutlaka bir pusula yönü değildir, herhangi bir açıda olabilir.
Ben Voigt

Döndürülmemiş dikdörtgenler rectA (x = 0, y = 0, genişlik = 1, yükseklik = 1) ve rectB (x = 2, y = 0, genişlik = 100, yükseklik = 1) kesişmiyor, ancak yönteminiz kesişiyor kesiştiği. Yanlış bir şey mi yapıyorum?
Kagami Sascha Rosylight

4

Cocoa'da, seçilenArea rect'in döndürülmüş NSView'in çerçeve rect'iyle kesişip kesişmediğini kolayca tespit edebilirsiniz. Çokgenleri hesaplamanıza bile gerek yok, normaller böyle. Bu yöntemleri NSView alt sınıfınıza eklemeniz yeterlidir. Örneğin, kullanıcı NSView'in denetimindeki bir alanı seçer, sonra seçilenArea rectini geçen DoesThisRectSelectMe yöntemini çağırırsınız. API convertRect: bu işi yapar. Aynı hile NSView seçmek için tıklattığınızda çalışır. Bu durumda, aşağıdaki gibi hitTest yöntemini geçersiz kılın. API convertPoint: bu işi yapacak ;-)

- (BOOL)DoesThisRectSelectMe:(NSRect)selectedArea
{
    NSRect localArea = [self convertRect:selectedArea fromView:self.superview];

    return NSIntersectsRect(localArea, self.bounds);
}


- (NSView *)hitTest:(NSPoint)aPoint
{
    NSPoint localPoint = [self convertPoint:aPoint fromView:self.superview];
    return NSPointInRect(localPoint, self.bounds) ? self : nil;
}

2
Bu kod yalnızca ekranın kare şeklindeki dikdörtgenler için geçerlidir. Bu önemsiz bir durum. Varsayım, ekrana veya birbirlerine 90 derecelik açıda olmayan dikdörtgenlerle uğraştığımızdır.
Duncan C

Uygulamalarımda kontrol ettiğim ve kullandığım için, bu kod döndürülmüş bir dikdörtgen üzerinde çalışıyor. Dönüş derecesi ne olursa olsun.
Leonardo

Bu algoritmayı tanımlamıyor, ancak zaten kullanan bir kütüphaneden bahsediyor.
Ben Voigt

2

Bir dikdörtgendeki çizgilerin herhangi birinin diğerinden gelen çizgilerle kesişip kesişmediğini kontrol edin. Saf çizgi segmenti kesişiminin kodlanması kolaydır.

Daha fazla hıza ihtiyacınız varsa, çizgi segmenti kesişimi (tarama çizgisi) için gelişmiş algoritmalar vardır. Bkz. Http://en.wikipedia.org/wiki/Line_segment_intersection


4
Dikkatli! Bir dikdörtgenin diğerini tamamen çevrelediği durumu unutmayın
Pitarou

2

Bir çözüm, Uygun Olmayan Çokgen adı verilen bir şey kullanmaktır. Bu çokgen iki çokgenden hesaplanır (kavramsal olarak bir diğerinin etrafında kaydırılarak) ve çokgenlerin göreli ofsetleri verildiğinde üst üste geldiği alanı tanımlar. Bu NFP'ye sahip olduğunuzda, iki çokgenin göreli uzaklığı tarafından verilen bir noktaya sahip bir dahil etme testi yapmanız yeterlidir. Bu dahil etme testi hızlı ve kolaydır, ancak önce NFP'yi oluşturmanız gerekir.

Web üzerinde Uygun Olmayan Çokgen için bir arama yapın ve dışbükey çokgenler için bir algoritma bulabileceğinizi görün (içbükey çokgenleriniz varsa çok daha karmaşık hale gelir). Eğer bir şey bulamazsanız o zaman bana howard dot e-posta J nokta olabilir gmail dot com


1

İşte tüm olası vakaları halledeceğini düşünüyorum. Aşağıdaki testleri yapın.

  1. Dikdörtgen 1'in köşelerinden herhangi birini dikdörtgen 2'nin içinde olup olmadığını kontrol edin (veya tersi). Diğer dikdörtgenin içinde bulunan bir tepe noktası bulduğunuzda, aramayı kesip durdurdukları sonucuna varabilirsiniz. Bu, tamamen diğerinin içinde bulunan bir dikdörtgenin bakımını yapar.
  2. Yukarıdaki test sonuçsuzsa, 1 dikdörtgenin her bir çizgisinin diğer dikdörtgenin her bir çizgisiyle kesişen noktalarını bulun. Bir kesişme noktası bulunduğunda, karşılık gelen 4 nokta tarafından oluşturulan hayali dikdörtgenin içinde olup olmadığını kontrol edin. Böyle bir nokta bulunduğunda aramayı kesip durdurdukları sonucuna varırlar.

Yukarıdaki 2 test yanlış döndürürse, bu 2 dikdörtgen çakışmaz.


0

Java kullanıyorsanız, Şekil arabiriminin tüm uygulamalarında dikdörtgen alan bir kesişme yöntemi vardır.


Ne yazık ki C # kullanıyorum. Rectangle sınıfının bir Contains () yöntemi vardır, ancak yalnızca döndürülmemiş dikdörtgenler içindir.
user20493

intersects () yöntemi sanırım kesişim yerine boole döndürdüğü için oldukça işe yaramaz.
ZZ 5

0

Kaba kuvvet yöntemi, yatay dikdörtgenin kenarlarını yürümek ve kenar boyunca her noktayı kontrol etmek veya diğer dikdörtgenin içine düşüp düşmediğini kontrol etmektir.

Matematiksel cevap, her iki dikdörtgenin her bir kenarını tanımlayan denklemler oluşturmaktır. Şimdi, A dikdörtgenindeki dört satırdan herhangi birinin, basit (hızlı) doğrusal bir denklem çözücü olması gereken B dikdörtgeninin herhangi bir çizgisiyle kesişip kesişmediğini görebilirsiniz.

-Adam


2
Denklemlerle ilgili sorun, sonsuz eğime sahip dikey bir çizginiz olduğundadır.
user20493

Her çözüm için köşe kutuları vardır.
Adam Davis

2
ve bir kare tamamen diğerini çevreler.
Oliver Hallam

0

Açılı dikdörtgenin her bir tarafının eksenle hizalanmış her iki tarafının kesişimini bulabilirsiniz. Bunu, her bir tarafın bulunduğu sonsuz çizginin (yani v1 + t (v2-v1) ve v'1 + t '(v'2-v'1)) denklemini bularak, çizgiler, bu iki denklem eşit olduğunda (paralel ise, bunu test edebilirsiniz) çözerek ve bu noktanın iki köşe arasındaki çizgi segmentinde olup olmadığını test ederek, yani 0 <= t <= 1 ve 0 <= t '<= 1.

Ancak, bir dikdörtgen diğerini tamamen kapladığında bu durum söz konusu değildir. Herhangi bir dikdörtgenin dört noktasının da diğer dikdörtgenin içinde olup olmadığını test ederek kapatabileceğiniz.


0

Bu sorunun 3D sürümü için yapacağım şey budur :

2 dikdörtgeni P1 ve P2 denklemi ile tanımlanan düzlemler olarak modelleyin, sonra P1 = P2 yazın ve düzlemler paralelse (kavşak yoksa) veya aynı düzlemdeyse var olmayacak olan kesişim denklem çizgisinden türetin, bu durumda 0 = 0 alırsınız. Bu durumda, 2B dikdörtgen kesişme algoritması kullanmanız gerekir.

Sonra her iki dikdörtgenin düzlemindeki çizginin her iki dikdörtgenden de geçip geçmediğini göreceğim. Eğer öyleyse, 2 dikdörtgenin kesişim noktası var, aksi takdirde kafamda bir köşe davasını kaçırmış olabilirim (ya da etmemeliydim).

Bir çizginin aynı düzlemdeki bir dikdörtgenden geçip geçmediğini bulmak için, çizginin ve dikdörtgenin kenarlarının 2 kesişme noktasını (çizgi denklemleri kullanarak modelleme) bulur ve kesişme noktalarının Aralık.

Bu matematiksel açıklamalar, ne yazık ki yukarı yapmak için hiçbir kod var.


Düzlemsel kesişim çizgisini bulursanız, bir kısmının her iki dikdörtgenin içinde olduğundan emin olmanız gereken kısmı kaçırdınız.
Lee Louviere

0

Ayırma ekseni testini kullanmaktan biraz daha hızlı olan testi yapmanın başka bir yolu , her iki dikdörtgenin (isteğe bağlı olarak seçilen) her tepe noktasında sargı sayıları algoritmasını (sadece çeyreklerde - korkunç derecede yavaş olan açı toplamını değil ) kullanmaktır. Köşelerden herhangi birinin sıfır olmayan sargı numarası varsa, iki dikdörtgen üst üste gelir.

Bu algoritma, ayırma ekseni testinden biraz daha uzun sargılıdır, ancak daha hızlıdır, çünkü kenarlar iki kadranı geçiyorsa sadece bir yarım düzlemli test gerektirir (ayırma ekseni yöntemini kullanarak 32 testin aksine)

Algoritma ayrıca herhangi bir çokgenin (dışbükey veya içbükey) üst üste binmesini test etmek için kullanılabilmesi avantajına sahiptir . Bildiğim kadarıyla, algoritma sadece 2B alanda çalışıyor.


3
Yanılıyor olabilirim, ama bu sadece bir dikdörtgenin köşelerinin diğerinin içinde olup olmadığını kontrol etmiyor mu? Evet ise, yeterli değildir, çünkü dikdörtgenler içeride herhangi bir köşe olmadan üst üste gelebilir.
sinelaw

Dikdörtgenlerle yapabilirler mi? Nasıl? Bana öyle geliyor ki 2 dikdörtgenin kesişmesi için, dikdörtgenlerden birinin en az bir tepe noktası diğer dikdörtgenin üzerinde olmalıdır.
Duncan C

@DuncanC: Evet yapabilirler. Karşı örnek, bir çarpıdır ve orijinal soruda bile listelenmiştir.
Ben Voigt

@BenVoigt Bu çok eski bir konu, ama kesinlikle haklısın.
Duncan C

0

Ya başka bir şey eksik, neden bu kadar karmaşık?

(x1, y1) ve (X1, Y1) dikdörtgenlerin köşeleri ise, kavşak bulmak için:

    xIntersect = false;
    yIntersect = false;
    if (!(Math.min(x1, x2, x3, x4) > Math.max(X1, X2, X3, X4) || Math.max(x1, x2, x3, x4) < Math.min(X1, X2, X3, X4))) xIntersect = true;
    if (!(Math.min(y1, y2, y3, y4) > Math.max(Y1, Y2, Y3, Y4) || Math.max(y1, y2, y3, y4) < Math.min(Y1, Y2, Y3, Y4))) yIntersect = true;
    if (xIntersect && yIntersect) {alert("Intersect");}

3
Kişinin keyfi bir açıyla döndürülmesini istediğini kaçırıyorsunuz.
Robotbugs

0

Ben böyle uyguladı:

bool rectCollision(const CGRect &boundsA, const Matrix3x3 &mB, const CGRect &boundsB)
{
    float Axmin = boundsA.origin.x;
    float Axmax = Axmin + boundsA.size.width;
    float Aymin = boundsA.origin.y;
    float Aymax = Aymin + boundsA.size.height;

    float Bxmin = boundsB.origin.x;
    float Bxmax = Bxmin + boundsB.size.width;
    float Bymin = boundsB.origin.y;
    float Bymax = Bymin + boundsB.size.height;

    // find location of B corners in A space
    float B0x = mB(0,0) * Bxmin + mB(0,1) * Bymin + mB(0,2);
    float B0y = mB(1,0) * Bxmin + mB(1,1) * Bymin + mB(1,2);

    float B1x = mB(0,0) * Bxmax + mB(0,1) * Bymin + mB(0,2);
    float B1y = mB(1,0) * Bxmax + mB(1,1) * Bymin + mB(1,2);

    float B2x = mB(0,0) * Bxmin + mB(0,1) * Bymax + mB(0,2);
    float B2y = mB(1,0) * Bxmin + mB(1,1) * Bymax + mB(1,2);

    float B3x = mB(0,0) * Bxmax + mB(0,1) * Bymax + mB(0,2);
    float B3y = mB(1,0) * Bxmax + mB(1,1) * Bymax + mB(1,2);

    if(B0x<Axmin && B1x<Axmin && B2x<Axmin && B3x<Axmin)
        return false;
    if(B0x>Axmax && B1x>Axmax && B2x>Axmax && B3x>Axmax)
        return false;
    if(B0y<Aymin && B1y<Aymin && B2y<Aymin && B3y<Aymin)
        return false;
    if(B0y>Aymax && B1y>Aymax && B2y>Aymax && B3y>Aymax)
        return false;

    float det = mB(0,0)*mB(1,1) - mB(0,1)*mB(1,0);
    float dx = mB(1,2)*mB(0,1) - mB(0,2)*mB(1,1);
    float dy = mB(0,2)*mB(1,0) - mB(1,2)*mB(0,0);

    // find location of A corners in B space
    float A0x = (mB(1,1) * Axmin - mB(0,1) * Aymin + dx)/det;
    float A0y = (-mB(1,0) * Axmin + mB(0,0) * Aymin + dy)/det;

    float A1x = (mB(1,1) * Axmax - mB(0,1) * Aymin + dx)/det;
    float A1y = (-mB(1,0) * Axmax + mB(0,0) * Aymin + dy)/det;

    float A2x = (mB(1,1) * Axmin - mB(0,1) * Aymax + dx)/det;
    float A2y = (-mB(1,0) * Axmin + mB(0,0) * Aymax + dy)/det;

    float A3x = (mB(1,1) * Axmax - mB(0,1) * Aymax + dx)/det;
    float A3y = (-mB(1,0) * Axmax + mB(0,0) * Aymax + dy)/det;

    if(A0x<Bxmin && A1x<Bxmin && A2x<Bxmin && A3x<Bxmin)
        return false;
    if(A0x>Bxmax && A1x>Bxmax && A2x>Bxmax && A3x>Bxmax)
        return false;
    if(A0y<Bymin && A1y<Bymin && A2y<Bymin && A3y<Bymin)
        return false;
    if(A0y>Bymax && A1y>Bymax && A2y>Bymax && A3y>Bymax)
        return false;

    return true;
}

Matris mB, B uzayındaki noktaları A uzayındaki noktalara dönüştüren herhangi bir afin dönüşüm matrisidir. Bu, basit döndürme ve çeviri, döndürme artı ölçekleme ve tam afin çözgüleri içerir, ancak perspektif çözgüleri içermez.

Mümkün olduğunca optimal olmayabilir. Hız büyük bir endişe değildi. Ancak benim için iyi çalışıyor gibi görünüyor.


0

Kabul edilen cevabın matlab uygulaması:

function olap_flag = ol(A,B,sub)

%A and B should be 4 x 2 matrices containing the xy coordinates of the corners in clockwise order

if nargin == 2
  olap_flag = ol(A,B,1) && ol(B,A,1);
  return;
end

urdl = diff(A([1:4 1],:));
s = sum(urdl .* A, 2);
sdiff = B * urdl' - repmat(s,[1 4]);

olap_flag = ~any(max(sdiff)<0);

0

Bu geleneksel yöntemdir, satır satır gidin ve çizgilerin kesişip kesişmediğini kontrol edin. MATLAB'daki kod budur.

C1 = [0, 0];    % Centre of rectangle 1 (x,y)
C2 = [1, 1];    % Centre of rectangle 2 (x,y)
W1 = 5; W2 = 3; % Widths of rectangles 1 and 2
H1 = 2; H2 = 3; % Heights of rectangles 1 and 2
% Define the corner points of the rectangles using the above
R1 = [C1(1) + [W1; W1; -W1; -W1]/2, C1(2) + [H1; -H1; -H1; H1]/2];
R2 = [C2(1) + [W2; W2; -W2; -W2]/2, C2(2) + [H2; -H2; -H2; H2]/2];

R1 = [R1 ; R1(1,:)] ;
R2 = [R2 ; R2(1,:)] ;

plot(R1(:,1),R1(:,2),'r')
hold on
plot(R2(:,1),R2(:,2),'b')


%% lines of Rectangles 
L1 = [R1(1:end-1,:) R1(2:end,:)] ;
L2 = [R2(1:end-1,:) R2(2:end,:)] ;
%% GEt intersection points
P = zeros(2,[]) ;
count = 0 ;
for i = 1:4
    line1 = reshape(L1(i,:),2,2) ;
    for j = 1:4
        line2 = reshape(L2(j,:),2,2) ;
        point = InterX(line1,line2) ;
        if ~isempty(point)
            count = count+1 ;
            P(:,count) = point ;
        end
    end
end
%%
if ~isempty(P)
    fprintf('Given rectangles intersect at %d points:\n',size(P,2))
    plot(P(1,:),P(2,:),'*k')
end

InterX işlevi şu adresten indirilebilir: https://in.mathworks.com/matlabcentral/fileexchange/22441-curve-intersections?focused=5165138&tab=function


0

2 dikdörtgenimiz varsa, daha basit bir yöntemim var:

R1 = (min_x1, maks_x1, min_y1, maks_y1)

R2 = (min_x2, maks_x2, min_y2, maks_y2)

Yalnızca aşağıdaki durumlarda çakışırlar:

Çakışma = (max_x1> min_x2) ve (max_x2> min_x1) ve (max_y1> min_y2) ve (max_y2> min_y1)

3D kutular için de yapabilirsiniz, aslında herhangi bir boyut için çalışır.


0

Yeterli diğer cevaplarda söylendi, bu yüzden sadece bir satırlık sahte kod ekleyeceğim:

!(a.left > b.right || b.left > a.right || a.top > b.bottom || b.top > a.bottom);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.