Tìm kiếm các ô được giao nhau bởi một dòng, mà không lặp qua tất cả chúng hoặc bỏ qua bất kỳ


10

Tôi đã nhìn chằm chằm vào vấn đề này trong vài ngày nay. Tôi đã dựng lên đồ họa này để giúp tôi hình dung ra vấn đề: nhập mô tả hình ảnh ở đây (từ biểu đồ, chúng ta biết rằng đường thẳng giao nhau [1, 1], [1, 2], [2, 2], [2, 3], kết thúc bằng [ 3,3])

Tôi muốn bước dọc theo dòng đến từng không gian lưới và kiểm tra xem liệu vật liệu của không gian lưới có vững chắc không. Tôi cảm thấy như tôi đã biết toán học liên quan, nhưng tôi chưa thể kết hợp nó với nhau. Tôi đang sử dụng điều này để kiểm tra đường ngắm và loại bỏ các nút sau khi tìm thấy đường đi thông qua thuật toán tìm đường của tôi - các tác nhân của tôi không thể nhìn xuyên qua một khối rắn, do đó chúng không thể di chuyển qua một, do đó nút không bị loại khỏi đường dẫn bởi vì nó được yêu cầu để điều hướng một góc.

Vì vậy, tôi cần một thuật toán sẽ bước dọc theo dòng đến từng không gian lưới mà nó giao nhau. Có ý kiến ​​gì không?

Tôi đã xem xét rất nhiều thuật toán phổ biến, như của Bresenham, và một thuật toán bước theo các khoảng thời gian được xác định trước dọc theo đường (không may, phương pháp này bỏ qua các ô nếu chúng giao nhau với một nêm nhỏ hơn kích thước bước).

Bây giờ tôi đang điền vào bảng trắng của mình với một khối các hàm sàn () và trần () - nhưng nó quá phức tạp và tôi sợ nó có thể gây ra sự chậm lại.


Bạn đã biết làm thế nào để kiểm tra giao lộ hộp thực tế, phải không? Chỉ cần hỏi, vì điều này có liên quan đến câu trả lời.
TravisG

Câu trả lời:


6

Nếu bạn biết khối bắt đầu (bạn biết điểm X và bạn không bao gồm khối [0,1] trong danh sách khối, vì vậy tôi cho rằng bạn cũng biết khối bắt đầu), tôi nghĩ bạn chắc chắn nên sử dụng thuật toán của Bresenham. Bạn viết, bạn nhìn nó.

Đó là thuật toán phù hợp cho vấn đề này. Nó cũng có thể được viết theo một cách, nó chỉ tính toán với số nguyên. Bạn có thể tìm thấy rất nhiều triển khai trên web.

BIÊN TẬP:

Tôi xin lỗi, tôi đã không nhận ra rằng Bresenham sẽ không tìm thấy tất cả các khối. Vì vậy, tôi tìm thấy giải pháp tốt hơn . Cũng có mã được viết bằng C ++, nhưng tôi nghĩ nó không nên khó hiểu :)


1
Lý do tôi nhìn qua thuật toán Bresenham hoàn toàn là vì hình ảnh trên Wikipedia. ( en.wikipedia.org/wiki/File:Bresenham.svg ) Bạn có thể thấy rằng dòng chặn một số hình vuông không có bóng, mặc dù hầu như không. Tôi cần một cái gì đó sẽ phát hiện mọi ô, bất kể lát cắt nhỏ đến mức nào. Chỉnh sửa: Dường như tôi đã hiểu nhầm bresenham. Tôi cần đảo ngược nó - tôi có điểm đầu tiên và điểm cuối cùng, và tôi cần các ô mà nó giao nhau - chứ không phải là dòng tốt nhất để vẽ.
Suds

@JustSuds: Kiểm tra cập nhật trong bài.
zacharmarz

Này này! gần như trực tiếp với những gì tôi có trên bảng trắng của mình! Cảm ơn, hệ thống của tôi hiện đang được thực hiện và làm việc. :-)
Suds

Bạn có thể xóa phần về thuật toán của Bresenham vì nó không trả lời được câu hỏi không? Đừng lo lắng, nó sẽ ở trong lịch sử chỉnh sửa câu trả lời của bạn.
đỉnh

1

Mã trong ví dụ mà câu trả lời được chấp nhận liên kết cần một số điều chỉnh cho các đường chéo hoàn hảo. Đây là một ứng dụng demo hoàn chỉnh được viết bằng Qt (C ++ và QML).

giao lộ đường lưới

Mã C ++ có liên quan:

void rayCast()
{
    if (!isComponentComplete())
        return;

    mTiles.clear();
    mTiles.fill(QColor::fromRgb(255, 222, 173), mSizeInTiles.width() * mSizeInTiles.height());

    const QPoint startTile = startTilePos();
    const QPoint endTile = endTilePos();
    // http://playtechs.blogspot.com/2007/03/raytracing-on-grid.html
    int x0 = startTile.x();
    int y0 = startTile.y();
    int x1 = endTile.x();
    int y1 = endTile.y();

    int dx = abs(x1 - x0);
    int dy = abs(y1 - y0);
    int x = x0;
    int y = y0;
    int n = 1 + dx + dy;
    int x_inc = (x1 > x0) ? 1 : -1;
    int y_inc = (y1 > y0) ? 1 : -1;
    int error = dx - dy;
    dx *= 2;
    dy *= 2;

    for (; n > 0; --n)
    {
        visit(x, y);

        if (error > 0)
        {
            x += x_inc;
            error -= dy;
        }
        else if (error < 0)
        {
            y += y_inc;
            error += dx;
        }
        else if (error == 0) {
            // Ensure that perfectly diagonal lines don't take up more tiles than necessary.
            // http://playtechs.blogspot.com/2007/03/raytracing-on-grid.html?showComment=1281448902099#c3785285092830049685
            x += x_inc;
            y += y_inc;
            error -= dy;
            error += dx;
            --n;
        }
    }

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