线条(直线)

 

直线生成算法

要设计一条直线生成算法,我们可以利用直线方程进行迭代计算。假设给定直线段的起点坐标为 (x1, y1) 和终点坐标为 (x2, y2),我们可以得到直线方程为:

Y = mx + b

其中 m 为斜率,b 为截距。斜率 m 和截距 b 的计算公式如下:

m = (y2 - y1) / (x2 - x1)

b = y1 - m * x1

详细解析过程

计算斜率 m:

m = (y2 - y1) / (x2 - x1)

计算截距 b:

b = y1 - m * x1

初始化起点:

x0 = x1
y0 = y1

迭代计算:

i = 0 开始,直到 x_i = x2:

x_i+1 = x_i + 1
y_i+1 = m * x_i + b

取整:

由于像素坐标是整数,需要对计算出的 y 值进行取整,即 y_i = round(y_i)

输出像素:

将每个计算出的像素 (x_i, y_i) 绘制到屏幕上。

代码实现

def generate_line(x1, y1, x2, y2):
    # 计算斜率 m 和截距 b
    m = (y2 - y1) / (x2 - x1)
    b = y1 - m * x1

    # 初始化起点
    x = x1
    y = y1

    # 迭代计算并输出像素
    while x <= x2:
        print(f"({int(x)}, {int(round(y))})")
        x += 1
        y += m

DDA(Digital Differential Analyzer)画线法是一种计算机图形学中用于绘制直线的算法。它通过计算直线上每个像素点的位置,并逐步绘制这些点来生成直线。

DDA 画线法介绍

DDA(Digital Differential Analyzer)算法是一种用于绘制直线的简单而有效的方法。以下是DDA算法的基本步骤:

  1. 初始化

    • 确定起点 (x1,y1) 和终点 (x2,y2)
    • 计算直线的总步数 steps,即 max⁡(∣x2−x1∣,∣y2−y1∣)
  2. 计算增量

    • 计算每一步在 x 方向上的增量 Δx=x2−x1steps
    • 计算每一步在 y 方向上的增量 Δy=y2−y1steps
  3. 迭代绘制

    • 从起点开始,每次增加 Δx 和 Δy,直到到达终点。
    • 在每一步中,将当前点 (x,y) 显示或绘制出来。

代码实现

#include <iostream>
#include <cmath>

void DDAline(int x1, int y1, int x2, int y2) {
    int steps;
    float m, x, y, dx, dy;

    // 误差分析
    double distance = 0.0; // 生成点到理想直线的距离
    double kaverage = 0.0; // 生成点和起点间斜率平均值

    x = x1 + 0.5f;
    y = y1 + 0.5f;
    steps = abs(x2 - x1) > abs(y2 - y1) ? abs(x2 - x1) : abs(y2 - y1);

    dx = (float)(x2 - x1) / steps;
    dy = (float)(y2 - y1) / steps;

    // 计算直线斜率和截距
    m = (float)(y2 - y1) / (float)(x2 - x1);
    float b = y2 - m * x2;

    for (int i = 0; i < steps; i++) {
        // 在终端显示坐标点
        std::cout << "(" << (int)x << ", " << (int)y << ")\n";

        // 计算误差
        distance += fabs(x * m + b - y) / sqrt(m * m + 1);
        kaverage += fabs((y - y1) / (x - x1));

        // 更新 x 和 y 的值
        x += dx;
        y += dy;
    }

    // 计算平均误差和平均平滑度
    double ddaError = distance / steps;
    double ddaSmooth = fabs(kaverage / steps - m);

    // 输出误差信息
    std::cout << "Average Error: " << ddaError << "\n";
    std::cout << "Average Smoothness: " << ddaSmooth << "\n";
}

int main() {
    int x1 = 0, y1 = 0, x2 = 10, y2 = 10;
    DDAline(x1, y1, x2, y2);
    return 0;
}

布雷森汉姆直线算法

布雷森汉姆直线算法是一种用于在光栅显示器上绘制直线段的高效计算机图形学算法。该算法通过计算像素点位置来近似表示两点之间的直线,从而避免了浮点运算,提高了算法效率。

工作原理

对于斜率小于1的直线,通常初始化两个变量。第一个像素的决定参数 p2Δy−Δx,其中 ΔxΔy 分别是直线段的 x 轴和 y 轴长度;错误积累项 e2Δy。如果直线的起始点位于 (0,0),则第一个像素点是 (0,0)。

判断下一个像素点的位置:

  • 如果 p≤0,则下一个像素点的位置是 (x+1, y),并且决策参数 p 更新为 p+2Δy
  • 如果 p>0,则下一个像素点的位置是 (x+1, y+1),决策参数 p 更新为 p+2Δy−2Δx

循环执行上述步骤,直到遍历完所有 x 坐标,从而确定了所有应该点亮的像素点。

误差 e 的初值计算方法

不难由斜率推出误差 e 的初值计算方法为 4x1−Δy。当 y 方向增量为 0 即选 P 时,下一步的误差 e 计算公式为 e=−x2−e+x1。当 y 方向增量为 1,即选 P 时,下一步的误差 e 计算公式为 e′=x2−1−e+x1−1。为了将误差 e 与 0.5 比较转换成与 0 比较,令 e 初值为 e−1/2

代码实现

 

void line(int x0, int y0, int x1, int y1) {
    int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
    int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
    int err = dx + dy, e2; // error value e_xy

    for (;;) {
        cout(x0, y0);
        if (x0 == x1 && y0 == y1) break;
        e2 = 2 * err;
        if (e2 >= dy) { // e_xy + e_x > 0
            err += dy;
            x0 += sx;
        }
        if (e2 <= dx) { // e_xy + e_y < 0
            err += dx;
            y0 += sy;
        }
    }
}

 

posted @   安娜アンナ  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示