当前位置: 首页 > news >正文

【图形学入门】直线光栅化——Bresenham / 中点画线算法

在看 这篇文章时,上面的公式没明白,这里做笔记记录一下。
image

这里表达的是:用一个“判别变量 d”来画直线,每次不用重新代入直线方程算,而是用增量更新。

它本质上是在讲 Bresenham / 中点画线算法


1. 这条直线先被写成隐式方程

图里给了:

\[f(x,y)=(y_0-y_1)x+(x_1-x_0)y+x_0y_1-x_1y_0 \]

这其实就是过两点:

\[(x_0,y_0),\quad (x_1,y_1) \]

的直线方程。

它的作用不是直接求 (y=kx+b),而是判断一个点 ((x,y)) 在直线的哪一侧。

对于这条直线:

\[f(x,y)=0 \]

表示点正好在直线上。

如果:

\[f(x,y)>0 \]

说明点在直线一侧。

如果:

\[f(x,y)<0 \]

说明点在直线另一侧。

在常见的数学坐标系下,假设 (0<k<1),也就是直线从左下往右上走,那么:

\[f(x,y)>0 \]

通常表示点在直线上方;

\[f(x,y)<0 \]

表示点在直线下方。


2. 画线时,每次 x 增加 1

假设我们从左往右画线,并且斜率满足:

\[0<k<1 \]

也就是说,直线比较平缓。

那么每走一步,(x) 必然加 1。

但是 (y) 有两个选择:

选择 1:往右走

\[(x+1,y) \]

这个像素可以叫做 E,East。

选择 2:往右上走

\[(x+1,y+1) \]

这个像素可以叫做 NE,North-East。

所以问题变成:

下一步到底选 ((x+1,y)),还是选 ((x+1,y+1))?


3. 用中点判断选下面还是上面

这两个候选像素中间有一个点:

\[(x+1,y+0.5) \]

它就是下面像素和上面像素之间的中点。

也就是:

(x+1, y+1)   上面的候选像素(x+1, y+0.5) 中点(x+1, y)     下面的候选像素

于是算法的判断逻辑是:

如果真实直线在这个中点上方,那么上面的像素更接近直线,选:

\[(x+1,y+1) \]

如果真实直线在这个中点下方,那么下面的像素更接近直线,选:

\[(x+1,y) \]

所以我们只需要判断:

\[f(x+1,y+0.5) \]

的符号。

图里写:

\[d=f(x_0+1,y_0+0.5) \]

这个 (d) 就是第一次的中点判别值。


4. 为什么 d < 0 时 y = y + 1?

图里的伪代码是:

if d < 0 theny = y + 1d = d + (x1 - x0) + (y0 - y1)
elsed = d + (y0 - y1)

这里的含义是:

当前中点是:

\[M=(x+1,y+0.5) \]

计算:

\[d=f(M) \]

如果:

\[d<0 \]

说明这个中点在直线下方。

也就是说,真实直线比中点更高。

因此上面的像素 ((x+1,y+1)) 更接近直线,所以:

\[y=y+1 \]

如果:

\[d\ge 0 \]

说明中点在直线上方或正好在线上,那么下面的像素 ((x+1,y)) 更合适,所以 (y) 不变。


5. 重点:为什么后面不用重新算 f?

如果每一步都重新算:

\[f(x+1,y+0.5) \]

那就要做乘法、加法,比较麻烦。

但是观察这个函数:

\[f(x,y)=(y_0-y_1)x+(x_1-x_0)y+x_0y_1-x_1y_0 \]

它是一个一次函数。

所以当 (x) 增加 1 时,(f) 的变化量是固定的。


情况一:下一步只向右走

也就是从:

\[(x,y) \]

变成:

\[(x+1,y) \]

那么:

\[f(x+1,y)=f(x,y)+(y_0-y_1) \]

这就是图里第一条:

\[f(x+1,y)=f(x,y)+(y_0-y_1) \]

意思是:

横坐标加 1,纵坐标不变时,f 的值只需要加上 ((y_0-y_1))。


情况二:下一步向右上走

也就是从:

\[(x,y) \]

变成:

\[(x+1,y+1) \]

那么:

\[f(x+1,y+1)=f(x,y)+(y_0-y_1)+(x_1-x_0) \]

这就是图里第二条:

\[f(x+1,y+1)=f(x,y)+(y_0-y_1)+(x_1-x_0) \]

意思是:

横坐标加 1,纵坐标也加 1 时,f 的值只需要加上两个增量。


6. 把整个过程用人话说一遍

假设当前已经画到了:

\[(x,y) \]

下一列一定是:

\[x+1 \]

但是有两个候选像素:

\[(x+1,y) \]

和:

\[(x+1,y+1) \]

于是看它们中间的点:

\[(x+1,y+0.5) \]

如果真实直线在这个中点上方,就选上面的像素。

如果真实直线在这个中点下方,就选下面的像素。

判断中点在直线哪边,用:

\[d=f(x+1,y+0.5) \]

如果:

\[d<0 \]

说明中点在直线下方,选上面的像素,所以:

\[y=y+1 \]

如果:

\[d\ge 0 \]

说明中点在直线上方,选下面的像素,所以 (y) 不变。

然后更新 (d)。

关键是,更新 (d) 不用重新算 (f),只需要加固定增量。


7. 图里的伪代码整体含义

y = y0
d = f(x0 + 1, y0 + 0.5)for x = x0 to x1 dodraw(x, y)if d < 0 theny = y + 1d = d + (x1 - x0) + (y0 - y1)elsed = d + (y0 - y1)

对应的中文解释是:

  1. 从起点 ((x_0,y_0)) 开始。
  2. 初始 (y=y_0)。
  3. 先计算第一个中点的判别值:

\[d=f(x_0+1,y_0+0.5) \]

  1. 每次画当前像素 ((x,y))。
  2. 然后判断下一步应该走右边还是右上。
  3. 如果 (d<0),说明真实直线在中点上方,所以 (y) 加 1。
  4. 如果 (d> 0),说明真实直线在中点下方或附近,所以 (y) 不变。
  5. 每次根据走法更新 (d),避免重新计算直线方程。

8. 核心一句话

这段想表达的是:

画一条斜率在 (0) 到 (1) 之间的直线时,每次 (x) 加 1,(y) 只可能不变或者加 1。为了决定选哪个像素,用中点 ((x+1,y+0.5)) 判断真实直线在上方还是下方。判别值 (d=f(x+1,y+0.5)) 第一次直接算,之后用固定增量更新,所以整个算法不需要反复做浮点乘除运算。

这就是中点画线算法的核心。

http://www.jsqmd.com/news/734251/

相关文章:

  • 第2篇:数据与数据类型——存储信息的小盒子 Rust中文编程
  • 开源天文历书MCP服务器:AI时代的天文数据接口实践
  • 3分钟掌握终极麦克风静音神器:MicMute完整使用指南
  • Office Custom UI Editor:5步完成零代码Office界面定制的终极指南
  • HMC7044上电锁不住?手把手教你排查PLL锁定问题(从读取0x007D寄存器开始)
  • MIPI D-PHY电路设计避坑指南:从1.8V HSTL到2.5V LVCMOS的PCB实战要点
  • 题解:AcWing 3483 2的幂次方
  • 【maaath】Flutter for OpenHarmony 实战:构建跨平台房产租售应用
  • 第4篇:如果...那么——让程序做选择 Rust中文编程
  • 甲言Jiayan:古汉语NLP终极解决方案,让文言文处理变得简单高效
  • Linux Shell 中有个字符让我瞬间感觉自己像个黑客
  • 别再手动导Jar包了!用Maven私服一键管理KingbaseES 8.6.0 JDBC驱动(SpringBoot整合指南)
  • 雀魂牌谱屋完全指南:用数据驱动你的麻将竞技提升
  • 题解:AcWing 6057 最短路
  • PCL2整合包导出:3分钟掌握智能分享的正确姿势 [特殊字符]
  • 告别手动!SWMM 5.2 批量设置检查井与管道的3种高效方法(附脚本思路)
  • claw-exterminator:基于clang-format的代码格式化自动化工具实战
  • 语雀Lake文档智能解析引擎:解锁知识资产跨平台流动新范式
  • 【仅限前500名技术负责人】VSCode 2026企业级启动优化包:含自定义shell环境注入模块、离线符号表预加载工具及启动火焰图诊断模板
  • 从F103到F407:手把手教你移植广州大彩串口屏HAL库驱动(避坑指南)
  • 开源大模型Grok本地部署与优化实战:从架构解析到应用落地
  • 显卡驱动清理终极指南:5个专业技巧彻底解决驱动残留问题
  • 题解:AcWing 6058 亲戚
  • Gemma 2本地部署方案与优化技巧详解
  • 为 Hermes Agent 配置自定义供应商并指向 Taotoken 服务
  • 终极Mac剪贴板管理方案:Maccy完整使用指南与深度优化
  • OmniInsert:无掩码视频插入技术的原理与应用
  • 基于LLM的GUI自动化智能体:从原理到实践
  • Motif-2-12.7B模型架构与优化技术解析
  • 基于Claude的AI任务编排框架:MissionRunner实战指南