Thuật toán phát hiện giao điểm của hai hình chữ nhật?


143

Tôi đang tìm kiếm một thuật toán để phát hiện nếu hai hình chữ nhật cắt nhau (một hình vuông ở góc tùy ý, hình kia chỉ có các đường thẳng đứng / nằm ngang).

Kiểm tra nếu một góc của một trong ALMOST khác hoạt động. Nó thất bại nếu các hình chữ nhật tạo thành một hình dạng giống nhau.

Có vẻ như là một ý tưởng tốt để tránh sử dụng độ dốc của các đường, trong đó sẽ yêu cầu các trường hợp đặc biệt cho các đường thẳng đứng.


Điều gì nếu bạn thêm vào kiểm tra góc của bạn, một kiểm tra để xem nếu hình chữ nhật thứ hai nằm trong giới hạn (hình chữ nhật) của hình chữ nhật góc?
Wes P

Ngôn ngữ nào bạn sẽ làm điều này trong? Bởi vì trong Java có các lớp dựng sẵn cho phép bạn làm điều này.
Martijn

Tôi nghĩ api đồ họa và hầu hết các thư viện GUI (như swing) đã thực hiện điều này.
l_39217_l

có thể bỏ lỡ các trường hợp chúng chồng lên nhau nhưng không có góc nào nằm trong bất kỳ hình chữ nhật nào
Florian Bösch

1
Câu hỏi này gần giống như: stackoverflow.com/questions/306316/ . Mặc dù, đây là tìm kiếm một giải pháp dành riêng cho C ++. Câu trả lời được chấp nhận cũng khá đơn giản và dễ hiểu.
Bạc Gonzales

Câu trả lời:


162

Phương pháp tiêu chuẩn sẽ là thực hiện kiểm tra trục tách (thực hiện tìm kiếm google trên đó).

Nói ngắn gọn:

  • Hai đối tượng không giao nhau nếu bạn có thể tìm thấy một đường ngăn cách hai đối tượng. ví dụ: các đối tượng / tất cả các điểm của một đối tượng nằm trên các cạnh khác nhau của dòng.

Điều thú vị là, chỉ cần kiểm tra tất cả các cạnh của hai hình chữ nhật là đủ. Nếu các hình chữ nhật không trùng nhau, một trong các cạnh sẽ là trục phân tách.

Trong 2D bạn có thể làm điều này mà không cần sử dụng độ dốc. Một cạnh được định nghĩa đơn giản là sự khác biệt giữa hai đỉnh, vd

  edge = v(n) - v(n-1)

Bạn có thể có được một đường vuông góc với điều này bằng cách xoay nó 90 độ. Trong 2D, điều này dễ như:

  rotated.x = -unrotated.y
  rotated.y =  unrotated.x

Vì vậy, không có lượng giác hoặc độ dốc liên quan. Bình thường hóa vectơ thành đơn vị chiều dài cũng không bắt buộc.

Nếu bạn muốn kiểm tra xem một điểm nằm ở một hoặc một phía khác của dòng, bạn chỉ có thể sử dụng sản phẩm chấm. biển báo sẽ cho bạn biết bạn đang đứng về phía nào:

  // rotated: your rotated edge
  // v(n-1) any point from the edge.
  // testpoint: the point you want to find out which side it's on.

  side = sign (rotated.x * (testpoint.x - v(n-1).x) + 
               rotated.y * (testpoint.y - v(n-1).y);

Bây giờ kiểm tra tất cả các điểm của hình chữ nhật A so với các cạnh của hình chữ nhật B và ngược lại. Nếu bạn tìm thấy một cạnh tách biệt, các đối tượng không giao nhau (cung cấp tất cả các điểm khác trong B nằm ở phía bên kia của cạnh đang được kiểm tra - xem bản vẽ bên dưới). Nếu bạn không tìm thấy cạnh tách nào thì hình chữ nhật đang giao nhau hoặc một hình chữ nhật được chứa trong hình kia.

Thử nghiệm hoạt động với bất kỳ đa giác lồi btw ..

Sửa đổi: Để xác định một cạnh tách biệt, không đủ để kiểm tra tất cả các điểm của một hình chữ nhật so với mỗi cạnh của cạnh kia. Cạnh E ứng cử viên (bên dưới) sẽ được xác định là cạnh tách biệt, vì tất cả các điểm trong A nằm trong cùng một nửa mặt phẳng của E. Tuy nhiên, nó không phải là cạnh tách biệt vì các đỉnh Vb1 và Vb2 của B cũng nằm trong nửa mặt phẳng đó. Nó sẽ chỉ là một cạnh tách biệt nếu đó không phải là trường hợp http://www.iassess.com/collision.png


2
Thuật toán này không hoạt động cho tất cả các trường hợp. Có thể đặt hình chữ nhật thứ hai xoay 45 độ sang hình chữ nhật thứ nhất và bù dọc theo đường chéo để nó hoàn thành các bài kiểm tra giao nhau ở trên nhưng không giao nhau.
Skizz

6
Skizz, kiểm tra tất cả tám cạnh. Nếu các đối tượng không giao nhau, một trong tám cạnh sẽ tách chúng ra. Tại sao bạn không đăng một hình ảnh cho thấy trường hợp của bạn? Tôi có thể chỉ cho bạn trục ..
Nils Pipenbrinck

2
Sai lầm của tôi, nó không đối phó với điều kiện đó.
Skizz

2
Hình ảnh đã chết ngay bây giờ (nov 2012)
John Dvorak

2
Tôi đã gặp rất nhiều khó khăn khi hình dung điều này vì vậy tôi đã tạo lại những gì tôi nghĩ rằng hình ảnh được tham chiếu trông như thế nào. imgur.com/bNwrzsv
Rjdlee

16

Về cơ bản nhìn vào bức tranh sau đây:


Nếu hai hộp va chạm, các dòng A và B sẽ trùng nhau.

Lưu ý rằng điều này sẽ phải được thực hiện trên cả trục X và trục Y và cả hai cần phải chồng lên nhau để các hình chữ nhật va chạm.

Có một bài viết hay trong gamasutra.com trong đó trả lời câu hỏi (hình ảnh là từ bài viết). Tôi đã làm thuật toán tương tự 5 năm trước và tôi phải tìm đoạn mã của mình để đăng nó ở đây sau

Sửa đổi : Định lý trục tách biệt nói rằng hai hình lồi không trùng nhau nếu tồn tại một trục tách (tức là một hình chiếu trong đó các hình chiếu như hình không trùng nhau). Vì vậy "Một trục tách tồn tại" => "Không trùng lặp". Đây không phải là một hàm ý bi nên bạn không thể kết luận điều ngược lại.


1
Rõ ràng, vì hai hình vuông (0,0,1,1) và (0,3,1,4) không trùng nhau nhưng các hình chiếu của chúng trên trục x hoàn toàn trùng nhau. Cả hai bài kiểm tra là cần thiết, sự kết hợp là đủ.
MSalters

18
Không đủ để các phép chiếu x và y trùng nhau: ví dụ: các hình chữ nhật [(0,0), (0,3), (3,3), (3,0)] và [(2,5), (5,2), (7,4), (4,7)].
Joel ở Gô

4
Tôi đồng ý với @Joel ở Gô. Phương pháp này bỏ lỡ một tập hợp lớn các trường hợp hình chữ nhật không trùng nhau, nhưng bán kính dự kiến ​​của chúng thực hiện ở cả x và y.
Scottie T

5
Câu trả lời này không sai, nhưng nó gây hiểu nhầm. Đúng là: Nếu hai hộp va chạm, các dòng A và B sẽ trùng nhau. nhưng cũng đúng là: Nếu các đường A và B trùng nhau, hai hộp có thể hoặc không thể va chạm
matt đốt cháy

7
@floater: Tôi sẽ nói rằng nó không chỉ sai, mà còn gây hiểu lầm, thậm chí còn tồi tệ hơn.
BlueRaja - Daniel Pflughoeft

4

Câu trả lời của m_pGladinator là đúng và tôi thích nó hơn. Kiểm tra trục tách là phương pháp đơn giản và tiêu chuẩn nhất để phát hiện sự chồng chéo hình chữ nhật. Một đường mà các khoảng chiếu không trùng nhau, chúng ta gọi là trục tách . Giải pháp của Nils Pipenbrinck là quá chung chung. Nó sử dụng sản phẩm chấm để kiểm tra xem một hình có hoàn toàn ở một bên của cạnh kia không. Giải pháp này thực sự có thể gây ra đa giác lồi n cạnh. Tuy nhiên, nó không được tối ưu hóa cho hai hình chữ nhật.

điểm quan trọng trong câu trả lời của m_pGladuler là chúng ta nên kiểm tra hình chiếu của hai hình chữ nhật trên cả hai trục (x và y). Nếu hai hình chiếu chồng lên nhau, thì chúng ta có thể nói hai hình chữ nhật này chồng lên nhau. Vì vậy, các ý kiến ​​trên cho câu trả lời của m_pGladinator là sai.

Đối với tình huống đơn giản, nếu hai hình chữ nhật không được xoay, chúng tôi trình bày một hình chữ nhật có cấu trúc:

struct Rect {
    x, // the center in x axis
    y, // the center in y axis
    width,
    height
}

ta đặt tên hình chữ nhật A, B với orthA, orthB.

    if Math.abs(rectA.x - rectB.x) < (Math.abs(rectA.width + rectB.width) / 2) 
&& (Math.abs(rectA.y - rectB.y) < (Math.abs(rectA.height + rectB.height) / 2))
    then
        // A and B collide
    end if

nếu bất kỳ một trong hai hình chữ nhật được xoay, có thể cần một số nỗ lực để xác định hình chiếu của chúng trên các trục x và y. Xác định struct RotatedRect như sau:

struct RotatedRect : Rect {
    double angle; // the rotating angle oriented to its center
}

sự khác biệt là cách độ rộng 'bây giờ hơi khác một chút: widthA' cho orthA: Math.sqrt(rectA.width*rectA.width + rectA.height*rectA.height) * Math.cos(rectA.angle) widthB 'cho orthB:Math.sqrt(rectB.width*rectB.width + rectB.height*rectB.height) * Math.cos(rectB.angle)

    if Math.abs(rectA.x - rectB.x) < (Math.abs(widthA' + widthB') / 2) 
&& (Math.abs(rectA.y - rectB.y) < (Math.abs(heightA' + heightB') / 2))
    then
        // A and B collide
    end if

Có thể tham khảo GDC (Hội nghị phát triển trò chơi 2007) PPT www.realtimecollisiondetection.net/pub/GDC07_Ericson_Physics_Tutorial_SAT.ppt


Tại sao bạn cần Math.abs () trong "Math.abs (orthA. Thong + orthB. Thong)", để xử lý độ rộng âm?
AlexWien

Trục tách không nhất thiết là hướng la bàn, nó có thể có bất kỳ góc nào.
Ben Voigt

Các hình chữ nhật không xoay orthA (x = 0, y = 0, width = 1, height = 1) và orthB (x = 2, y = 0, width = 100, height = 1) không giao nhau nhưng phương thức của bạn cho biết chúng giao nhau. Tôi có làm điều gì sai?
Kagami Sascha Rosylight

4

Trong Ca cao, bạn có thể dễ dàng phát hiện xem bộ chỉnh lưu được chọn có giao với khung chỉnh sửa NSView đã xoay hay không. Bạn thậm chí không cần phải tính toán đa giác, quy tắc như vậy. Chỉ cần thêm các phương thức này vào lớp con NSView của bạn. Chẳng hạn, người dùng chọn một khu vực trên giám sát của NSView, sau đó bạn gọi phương thức Does ThisRectSelectMe đi qua bộ chỉnh lưu được chọn. API convertRect: sẽ thực hiện công việc đó. Thủ thuật tương tự hoạt động khi bạn nhấp vào NSView để chọn nó. Trong trường hợp đó, chỉ cần ghi đè phương thức hitTest như bên dưới. API convertPoint: sẽ thực hiện công việc đó ;-)

- (BOOL)DoesThisRectSelectMe:(NSRect)selectedArea
{
    NSRect localArea = [self convertRect:selectedArea fromView:self.superview];

    return NSIntersectsRect(localArea, self.bounds);
}


- (NSView *)hitTest:(NSPoint)aPoint
{
    NSPoint localPoint = [self convertPoint:aPoint fromView:self.superview];
    return NSPointInRect(localPoint, self.bounds) ? self : nil;
}

2
Mã đó chỉ hoạt động cho hình chữ nhật vuông với màn hình. Đó là một trường hợp tầm thường. Giả định là chúng ta đang xử lý các hình chữ nhật không nằm ở góc 90 độ so với màn hình hoặc nhau.
Duncan C

Như tôi đã kiểm tra và sử dụng trong các ứng dụng của mình, mã đó hoạt động trên bất kỳ hình chữ nhật xoay nào. Không có vấn đề mức độ xoay.
Leonardo

Điều này không mô tả thuật toán, tuy nhiên, nó chỉ đề cập đến một thư viện đã sử dụng nó.
Ben Voigt

2

Kiểm tra xem liệu bất kỳ dòng nào từ một hình chữ nhật cắt nhau bất kỳ dòng nào từ dòng kia. Giao lộ đoạn ngây là dễ dàng để mã lên.

Nếu bạn cần thêm tốc độ, có các thuật toán nâng cao cho giao lộ đoạn đường (đường quét). Xem http://en.wikipedia.org/wiki/Line_seribution_intersection


4
Cẩn thận! Đừng quên trường hợp một hình chữ nhật hoàn toàn bao quanh một hình khác
Pitarou

2

Một giải pháp là sử dụng một thứ gọi là Đa giác Không Vừa. Đa giác này được tính từ hai đa giác (về mặt khái niệm bằng cách trượt cái này xung quanh cái kia) và nó xác định khu vực mà đa giác chồng lên nhau cho phần bù tương đối của chúng. Khi bạn đã có NFP này rồi, bạn chỉ cần thực hiện một bài kiểm tra bao gồm với một điểm được cho bởi độ lệch tương đối của hai đa giác. Thử nghiệm bao gồm này nhanh chóng và dễ dàng nhưng trước tiên bạn phải tạo NFP.

Có một tìm kiếm cho Đa giác Không phù hợp trên web và xem liệu bạn có thể tìm thấy thuật toán cho đa giác lồi hay không (nó sẽ phức tạp hơn nếu bạn có đa giác lõm). Nếu bạn không thể tìm thấy bất cứ điều gì thì hãy gửi email cho tôi tại howard dot J dot có thể gmail dot com


1

Đây là những gì tôi nghĩ sẽ chăm sóc tất cả các trường hợp có thể. Làm các xét nghiệm sau.

  1. Kiểm tra bất kỳ đỉnh nào của hình chữ nhật 1 nằm bên trong hình chữ nhật 2 và ngược lại. Bất cứ khi nào bạn tìm thấy một đỉnh nằm bên trong hình chữ nhật khác, bạn có thể kết luận rằng chúng giao nhau và dừng tìm kiếm. Họ sẽ chăm sóc một hình chữ nhật nằm hoàn toàn bên trong cái kia.
  2. Nếu thử nghiệm trên không có kết luận, hãy tìm các điểm giao nhau của mỗi dòng của 1 hình chữ nhật với mỗi dòng của hình chữ nhật khác. Khi một điểm giao nhau được tìm thấy, hãy kiểm tra xem nó có nằm giữa bên trong hình chữ nhật tưởng tượng được tạo bởi 4 điểm tương ứng không. Khi tìm thấy một điểm như vậy, kết luận rằng chúng giao nhau và dừng tìm kiếm.

Nếu 2 bài kiểm tra trên trả về sai thì 2 hình chữ nhật này không trùng nhau.


0

Nếu bạn đang sử dụng Java, tất cả các cài đặt của giao diện Shape đều có phương thức giao nhau lấy hình chữ nhật.


Thật không may, tôi đang sử dụng C #. Lớp Hình chữ nhật có phương thức Chứa (), nhưng nó chỉ dành cho hình chữ nhật không xoay.
dùng20493

Phương thức giao nhau () là khá vô dụng vì nó trả về boolean thay vì giao nhau tôi đoán.
ZZ 5

0

Chà, phương pháp vũ phu là đi các cạnh của hình chữ nhật nằm ngang và kiểm tra từng điểm dọc theo cạnh để xem nó có rơi vào hoặc trong hình chữ nhật khác không.

Câu trả lời toán học là hình thành các phương trình mô tả từng cạnh của cả hai hình chữ nhật. Bây giờ bạn có thể chỉ cần tìm nếu bất kỳ trong bốn dòng từ hình chữ nhật A cắt bất kỳ dòng nào của hình chữ nhật B, đó sẽ là một bộ giải phương trình tuyến tính đơn giản (nhanh).

-Adam


2
Vấn đề với các phương trình là khi bạn có một đường thẳng đứng, có độ dốc vô hạn.
dùng20493

Có trường hợp góc cho mọi giải pháp.
Adam Davis

2
và một hình vuông hoàn toàn bao quanh cái kia.
Oliver Hallam

0

Bạn có thể tìm thấy giao điểm của mỗi bên của hình chữ nhật góc với mỗi bên của trục được căn chỉnh theo trục. Thực hiện việc này bằng cách tìm phương trình của đường vô hạn mà mỗi bên nằm (ví dụ v1 + t (v2-v1) và v'1 + t '(v'2-v'1) về cơ bản), tìm điểm tại đó các dòng gặp nhau bằng cách giải cho t khi hai phương trình đó bằng nhau (nếu chúng song song, bạn có thể kiểm tra điều đó) và sau đó kiểm tra xem điểm đó có nằm trên đoạn thẳng giữa hai đỉnh không, có đúng là 0 <= t <= 1 và 0 <= t '<= 1.

Tuy nhiên, điều này không bao gồm trường hợp khi một hình chữ nhật hoàn toàn bao phủ khác. Bạn có thể bao quát bằng cách kiểm tra xem tất cả bốn điểm của một trong hai hình chữ nhật có nằm trong hình chữ nhật khác không.


0

Đây là những gì tôi sẽ làm, cho phiên bản 3D của vấn đề này:

Mô hình 2 hình chữ nhật là các mặt phẳng được mô tả bởi phương trình P1 và P2, sau đó viết P1 = P2 và xuất phát từ đó phương trình giao tuyến, sẽ không tồn tại nếu các mặt phẳng song song (không có giao điểm) hoặc nằm trong cùng một mặt phẳng, trong trường hợp đó bạn nhận được 0 = 0. Trong trường hợp đó, bạn sẽ cần sử dụng thuật toán giao nhau hình chữ nhật 2D.

Sau đó, tôi sẽ xem nếu dòng đó, nằm trong mặt phẳng của cả hai hình chữ nhật, đi qua cả hai hình chữ nhật. Nếu đúng như vậy, thì bạn có một giao điểm gồm 2 hình chữ nhật, nếu không thì bạn không (hoặc không nên, tôi có thể đã bỏ lỡ một trường hợp góc trong đầu).

Để tìm xem một đường thẳng đi qua một hình chữ nhật trong cùng một mặt phẳng, tôi sẽ tìm 2 điểm giao nhau của đường thẳng và các cạnh của hình chữ nhật (mô hình hóa chúng bằng các phương trình đường thẳng), và sau đó đảm bảo các điểm giao nhau nằm trong phạm vi.

Đó là mô tả toán học, tiếc là tôi không có mã để làm ở trên.


Bạn đã bỏ lỡ phần mà nếu bạn tìm thấy đường giao nhau của mặt phẳng, bạn phải đảm bảo rằng một phần của nó tồn tại trong cả hai hình chữ nhật.
Lee Louviere

0

Một cách khác để thực hiện phép thử nhanh hơn một chút so với sử dụng phép thử trục tách, là sử dụng thuật toán số quanh co (chỉ trên góc phần tư - không phải là tổng góc là chậm kinh khủng) trên mỗi đỉnh của hình chữ nhật (được chọn tùy ý). Nếu bất kỳ đỉnh nào có số quanh co khác không, hai hình chữ nhật trùng nhau.

Thuật toán này có phần dài hơn so với thử nghiệm trục tách, nhưng nhanh hơn vì nó chỉ yêu cầu thử nghiệm nửa mặt phẳng nếu các cạnh vượt qua hai góc phần tư (trái ngược với tối đa 32 thử nghiệm sử dụng phương pháp trục tách)

Thuật toán có lợi thế hơn nữa là nó có thể được sử dụng để kiểm tra sự chồng chéo của bất kỳ đa giác (lồi hoặc lõm). Theo tôi biết, thuật toán chỉ hoạt động trong không gian 2D.


3
Tôi có thể sai, nhưng không phải chỉ kiểm tra xem các đỉnh của một hình chữ nhật có nằm trong một hình chữ nhật khác không? Nếu có, nó không đủ vì hình chữ nhật có thể chồng lên nhau mà không có bất kỳ đỉnh nào bên trong.
sinelaw

Họ có thể, với hình chữ nhật? Làm sao? Dường như với tôi, để 2 hình chữ nhật cắt nhau, ít nhất một đỉnh của một trong các hình chữ nhật phải nằm trên hình chữ nhật khác.
Duncan C

@DuncanC: Vâng, họ có thể. Ví dụ là một chữ thập và thậm chí nó được liệt kê trong câu hỏi ban đầu.
Ben Voigt

@BenVoigt Đây là một chủ đề rất cũ, nhưng bạn hoàn toàn đúng.
Duncan C

0

Hoặc là tôi đang thiếu một cái gì đó tại sao làm cho điều này quá phức tạp?

if (x1, y1) và (X1, Y1) là các góc của hình chữ nhật, sau đó để tìm giao điểm làm:

    xIntersect = false;
    yIntersect = false;
    if (!(Math.min(x1, x2, x3, x4) > Math.max(X1, X2, X3, X4) || Math.max(x1, x2, x3, x4) < Math.min(X1, X2, X3, X4))) xIntersect = true;
    if (!(Math.min(y1, y2, y3, y4) > Math.max(Y1, Y2, Y3, Y4) || Math.max(y1, y2, y3, y4) < Math.min(Y1, Y2, Y3, Y4))) yIntersect = true;
    if (xIntersect && yIntersect) {alert("Intersect");}

3
Bạn đang thiếu rằng anh ấy muốn một người được xoay bởi một góc tùy ý.
Robotbugs

0

Tôi đã thực hiện nó như thế này:

bool rectCollision(const CGRect &boundsA, const Matrix3x3 &mB, const CGRect &boundsB)
{
    float Axmin = boundsA.origin.x;
    float Axmax = Axmin + boundsA.size.width;
    float Aymin = boundsA.origin.y;
    float Aymax = Aymin + boundsA.size.height;

    float Bxmin = boundsB.origin.x;
    float Bxmax = Bxmin + boundsB.size.width;
    float Bymin = boundsB.origin.y;
    float Bymax = Bymin + boundsB.size.height;

    // find location of B corners in A space
    float B0x = mB(0,0) * Bxmin + mB(0,1) * Bymin + mB(0,2);
    float B0y = mB(1,0) * Bxmin + mB(1,1) * Bymin + mB(1,2);

    float B1x = mB(0,0) * Bxmax + mB(0,1) * Bymin + mB(0,2);
    float B1y = mB(1,0) * Bxmax + mB(1,1) * Bymin + mB(1,2);

    float B2x = mB(0,0) * Bxmin + mB(0,1) * Bymax + mB(0,2);
    float B2y = mB(1,0) * Bxmin + mB(1,1) * Bymax + mB(1,2);

    float B3x = mB(0,0) * Bxmax + mB(0,1) * Bymax + mB(0,2);
    float B3y = mB(1,0) * Bxmax + mB(1,1) * Bymax + mB(1,2);

    if(B0x<Axmin && B1x<Axmin && B2x<Axmin && B3x<Axmin)
        return false;
    if(B0x>Axmax && B1x>Axmax && B2x>Axmax && B3x>Axmax)
        return false;
    if(B0y<Aymin && B1y<Aymin && B2y<Aymin && B3y<Aymin)
        return false;
    if(B0y>Aymax && B1y>Aymax && B2y>Aymax && B3y>Aymax)
        return false;

    float det = mB(0,0)*mB(1,1) - mB(0,1)*mB(1,0);
    float dx = mB(1,2)*mB(0,1) - mB(0,2)*mB(1,1);
    float dy = mB(0,2)*mB(1,0) - mB(1,2)*mB(0,0);

    // find location of A corners in B space
    float A0x = (mB(1,1) * Axmin - mB(0,1) * Aymin + dx)/det;
    float A0y = (-mB(1,0) * Axmin + mB(0,0) * Aymin + dy)/det;

    float A1x = (mB(1,1) * Axmax - mB(0,1) * Aymin + dx)/det;
    float A1y = (-mB(1,0) * Axmax + mB(0,0) * Aymin + dy)/det;

    float A2x = (mB(1,1) * Axmin - mB(0,1) * Aymax + dx)/det;
    float A2y = (-mB(1,0) * Axmin + mB(0,0) * Aymax + dy)/det;

    float A3x = (mB(1,1) * Axmax - mB(0,1) * Aymax + dx)/det;
    float A3y = (-mB(1,0) * Axmax + mB(0,0) * Aymax + dy)/det;

    if(A0x<Bxmin && A1x<Bxmin && A2x<Bxmin && A3x<Bxmin)
        return false;
    if(A0x>Bxmax && A1x>Bxmax && A2x>Bxmax && A3x>Bxmax)
        return false;
    if(A0y<Bymin && A1y<Bymin && A2y<Bymin && A3y<Bymin)
        return false;
    if(A0y>Bymax && A1y>Bymax && A2y>Bymax && A3y>Bymax)
        return false;

    return true;
}

Ma trận mB là bất kỳ ma trận biến đổi affine nào chuyển đổi các điểm trong không gian B thành các điểm trong không gian A. Điều này bao gồm xoay và dịch đơn giản, xoay cộng với chia tỷ lệ, và warp đầy đủ affine, nhưng không phải là warps phối cảnh.

Nó có thể không tối ưu nhất có thể. Tốc độ không phải là một mối quan tâm lớn. Tuy nhiên nó có vẻ hoạt động tốt với tôi.


0

Đây là một triển khai MATLAB của câu trả lời được chấp nhận:

function olap_flag = ol(A,B,sub)

%A and B should be 4 x 2 matrices containing the xy coordinates of the corners in clockwise order

if nargin == 2
  olap_flag = ol(A,B,1) && ol(B,A,1);
  return;
end

urdl = diff(A([1:4 1],:));
s = sum(urdl .* A, 2);
sdiff = B * urdl' - repmat(s,[1 4]);

olap_flag = ~any(max(sdiff)<0);

0

Đây là phương pháp thông thường, đi từng dòng một và kiểm tra xem các dòng có giao nhau không. Đây là mã trong MATLAB.

C1 = [0, 0];    % Centre of rectangle 1 (x,y)
C2 = [1, 1];    % Centre of rectangle 2 (x,y)
W1 = 5; W2 = 3; % Widths of rectangles 1 and 2
H1 = 2; H2 = 3; % Heights of rectangles 1 and 2
% Define the corner points of the rectangles using the above
R1 = [C1(1) + [W1; W1; -W1; -W1]/2, C1(2) + [H1; -H1; -H1; H1]/2];
R2 = [C2(1) + [W2; W2; -W2; -W2]/2, C2(2) + [H2; -H2; -H2; H2]/2];

R1 = [R1 ; R1(1,:)] ;
R2 = [R2 ; R2(1,:)] ;

plot(R1(:,1),R1(:,2),'r')
hold on
plot(R2(:,1),R2(:,2),'b')


%% lines of Rectangles 
L1 = [R1(1:end-1,:) R1(2:end,:)] ;
L2 = [R2(1:end-1,:) R2(2:end,:)] ;
%% GEt intersection points
P = zeros(2,[]) ;
count = 0 ;
for i = 1:4
    line1 = reshape(L1(i,:),2,2) ;
    for j = 1:4
        line2 = reshape(L2(j,:),2,2) ;
        point = InterX(line1,line2) ;
        if ~isempty(point)
            count = count+1 ;
            P(:,count) = point ;
        end
    end
end
%%
if ~isempty(P)
    fprintf('Given rectangles intersect at %d points:\n',size(P,2))
    plot(P(1,:),P(2,:),'*k')
end

có thể tải xuống chức năng InterX từ: https://in.mathworks.com/matlabcentral/fileexchange/22441-curve-intersections?focused=5165138&tab=f ghép


0

Tôi có một phương pháp đơn giản hơn, nếu chúng ta có 2 hình chữ nhật:

R 1 = (min_x1, max_x1, min_y1, max_y1)

R2 = (min_x2, max_x2, min_y2, max_y2)

Chúng trùng nhau khi và chỉ khi:

Chồng chéo = (max_x1> min_x2) và (max_x2> min_x1) và (max_y1> min_y2) và (max_y2> min_y1)

Bạn cũng có thể làm điều đó cho các hộp 3D, thực tế nó hoạt động với bất kỳ số lượng kích thước nào.


0

Đã đủ nói trong các câu trả lời khác, vì vậy tôi sẽ chỉ thêm mã giả một lần:

!(a.left > b.right || b.left > a.right || a.top > b.bottom || b.top > a.bottom);
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.