คุณจะวาดเส้นตรงระหว่างสองจุดในบิตแมปได้อย่างไร?


17

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

มันง่ายมากถ้าคะแนนของคุณแชร์พิกัด X หรือ Y หรือถ้าพวกมันอยู่ในแนวเดียวกันคุณก็สามารถวาดเส้นทแยงมุมได้ แต่ในกรณีอื่น ๆ ทั้งหมดมันมีเล่ห์เหลี่ยม

คุณใช้อัลกอริทึมแบบใดในการพิจารณาว่าพิกเซลใดที่จำเป็นต้องมีสีเพื่อให้เป็นเส้น "ตรง"

คำตอบ:


25

ผมคิดว่าสิ่งที่คุณต้องมีขั้นตอนวิธีการสาย Bresenham ของ

จากสิ่งที่ผมจำได้ว่ามันจะถูกใช้ในการกำหนดสิ่งที่จุดควรจะมีสีไม่เท่าไหร่แต่ละจุดควรจะมีสี


21

อัลกอริธึมบรรทัดของ Bresenhamสามารถใช้เพื่อกำหนดว่าจุดใดในตารางแรสเตอร์ที่จะลงจุดเพื่อให้ได้การประมาณภาพที่เหมาะสมของส่วนของเส้น

อัลกอริทึมครอบคลุม rasterization ของบรรทัดที่กำหนดโดยจุดเริ่มต้นและจุดสิ้นสุดในพื้นที่พิกัดที่จุดกำเนิดอยู่ทางซ้ายบน พิกัดจำนวนเต็มจะถูกสันนิษฐานว่าทำแผนที่กับจุดศูนย์กลางพิกเซล รูปแบบพื้นฐานของอัลกอริธึมครอบคลุมเพียงหนึ่ง octant ของวงกลม: เส้นที่เพิ่มขึ้นพิกัด X และ Y แต่ความชันเชิงลบที่มีค่าสัมบูรณ์น้อยกว่า 1 octants อื่นทั้งหมดสามารถได้รับการแปลงอย่างง่ายของเรื่องนี้ octant พื้นฐาน

ใน psuedocode รูปแบบพื้นฐานนี้ดูเหมือนว่า:

void DrawLine(Point origin, Point endpoint, Bitmap surface) {
    deltaX = endpoint.X - origin.X
    deltaY = endpoint.Y - origin.Y
    error = 0

    // Note the below fails for completely vertical lines.
    deltaError = absoluteValue(deltaY / deltaX)

    Y = origin.Y
    for (X from origin.X to endpoint.X) {
        surface.PlotPixel(X, Y)
        error = error + deltaError 
        if (error >= 0.5) {
            ++Y;
            error -= 1.0
        }
    }
}

เว็บไซต์ Rosetta รหัสมีคอลเลกชันของการใช้งานที่เป็นรูปธรรมในความหลากหลายของภาษา

คุณอาจสนใจอัลกอริทึมแบบบรรทัดของ Wuซึ่งช่วยให้สามารถป้องกันนามแฝงได้


3
เพียงแค่ต้องการเตือนผู้คนโดยไม่ให้ใช้ pseudocode ที่รวมอยู่นอกบริบทเนื่องจากมันจะไม่ทำงานนอกกรอบ ใช้งานได้เฉพาะ octant ที่เฉพาะเจาะจง (อ่านคำตอบที่เหลือ) หากคุณกำลังมองหารหัสที่จะคัดลอก / วางให้ลองลิงค์ไปยังเว็บไซต์รหัส Rosetta
congusbongus

1
สำหรับทุกคนที่ต้องการตรวจสอบอัลกอริทึมบรรทัดของ Wu รุ่น c ฉันอยากจะเตือนคุณว่ามันไม่สมบูรณ์ ใน _dla_changebrightness เมื่อคุณเปลี่ยนความสว่างที่คุณต้องการที่จะเปลี่ยนมันจาก: ต่อไปนี้:to->red = br * (float)from->red; to->red = (br * (float)from->red) + ((1-br) * (float) to->red);ทำเช่นเดียวกันสำหรับสีเขียวและสีฟ้าอย่างเคารพนับถือ
Fredrik Boston Westman

2

นี่เป็นวิธีวาดเส้นที่ง่ายมาก สามารถเปลี่ยนฟังก์ชั่นได้อย่างง่ายดายเพื่อใช้ในโครงการ

void draw_line(float x0, float y0, const float& x1, const float& y1)
{
    float x{x1 - x0}, y{y1 - y0};
    const float max{std::max(std::fabs(x), std::fabs(y))};
    x /= max; y /= max;
    for (float n{0}; n < max; ++n)
    {
        // draw pixel at ( x0, y0 )
        x0 += x; y0 += y;
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.