Hızlı dikdörtgenden dikdörtgene kesişim


81

2 dikdörtgenin kesişip kesişmediğini test etmenin hızlı yolu nedir?


İnternette bir arama bu tek satırlık (WOOT!) İle geldi, ancak Javascript'te nasıl yazılacağını anlamıyorum, eski bir C ++ formunda yazılmış gibi görünüyor.

struct
{
    LONG    left;
    LONG    top;
    LONG    right;
    LONG    bottom;
} RECT; 

bool IntersectRect(const RECT * r1, const RECT * r2)
{
    return ! ( r2->left > r1->right
        || r2->right < r1->left
        || r2->top > r1->bottom
        || r2->bottom < r1->top
        );
}

5
Sanırım kopyalama / yapıştırma
işleminizde

5
Orijinal makalede bir yazım hatası var. r2->right leftmantıklı değil. HTML çıkış sorunları nedeniyle bozuk olabilir.
Marcelo Cantos

42
Yukarıdaki kodun "modern" bir C ++ biçiminde nasıl farklı olacağını düşündüğünüzü merak ediyorum.
jamesdlin

3
Eminim eksik karakterler <html kaçışından dolayı sembollerdir.
devios1

1
@jamesdlin işlevi, bir parametre alarak yapının bir üye işlevi olarak yaparsınız. İkinci olarak, normalde const * yerine const & kullanırsınız. Şablonları, bazı Win32 makrosu kullanmak yerine hem int, hem uzun hem de çift sürümlere sahip olmak için kullanabilirsiniz ... (RECT, bir tür adı değil, adlandırılmamış bir yapının bir örneği olduğu için bu da derlenmez.) Örnek : ideone.com/bnzwl3
Sebastian Wahl

Yanıtlar:


142

Bu kodun JavaScript'e nasıl çevrilebileceğidir. Yorumların önerdiği gibi, kodunuzda ve makaleninkinde bir yazım hatası olduğunu unutmayın. İşlevin çalışması için özel olarak r2->right leftolmalı r2->right < r1->leftve r2->bottom topolmalıdır r2->bottom < r1->top.

function intersectRect(r1, r2) {
  return !(r2.left > r1.right || 
           r2.right < r1.left || 
           r2.top > r1.bottom ||
           r2.bottom < r1.top);
}

Test durumu:

var rectA = {
  left:   10,
  top:    10,
  right:  30,
  bottom: 30
};

var rectB = {
  left:   20,
  top:    20,
  right:  50,
  bottom: 50
};

var rectC = {
  left:   70,
  top:    70,
  right:  90,
  bottom: 90
};

intersectRect(rectA, rectB);  // returns true
intersectRect(rectA, rectC);  // returns false

Sadece eklemek / onaylamak için - bu, 30px x 30px olan rectB dışında 20px x 20px olan üç kutuyu test ediyor
verenion

6
r1 ve r2 aynıysa, intersectRect işlevi yanlış döndürür
zumalifeguard

Fantastik Güzel Uygulama. Sevdim! +1, oyunum için mükemmel çalıştı.
Unome

1
@zumalifeguard Neden böyle düşünüyorsun?
Minix

Bu işlev çok dahice. Bunu hiç düşünmezdim, bunun yerine iki kutuyu kesişir hale getirmeye çalışırdım.
nikk wong

69
function intersect(a, b) {
  return (a.left <= b.right &&
          b.left <= a.right &&
          a.top <= b.bottom &&
          b.top <= a.bottom)
}

Bu top, normalde daha küçük olduğunu varsayar bottom(yani ykoordinatlar aşağı doğru artar).


İyi ve çalışan bir çözüm, ancak tüm koşulların değerlendirilmesi gerektiğinden biraz daha yavaş olmalı. Diğer çözüm, koşullardan biri doğru olarak değerlendirildiği anda yapılır.
Gigo

21
Bu aynı zamanda koşullardan biri yanlış olarak değerlendirildiğinde yapılır. Yani diğeriyle tamamen aynı durumda.
DS.

3
Bu, olumsuzlama eylemini ortadan kaldırdığı için daha iyidir.
Discipol

4
+1, kabul edilen cevap kadar düzgün. Değişen, (yani dikdörtgen tepe ve sol ama alt ve sağ olarak ortak birçok grafik sistemlerinde olduğu içermez) yarı açık aralıkları kullanılıyorsa <=için <çalışmalıdır.
Jules

Bu çözümü seviyorum çünkü =her koşul için öğesini kaldırabiliyorum ve dikdörtgenlerin sınırlara "dokunmasına" izin veriyor.
prograhammer

20

.NET Framework, Dikdörtgen'i bu şekilde uygular.

public bool IntersectsWith(Rectangle rect)
{
  if (rect.X < this.X + this.Width && this.X < rect.X + rect.Width && rect.Y < this.Y + this.Height)
    return this.Y < rect.Y + rect.Height;
  else
    return false;
}

Veya statik versiyon:

public static Rectangle Intersect(Rectangle a, Rectangle b)
{
  int x = Math.Max(a.X, b.X);
  int num1 = Math.Min(a.X + a.Width, b.X + b.Width);
  int y = Math.Max(a.Y, b.Y);
  int num2 = Math.Min(a.Y + a.Height, b.Y + b.Height);
  if (num1 >= x && num2 >= y)
    return new Rectangle(x, y, num1 - x, num2 - y);
  else
    return Rectangle.Empty;
}

6

Daha basit bir yol. (Bu, y ekseninin aşağı doğru arttığını varsayar).

function intersect(a, b) {
  return Math.max(a.left, b.left) < Math.min(a.right, b.right) &&
          Math.max(a.top, b.top) < Math.min(a.bottom, b.bottom);
}

Yukarıdaki durumda bulunan 4 sayı (maksimumlar ve minimumlar) da kesişme noktalarını verir.



0

Büyük bir dikdörtgenin içinde daha küçük bir dikdörtgeni tespit etmek için bir yöntem karışımı kullandım. Bu bir nodejs yöntemidir ve genişlik / yükseklik kullanır, ancak kolayca uyarlanabilir.

            isIntersectingRect: function (r1, r2) {
              var quickCheck = (r1.x <= r2.x + r2.w &&
                      r2.x <= r1.x + r1.w &&
                      r1.y <= r2.y + r2.h &&
                      r2.y <= r1.y + r1.h)
              if (quickCheck) return true;
              var x_overlap = Math.max(0, Math.min(r1.x + r1.w, r2.x + r2.w) - Math.max(r1.x, r2.x));
              var y_overlap = Math.max(0, Math.min(r1.y + r1.h, r2.y + r2.h) - Math.max(r1.y, r2.y));
              var overlapArea = x_overlap * y_overlap;
              return overlapArea == 0;
            }
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.