Xác định xem hai hình chữ nhật có trùng nhau không?


337

Tôi đang cố gắng viết chương trình C ++ lấy các đầu vào sau từ người dùng để xây dựng hình chữ nhật (từ 2 đến 5): chiều cao, chiều rộng, x-pos, y-pos. Tất cả các hình chữ nhật này sẽ tồn tại song song với trục x và trục y, đó là tất cả các cạnh của chúng sẽ có độ dốc bằng 0 hoặc vô cùng.

Tôi đã cố gắng thực hiện những gì được đề cập trong câu hỏi này nhưng tôi không gặp nhiều may mắn.

Việc triển khai hiện tại của tôi thực hiện như sau:

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

Tuy nhiên tôi không chắc chắn nếu (a) tôi đã triển khai thuật toán mà tôi đã liên kết chính xác hay liệu tôi đã làm chính xác cách giải thích điều này?

Bất kỳ đề xuất?


3
Tôi nghĩ rằng giải pháp cho vấn đề của bạn không liên quan đến bất kỳ phép nhân nào .
Scott Evernden

Câu trả lời:


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

hoặc, sử dụng tọa độ Descartes

(Với X1 bị bỏ coord, X2 là coord đúng, tăng từ trái sang phải và Y1 được trên coord, và Y2 là dưới coord, tăng từ dưới lên trên - nếu điều này không phải là cách hệ tọa độ của bạn [ví dụ như hầu hết các máy tính có Hướng Y đảo ngược], hoán đổi các so sánh bên dưới ) ...

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

Giả sử bạn có Rect A và Rect B. Bằng chứng là do mâu thuẫn. Bất kỳ một trong bốn điều kiện đảm bảo rằng không có sự trùng lặp có thể tồn tại :

  • Cond1. Nếu cạnh trái của A nằm bên phải cạnh B, - thì A hoàn toàn ở bên phải của B
  • Cond2. Nếu cạnh phải của A nằm bên trái cạnh trái của B, - thì A hoàn toàn nằm bên trái B
  • Cond3. Nếu cạnh trên của A nằm dưới cạnh dưới của B, - thì A hoàn toàn nằm dưới B
  • Cond4. Nếu cạnh dưới của A nằm trên cạnh trên của B, - thì A hoàn toàn ở trên B

Vì vậy, điều kiện để không chồng chéo là

Không chồng chéo => Cond1 Hoặc Cond2 hoặc Cond3 hoặc Cond4

Do đó, một điều kiện đủ cho Overlap là ngược lại.

Chồng chéo => KHÔNG (Cond1 Hoặc Cond2 hoặc Cond3 hoặc Cond4)

Luật của De Morgan nói
Not (A or B or C or D)giống như Not A And Not B And Not C And Not D
sử dụng De Morgan, chúng ta có

Không phải Cond1 và không phải Cond2 và không phải Cond3 và không phải Cond4

Điều này tương đương với:

  • Cạnh trái của A ở bên trái cạnh phải của B, [ RectA.Left < RectB.Right] và
  • Cạnh phải của A bên phải cạnh trái của B, [ RectA.Right > RectB.Left] và
  • Đỉnh A phía trên đáy B, [ RectA.Top > RectB.Bottom] và
  • A dưới bên dưới B của [[ RectA.Bottom < RectB.Top]

Lưu ý 1 : Rõ ràng nguyên tắc tương tự này có thể được mở rộng cho bất kỳ số lượng kích thước nào.
Lưu ý 2 : Cũng khá rõ ràng khi đếm các lớp phủ chỉ một pixel, thay đổi <và / hoặc >trên ranh giới đó thành a <=hoặc a >=.
Lưu ý 3 : Câu trả lời này, khi sử dụng tọa độ Cartesian (X, Y) dựa trên tọa độ Cartesian đại số tiêu chuẩn (x tăng từ trái sang phải và Y tăng từ dưới lên trên). Rõ ràng, khi một hệ thống máy tính có thể cơ giới hóa các tọa độ màn hình khác nhau, (ví dụ: tăng Y từ trên xuống dưới hoặc X Từ phải sang trái), cú pháp sẽ cần được điều chỉnh cho phù hợp /


489
Nếu bạn gặp khó khăn trong việc hình dung lý do tại sao nó hoạt động, tôi đã tạo một trang ví dụ tại quietmatt.com/intersection.html nơi bạn có thể kéo hình chữ nhật xung quanh và xem các so sánh.
Matthew Crumley

4
bạn không nghĩ rằng bạn đang sử dụng các ràng buộc cứng? Điều gì nếu hai hình chữ nhật chồng lên nhau chính xác trên cạnh đó? bạn không nên xem xét <=,> = ??
Nawshad Farruque

6
@MatthewCrumley cho A.Y1 <B.Y2 và A.Y2> B.Y1 trên liên kết của bạn, không nên đảo ngược các dấu hiệu gt & lt?
NikT

15
Tôi đã phải trao đổi <và> trong hai lần so sánh gần đây để làm cho nó hoạt động
DataGreed

17
Không, câu trả lời đúng như đã nêu. Nó dựa trên việc sử dụng tọa độ Descartes tiêu chuẩn. Nếu bạn đang sử dụng một hệ thống khác, (Y tăng từ trên xuống dưới), sau đó thực hiện các điều chỉnh thích hợp.
Charles Bretana

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

15
Câu trả lời đơn giản và sạch sẽ nhất.
ldog

1
@ e.James Tôi đoán cuối cùng B.heightnên làA.height
mat_boy

'min' và 'max' là các từ khóa dành riêng trong <windows.h>. bạn có thể sửa nó bằng cách thực hiện #undef min#undef maxbằng cách sử dụng các tên tham số khác nhau.
mchiasson

Nếu bạn sử dụng rộng rãi, bạn có thể giao dịch valueInRange cho một#define BETWEEN(value,min,max) \ (\ value > max ? max : ( value < min ? min : value )\ )
Ratata Tata

@Nemo Trên thực tế, kiểm tra xOverlaplà một chiều; rectOverlaplà hai chiều. Nó có thể được mở rộng đến N kích thước bằng cách sử dụng một vòng lặp.
Justme0

27
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's minimum in some dimension 
    // is greater than the other's maximum in
    // that dimension.

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

    return !noOverlap;
}

Đẹp quá Áp dụng luật De Morgans thu được: r1.x1 <= r2.x2 && r2.x1 <= r1.x2 && r1.y1 <= r2.y2 && r2.y1 <= r1.y2.
Borzh

23

Sẽ dễ dàng hơn để kiểm tra nếu một hình chữ nhật hoàn toàn bên ngoài cái kia, vì vậy nếu nó là một trong hai

bên trái...

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

hoặc bên phải ...

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

hoặc trên đầu ...

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

hoặc ở phía dưới ...

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

của hình chữ nhật thứ hai, nó không thể va chạm với nó. Vì vậy, để có một hàm trả về Boolean cho biết thời tiết các hình chữ nhật va chạm, chúng ta chỉ cần kết hợp các điều kiện bằng các OR logic và phủ định kết quả:

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

Để đã nhận được kết quả tích cực khi chỉ chạm vào, chúng ta có thể thay đổi "<" và ">" bằng "<=" và "> =".


3
Và áp dụng luật de morgan cho nó.
Borzh

6

Hãy tự hỏi mình câu hỏi ngược lại: Làm thế nào tôi có thể xác định nếu hai hình chữ nhật không giao nhau? Rõ ràng, một hình chữ nhật A hoàn toàn ở bên trái của hình chữ nhật B không giao nhau. Ngoài ra nếu A hoàn toàn bên phải. Và tương tự nếu A hoàn toàn trên B hoặc hoàn toàn dưới B. Trong mọi trường hợp khác A và B cắt nhau.

Điều gì sau đây có thể có lỗi, nhưng tôi khá tự tin về thuật toán:

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

Giả sử rằng bạn đã xác định vị trí và kích thước của hình chữ nhật như thế này:

nhập mô tả hình ảnh ở đây

Việc thực hiện C ++ của tôi là như thế này:

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

Một ví dụ gọi hàm theo hình đã cho ở trên:

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

Các so sánh bên trong ifkhối sẽ như sau:

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

3

Đây là cách nó được thực hiện trong API Java:

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

Lưu ý rằng trong C ++, các thử nghiệm cho tràn này sẽ không hoạt động, vì tràn số nguyên đã ký không được xác định.
Ben Voigt

2

Trong câu hỏi, bạn liên kết với các toán học khi hình chữ nhật ở các góc quay tùy ý. Tuy nhiên, nếu tôi hiểu một chút về các góc trong câu hỏi, tôi giải thích rằng tất cả các hình chữ nhật đều vuông góc với nhau.

Một tổng quát biết khu vực của công thức chồng chéo là:

Sử dụng ví dụ:

   1 2 3 4 5 6

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

1) thu thập tất cả các tọa độ x (cả trái và phải) vào một danh sách, sau đó sắp xếp nó và loại bỏ trùng lặp

1 3 4 5 6

2) thu thập tất cả các tọa độ y (cả trên và dưới) vào một danh sách, sau đó sắp xếp nó và loại bỏ trùng lặp

1 2 3 4 6

3) tạo một mảng 2D theo số khoảng trống giữa các tọa độ x duy nhất * số khoảng trống giữa các tọa độ y duy nhất.

4 * 4

4) vẽ tất cả các hình chữ nhật vào lưới này, tăng số lượng của mỗi ô mà nó xuất hiện:

   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) Khi bạn vẽ các hình chữ nhật, thật dễ dàng để chặn các lớp phủ.


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

1

Đừng nghĩ về tọa độ như chỉ ra các pixel ở đâu. Hãy nghĩ về chúng như là giữa các pixel. Theo cách đó, diện tích của hình chữ nhật 2x2 phải là 4 chứ không phải 9.

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

1

Cách dễ nhất là

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

trước hết hãy ghi nhớ rằng trong máy tính, hệ tọa độ bị đảo lộn. trục x giống như trong toán học nhưng trục y tăng xuống và giảm khi đi lên .. nếu hình chữ nhật được vẽ từ tâm. nếu tọa độ x1 lớn hơn x2 cộng với một nửa độ rộng của nó. sau đó nó có nghĩa là đi một nửa họ sẽ chạm vào nhau. và theo cách tương tự đi xuống + một nửa chiều cao của nó. nó sẽ va chạm ..


1

Giả sử hai hình chữ nhật là hình chữ nhật A và hình chữ nhật B. Đặt tâm của chúng là A1 và B1 (có thể dễ dàng tìm ra tọa độ của A1 và B1), hãy để chiều cao là Ha và Hb, chiều rộng là Wa và Wb, hãy để dx là khoảng cách chiều rộng (x) giữa A1 và B1 và ​​dy là khoảng cách chiều cao (y) giữa A1 và B1.

Bây giờ chúng ta có thể nói chúng ta có thể nói A và B trùng nhau: khi nào

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

0

Tôi đã thực hiện một phiên bản C #, nó dễ dàng được chuyển đổi thành 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;
}

2
Đối với mắt được đào tạo, rõ ràng bạn có nghĩa đây là một lớp mở rộng cho Hình chữ nhật, nhưng bạn đã không cung cấp bất kỳ giới hạn hoặc mã nào để thực sự làm điều đó. Sẽ thật tuyệt nếu bạn đã thực hiện điều đó hoặc giải thích rằng phương pháp của bạn được sử dụng như thế nào và điểm thưởng nếu các biến của bạn thực sự có đủ tên mô tả cho bất kỳ ai theo dõi để hiểu mục đích / ý định của họ.
sinh viên

0

Tôi có một giải pháp rất dễ dàng

Đặt x1, y1 x2, y2, l1, b1, l2, lần lượt là các khoảng cách và độ dài và chiều rộng của chúng

xem xét điều kiện ((x2

Bây giờ cách duy nhất các hình chữ nhật này sẽ trùng nhau là nếu đường chéo điểm đến x1, y1 sẽ nằm bên trong hình chữ nhật khác hoặc tương tự đường chéo điểm với x2, y2 sẽ nằm bên trong hình chữ nhật khác. đó chính xác là điều kiện trên ngụ ý.


0

A và B là hai hình chữ nhật. C là hình chữ nhật bao phủ của chúng.

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) 

Nó chăm sóc tất cả các trường hợp có thể.


0

Đây là từ bài tập 3.28 từ cuốn sách Giới thiệu về lập trình Java - Phiên bản toàn diện. Mã kiểm tra xem hai hình chữ nhật có thụt vào không, liệu cái này có ở bên trong cái kia hay không và cái này có nằm ngoài cái kia không. Nếu không có điều kiện nào được đáp ứng thì hai cái này trùng nhau.

** 3.28 (Hình học: hai hình chữ nhật) Viết chương trình nhắc người dùng nhập tâm x-, tọa độ y, chiều rộng và chiều cao của hai hình chữ nhật và xác định xem hình chữ nhật thứ hai nằm trong hình đầu tiên hay chồng chéo với hình đầu tiên, như thể hiện trong hình 3.9. Kiểm tra chương trình của bạn để bao gồm tất cả các trường hợp. Dưới đây là các mẫu chạy:

Nhập tâm của x1, tọa độ y, chiều rộng và chiều cao: 2,5 4 2,5 43 Nhập tâm của r2, tọa độ y, chiều rộng và chiều cao: 1,5 5 0,5 3 r2 nằm trong r1

Nhập tâm của x1, tọa độ y, chiều rộng và chiều cao: 1 2 3 5.5 Nhập tâm của r2, tọa độ y, chiều rộng và chiều cao: 3 4 4,5 5 r2 chồng chéo r1

Nhập tâm của x1, tọa độ y, chiều rộng và chiều cao: 1 2 3 3 Nhập tâm của r2, tọa độ y, chiều rộng và chiều cao: 40 45 3 2 r2 không trùng với 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
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

Đối với những người bạn đang sử dụng điểm trung tâm và một nửa kích thước cho dữ liệu hình chữ nhật của họ, thay vì x, y, w, h hoặc x0, y0, x1, x1, đây là cách bạn có thể thực hiện:

#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
struct point { int x, y; };

struct rect { point tl, br; }; // top left and bottom right points

// return true if rectangles overlap
bool overlap(const rect &a, const rect &b)
{
    return a.tl.x <= b.br.x && a.br.x >= b.tl.x && 
           a.tl.y >= b.br.y && a.br.y <= b.tl.y;
}

0

Nếu các hình chữ nhật trùng nhau thì diện tích chồng lấp sẽ lớn hơn 0. Bây giờ chúng ta hãy tìm khu vực chồng lấp:

Nếu chúng trùng nhau thì cạnh trái của chồng chéo sẽ là max(r1.x1, r2.x1)cạnh phải và cạnh phải min(r1.x2, r2.x2). Vì vậy, độ dài của sự chồng chéo sẽ làmin(r1.x2, r2.x2) - max(r1.x1, r2.x1)

Vì vậy, khu vực sẽ là:

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

Nếu area = 0sau đó họ không chồng chéo.

Đơn giản phải không?


3
Điều này hoạt động cho sự chồng chéo (đó là câu hỏi) nhưng sẽ không hoạt động cho giao lộ, vì nó sẽ không hoạt động nếu chúng giao nhau ở một góc chính xác.
Lance Roberts

Tôi đã thử mã này và nó không hoạt động. Tôi chỉ nhận được số dương ngay cả khi chúng không trùng nhau.
Brett

@Brett: Có, vì tích của hai số âm là dương.
Ben Voigt

@BenVoigt, vấn đề là hàm không trả về 0 khi không có sự trùng lặp. Tôi đã không rõ ràng với nhận xét của mình, nhưng vâng, tôi chỉ nhận được khu vực> 0 từ chức năng này.
Brett

Nếu bạn đang làm việc với các số dấu phẩy động, thông thường bạn nên sử dụng phép trừ và các công cụ số học khác trước khi so sánh bất kỳ số nào. Đặc biệt nếu bạn cần so sánh với một giá trị chính xác - trong trường hợp này bằng không. Nó hoạt động trong lý thuyết, nhưng không thực tế.
maja


-1

Mã Java để tìm hiểu xem hình chữ nhật có liên hệ hoặc chồng chéo lẫn nhau không

...

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

...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.