Search…

Collision Detection – Xét Va Chạm Giữa Hình Tròn và Hình Chữ Nhật

27/08/20202 min read
Để mô phỏng được các tình huống như ở thế giới thực thì cần phải kết hợp vật lý trong thế giới thực, các tính năng như phát hiện va chạm, lực đàn hồi, độ đàn hồi, ma sát, ... cần được đưa vào phần mềm. Bài viết này  giới thiệu 1 trong các tình huống đó là phát hiện va chạm giữa hình tròn và hình chữ nhật.

Va chạm giữa hình tròn và hình chữ nhật

Thuật toán

Gọi C(Xc, Yc) là tâm hình tròn có bán kính là R. Tìm điểm A là điểm gần nhất thuộc hình chữ nhật đến tâm C. So sánh độ dài CA và R. Nếu CA<=R thì va chạm. CA>R thì không va chạm. (Khi C nằm trong hình chữ nhật thì C trùng A).

Khoảng cách CA được biểu diễn như hình vẽ:

Kiểm tra va chạm giữa hình chữ nhật và hình tròn

Để tính được CA, cần xác định điểm A theo thuật toán sau:

  • B1: Gán A = C (Xa = Xc, Ya = Yc)
  • B2: Nếu Xc < rect.left thì Xa=rect.left
    • Xc > rect.right thì Xa = rect.right
    • Xc >= rect.left && Xc <= rect.right thì Xa = Xc
  • B3: Nếu Yc < rect.top thì Ya = rect.top
    • Nếu Yc > rect.bottom thì Ya = rect.bottom
    • Nếu Yc >= rect.top && Yc<= rect.right thì Ya = Yc 

* Trường hợp điểm 0(0, 0) nằm ở góc trên bên trái màn hình, trục tọa độ hướng xuống.

Có điểm A, tính CA rồi so sánh với R.

Code mẫu C++ xét sự tương quan giữa hình tròn và hình chữ nhật

Khai báo các thành phần của hình tròn và hình chữ nhật

struct Point
{
    double x;
    double y;

    Point(Point p)
    {
        x = p.x;
        y = p.y;
    }
};

struct Circle
{
    Point O;
    double r;

    Circle(Point _o, double _r) : Point(_o)
    {
        r = _r;
    }
};

struct Rectangle
{
    double top;
    double bottom;
    double left;
    double right;

    Rectangle(double _top, double _bottom, double _left, double _right)
    {
        top = _top;
        bottom = _bottom;
        left = _left;
        right = _right;
    }
};

bool checkCollision(Circle cir, Rectangle rect)
{
    double Ax = cir.O.x;
    double Ay = cir.O.y;

    if(cir.O.x < rect.left)
        Ax = rect.left;
    else if(cir.O.x > rect.right)
        Ax = rect.right;

    if(cir.O.y < rect.top)
        Ay = rect.top;
    else if(cir.O.y > rect.bottom)
        Ay = rect.bottom;

    double dx = cir.O.x - Ax;
    double dy = cir.O.y - Ay;

    return (dx * dx + dy * dy) <= cir.r * cir.r;
}

int main()
{
    Point p(2.5, 6.6);
    
    Circle cir(p, 2.5);
    Rectangle rect(1.56, 7.95, 3.28, 13.4);
    
    if(checkCollision(cir, rect))
        cout << "cir(rect)";
    else cout << "cir   rect";
    
    return 0;
}

Bài chung series

IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024