【光栅图形学】直线和圆的扫描线算法(代码及推导过程)

直线和圆的扫描转化算法

给定两点   A ( x a , y a ) , B ( x b , y b ) , ( x a ≤ x b )   ~A(x_a,y_a),B(x_b,y_b),(x_a\le x_b)~  A(xa,ya),B(xb,yb),(xaxb) ,在像素整点上画出该线段。

我们不妨先假设   0 ≤ k ≤ 1 ~0\le k\le1  0k1,我们探讨如下三种算法:

数值微分算法DDA(Digital Differential Analyzer)

显然直线方程   A B : y − y a x − x a = y b − y a x b − x a ~AB:\displaystyle\frac{y-y_a}{x-x_a}=\frac{y_b-y_a}{x_b-x_a}  AB:xxayya=xbxaybya

转化为直线   y = k x + b    ( k = y b − y a x b − x a , b = y a − k x a = x b y a − x a y b x b − x a ) ~\displaystyle y=kx+b~~(k=\frac{y_b-y_a}{x_b-x_a},b=y_a-kx_a=\frac{x_by_a-x_ay_b}{x_b-x_a})  y=kx+b  (k=xbxaybya,b=yakxa=xbxaxbyaxayb)

我们可以枚举 x = x a , x a + 1 , x a + 2 , … , x b   x=x_a,x_a+1,x_a+2,\dots,x_b~ x=xa,xa+1,xa+2,,xb 得要相应的   y = k x + b ~y=kx+b  y=kx+b,计算量为一次加法一次乘法和一次取整运算。如何优化?

增量思想代替原式中的乘法,递推计算   y i = k x i + b   ~y_i=kx_i+b~  yi=kxi+b ,有

y i + 1 = k x i + 1 + b = k ( x i + 1 ) + b = ( k x i + b ) + k = y i + k y_{i+1}=kx_{i+1}+b=k(x_i+1)+b=(kx_i+b)+k=y_i+k yi+1=kxi+1+b=k(xi+1)+b=(kxi+b)+k=yi+k

我们得到算法的递推式:
P i ( x i , y i ) = { ( x a , y a ) i = 1 ( x i − 1 + 1 , y i − 1 + k ) i ≥ 2 P_i(x_i,y_i)=\left\{\begin{aligned} &(x_a,y_a)&i=1\\ &(x_{i-1}+1,y_{i-1}+k)&i\ge2 \end{aligned}\right. Pi(xi,yi)={ (xa,ya)(xi1+1,yi1+k)i=1i2

完整的代码如下(包括 ∣ k ∣ ≥ 1 |k|\ge1 k1的部分)

void DDA(int x1,int y1,int x2,int y2)
{
	int dx=std::abs(x1-x2),dy=std::abs(y1-y2);
	// if |k| greater than 1, enumerate x and calculate y=kx+b
	if(dx>dy)
	{
		// we assume that x1<=x2
		if(x1>x2) std::swap(x1,x2),std::swap(y1,y2);
		double k=double(y2-y1)/(x2-x1),y=y1;
		// x_{i+1}=x_i+1,y_{i+1}=y_i+k for x \in [x1+1,x2]
		for(int x=x1;x<=x2;x++,y+=k)
		{
			// draw current pixel
			draw_pixel(x,int(y));
		}
	}
	// if |k| less than 1, enumerate y
	else
	{
		// same as above
		if(y1>y2) std::swap(y1,y2),std::swap(x1,x2);
		double k=double(x2-x1)/(y2-y1),x=x1;
		for(int y=y1;y<=y2;y++,x+=k)
		{
			draw_pixel(int(x),y);
		}
	}
}
中点画线法

将直线转化为一般式   f ( x , y ) =   A x + B y + C = 0   ~f(x,y)=~Ax+By+C=0~  f(x,y)= Ax+By+C=0 ,即 ( y a − y b

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值