计算机图形学作业:中点画线法和 Bresenham 法绘制直线

作业要求:

1. 请采用中点画线法和 Bresenham 法绘制直线(共100 分)。

要求: (1) 给出每种算法的文字描述(共 50 分,每种算法各 25 分)。 (2) 编写函数,在给定起点和终点的情况下,计算出直线上 其它的点,并将这些点存储在数组中(共 50 分,每个函数各 25 分)。

中点画线法

一、算法的文字描述

首先需要根据直线段的斜率k,除了斜率不存在的情况(该情况直线可以直接画出)将直线划分为k>1、0<=k<=1、-1<=k<0、k<-1 四种情况,当0<=k<=1、-1<=k<0时,x方向为主位移方向;k>1、k<-1时,y方向为主位移方向。

以下做分类说明:

 

1.在0<=k<=1时的中点画线算法:

  1. 输入直线的起点(x1,y1),(x2,y2)
  2. 初始化,计算出dx=x2-x1,dy=y2-y1,d=dx-2dy,x=x1,y=y1,deta1=-2dy,deta2=2dx-2dy。
  3. 将点(x,y)存入数组
  4. 判断x是否小于x2,如果x<x2,执行步骤(5),否则算法结束
  5. 如果d<0,则x=x+1,y=y+1,d=d+deta2;否则x=x+1,y不变,d=d+deta1
  6. 将点(x,y)存入数组,并转入步骤(4)

 

2.在-1<=k<0时的中点画线算法:

  1. 输入直线的起点(x1,y1),(x2,y2)
  2. 初始化,计算出dx=x2-x1,dy=y2-y1,d=-dx-2dy,x=x1,y=y1,deta1=-2dy,deta2=-2dx-2dy。
  3. 将点(x,y)存入数组
  4. 判断x是否小于x2,如果x<x2,执行步骤(5),否则算法结束
  5. 如果d>=0,则x=x+1,y=y-1,d=d+deta2;否则x=x+1,y不变,d=d+deta1
  6. 将点(x,y)存入数组,并转入步骤(4)

 

3.在k>1时的中点画线算法:

  1. 输入直线的起点(x1,y1),(x2,y2)
  2. 初始化,计算出dx=x2-x1,dy=y2-y1,d=2dx-dy,x=x1,y=y1,deta1=2dx,deta2=2dx-2dy。
  3. 将点(x,y)存入数组
  4. 判断y是否小于y2,如果y<y2,执行步骤(5),否则算法结束
  5. 如果d>=0,则y=y+1,x=x+1,d=d+deta2;否则y=y+1,x不变,d=d+deta1
  6. 将点(x,y)存入数组,并转入步骤(4)

 

 

4.在k<-1时的中点画线算法:

  1. 输入直线的起点(x1,y1),(x2,y2)
  2. 初始化,计算出dx=x2-x1,dy=y2-y1,d=2dx+dy,x=x1,y=y1,deta1=2dx,deta2=2dx+2dy。
  3. 将点(x,y)存入数组
  4. 判断y是否小于y2,如果y<y2,执行步骤(5),否则算法结束
  5. 如果d<0,则y=y+1,x=x-1,d=d+deta2;否则y=y+1,x不变,d=d+deta1
  6. 将点(x,y)存入数组,并转入步骤(4)

 

二 、编写函数,在给定起点和终点的情况下,计算出直线上其它的点,并将这些点存储在数组中

 

 

void  MidLine(int x1, int y1, int x2, int y2)

{

        linepoint linepoints[N]; int i{0};double k{ 0 };

        int dx, dy, d, Deta1, Deta2, x, y;

        if (x1 != x2) k = (1.0 * y2 - y1) / (x2 - x1);

        if ((x1 > x2 && abs(k) <= 1)||(y1 > y2 && abs(k) > 1))

        {

                x = x2; x2 = x1; x1 = x; y = y2; y2 = y1; y1 = y;

        }

//初始化

        x = x1; y = y1;dx = x2 - x1; dy = y2 - y1;

   

        if (k >= 0 && k <= 1)

        {

                Deta1 = -2 * dy ; Deta2 = 2 * dx - 2 * dy; d = dx - 2 * dy;

                while (x < x2)

                {

                        linepoints[i].x = x; linepoints[i++].y = y;

                        x++;

                        if (d < 0)

                        {

                                y++;d += Deta2;

                        }

                        else

                                d += Deta1;

                }

        }

 

else if (k <= 0 && k >= -1)

        {

                Deta1 = -2 * dy; Deta2 = -2 * dx - 2 * dy; d = -dx - 2 * dy;

                while (x < x2)

                {

                        linepoints[i].x = x; linepoints[i++].y = y;

                        x++;

                        if (d >= 0)

                        {

                                y--;d += Deta2;

                        }

                        else

                                d += Deta1;

                }

        }

        else if (k > 1)

        {

                Deta1 = 2 * dx; Deta2 = 2 * dx - 2 * dy; d = 2 * dx - dy;

                while (y < y2)

                {

                        linepoints[i].x = x; linepoints[i++].y = y;

                        y++;

                        if (d >= 0)

                        {

                                x++;d += Deta2;

                        }

                        else

                                d += Deta1;

                }

        }

        else

        {

                Deta1 = 2 * dx; Deta2 = 2 * dx + 2 * dy; d = 2 * dx + dy;

                while (y < y2)

                {

                        linepoints[i].x = x; linepoints[i++].y = y;

                        y++;

                        if (d <0)

                        {

                                x--;d += Deta2;

                        }

                        else

                                d += Deta1;

                }

        }

}

 

Bresenham

一、算法的文字描述

同样地,需要分为k>1、0<=k<=1、-1<=k<0、k<-1 四种情况,当0<=k<=1、-1<=k<0时,x方向为主位移方向;k>1、k<-1时,y方向为主位移方向。e的值用2e∆x的形式。

 

以下做分类说明: 

 

1.在0<=k<=1时的中点画线算法:

  1. 输入直线的起点(x1,y1),(x2,y2)
  2. 初始化,计算出dx=x2-x1,dy=y2-y1,e=2dy-dx,x=x1,y=y1,deta1=2dy,deta2=2dy-2dx。
  3. 将点(x,y)存入数组
  4. 判断x是否小于x2,如果x<x2,执行步骤(5),否则算法结束
  5. 如果e<0,则x=x+1,e=e+deta1;否则x=x+1,y=y+1,e=e+deta2
  6. 将点(x,y)存入数组,并转入步骤(4)

 

2.在-1<=k<0时的中点画线算法:

  1. 输入直线的起点(x1,y1),(x2,y2)
  2. 初始化,计算出dx=x2-x1,dy=y2-y1,e=-dx-2dy,x=x1,y=y1,deta1=-2dy,deta2=-2dx-2dy。
  3. 将点(x,y)存入数组
  4. 判断x是否小于x2,如果x<x2,执行步骤(5),否则算法结束
  5. 如果e>=0,则x=x+1,y=y-1,e=e+deta2;否则x=x+1,y不变,e=e+deta1
  6. 将点(x,y)存入数组,并转入步骤(4)

 

3.在k>1时的中点画线算法:

  1. 输入直线的起点(x1,y1),(x2,y2)
  2. 初始化,计算出dx=x2-x1,dy=y2-y1,e=2dx-dy,x=x1,y=y1,deta1=2dx,deta2=2dx-2dy。
  3. 将点(x,y)存入数组
  4. 判断y是否小于y2,如果y<y2,执行步骤(5),否则算法结束
  5. 如果e>=0,则y=y+1,x=x+1,e=e+deta2;否则y=y+1,x不变,e=e+deta1
  6. 将点(x,y)存入数组,并转入步骤(4)

 

 

4.在k<-1时的中点画线算法:

  1. 输入直线的起点(x1,y1),(x2,y2)
  2. 初始化,计算出dx=x2-x1,dy=y2-y1,e=-2dx-dy,x=x1,y=y1,deta1=-2dx,deta2=-2dx-2dy。
  3. 将点(x,y)存入数组
  4. 判断y是否小于y2,如果y<y2,执行步骤(5),否则算法结束
  5. 如果e>=0,则y=y+1,x=x-1,e=e+deta2;否则y=y+1,x不变,e=e+deta1
  6. 将点(x,y)存入数组,并转入步骤(4)

 

可看出计算误差e时,|k|>1和|k|<1的计算公式仅是dx和dy交换的结果。且|k|>1的两种情况和|k|<1的两种情况的误差及误差增量计算实际上是分别相同的。|k|<1时,e初值为2|dy|-|dx|,e<0时增量为2|dy|,反之是2|dy|-2|dx|。|k|>1时做相应的dx和dy交换即可。

 

二、编写函数,在给定起点和终点的情况下,计算出直线上其它的点,并将这些点存储在数组 

 

void  BresenhamLine(int x0, int y0, int x1, int y1)
{
	linepoint linepoints[N]; int i{0}; double k{0};int dx, dy, e{0},x, y;
	if(x0!=x1) k = (1.0 * y1 - y0) / (x1 - x0);
	if (x0 > x1&&abs(k)>0&&abs(k)<=1)
	{
		x = x1; x1 = x0; x0 = x;y = y1; y1 = y0; y0 = y;
	}
	else if (y0 > y1 &&  abs(k) > 1)
	{
		x = x1; x1 = x0; x0 = x;y = y1; y1 = y0; y0 = y;
	}
	x = x0; y = y0;dx = abs(x1 - x0); dy = abs(y1 - y0);
if (abs(k) <= 1)
	{
		while(x<x1)
		{
			e = 2 * dy - dx;
			linepoints[i].x = x; linepoints[i++].y = y;
			x++;
			if (e < 0)
				e += 2 * dy;
else
			{
				if (y1 > y0)   y++;
				else        y--;
				e += 2 * dy - 2 * dx;

}
		}
	}
	else
	{
		while(y<y1)
		{
		e = 2 * dx - dy;
		linepoints[i].x = x; linepoints[i++].y = y;
		y++;
		if (e < 0)
			e += 2 * dx;
		else
		{
			if (x1 > x0)   x++;
			else        x--;
			e += 2 * dx - 2 * dy;
		}
		}
	}
}

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

guts350

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

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

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

打赏作者

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

抵扣说明:

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

余额充值