86 votes

Intersection rapide de rectangle à rectangle

Quel est le moyen le plus rapide de tester si deux rectangles se croisent ?


Une recherche sur Internet m'a permis de trouver cette phrase (WOOT !), mais je ne comprends pas comment l'écrire en Javascript, elle semble être écrite dans une ancienne forme de C++.

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 votes

Je pense que vous avez fait une erreur de frappe dans votre copier/coller.

0 votes

Eh bien, c'est d'ici que ça vient et ça me semble identique tekpool.wordpress.com/2006/10/11/

5 votes

L'article original a une coquille. r2->right left n'a pas de sens. Il est peut-être cassé à cause de problèmes d'échappement HTML.

152voto

Daniel Vassallo Points 142049

C'est ainsi que ce code peut être traduit en JavaScript. Notez qu'il y a une coquille dans votre code, et dans celui de l'article, comme les commentaires l'ont suggéré. Plus précisément r2->right left devrait être r2->right < r1->left y r2->bottom top devrait être r2->bottom < r1->top pour que la fonction fonctionne.

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

Cas de test :

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

0 votes

Juste pour ajouter/confirmer - il s'agit de tester trois boîtes qui font 20px x 20px, sauf rectB, qui fait 30px x 30px.

7 votes

Si r1 et r2 sont identiques, la fonction intersectRect renverrait faux

0 votes

Une mise en œuvre fantastique et éloquente. Je l'adore ! +1, a fonctionné parfaitement pour mon jeu.

71voto

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

Cela suppose que le top est normalement inférieure à bottom (c'est-à-dire que y les coordonnées augmentent vers le bas).

1 votes

Bonne solution qui fonctionne, mais qui devrait être un peu plus lente puisque toutes les conditions doivent être évaluées. L'autre solution est réalisée dès qu'une des conditions est évaluée comme vraie.

21 votes

Celle-ci est également effectuée dès que l'une des conditions est évaluée à false. C'est-à-dire exactement dans les mêmes cas que l'autre.

3 votes

C'est mieux car cela supprime l'action de négation.

20voto

Schwarrior Points 21

Voici comment le .NET Framework implémente Rectangle.Intersect

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;
}

Ou la version statique :

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;
}

6voto

Duke Points 191

Un autre moyen plus simple. (Cela suppose que l'axe des y augmente vers le bas).

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);
}

Les 4 nombres (max et min) dans la condition ci-dessus donnent également les points d'intersection.

1voto

englebart Points 93

Ceci a un type Rect que vous pouvez utiliser. C'est déjà du JavaScript.

https://dxr.mozilla.org/mozilla-beta/source/toolkit/modules/Geometry.jsm

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X