Определить, перекрывают ли два прямоугольника друг друга? - PullRequest
310 голосов
/ 20 ноября 2008

Я пытаюсь написать программу на C ++, которая использует следующие входные данные от пользователя для построения прямоугольников (между 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;  

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

Есть предложения?

Ответы [ 22 ]

1 голос
/ 28 июня 2012

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

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

if(!(dx > Wa+Wb)||!(dy > Ha+Hb)) returns true
1 голос
/ 26 мая 2014

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

/**
 * 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 плюс его половина видимости. тогда это означает, что половину они коснутся друг друга. и таким же образом идет вниз + половина его высоты. оно столкнется ..

0 голосов
/ 23 января 2019

Взгляд на это с другого сайта.

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

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

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

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

#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);
}
0 голосов
/ 13 августа 2017

Для тех из вас, кто использует центральные точки и половинные размеры для своих данных прямоугольника вместо типичных 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)); 
}
0 голосов
/ 08 октября 2016

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

...

0 голосов
/ 07 августа 2016
bool Square::IsOverlappig(Square &other)
{
    bool result1 = other.x >= x && other.y >= y && other.x <= (x + width) && other.y <= (y + height); // other's 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's 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's 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's bottom right falls within this area
    return result1 | result2 | result3 | result4;
}
0 голосов
/ 01 августа 2015

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

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

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

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

Введите x-, y-координаты, ширину и высоту центра r1: 1 2 3 3 Введите x-, y-координаты, ширину и высоту центра r2: 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's 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's 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");
    }

}
}
0 голосов
/ 20 ноября 2008

Я реализовал версию C #, она легко конвертируется в C ++.

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;
}
0 голосов
/ 16 января 2014

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) 

Он заботится обо всех возможных случаях.

0 голосов
/ 04 июня 2013

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

enter image description here

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

...