计算机图形学 绘制直线(C++)

1. 数值微分法DDA(Digital Differential Analyzer)

基本思想:先对一个方向的坐标取单位步长的变化,然后计算另一方向坐标相应的变化值。
当一条直线的斜率不为0时,它可以用方程y=kx+b来表示,假定直线的起点和终点分别为(x1,y1),(x2,y2),且都为整数,那么k = (y2-y1)/(x2-x1);

由k的大小确定取单位步长的方向:
① |k|<1,取增长单位步长方向为x轴(Δx=1),y的增量大小为
y i + 1 = k ( x i + 1 ) + b = y i + k y_{i+1}=k(x_i+1)+b= y_i+k yi+1=k(xi+1)+b=yi+k
②|k|>1,则取增长单位步长方向为y轴(Δy=1),可得如下x的增量方程:
x i + 1 = x i + 1 k x_{i+1}=x_i+\frac1k xi+1=xi+k1
③若开始的端点在终点右方,则有
Δx = -1时 y i + 1 = k ( x i − 1 ) + b = y i − k y_{i+1}=k(x_i-1)+b= y_i-k yi+1=k(xi1)+b=yik
Δy = -1时 x i + 1 = x i − 1 k x_{i+1}=x_i-\frac1k xi+1=xik1

实例:绘制从A(11,7)到B(3,2)的直线
k =(y2-y1)/(x2-x1)=0.625,增量方向为x轴,且起点在终点右侧,Δx=-1,y的改变量Δy=-0.625
在这里插入图片描述

i i i x i x_i xi y i y_i yi坐标(四舍五入)
0 x 0 = 11 x_0 = 11 x0=11 y 0 = 7 y_0 = 7 y0=7(11,7)
1 x 1 = 10 x_1 = 10 x1=10 y 1 = 6.375 y_1 = 6.375 y1=6.375(10,6)
2 x 2 = 9 x_2 = 9 x2=9 y 2 = 5.75 y_2 = 5.75 y2=5.75(9,6)
3 x 3 = 8 x_3 = 8 x3=8 y 3 = 5.125 y_3 = 5.125 y3=5.125(8,5)
4 x 4 = 7 x_4 = 7 x4=7 y 4 = 4.5 y_4 = 4.5 y4=4.5(7,5)
……………………

在C++,MFC中实现代码如下

void Draw(CDC *pCD,int x1,int y1,int x2,int y2,COLORREF color)
{
	//该程序考虑到了k范围不同,以及k不存在时的情况
	int dx,dy,n,k;
	double xinc,yinc,x,y;
	dx = x2-x1;
	dy = y2-y1;
	if(abs(dx)-abs(dy)>0) //比较两参数的绝对值哪一个大,哪一个就作为步长参数(n),
							此参数将作为沿直线所画出点的数目
		n = abs(dx);
	else
		n = abs(dy);
	xinc = (double)dx/n;
	yinc = (double)dy/n;
	x = x1;
	y = y1;
	for(k = 0;k<n;k++)
	{
		pCD->SetPixel(floor(x + 0.5),floor(y + 0.5),color);
		x+=xinc;
		y+=yinc;
	}
}

2. 中点画线法

基本思想:假设直线的起点和终点分别为(x1,y1)和(x2,y2),则方程为: a x + b y + c = 0 ax+by+c=0 ax+by+c=0其中a=y1-y2, b=x2-x1, c=x1y2-x2y1

在这里插入图片描述

构造判别式:中点M(xi+1,yi+0.5),如下图所示
d=F(M)=F(xi+1,yi+0.5) =a(xi+1)+b(yi+0.5)+c
当d<0,M在直线(Q点)下方,取右上方P1;
当d>0,M在直线(Q点)上方,取右方P2;
当d=0,选P1或P2均可,约定取P2;

在这里插入图片描述
①若d>0,即M在直线上方,取P2。再下一个象素的判别式为
d1=F(xi+2, yi+0.5)= a(xi +1)+b(yi +0.5)+c +a =d+a; 增量为a。
②若d<0,即M在直线下方,取P1.再下一个象素的判别式为
d2= F(xi+2, yi+1.5)= a(xi +1)+b(yi +0.5)+c +a +b =d+a+b ; 增量为a+b
③d的初始值(第一个象素应取左端点(x1,y1))
d0= F(x0+1, y0+0.5)= F(x0, y0) +a +0.5b= a +0.5b

注:由于0.5b很有可能出现小数,不易于计算,此处我们都去增量大两倍,d1 = 2a;d2 = 2(a+b);d0=2a+b.

实例:绘制从A(11,7)到B(3,2)的直线
在这里插入图片描述
取B为起点,A为终点,计算相关参量:
a = y1 –y2 = 2 - 7 = -5;
b = x2-x1 = 11 – 3 = 8;
d0 = 2a+b = -2
d1 = 2
a = -10
d2 = 2*(a+b) = 6

i i i x i x_i xi y i y_i yi d i d_i di坐标
032-2(3,2)
1434(4,3)
253-6(5,3)
3640(6,4)
474-10(7,4)
…………………………

3. Bresenham画线算法

基本思想:过各行、各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线与各垂直网格线的交点,然后确定该列像素中与此交点最近的像素.
如图所示,先假设直线的斜率在0~1之间。设Pi-1是已选定的离直线最近的象素,现在要决定下一个象素是Ti还是Si:
若s<t,则Si比较靠近直线,应选Si;
若s>=t,则应选Ti。
在此不再详细阐述,有兴趣请自行查阅资料。
在这里插入图片描述

  • 4
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值