【图形学】直线光栅化算法(DDA算法和Bresenham算法)

在数学上,直线就是由无穷多个点组成的, 在计算机屏幕显示的话, 需要做一些处理,对于光栅显示器,就是用有限多个点去逼近直线, 我们需要知道每一个像素点的坐标(都是整数)
在这里插入图片描述

数学上直线的方程如下 y = k x + b y=kx+b y=kx+b,给定直线的起点坐标 P 0 ( x 0 , y 0 ) P_0(x_0,y_0) P0(x0,y0)终点坐标 P 1 ( x 1 , y 1 ) P_1(x_1,y_1) P1(x1,y1)水平方向的位移 Δ x = x 1 − x 0 \Delta x=x_1-x_0 Δx=x1x0垂直方向的位移 Δ y = y 1 − y 0 \Delta y=y_1-y_0 Δy=y1y0 在直线的光栅化算法中要通过 Δ x 和 Δ y \Delta x 和 \Delta y ΔxΔy 的大小来确定绘图的主位移方向,主位移方向执行 ± 1 \pm1 ±1

条件主方向
Δ x > Δ y \Delta x>\Delta y Δx>Δyx方向
Δ x = Δ y \Delta x=\Delta y Δx=Δyx方向或y方向
Δ x < Δ y \Delta x<\Delta y Δx<Δyy方向

DDA算法

直线的斜截式方程用微分的形式表示为 d y d x = Δ y Δ x = k \frac{dy}{dx}=\frac{\Delta y}{\Delta x}=k dxdy=ΔxΔy=k
那么可以得到直线上的像素点 P i + 1 和 P i P_{i+1}和P_{i} Pi+1Pi的递推关系
{ x i + 1 = x i + Δ x y i + 1 = y i + Δ y = y i + k Δ x \begin{cases} x_{i+1}=x_i+\Delta x \\ y_{i+1}=y_i +\Delta y=y_i+k\Delta x \end{cases} {xi+1=xi+Δxyi+1=yi+Δy=yi+kΔx
以斜率 0 ≤ k < 1 0\leq k <1 0k<1为例,有 Δ x > Δ y \Delta x>\Delta y Δx>Δy ,主方向是x,那么上面的式子就变成了
{ x i + 1 = x i + 1 y i + 1 = y i + k \begin{cases} x_{i+1}=x_i+1 \\ y_{i+1}=y_i +k \end{cases} {xi+1=xi+1yi+1=yi+k
设点 E ( x i + 1 , y i + k ) E(x_i+1,y_i+k) E(xi+1,yi+k)是理想直线和线 x i + 1 = x i + 1 的交点 x_{i+1}=x_i+1的交点 xi+1=xi+1的交点那么用来逼近这个点的可能的像素点有两个 D ( x i + 1 , y i + 1 ) 和 C ( x i + 1 , y i ) D(x_i+1,yi+1)和C(x_i+1,y_i) D(xi+1,yi+1)C(xi+1,yi)具体选择那个,就根据k的值确定(? y i + k y_i +k yi+k四舍五入? y i + 1 = i n t ( y_{i+1}=int( yi+1=int(y_i+k+0.5 ) ) ))
在这里插入图片描述

下面给出DDA算法画任意斜率直线的主要代码

void CLine::DrawLine(CDC* pDC)
{
    int dx = m_p2.x - m_p1.x;//m_p1,m_p2(CPoint)
    int dy = m_p2.y - m_p1.y;
    double k = (double)(dy) / (double)(dx);  //斜率

    //确定主方向
    int e = abs(k) > 1 ? abs(dy) : abs(dx);
    double xadd = (double)(dx) / (double)(e);
    double yadd = (double)(dy) / (double)(e);
    double x = (double)(m_p1.x);
    double y = (double)(m_p1.y);
    for (int i = 0; i <= e; i++) {
        pDC->SetPixel((int)(x + 0.5), (int)(y + 0.5), RGB(0, 0, 0));
        x += xadd;
        y += yadd;
    }
}

Bresenham算法

在这里插入图片描述

Bresenham算法在主位移方向上也是移动一个单位,另一个方向移动0还是1取决于像素点和理想直线的距离d
还是以斜率 0 ≤ k < 1 0\le k <1 0k<1为例,x方向是主位移方向,点 Q ( x i + 1 , y i + 1 ) Q(x_{i+1},y_{i+1}) Q(xi+1,yi+1)是理想直线和 x i + 1 = x i + 1 x_{i+1}=x_i+1 xi+1=xi+1的交点,两个可能的像素的 P u p ( x i , y i + 1 ) 和 P d o w n ( x i , y i ) P_{up}(x_i,y_i+1) 和P_{down}(x_i,y_i) Pup(xi,yi+1)Pdown(xi,yi),选那一个就取决于Q点和 P d o w n P_{down} Pdown的距离 d i + 1 d_{i+1} di+1,对于误差项d的计算向x方向递增1个单位就有 d i + 1 = d i + k d_{i+1}=d_i+k di+1=di+k,如果向y方向递增一个单位就还要减1。
d 0 = 0 y i + 1 = { y i + 1 , d i + 1 ≥ 0.5 y i , d i + 1 < 0.5 d_0=0 \\ \\ y_{i+1}=\begin{cases} y_{i}+1 ,d_{i+1}\geq 0.5\\ y_i,d_{i+1}<0.5 \end{cases} d0=0yi+1={yi+1,di+10.5yi,di+1<0.5
不过通常不是用误差项d进行计算,取一个变量e, e 0 = − Δ x e_0=-\Delta x e0=Δx,沿x方向每递增一个单位就有 e i + 1 = e i + 2 Δ y e_{i+1}=e_i+2\Delta y ei+1=ei+y,当 e i + 1 ≥ 0 e_{i+1}\geq 0 ei+10时下一个像素点就是( x i + 1 , y i + 1 x_i+1,y_i+1 xi+1,yi+1),并且要更新 e i + 1 = e i + 1 − 2 Δ x e_{i+1}=e_{i+1}-2\Delta x ei+1=ei+1x;否则下一个像素点就是( x i + 1 , y i x_i+1,y_i xi+1,yi)。

原始的Bresenham只能画指向第一象限并且斜率小于1的直线,但实际有这么多种情况,但是别慌,可以利用直线的对称性解决。
在这里插入图片描述

对于相同象限, 斜率不同的情况, 其实就是将斜率在0到1之间的线作关于函数y = x 对称而得到。对应到代码中就是将所有的y和所有的x调换位置。比如, e 0 = − Δ y e_0=-\Delta y e0=Δy e i + 1 = e i + 2 Δ x e_{i+1}=e_i+2\Delta x ei+1=ei+x,当 e i + 1 ≥ 0 e_{i+1}\geq 0 ei+10时下一个像素点就是( x i + 1 , y i + 1 x_i+1,y_i+1 xi+1,yi+1),并且要更新 e i + 1 = e i + 1 − 2 Δ y e_{i+1}=e_{i+1}-2\Delta y ei+1=ei+1y;否则下一个像素点就是( x i + 1 , y i x_i+1,y_i xi+1,yi)。
下面给出通用的Bresenham算法

void CLine::DrawLine(CDC* pDC)
{
    int dx = abs(m_p2.x - m_p1.x);//m_p1,m_p2(CPoint)
    int dy = abs(m_p2.y - m_p1.y);
    double k = (double)(dy) / (double)(dx);  //斜率
	BOOL wayChange = FALSE;//主方向是否发生改变,默认是x方向
	int e,mainway,subway;
	e = -dx;
	mainway = dx;
	subway = dy;
	int addx, addy;
	addx = (m_p2.x > m_p1.x) ? 1 : ((m_p2.x < m_p1.x) ? -1 : 0);
	addy = (m_p2.y > m_p1.y) ? 1 : ((m_p2.y < m_p1.y) ? -1 : 0);
	if (dy > dx) {//主方向是y
		mainway = dy;
		subway = dx;
		wayChange = TRUE;
	}
	CPoint p = m_p1;
	for (int i = 0; i <= mainway; i++) {
		pDC->SetPixel(p, RGB(0, 255, 0));
		if (wayChange)
			p.y += addy;
		else
			p.x += addx;
		e += 2 * subway;
		if (e >= 0) {
			if (wayChange)
				p.x += addx;
			else
				p.y += addy;
			e -= 2 * mainway;
		}
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/326189.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

开源 UI 组件库和开发工具库概览 | 开源专题 No.59

ant-design/ant-design Stars: 87.9k License: MIT Ant Design 是一个企业级 UI 设计语言和 React UI 库。 为 Web 应用程序设计的企业级 UI。提供一套高质量的开箱即用的 React 组件。使用可预测静态类型编写 TypeScript 代码。包含完整的设计资源和开发工具包。支持数十种语…

QT上位机开发(软件的发布和部署)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 我们在读书的时候&#xff0c;如果程序写好了&#xff0c;这个时候一般直接把exe拷贝给老师就可以了。这就是最原始的软件发布。但是&#xff0c;这…

“核弹级“攻击队视角下的监管痛点解决方案

痛点分析及解决方案 一、辖区企业资产分散且不透明 - 传统的监管体系中&#xff0c;政府监管单位往往面临着辖区企业资产分散且不透明的问题。 - 企业无法梳理自身资产&#xff0c;上报的资产台账无法涵盖全部自身资产 - 监管单位精力有限&#xff0c;无法保证辖区企业资产台账…

解决jmeter测试计划无法保存、另存为的问题

问题&#xff1a; 在保存测试计划时直接保存在C:\Windows\System32&#xff0c; 导致执行时报错Couldn’t save test plan to file&#xff1a;C:\Windows\System32 解决方案&#xff1a; 将路径改为 options--------Look And Feel-------windows

Express框架使用全流程

1.目的和使用场景 对于像我这样不常使用 Node.js 进行开发的人来说&#xff0c;每次开始一个新项目都意味着从头开始设置环境&#xff0c;这个过程相当繁琐。因此&#xff0c;我决定自己构建一个开箱即用的项目脚手架。我的目标是创建一个简单易用的基础框架&#xff0c;能让我…

NET Core发布 HTTP Error 500.31 - Failed to load ASP.NET Core runtime

记录一下踩过的坑&#xff1a; 首先&#xff0c;不论是500.31还是500.30 &#xff0c;首先确保安装了三个文件 1.NET Core RunTime 2.NET SDK 3.NET Hosting 其次&#xff0c;确保三个文件的版本一致&#xff0c;如下&#xff1a; 要装就统一装同一个大版本&#xff0c;不要东…

51单片机学习总结(自学)

1、模块化编程 c语言模块化编程实现思路设计代码 具体的程序实现代码如下所示 1&#xff1a;程序的头文件 2&#xff1a;程序的函数文件 3&#xff1a;程序的主文件控制函数的实现 持续更新中......

训练YOLOS-S

文章目录 1 数据处理2 配置训练参数3 可能会遇到的报错 1 数据处理 修改类别数&#xff1a;在models/detector.py中定位到def build(args):&#xff0c;将num_classes进行修改&#xff0c;改为最大的类别id1。我有4个类别&#xff0c;类别id是从0~3&#xff0c;因此max_id3&am…

怎样才能找到合适的产品说明书模板 方法献上

制作一份专业而吸引人的产品手册对于企业来说至关重要。然而&#xff0c;对于许多企业和个人而言&#xff0c;制作产品手册可能是一个挑战&#xff0c;因为需要一定的设计和排版能力。为了帮助大家更轻松地制作出优质的产品手册&#xff0c;下面将向大家推荐三款优秀的产品手册…

如何提高客户消息的快速准确回复能力?

无论是企业还是个人&#xff0c;能够快速而准确地回复客户消息是非常重要的&#xff0c;这不仅可以增强客户对你的信任度&#xff0c;还能促进客户的满意度。 那么&#xff0c;我们该如何提高自己的回复能力呢&#xff1f;接着往下看&#xff0c;你就知道啦&#xff01; 1、学…

华为埋头造车,躺赚的却是黄牛?

文 | AUTO芯球 作者 | 雷歌 华为和赛力斯正在重庆哼哧a哼哧建厂造车&#xff0c;黄牛却在网上倒卖订单躺着赚钱。 前两天雷歌刚去试驾了问界M9&#xff0c;现场一车难求。 今天回来一看&#xff0c;好家伙&#xff0c;咸鱼上&#xff0c;黄牛们大量倒卖M9的大定订单&#x…

瑞_Java开发手册_(七)设计规约

文章目录 设计规约的意义设计规约 &#x1f64a;前言&#xff1a;本文章为瑞_系列专栏之《Java开发手册》的设计规约篇。由于博主是从阿里的《Java开发手册》学习到Java的编程规约&#xff0c;所以本系列专栏主要以这本书进行讲解和拓展&#xff0c;有需要的小伙伴可以点击链接…

大物②练习题解

1.【单选题】关于磁场中磁通量&#xff0c;下面说法正确的是&#xff08; D&#xff09; A、穿过闭合曲面的总磁通量不一定为零 B、磁感线从闭合曲面内穿出&#xff0c;磁通量为负 C、磁感线从闭合曲面内穿入&#xff0c;磁通量为正D、穿过闭合曲面的总磁通量一定为零 磁感线从…

WebGL在家居设计领域中的应用

WebGL&#xff08;Web Graphics Library&#xff09;是一种用于在Web浏览器中进行3D图形渲染的JavaScript API。在家居设计方面&#xff0c;WebGL可以提供一些强大的应用&#xff0c;使用户能够交互式地浏览和体验设计方案。以下是一些家居设计领域中WebGL的应用&#xff0c;希…

Mac安装MySQL

环境 电脑: macOS Monterey 12.7.2 MacBook Pro( Retina, 13-inch, Early 2015) 处理器: 2.7GHz 双核 Inter Core i5 MySQL 的安装版本: 8.2.0 最近有更新系统, 重新配置了电脑, 因此, 之前安装的 MySQL 也都删除了, 这次安装经历有点坎坷, 记录下来, 希望可以帮助到需要的小伙…

Jmeter接口测试实战篇:10分钟学会Jmeter的用法

一提到接口测试&#xff0c;通常大家会有这样的疑问&#xff1a;前端测试不是已经覆盖到各种业务逻辑了吗&#xff1f;为什么还要做接口测试&#xff0c;接口测试和前端测试是不是重复了&#xff1f;对于这个问题&#xff0c;可以从下面几个方面来解释&#xff1a; 什么是接口…

PyCharm中配置安装PyQt5、QtDesigner

PyCharm中配置安装PyQt5 使用 pip install PyQt5 命令安装。 安装pyqt5-tools&#xff1a;pip install pyqt5-tools 安装PyQt5Designer&#xff1a;pip install PyQt5Designer 上述三个都安装好之后&#xff0c;输入 pip list 查看一下 有如下内容就安装成功啦&#xff01;…

用el-image-viewer实现全局预览图片

背景 在后台管理系统中&#xff0c;一些预览图片的场景&#xff0c;通常都是使用 el-image-viewer 去实现&#xff0c;但是如果多个地方都需要预览图片&#xff0c;又要重复的去写 el-image-viewer 以及一些重复的和预览相关的代码。 可以把预览图片的组件放在根文件&#x…

java基础 - 05 Vector

Vector 学过C的同学都知道&#xff0c;Vector也在C中存在&#xff0c;他可以说是两种编程语言中都存在的数据结构&#xff0c;但是值得我们注意的是&#xff0c;Vector在java中和在C中是存在差别的&#xff0c;在Java中&#xff0c;Vector是一个数组。并且他是动态的&#xff…

记一次 JMeter 压测 HTTPS 性能问题

问题背景 在使用 JMeter 压测时&#xff0c;发现同一后端服务&#xff0c;在单机 500 并发下&#xff0c;HTTP 和 HTTPS 协议压测 RT 差距非常大。同时观测后端服务各监控指标水位都很低&#xff0c;因此怀疑性能瓶颈在 JMeter 施压客户端。 问题分析 切入点&#xff1a;垃圾…