计算机图形学-直线,圆,椭圆扫描转换算法

1. 直线的扫描转换

1.1 DDA算法

增量算法,每一步都需要进行舍入取整,不利于硬件实现

使用C++代码:

void DDALine(int x0,int y0,int x1,int y1)
{
    int dx,dy,epsl,k;
    float x,y,xIncre,yIncre;
    dx=x1-x0;
    dy=y1-y0;
    x=x0;
    y=y0;
    if(abs(dx)>abs(dy))   //abs()函数为取绝对值函数
        espl=abs(dx);
    else
        espl=abs(dy);
    xIncre=(float)dx/(float)epsl;
    yIncre=(float)dy/(float)epsl;
    
    for(k=0;k<=epsl;k++)
    {
        putpixel(int(x+0.5),int(y+0.5);   //画点
        x+=xIncre; 
        y+=yIncre;   //寻找下一个点
    }
}

1.2 中点Bresenham算法

每次在最大位移方向上走一步,另一个方向是否走步取决于误差项的判别

当0<k<1时,代码如下:

void MidBresenhamLine(int x0,int y0,int x1,int y1,int color)
{
    int dx,dy,d,UpIncre,DownIncre,x,y;
    if(x0<x1)
    {
        Swap(x0,x1);
        Swap(y0,y1);
    }
    x=x0; y=y0;
    dx=x1-x0;
    dy=y1-y0;
    d=dx-2*dy   //消除浮点运算
    UpIncre=2*dx-2*dy;
    DownIncre=-2*dy;
    while(x<=x1)
    {
        putpixel(x,y,color);
        x++;
        if(d<0)
        {
            y++;
            d+=UpIncre;
        }
        else
            d+=DownIncre;
    }
}

1.3 Bresenham算法

在误差项上进行替换

仍旧是0<k<1时的代码示例:

void BresenhamLine(int x0, int y0; int x1, int y1)
{
	int x, y, dx, dy, e;
	dx = x1 - x0;
	dy = y1 - y0;
	e = -dx;  x = x0; y = y0;
	while (x <= x1)
	{
		putpixel(x, y, color);
		x++;
		e = e + 2 * dy;
		if (e > 0)
		{
			y++;
			e = e - 2 * dx;
		}
	}
}

2. 圆的扫描转换

2.1 八分法画圆

只要扫描转换圆的八分之一即可根据圆的对称性画出整个圆。

八分法画圆程序(以原点为坐标):

void Circle(int x, int y, int color)
{
	putpixel(x, y, color);
	putpixel(-x, y, color);
	putpixel(x, -y, color);
	putpixel(-x, -y, color);
	putpixel(y, x, color);
	putpixel(-y, x, color);
	putpixel(y, -x, color);
	putpixel(-y, -x, color);
	
}

以任意点为原点时:

void Circle(int x0,int y0,int x, int y, int color)
{
	putpixel(x0+x, y0+y, color);
	putpixel(x0-x, y0+y, color);
	putpixel(x0+x, y0-y, color);
	putpixel(x0-x, y0-y, color);
	putpixel(y0+y, x0+x, color);
	putpixel(y0-y, x0+x, color);
	putpixel(y0+y, x0-x, color);
	putpixel(y0-y, x0-x, color);
	
}

2.2 中点Bresenham画圆算法

步骤如下:

① 输入圆的半径R

② 计算初始值 d=1-R, x=0, y=R

③ 绘制点(x,y)及其在八分圆中的另外7个对称点

④ 判断d的符号。若d<0,则先将d更新为d+2x+3,再将(x,y)更新为(x+1,y);否则,先将d更新为d+2(x-y)+5;再将(x,y)更新为(x+1.y-1)

⑤ 当x<y时,重复步骤③和④;否则结束。

代码如下:

void MidBresenhamCircle(int r, int color)
{
	int x, y, d;
	x = 0; y = r; d = 1 - r;
	while (x <= y)   //判断是否结束
	{
		Circle(x, y, color);//调用八分法画圆
		if (d < 0)
			d += 2 * x + 3;
		else
		{
			d += 2 * (x - y) + 5;
			y--;
		}
		x++;
	}
}

3. 椭圆的扫描转换

3.1 椭圆的中点Bresenham算法

与圆的扫描转换方法类似,但是需要判断切线的斜率

代码如下:

void Ellipse(int x, int y, int color)  //四分法画椭圆
{
	putpixel(x, y, color);
	putpixel(-x, y, color);
	putpixel(x, -y, color);
	putpixel(-x, -y, color);
}

void MidBresenhamEllipse(int a, int b, int color)
{
	int x, y;
	float d1, d2;
	x = 0; y = b;
	d1 = b * b + a * a * (-b + 0.25);
	Ellipse(x, y, color);   //调用四分法画圆
	while (b * b * (x + 1) < a * a * (y - 0.5))   //椭圆上半部分
	{
		if (d1 <= 0)
		{
			d1 += b * b * (2 * x + 3);
			x++;
		}
		else
		{
			d1 += b * b * (2 * x + 3) + a * a * (-2 * y + 2);
			x++;
			y--;
		}
		Ellipse(x, y, color);
	}
	//椭圆的下半部分
	d2 = b * b * (x + 0.5) * (x + 0.5) + a * a * (y - 1) * (y - 1) - a * a * b * b;
	while (y > 0)
	{
		if (d2 <= 0)
		{
			d2 += b * b * (2 * x + 2) + a * a * (-2 * y + 3);
			x++;
			y--;
		}
		else
		{
			d2 += a * a * (-2 * y + 3);
			y--;
		}
		Ellipse(x, y, color);
	}
}

 

  • 2
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆豆豆豆芽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值