การค้นหาไทล์ใดที่ถูกตัดกันโดยบรรทัดโดยไม่ต้องวนลูปทั้งหมดหรือข้ามใด ๆ


10

ฉันกำลังจ้องมองปัญหานี้มาสองสามวันแล้ว ฉันดึงภาพนี้ขึ้นมาเพื่อช่วยให้เห็นภาพของปัญหา: ป้อนคำอธิบายรูปภาพที่นี่ (จากกราฟเรารู้ว่าเส้นตัดกัน [1, 1], [1, 2], [2, 2], [2, 3] ซึ่งลงท้ายด้วย [ 3,3])

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

ดังนั้นฉันต้องการอัลกอริทึมที่จะไปตามเส้นตรงไปยังพื้นที่กริดแต่ละอันที่มันตัดกัน ความคิดใด ๆ

ฉันได้ดูอัลกอริธึมทั่วไปจำนวนมากเช่นของ Bresenham และขั้นตอนที่กำหนดช่วงเวลาตามเส้นที่กำหนดไว้ล่วงหน้า (น่าเสียดายที่วิธีนี้ข้ามกระเบื้องถ้าพวกเขาตัดกันด้วยลิ่มที่เล็กกว่าขนาดขั้นตอน)

ตอนนี้ฉันกำลังเติมไวท์บอร์ดของฉันด้วยพื้น () และฟังก์ชั่น ceil () - แต่มันซับซ้อนเกินไปและฉันกลัวว่ามันอาจทำให้เกิดการชะลอตัว


คุณรู้วิธีทดสอบจุดตัดของกล่องสัญญาณจริงใช่ไหม เพียงแค่ถามเพราะมันเกี่ยวข้องกับคำตอบ
TravisG

ความเป็นไปได้ที่ซ้ำกันของฉันจะพูดคุยเกี่ยวกับอัลกอริธึมบรรทัดของ Bresenham กับจุดลอยตัวได้อย่างไร (คำถามไม่ได้เกี่ยวกับ Bresenham)
sam hocevar

คำตอบ:


6

หากคุณรู้จักบล็อกเริ่มต้น (คุณรู้จักจุด X และคุณไม่ได้รวมบล็อก [0,1] ไว้ในรายการบล็อกดังนั้นฉันคิดว่าคุณรู้จักบล็อกเริ่มต้นด้วย) ฉันคิดว่าคุณควรใช้อัลกอริทึมของ Bresenham คุณเขียนคุณดูมัน

เป็นอัลกอริทึมที่เหมาะสมสำหรับปัญหานี้ มันสามารถเขียนด้วยวิธีคำนวณด้วยจำนวนเต็มเท่านั้น คุณสามารถพบการใช้งานมากมายบนเว็บ

แก้ไข:

ฉันขอโทษฉันไม่ได้ตระหนักว่า Bresenham จะไม่พบบล็อกทั้งหมด ดังนั้นผมจึงพบทางออกที่ดีกว่า นอกจากนี้ยังมีโค้ดที่เขียนใน C ++ แต่ฉันคิดว่ามันไม่ควรเข้าใจยาก :)


1
เหตุผลที่ฉันมองผ่านอัลกอริธึม Bresenham นั้นล้วนเป็นเพราะภาพบนวิกิพีเดีย ( en.wikipedia.org/wiki/File:Bresenham.svg ) คุณจะเห็นได้ว่าเส้นนั้นจะตัดกำลังสองบางส่วนที่ไม่มีเงา ฉันต้องการบางสิ่งที่จะตรวจจับไทล์ได้ทุกชิ้นโดยไม่คำนึงว่าชิ้นเล็กแค่ไหน แก้ไข: ดูเหมือนว่าฉันมีความเข้าใจผิดของ bresenham อยู่ดี ฉันต้องการย้อนกลับ - ฉันมีจุดแรกและจุดสุดท้ายและฉันต้องการกระเบื้องที่ตัดกัน - แทนที่จะเป็นเส้นที่ดีที่สุดในการพล็อต
Suds

@JustSuds: ตรวจสอบการอัปเดตในโพสต์
zacharmarz

เฮ้เฮ้! ที่เกือบจะตรงกับสิ่งที่ฉันมีในไวท์บอร์ดของฉัน! ขอขอบคุณระบบของฉันได้รับการติดตั้งและใช้งานได้แล้ว :-)
Suds

คุณสามารถลบส่วนที่เกี่ยวกับอัลกอริทึมของ Bresenham ออกได้หรือไม่ตอบคำถามได้หรือไม่? ไม่ต้องกังวลมันจะอยู่ในประวัติการแก้ไขคำตอบของคุณ
สุดยอด

1

โค้ดในตัวอย่างที่คำตอบที่ยอมรับนั้นเชื่อมโยงกับความต้องการการปรับเปลี่ยนบางอย่างสำหรับเส้นทแยงมุมอย่างสมบูรณ์ นี่คือแอปพลิเคชั่นตัวอย่างสมบูรณ์ที่เขียนด้วย Qt (C ++ และ QML)

จุดตัดของเส้นกริด

รหัส C ++ ที่เกี่ยวข้อง:

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