Определите, перекрываются ли два прямоугольника друг с другом?

Я пытаюсь написать программу на С++, которая использует следующие входы от пользователя для создания прямоугольников (от 2 до 5): высота, ширина, x-pos, y-pos. Все эти прямоугольники будут существовать параллельно оси x и y, то есть все их ребра будут иметь наклоны 0 или бесконечность.

Я попытался реализовать то, что упоминается в этом, но мне не очень повезло.

Моя текущая реализация делает следующее:

// Gets all the vertices for Rectangle 1 and stores them in an array -> arrRect1
// point 1 x: arrRect1[0], point 1 y: arrRect1[1] and so on...
// Gets all the vertices for Rectangle 2 and stores them in an array -> arrRect2

// rotated edge of point a, rect 1
int rot_x, rot_y;
rot_x = -arrRect1[3];
rot_y = arrRect1[2];
// point on rotated edge
int pnt_x, pnt_y;
pnt_x = arrRect1[2]; 
pnt_y = arrRect1[3];
// test point, a from rect 2
int tst_x, tst_y;
tst_x = arrRect2[0];
tst_y = arrRect2[1];

int value;
value = (rot_x * (tst_x - pnt_x)) + (rot_y * (tst_y - pnt_y));
cout << "Value: " << value;  

Однако я не совсем уверен, что (а) я правильно применил алгоритм, который я связал, или если я сделал именно это, чтобы интерпретировать это?

Любые предложения?

Ответ 1

if (RectA.Left < RectB.Right && RectA.Right > RectB.Left &&
     RectA.Top > RectB.Bottom && RectA.Bottom < RectB.Top ) 

или, используя декартовы координаты

(С X1 слева координата, X2 является правой координатой, увеличиваясь слева направо и Y1 является верхней координатой, а Y2 является нижней координатой, увеличиваясь снизу вверх)...

if (RectA.X1 < RectB.X2 && RectA.X2 > RectB.X1 &&
    RectA.Y1 > RectB.Y2 && RectA.Y2 < RectB.Y1) 

ПРИМЕЧАНИЕ: ДЛЯ ВСЕХ ПОЛЬЗОВАТЕЛЕЙ С РЕГУЛИРОВАНИЕМ. ПОЖАЛУЙСТА, ОСТАНОВИТЕСЬ С ЭТИМ.

Скажем, у вас есть Rect A и Rect B. Доказательство противоречит. Любое из четырех условий гарантирует, что не существует перекрытия:

  • COND1. Если левый край находится справа от правого края B,      - тогда A полностью справа от B
  • cond2. Если правый край находится слева от левого края B,      - тогда A полностью слева от B
  • Cond3. Если верхний край ниже нижнего края B,      - тогда A полностью ниже B
  • Cond4. Если нижний край находится над верхним краем B,      - тогда A полностью выше B

Таким образом, условие для Non-Overlap

Cond1 Or Cond2 Or Cond3 Or Cond4

Следовательно, достаточным условием для перекрытия является противоположное.

Not (Cond1 Or Cond2 Or Cond3 Or Cond4)

Закон Де Моргана гласит: Not (A or B or C or D) совпадает с Not A And Not B And Not C And Not D
поэтому, используя De Morgan, мы имеем

Not Cond1 And Not Cond2 And Not Cond3 And Not Cond4

Это эквивалентно:

  • Левый край слева от правого края B, [ RectA.Left < RectB.Right] и
  • Правый край справа от левого края B, [ RectA.Right > RectB.Left] и
  • Верх над нижней частью B, [ RectA.Top > RectB.Bottom] и
  • Нижнее нижнее B Верх [ RectA.Bottom < RectB.Top]

Примечание 1. Очевидно, этот же принцип может быть расширен до любого числа измерений. Примечание 2. Также должно быть достаточно очевидно подсчитать перекрытие всего одного пикселя, изменить < и/или > на этой границе на <= или >=.
Примечание 3. Этот ответ при использовании декартовых координат (X, Y) основан на стандартных алгебраических декартовых координатах (x увеличивается слева направо, а Y увеличивается снизу вверх). Очевидно, что если компьютерная система может механизировать координаты экрана по-разному (например, увеличивая Y сверху вниз или X справа налево), синтаксис необходимо будет соответствующим образом скорректировать/

Ответ 2

struct rect
{
    int x;
    int y;
    int width;
    int height;
};

bool valueInRange(int value, int min, int max)
{ return (value >= min) && (value <= max); }

bool rectOverlap(rect A, rect B)
{
    bool xOverlap = valueInRange(A.x, B.x, B.x + B.width) ||
                    valueInRange(B.x, A.x, A.x + A.width);

    bool yOverlap = valueInRange(A.y, B.y, B.y + B.height) ||
                    valueInRange(B.y, A.y, A.y + A.height);

    return xOverlap && yOverlap;
}

Ответ 3

struct Rect
{
    Rect(int x1, int x2, int y1, int y2)
    : x1(x1), x2(x2), y1(y1), y2(y2)
    {
        assert(x1 < x2);
        assert(y1 < y2);
    }

    int x1, x2, y1, y2;
};

bool
overlap(const Rect &r1, const Rect &r2)
{
    // The rectangles don't overlap if
    // one rectangle minimum in some dimension 
    // is greater than the other maximum in
    // that dimension.

    bool noOverlap = r1.x1 > r2.x2 ||
                     r2.x1 > r1.x2 ||
                     r1.y1 > r2.y2 ||
                     r2.y1 > r1.y2;

    return !noOverlap;
}

Ответ 4

Легче проверить, является ли прямоугольник полностью вне другого, поэтому, если это либо

слева...

(r1.x + r1.width < r2.x)

или справа...

(r1.x > r2.x + r2.width)

или сверху...

(r1.y + r1.height < r2.y)

или внизу...

(r1.y > r2.y + r2.height)

второго прямоугольника, он не может столкнуться с ним. Таким образом, чтобы функция, возвращающая булевскую поговорку, сталкивается с прямоугольниками, мы просто объединяем условия с помощью логических OR и отрицаем результат:

function checkOverlap(r1, r2) : Boolean
{ 
    return !(r1.x + r1.width < r2.x || r1.y + r1.height < r2.y || r1.x > r2.x + r2.width || r1.y > r2.y + r2.height);
}

Чтобы получить положительный результат только при касании, мы можем изменить "<" и " > " на "< =" и " > =".

Ответ 5

Задайте себе противоположный вопрос: как определить, не пересекаются ли два прямоугольника? Очевидно, что прямоугольник A, полностью слева от прямоугольника B, не пересекается. Также, если A полностью справа. И аналогично, если A полностью выше B или полностью ниже B. В любом другом случае A и B пересекаются.

В следующих ниже могут быть ошибки, но я довольно уверен в этом алгоритме:

struct Rectangle { int x; int y; int width; int height; };

bool is_left_of(Rectangle const & a, Rectangle const & b) {
   if (a.x + a.width <= b.x) return true;
   return false;
}
bool is_right_of(Rectangle const & a, Rectangle const & b) {
   return is_left_of(b, a);
}

bool not_intersect( Rectangle const & a, Rectangle const & b) {
   if (is_left_of(a, b)) return true;
   if (is_right_of(a, b)) return true;
   // Do the same for top/bottom...
 }

bool intersect(Rectangle const & a, Rectangle const & b) {
  return !not_intersect(a, b);
}

Ответ 6

Предположим, что вы определили позиции и размеры прямоугольников следующим образом:

enter image description here

Моя реализация С++ такова:

class Vector2D
{
    public:
        Vector2D(int x, int y) : x(x), y(y) {}
        ~Vector2D(){}
        int x, y;
};

bool DoRectanglesOverlap(   const Vector2D & Pos1,
                            const Vector2D & Size1,
                            const Vector2D & Pos2,
                            const Vector2D & Size2)
{
    if ((Pos1.x < Pos2.x + Size2.x) &&
        (Pos1.y < Pos2.y + Size2.y) &&
        (Pos2.x < Pos1.x + Size1.x) &&
        (Pos2.y < Pos1.y + Size1.y))
    {
        return true;
    }
    return false;
}

Пример вызова функции в соответствии с приведенным выше рисунком:

DoRectanglesOverlap(Vector2D(3, 7),
                    Vector2D(8, 5),
                    Vector2D(6, 4),
                    Vector2D(9, 4));

Сравнение внутри блока if будет выглядеть следующим образом:

if ((Pos1.x < Pos2.x + Size2.x) &&
    (Pos1.y < Pos2.y + Size2.y) &&
    (Pos2.x < Pos1.x + Size1.x) &&
    (Pos2.y < Pos1.y + Size1.y))
                 ↓  
if ((   3   <    6   +   9    ) &&
    (   7   <    4   +   4    ) &&
    (   6   <    3   +   8    ) &&
    (   4   <    7   +   5    ))

Ответ 7

Вот как это делается в Java API:

public boolean intersects(Rectangle r) {
    int tw = this.width;
    int th = this.height;
    int rw = r.width;
    int rh = r.height;
    if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
        return false;
    }
    int tx = this.x;
    int ty = this.y;
    int rx = r.x;
    int ry = r.y;
    rw += rx;
    rh += ry;
    tw += tx;
    th += ty;
    //      overflow || intersect
    return ((rw < rx || rw > tx) &&
            (rh < ry || rh > ty) &&
            (tw < tx || tw > rx) &&
            (th < ty || th > ry));
}

Ответ 8

В этом вопросе вы ссылаетесь на математику, когда прямоугольники находятся под произвольными углами вращения. Однако, если я понимаю бит о углах в вопросе, я интерпретирую, что все прямоугольники перпендикулярны друг другу.

Общее знание области формулы перекрытия:

Используя пример:

   1   2   3   4   5   6

1  +---+---+
   |       |   
2  +   A   +---+---+
   |       | B     |
3  +       +   +---+---+
   |       |   |   |   |
4  +---+---+---+---+   +
               |       |
5              +   C   +
               |       |
6              +---+---+

1) собрать все координаты x (как слева, так и справа) в список, затем отсортировать его и удалить дубликаты

1 3 4 5 6

2) соберите все координаты y (как сверху, так и внизу) в список, затем отсортируйте его и удалите дубликаты

1 2 3 4 6

3) создать 2D-массив по количеству пробелов между уникальными координатами x * количество пробелов между уникальными координатами y.

4 * 4

4) покрасьте все прямоугольники в эту сетку, увеличивая количество каждой ячейки, в которой оно происходит:

   1   3   4   5   6

1  +---+
   | 1 | 0   0   0
2  +---+---+---+
   | 1 | 1 | 1 | 0
3  +---+---+---+---+
   | 1 | 1 | 2 | 1 |
4  +---+---+---+---+
     0   0 | 1 | 1 |
6          +---+---+

5) Когда вы рисуете прямоугольники, легко перехватывайте перекрытия.

Ответ 9

struct Rect
{
   Rect(int x1, int x2, int y1, int y2)
   : x1(x1), x2(x2), y1(y1), y2(y2)
   {
       assert(x1 < x2);
       assert(y1 < y2);
   }

   int x1, x2, y1, y2;
};

//some area of the r1 overlaps r2
bool overlap(const Rect &r1, const Rect &r2)
{
    return r1.x1 < r2.x2 && r2.x1 < r1.x2 &&
           r1.y1 < r2.y2 && r2.x1 < r1.y2;
}

//either the rectangles overlap or the edges touch
bool touch(const Rect &r1, const Rect &r2)
{
    return r1.x1 <= r2.x2 && r2.x1 <= r1.x2 &&
           r1.y1 <= r2.y2 && r2.x1 <= r1.y2;
}

Ответ 10

Не думайте о координатах, указывающих, где находятся пиксели. Думайте о них как о пикселях. Таким образом, площадь прямоугольника 2x2 должна быть 4, а не 9.

bool bOverlap = !((A.Left >= B.Right || B.Left >= A.Right)
               && (A.Bottom >= B.Top || B.Bottom >= A.Top));

Ответ 11

Допустим, два прямоугольника - это прямоугольник A и прямоугольник B. Пусть есть центры A1 и B1 (координаты A1 и B1 можно легко определить), пусть высоты равны Ha и Hb, ширина равна Wa и Wb, пусть dx будет width (x) расстояние между A1 и B1, а dy - расстояние по высоте (y) между A1 и B1.

Теперь мы можем сказать, что можем сказать, что А и В перекрываются: когда

if(!(dx > Wa+Wb)||!(dy > Ha+Hb)) returns true

Ответ 12

Самый простой способ -

/**
 * Check if two rectangles collide
 * x_1, y_1, width_1, and height_1 define the boundaries of the first rectangle
 * x_2, y_2, width_2, and height_2 define the boundaries of the second rectangle
 */
boolean rectangle_collision(float x_1, float y_1, float width_1, float height_1, float x_2, float y_2, float width_2, float height_2)
{
  return !(x_1 > x_2+width_2 || x_1+width_1 < x_2 || y_1 > y_2+height_2 || y_1+height_1 < y_2);
}

Прежде всего, поставите на мысль, что в компьютерах система координат перевернута. ось x такая же, как и в математике, но ось y увеличивается вниз и уменьшается при движении вверх. если прямоугольник вычерчен из центра. если координаты x1 больше, чем x2 плюс его половина его ширины. то это означает, что половина будет касаться друг друга. и таким же образом идет вниз + половина его высоты. он столкнется.

Ответ 13

Я реализовал версию С#, ее легко преобразовать в С++.

public bool Intersects ( Rectangle rect )
{
  float ulx = Math.Max ( x, rect.x );
  float uly = Math.Max ( y, rect.y );
  float lrx = Math.Min ( x + width, rect.x + rect.width );
  float lry = Math.Min ( y + height, rect.y + rect.height );

  return ulx <= lrx && uly <= lry;
}

Ответ 14

У меня очень простое решение

пусть x1, y1 x2, y2, l1, b1, l2, являются корнями, а длины и широты их соответственно

рассмотрим условие ((x2

теперь единственный способ, которым этот прямоугольник будет перекрываться, - это то, что диагональ точки x1, y1 будет находиться внутри другого прямоугольника или аналогично диагональ точки x2, y2 будет находиться внутри другого прямоугольника. что в точности означает указанное выше условие.

Ответ 15

A и B - два прямоугольника. C - их накрывающий прямоугольник.

four points of A be (xAleft,yAtop),(xAleft,yAbottom),(xAright,yAtop),(xAright,yAbottom)
four points of A be (xBleft,yBtop),(xBleft,yBbottom),(xBright,yBtop),(xBright,yBbottom)

A.width = abs(xAleft-xAright);
A.height = abs(yAleft-yAright);
B.width = abs(xBleft-xBright);
B.height = abs(yBleft-yBright);

C.width = max(xAleft,xAright,xBleft,xBright)-min(xAleft,xAright,xBleft,xBright);
C.height = max(yAtop,yAbottom,yBtop,yBbottom)-min(yAtop,yAbottom,yBtop,yBbottom);

A and B does not overlap if
(C.width >= A.width + B.width )
OR
(C.height >= A.height + B.height) 

Он принимает все возможные варианты.

Ответ 16

Это из упражнения 3.28 из книги "Введение в программирование на Java - всеобъемлющее издание". Код проверяет, являются ли два прямоугольника indenticle, независимо от того, находится ли он внутри другого и находится ли он вне другого. Если ни одно из этих условий не выполняется, то два перекрываются.

** 3.28 (Геометрия: два прямоугольника) Напишите программу, в которой пользователю предлагается ввести центр x-, y-координат, ширины и высоты двух прямоугольников и определяет является ли второй прямоугольник внутри первого или перекрывается с первым, как показано на рис. 3.9. Проверьте свою программу, чтобы охватить все случаи. Ниже приведены примеры прогона:

Введите r1 центр x-, y-координаты, ширину и высоту: 2,5 4 2,5 43 Введите r2 center x-, y-координаты, ширину и высоту: 1,5 5 0,5 3 r2 находится внутри r1

Введите r1 центр x-, y-координаты, ширину и высоту: 1 2 3 5.5 Введите r2 center x-, y-координаты, ширину и высоту: 3 4 4,5 5 r2 перекрывает r1

Введите r1 центр x-, y-координаты, ширину и высоту: 1 2 3 3 Введите r2 center x-, y-координаты, ширину и высоту: 40 45 3 2 r2 не перекрывается r1

import java.util.Scanner;

public class ProgrammingEx3_28 {
public static void main(String[] args) {
    Scanner input = new Scanner(System.in);

    System.out
            .print("Enter r1 center x-, y-coordinates, width, and height:");
    double x1 = input.nextDouble();
    double y1 = input.nextDouble();
    double w1 = input.nextDouble();
    double h1 = input.nextDouble();
    w1 = w1 / 2;
    h1 = h1 / 2;
    System.out
            .print("Enter r2 center x-, y-coordinates, width, and height:");
    double x2 = input.nextDouble();
    double y2 = input.nextDouble();
    double w2 = input.nextDouble();
    double h2 = input.nextDouble();
    w2 = w2 / 2;
    h2 = h2 / 2;

    // Calculating range of r1 and r2
    double x1max = x1 + w1;
    double y1max = y1 + h1;
    double x1min = x1 - w1;
    double y1min = y1 - h1;
    double x2max = x2 + w2;
    double y2max = y2 + h2;
    double x2min = x2 - w2;
    double y2min = y2 - h2;

    if (x1max == x2max && x1min == x2min && y1max == y2max
            && y1min == y2min) {
        // Check if the two are identicle
        System.out.print("r1 and r2 are indentical");

    } else if (x1max <= x2max && x1min >= x2min && y1max <= y2max
            && y1min >= y2min) {
        // Check if r1 is in r2
        System.out.print("r1 is inside r2");
    } else if (x2max <= x1max && x2min >= x1min && y2max <= y1max
            && y2min >= y1min) {
        // Check if r2 is in r1
        System.out.print("r2 is inside r1");
    } else if (x1max < x2min || x1min > x2max || y1max < y2min
            || y2min > y1max) {
        // Check if the two overlap
        System.out.print("r2 does not overlaps r1");
    } else {
        System.out.print("r2 overlaps r1");
    }

}
}

Ответ 17

bool Square::IsOverlappig(Square &other)
{
    bool result1 = other.x >= x && other.y >= y && other.x <= (x + width) && other.y <= (y + height); // other top left falls within this area
    bool result2 = other.x >= x && other.y <= y && other.x <= (x + width) && (other.y + other.height) <= (y + height); // other bottom left falls within this area
    bool result3 = other.x <= x && other.y >= y && (other.x + other.width) <= (x + width) && other.y <= (y + height); // other top right falls within this area
    bool result4 = other.x <= x && other.y <= y && (other.x + other.width) >= x && (other.y + other.height) >= y; // other bottom right falls within this area
    return result1 | result2 | result3 | result4;
}

Ответ 18

Для тех из вас, кто использует центральные точки и половинные размеры для своих данных прямоугольника, вместо типичных x, y, w, h или x0, y0, x1, x1, вот как вы можете это сделать:

#include <cmath> // for fabsf(float)

struct Rectangle
{
    float centerX, centerY, halfWidth, halfHeight;
};

bool isRectangleOverlapping(const Rectangle &a, const Rectangle &b)
{
    return (fabsf(a.centerX - b.centerX) <= (a.halfWidth + b.halfWidth)) &&
           (fabsf(a.centerY - b.centerY) <= (a.halfHeight + b.halfHeight)); 
}

Ответ 19

Посмотрите на вопрос с другого сайта.

Случай оказывается довольно простым, если мы посмотрим на проблему (алгоритм) с другой стороны.

Это означает, что вместо ответа на вопрос: "Прямоугольники перекрываются?", Мы ответим на вопрос: " Не перекрываются ли прямоугольники?".

В конце концов, оба вопроса решают одну и ту же проблему, но ответ на второй вопрос проще реализовать, потому что прямоугольники не перекрываются, только когда один находится под другим или когда один находится слева от другого (этого достаточно для одного из этих случаев иметь место, но, конечно, может случиться так, что оба будут происходить одновременно - здесь хорошее понимание логического условия "или" важно). Это уменьшает многие случаи, которые необходимо рассмотреть по первому вопросу.

Весь вопрос также упрощается путем использования соответствующих имен переменных:

#include<bits/stdc++.h> 

struct Rectangle
{ 
    // Coordinates of the top left corner of the rectangle and width and height
    float x, y, width, height; 
}; 

bool areRectanglesOverlap(Rectangle rect1, Rectangle rect2) 
{
  // Declaration and initialization of local variables

  // if x and y are the top left corner of the rectangle
  float left1, top1, right1, bottom1, left2, top2, right2, bottom2;
  left1 = rect1.x;
  top1 = rect1.y;
  right1 = rect1.x + rect1.width;
  bottom1 = rect1.y - rect1.height;
  left2 = rect2.x;
  top2 = rect2.y;
  right2 = rect2.x + rect2.width;
  bottom2 = rect2.y - rect2.height;

  // The main part of the algorithm

  // The first rectangle is under the second or vice versa
  if (top1 < bottom2 || top2 < bottom1)
  {
    return false;
  }
  // The first rectangle is to the left of the second or vice versa
  if (right1 < left2 || right2 < left1)
  {
    return false;
  }
  // Rectangles overlap
  return true;
}

Даже если у нас другое представление прямоугольника, легко адаптировать вышеуказанную функцию к нему, изменяя только раздел, в котором определены изменения переменных. Дальнейшая часть функции остается неизменной (конечно, комментарии здесь на самом деле не нужны, но я добавил их, чтобы каждый мог быстро понять этот простой алгоритм).

Эквивалентная, но, возможно, немного менее читаемая форма вышеприведенной функции может выглядеть так:

bool areRectanglesOverlap(Rectangle rect1, Rectangle rect2) 
{
  float left1, top1, right1, bottom1, left2, top2, right2, bottom2;
  left1 = rect1.x;
  top1 = rect1.y;
  right1 = rect1.x + rect1.width;
  bottom1 = rect1.y - rect1.height;
  left2 = rect2.x;
  top2 = rect2.y;
  right2 = rect2.x + rect2.width;
  bottom2 = rect2.y - rect2.height;

  return !(top1 < bottom2 || top2 < bottom1 || right1 < left2 || right2 < left1);
}

Ответ 20

***************
My c# Solution:
***************

Assumption:
l1: Top Left coordinate of first rectangle.
r1: Bottom Right coordinate of first rectangle.
l2: Top Left coordinate of second rectangle.
r2: Bottom Right coordinate of second rectangle.

using System;

public class Point
{
  public int x,y;

  public Point(int x, int y)
  {
    this.x = x;
    this.y = y;
  }
}

public class Rectangle 
{
  private Point topLeft;
  private Point bottomRight; 
  public Rectangle(Point topLeft, Point bottomRight) 
  { 
    this.topLeft = topLeft; 
    this.bottomRight = bottomRight; 
  } 

  public bool isOverLapping(Rectangle other) 
  { 
      if (this.topLeft.x > other.bottomRight.x // Rect1 is right to Rect2 
        || this.bottomRight.x < other.topLeft.x // Rect1 is left to Rect2 
        || this.topLeft.y < other.bottomRight.y // Rect1 is above Rect2 
        || this.bottomRight.y > other.topLeft.y) // Rect1 is below Rect2
        { 
          return false; 
        } 
        return true; 
  } 
}

class Solution
{
  static void Main(string[] args)
  {
      Point l1 = new Point(0, 10); 
      Point r1 = new Point(10, 0); 
      Point l2 = new Point(5, 5); 
      Point r2 = new Point(15, 0);

      Rectangle first = new Rectangle(l1, r1); 
      Rectangle second = new Rectangle(l2, r2); 
      if (first.isOverLapping(second)) 
      { 
         Console.WriteLine("Yes, two rectangles are intersecting with each other"); 
      } 
      else 
      { 
         Console.WriteLine("No, two rectangles are not overlapping with each other"); 
      } 

      Console.Read();
   }
}

Ответ 21

Этот ответ должен быть главным ответом:

Если прямоугольники перекрываются, то область перекрытия будет больше нуля. Теперь давайте найдем область перекрытия:

Если они перекрываются, то левый край прямоугольника перекрытия будет max(r1.x1, r2.x1) а правый край будет min(r1.x2, r2.x2). Таким образом, длина перекрытия будет min(r1.x2, r2.x2) - max(r1.x1, r2.x1)

Так что площадь будет:

area = (max(r1.x1, r2.x1) - min(r1.x2, r2.x2)) * (max(r1.y1, r2.y1) - min(r1.y2, r2.y2))

Если area = 0 то они не перекрываются.

Просто не так ли?

Ответ 22

"Если вы выполняете вычитание x или y координат, соответствующих вершинам двух, обращенных к каждому прямоугольнику, если результаты являются одним и тем же знаком, два прямоугольника не перекрывают оси, которые" (извините, я не уверен, что мой перевод правильный)

enter image description here

Источник: http://www.ieev.org/2009/05/kiem-tra-hai-hinh-chu-nhat-chong-nhau.html

Ответ 23

Java-код, чтобы выяснить, соприкасаются ли прямоугольники или перекрывают друг друга

...

for ( int i = 0; i < n; i++ ) {
    for ( int j = 0; j < n; j++ ) {
        if ( i != j ) {
            Rectangle rectangle1 = rectangles.get(i);
            Rectangle rectangle2 = rectangles.get(j);

            int l1 = rectangle1.l; //left
            int r1 = rectangle1.r; //right
            int b1 = rectangle1.b; //bottom
            int t1 = rectangle1.t; //top

            int l2 = rectangle2.l;
            int r2 = rectangle2.r;
            int b2 = rectangle2.b;
            int t2 = rectangle2.t;

            boolean topOnBottom = t2 == b1;
            boolean bottomOnTop = b2 == t1;
            boolean topOrBottomContact = topOnBottom || bottomOnTop;

            boolean rightOnLeft = r2 == l1;
            boolean leftOnRight = l2 == r1;
            boolean rightOrLeftContact = leftOnRight || rightOnLeft;

            boolean leftPoll = l2 <= l1 && r2 >= l1;
            boolean rightPoll = l2 <= r1 && r2 >= r1;
            boolean leftRightInside = l2 >= l1 && r2 <= r1;
            boolean leftRightPossiblePlaces = leftPoll || rightPoll || leftRightInside;

            boolean bottomPoll = t2 >= b1 && b2 <= b1;
            boolean topPoll = b2 <= b1 && t2 >= b1;
            boolean topBottomInside = b2 >= b1 && t2 <= t1;
            boolean topBottomPossiblePlaces = bottomPoll || topPoll || topBottomInside;


            boolean topInBetween = t2 > b1 && t2 < t1;
            boolean bottomInBetween = b2 > b1 && b2 < t1;
            boolean topBottomInBetween = topInBetween || bottomInBetween;

            boolean leftInBetween = l2 > l1 && l2 < r1;
            boolean rightInBetween = r2 > l1 && r2 < r1;
            boolean leftRightInBetween = leftInBetween || rightInBetween;

            if ( (topOrBottomContact && leftRightPossiblePlaces) || (rightOrLeftContact && topBottomPossiblePlaces) ) {
                path[i][j] = true;
            }
        }
    }
}

...