ตรวจสอบว่าสี่เหลี่ยมสองรูปทับกันหรือไม่


337

ฉันพยายามเขียนโปรแกรม 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;  

อย่างไรก็ตามฉันไม่แน่ใจว่า (ก) ฉันใช้อัลกอริทึมที่ฉันเชื่อมโยงกับถูกต้องหรือไม่หรือถ้าฉันทำตามวิธีการตีความนี้

ข้อเสนอแนะใด ๆ


3
ฉันคิดว่าวิธีแก้ปัญหาของคุณไม่เกี่ยวข้องกับการคูณ
Scott Evernden

คำตอบ:


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

หรือโดยใช้พิกัดคาร์ทีเซียน

(ด้วย X1 ที่เหลือ coord, X2 เป็น coord ที่เหมาะสมเพิ่มขึ้นจากซ้ายไปขวาและ Y1 เป็น Top coord และ Y2 เป็น Bottom coord เพิ่มขึ้นจากล่างขึ้นบน - ถ้านี่ไม่ใช่วิธีการที่ระบบพิกัดของคุณ [เช่นคอมพิวเตอร์ส่วนใหญ่มี ทิศทาง Y ย้อนกลับ], สลับการเปรียบเทียบด้านล่าง ) ...

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

สมมติว่าคุณมี Rect A และ Rect B. Proof นั้นขัดแย้งกัน หนึ่งในสี่เงื่อนไขใด ๆ รับประกันว่าจะไม่มีการทับซ้อน :

  • Cond1 ถ้าขอบด้านซ้ายของ A อยู่ทางขวาของขอบด้านขวาของ B - ดังนั้น A จะอยู่ทางด้านขวาทั้งหมดของ B
  • Cond2 ถ้าขอบด้านขวาของ A อยู่ทางซ้ายของขอบด้านซ้ายของ B - ดังนั้น A คือทั้งหมดไปทางซ้ายของ B
  • Cond3 ถ้าขอบด้านบนของ A อยู่ต่ำกว่าขอบด้านล่างของ B - ดังนั้น A จะต่ำกว่า B ทั้งหมด
  • Cond4 ถ้าขอบด้านล่างของ A อยู่เหนือขอบบนของ B - ดังนั้น A จะอยู่เหนือ B ทั้งหมด

ดังนั้นเงื่อนไขสำหรับการไม่ทับซ้อนกันคือ

NON-Overlap => Cond1 หรือ Cond2 หรือ Cond3 หรือ Cond4

ดังนั้นเงื่อนไขที่เพียงพอสำหรับการซ้อนทับจึงเป็นสิ่งที่ตรงกันข้าม

ทับซ้อน => ไม่ (Cond1 หรือ Cond2 หรือ Cond3 หรือ Cond4)

กฎหมายของเดอมอร์แกนกล่าวว่า
Not (A or B or C or D)เหมือนกันNot A And Not B And Not C And Not D
ดังนั้นใช้เดมอร์แกนเราก็มี

ไม่ Cond1 และไม่ Cond2 และไม่ Cond3 และไม่ Cond4

สิ่งนี้เทียบเท่ากับ:

  • ขอบด้านซ้ายของ A ไปทางซ้ายของขอบด้านขวาของ B [ RectA.Left < RectB.Right] และ
  • ขอบด้านขวาของ A ไปทางขวาของขอบด้านซ้ายของ B [ RectA.Right > RectB.Left] และ
  • ด้านบนของ A อยู่ด้านล่างของ B [ RectA.Top > RectB.Bottom] และ
  • ด้านล่าง A ของ B ด้านบน [ RectA.Bottom < RectB.Top]

หมายเหตุ 1 : มันค่อนข้างชัดเจนว่าหลักการเดียวกันนี้สามารถขยายไปยังขนาดใดก็ได้
หมายเหตุ 2 : มันก็ควรจะเป็นธรรมที่เห็นได้ชัดในการนับทับซ้อนเพียงหนึ่งพิกเซลเปลี่ยน<และ / หรือ>ในขอบเขตที่ไปหรือ<= หมายเหตุ 3 : คำตอบนี้เมื่อใช้พิกัดคาร์ทีเซียน (X, Y) ขึ้นอยู่กับมาตรฐานเชิงพีชคณิตแบบคาร์ทีเซียน (x เพิ่มจากซ้ายไปขวาและ Y เพิ่มจากล่างขึ้นบน) เห็นได้ชัดว่าระบบคอมพิวเตอร์อาจปรับตำแหน่งของหน้าจอให้แตกต่างกัน (เช่นการเพิ่ม Y จากบนลงล่างหรือ X จากขวาไปซ้าย) จำเป็นต้องปรับไวยากรณ์ตาม />=


489
หากคุณมีช่วงเวลาที่ยากลำบากในการแสดงให้เห็นว่าทำไมมันทำงานฉันทำหน้าตัวอย่างที่silentmatt.com/intersection.htmlที่คุณสามารถลากสี่เหลี่ยมรอบ ๆ และดูการเปรียบเทียบ
Matthew Crumley

4
คุณไม่คิดว่าคุณกำลังใช้ข้อ จำกัด อย่างหนัก? เกิดอะไรขึ้นถ้ารูปสี่เหลี่ยมสองอันซ้อนทับกันตรงขอบ คุณไม่ควรพิจารณา <=,> = ??
Nawshad Farruque

6
@MatthewCrumley สำหรับ A.Y1 <B.Y2 และ A.Y2> B.Y1 ในลิงก์ของคุณสัญญาณ gt & lt ไม่ควรกลับด้านใช่ไหม
NikT

15
ฉันต้องสลับ <และ> ในการเปรียบเทียบสองครั้งล่าสุดเพื่อให้ทำงานได้
DataGreed

17
ไม่คำตอบถูกต้องตามที่ระบุไว้ มันขึ้นอยู่กับการใช้พิกัดคาร์ทีเซียนมาตรฐาน หากคุณกำลังใช้ระบบที่แตกต่างกัน (Y เพิ่มจากบนลงล่าง) ให้ทำการปรับเปลี่ยนที่เหมาะสม
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
คำตอบที่ง่ายและสะอาดที่สุด
ldog

1
@ e.James ฉันเดาว่าB.heightควรจะเป็นครั้งสุดท้ายA.height
mat_boy

'min' และ 'max' เป็นคำหลักที่สงวนไว้ใน <windows.h> คุณสามารถแก้ไขได้โดยทำ#undef minและ#undef maxหรือใช้ชื่อพารามิเตอร์อื่น
mchiasson

หากคุณใช้อย่างกว้างขวางคุณสามารถแลกเปลี่ยนมูลค่าเป็นช่วงสำหรับ a#define BETWEEN(value,min,max) \ (\ value > max ? max : ( value < min ? min : value )\ )
Ratata Tata

@Nemo จริง ๆ แล้วการตรวจสอบxOverlapอยู่ในมิติเดียว; rectOverlapเป็นสองมิติ มันสามารถขยายไปยังมิติ N โดยใช้วง
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;
}

ทำได้ดีนี่! การใช้กฎหมาย De Morgans ขอรับ: r1.x1 <= r2.x2 && r2.x1 <= r1.x2 && r1.y1 <= r2.y2 && r2.y1 <= r1.y2
Borzh

23

มันง่ายกว่าที่จะตรวจสอบว่าสี่เหลี่ยมผืนผ้าอยู่นอกกรอบอื่นโดยสมบูรณ์หรือไม่

ทางซ้าย...

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

หากต้องการรับผลบวกเมื่อสัมผัสเท่านั้นเราสามารถเปลี่ยน "<" และ ">" โดย "<=" และ "> ="


3
และใช้กฎของเดอมอร์แกนกับมัน
Borzh

6

ถามตัวเองด้วยคำถามตรงข้าม: ฉันจะทราบได้อย่างไรว่าสี่เหลี่ยมสองรูปไม่ตัดกันหรือไม่ เห็นได้ชัดว่ารูปสี่เหลี่ยมผืนผ้า 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

สมมติว่าคุณได้กำหนดตำแหน่งและขนาดของรูปสี่เหลี่ยมผืนผ้าดังนี้:

ป้อนคำอธิบายรูปภาพที่นี่

การใช้ C ++ ของฉันเป็นเช่นนี้:

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

3

นี่เป็นวิธีที่ทำใน 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));
}

โปรดทราบว่าใน C ++ การทดสอบโอเวอร์โฟลว์จะไม่ทำงานเนื่องจากการโอเวอร์โฟลว์จำนวนเต็มที่ลงนามแล้วนั้นไม่ได้กำหนดไว้
Ben Voigt

2

ในคำถามคุณลิงก์ไปยังคณิตศาสตร์เมื่อสี่เหลี่ยมอยู่ในมุมการหมุนโดยพลการ ถ้าฉันเข้าใจถึงมุมเล็กน้อยในคำถามฉันก็ตีความว่ารูปสี่เหลี่ยมผืนผ้าทั้งหมดตั้งฉากกัน

ทั่วไปรู้ว่าพื้นที่ของสูตรทับซ้อนคือ:

ใช้ตัวอย่าง:

   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) ในขณะที่คุณวาดสี่เหลี่ยมมันง่ายที่จะสกัดกั้นการทับ


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

อย่าคิดว่าพิกัดระบุตำแหน่งของพิกเซล คิดว่าพวกเขาอยู่ระหว่างพิกเซล ด้วยวิธีนี้พื้นที่ของสี่เหลี่ยม 2x2 ควรเป็น 4 ไม่ใช่ 9

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

1

วิธีที่ง่ายที่สุดคือ

/**
 * 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 บวกครึ่งหนึ่งของ widht จากนั้นก็หมายความว่าจะไปครึ่งหนึ่งพวกเขาจะสัมผัสกัน และในลักษณะเดียวกันจะลดลง + ครึ่งหนึ่งของความสูง มันจะชนกัน ..


1

ให้บอกว่ารูปสี่เหลี่ยมผืนผ้าสองรูปนี้เป็นสี่เหลี่ยม A และสี่เหลี่ยม B ให้ศูนย์ของพวกเขาคือ A1 และ B1 (พิกัดของ A1 และ B1 สามารถหาได้ง่าย), ให้ความสูงเป็นฮาและ Hb, ความกว้างเป็น Wa และ Wb, ให้ dx เป็น ความกว้าง (x) ระยะทางระหว่าง A1 ถึง B1 และ dy คือความสูง (y) ระยะห่างระหว่าง A1 และ B1

ตอนนี้เราสามารถพูดได้ว่าเราสามารถพูดว่า A และ B ทับซ้อนกัน: เมื่อใด

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

0

ฉันใช้งาน 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;
}

2
สำหรับตาที่ผ่านการฝึกอบรมแล้วชัดเจนว่าคุณหมายถึงการเป็นคลาสเสริมสำหรับสี่เหลี่ยมผืนผ้า แต่คุณไม่ได้ให้การ จำกัด หรือโค้ดใด ๆ มันจะดีถ้าคุณทำอย่างนั้นหรืออธิบายว่าวิธีการของคุณมีไว้เพื่อใช้และคะแนนโบนัสถ้าตัวแปรของคุณมีชื่อที่สื่อความหมายเพียงพอสำหรับทุกคนที่ติดตามเพื่อทำความเข้าใจวัตถุประสงค์ / ความตั้งใจของพวกเขา
tpartee

0

ฉันมีทางออกที่ง่ายมาก

ให้ x1, y1 x2, y2, l1, b1, l2, เป็นลูกน้องและความยาวและความกว้างของพวกเขาตามลำดับ

พิจารณาเงื่อนไข ((x2)

ตอนนี้วิธีเดียวที่สี่เหลี่ยมเหล่านี้จะทับซ้อนกันคือถ้าจุดทแยงมุมถึง x1, y1 จะอยู่ในสี่เหลี่ยมมุมฉากอื่น ๆ หรือในทำนองเดียวกัน ซึ่งเป็นเงื่อนไขดังกล่าวข้างต้น


0

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

นี่คือจากแบบฝึกหัด 3.28 จากหนังสือ Introduction to Java Programming- Comprehensive Edition รหัสทดสอบว่าสี่เหลี่ยมสองอันนั้นเยื้องหรือไม่และอีกอันหนึ่งอยู่ด้านในและอีกอันหนึ่งอยู่ด้านนอก หากไม่ตรงตามเงื่อนไขเหล่านี้แสดงว่าทั้งสองทับซ้อนกัน

** 3.28 (เรขาคณิต: สองรูปสี่เหลี่ยม) เขียนโปรแกรมที่แจ้งให้ผู้ใช้ป้อนศูนย์กลาง x-, y- พิกัด, ความกว้างและความสูงของรูปสี่เหลี่ยมผืนผ้าสองรูปและกำหนดว่ารูปสี่เหลี่ยมผืนผ้าที่สองอยู่ภายในรูปแรกหรือทับซ้อนกับส่วนแรกหรือไม่ ดังแสดงในรูปที่ 3.9 ทดสอบโปรแกรมของคุณเพื่อครอบคลุมทุกกรณี นี่คือตัวอย่างการรัน:

ป้อนศูนย์กลางของ r1 x-, y- พิกัด, ความกว้างและความสูง: 2.5 4 2.5 43 ป้อนกึ่งกลางของ r1 x-, y- พิกัด, ความกว้างและความสูง: 1.5 5 0.5 3 r2 อยู่ภายใน r1

ป้อนศูนย์กลางของ r1 x-, y- พิกัด, ความกว้างและความสูง: 1 2 3 5.5 ป้อนศูนย์กลางของ r2 x-, y- พิกัด, ความกว้างและความสูง: 3 4 4.5 5 r2 ทับซ้อน r1

ป้อนศูนย์กลางของ r1 x-, y- พิกัด, ความกว้างและความสูง: 1 2 3 3 ป้อนศูนย์กลางของ r1 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'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

สำหรับผู้ที่ใช้จุดกึ่งกลางและขนาดครึ่งหนึ่งสำหรับข้อมูลรูปสี่เหลี่ยมผืนผ้าแทนที่จะเป็น 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
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

หากรูปสี่เหลี่ยมผืนผ้าเหลื่อมกันพื้นที่ทับซ้อนจะมากกว่าศูนย์ ตอนนี้ให้เราหาพื้นที่ทับซ้อน:

หากพวกเขาซ้อนทับกันแล้วขอบซ้ายของการทับซ้อน-ดูแลรักษาจะเป็นและขอบด้านขวาจะเป็น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พวกเขาไม่ทับซ้อนกัน

ง่ายใช่มั้ย


3
มันใช้งานได้สำหรับการทับซ้อน (ซึ่งเป็นคำถาม) แต่จะไม่ทำงานสำหรับการตัดกันเพราะมันจะไม่ทำงานหากพวกมันตัดกันตรงมุม
แลนซ์โรเบิร์ต

ฉันลองใช้รหัสนี้และมันไม่ทำงานเลย ฉันแค่รับตัวเลขบวกแม้ว่าพวกเขาจะไม่ทับซ้อนกันเลย
Brett

@ เบร็ท: ใช่เพราะผลิตภัณฑ์ของตัวเลขลบสองตัวเป็นค่าบวก
Ben Voigt

@BenVoigt ปัญหาคือว่าฟังก์ชั่นไม่ได้กลับ 0 เมื่อไม่มีการทับซ้อนกัน ฉันไม่ชัดเจนกับความคิดเห็นของฉัน แต่ใช่ฉันเคยได้รับพื้นที่> 0 จากฟังก์ชั่นนี้เท่านั้น
เบร็ท

หากคุณกำลังทำงานกับตัวเลขเลขทศนิยมมันเป็นความคิดที่ดีมากที่จะใช้การลบและเนื้อหาทางคณิตศาสตร์อื่น ๆ ก่อนที่จะทำการเปรียบเทียบตัวเลขใด ๆ โดยเฉพาะอย่างยิ่งถ้าคุณต้องการเปรียบเทียบกับค่าที่แน่นอน - ในกรณีนี้เป็นศูนย์ มันใช้งานได้ในทางทฤษฎี แต่ไม่ใช่ในทางปฏิบัติ
maja

-1

"ถ้าคุณทำการลบพิกัด x หรือ y ที่สอดคล้องกับจุดยอดของทั้งสองหันหน้าไปทางสี่เหลี่ยมแต่ละสี่เหลี่ยมถ้าผลลัพธ์เป็นสัญญาณเดียวกันสี่เหลี่ยมทั้งสองนั้นจะไม่ทับซ้อนแกนที่" (ฉันขอโทษฉันไม่แน่ใจว่าการแปลของฉันถูกต้องหรือไม่ )

ป้อนคำอธิบายรูปภาพที่นี่

ที่มา: http://www.ieev.org/2009/05/kiem-tra-hai-hinh-chu-nhat-chong-nhau.html


-1

รหัส 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;
            }
        }
    }
}

...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.