三种直线扫描转化算法简单比较

三种直线扫描转换算法简单比较(0<k<1)

数值微分法(DDA):

代码实现:
void DDALine(int x0, int y0, int x1, int y1, int color) {
	int x;
	float dx, dy, y, k;
	dx = x1 - x0, dy = y1 - y0;
	k = dy / dx;//求k
    y = y0;
	for (x = x0; x < x1; x++) {
		putpixel(x, (int)(y + 0.5), color);
		y = y + k;
	}
}

中点画线法:

代码实现:
void MidPointLine(int x0, int y0, int x1, int y1, int color) {
	int a, b, d1, d2, d, x, y;
	a = y0 - y1, b = x1 - x0, d = 2 * a + b;
	d1 = 2 * a, d2 = 2 * (a + b);
	x = x0, y = y0;
	putpixel(x, y, color);
	while (x < x1) {
		if (d < 0) {
			x++, y++, d += d2;
		}else {
			x++, d += d1;
		}
		putpixel(x, y, color);
	}
}

Bresenham算法:

代码实现:
void BresenhamLine(int x0, int y0, int x1, int y1, int color) {
	int x, y;
	float dx, dy;
	float k, e;
	dx = x1 - x0;
	dy = y1 - y0;
	k = dy / dx;
	e = -0.5, x = x0, y = y0;
	for (int i = 0; i < dx; i++) {
		putpixel(x,y,color);
		x++, e = e + k;
		if (e >= 0) {
			y++;
			e = e - 1;
		}
	}
}

三种算法比较

时间花费:

测试代码:(测试说明:连续画500条线)

#include<graphics.h>
#include<conio.h>
#include<iostream>
#include<time.h>
#include<stdlib.h>
void main() {
	initgraph(900, 900);//创建窗口
	setbkcolor(GREEN);
	clock_t startTime, endTime;//开始时间
	startTime = clock();
	int x = 200, y = 100;//初始点
	for (int i = 0; i < 500; i++) {
		DDALine(0, 0, x++, y++, RED);
        //MidPointLine(0, 0, x++, y++, RED);
		//BresenhamLine(0, 0, x++, y++, RED);
	}
	endTime = clock();
	cout << "DDA running time:" << endTime - startTime << endl;//结束时间
	_getch();
	closegraph();
}

结果:

在这里插入图片描述

结果三种算法时间分别为:

DDA中点画线Bresenham
时间(clock_t)438438435

可知三种算法在时间花费上十分接近

与理想直线误差:

通过测试实际点与理论点的差距来判断:

测试代码:

float result2 = DDALine(0, 763, 2804, 1804, RED, 0);
float result3 = MidPointLine(0, 763, 2804, 1804, RED, 0);
float result4 = BresenhamLine(0, 763, 2804, 1804, RED, 0);
cout << "DDA 误差为:" << result2<< endl;
cout << "MidPoint 误差为:" << result3 << endl;
cout << "Bresenham 误差为:" << result4 << endl;

//计算与理想点差距
	//DDA
	error += absf((int)(y + 0.5) - ((y1 - k * x1) + k * x));
	error/(x1 - x0);
	//MidPoint和Bresenham
	error += absf(y - ((y1 - k * x1) + k * x));
	error/(x1 - x0);

结果:

在这里插入图片描述

结果解释:

DDA算法与MidPoint和Bresenham两个的画直线方法思想不同,

DDA是y每次递增k,并加上0.5向下取整

而MidPoint和Bresenham算法是判断右边点和右上点哪一个更为接近理想点,所以最后效果两者是一样的,故误差也一样。

DDA的误差之所以大一些,是因为对于下一个要画的点,它并不是与理想点比较,而是在上一个点的基础上选择下一个点,而只有第一个点是理想点,所以随着点数的增大,误差越来越大。

对DDA算法所以随着点数的增大,误差越来越大的验证:

验证代码:

	for (int i = 1; i <= 30; i++) {
		float result = DDALine(0, 763+i*200, 3804+i*200, 1804+i*200, RED, 0);
		cout << "第" << i << "次结果 ";
		cout << "DDA 误差为:" << result << endl;
	}

结果:

在这里插入图片描述

整体上误差是越来越大。

再看一下其他两种算法:

代码

	for (int i = 1; i <= 30; i++) {
		float result1 = MidPointLine(0, 763+i*200, 3804+i*200, 1804+i*200, RED, 0);
		float result2 = BresenhamLine(0, 763 + i * 200, 3804 + i * 200, 1804 + i * 200, RED, 0);
		cout << "第" << i << "次结果 ";
		cout << "MidPoint 误差为:" << result1 << " ";
		cout << "Bresenham 误差为:" << result1 << endl;
	}

结果:

在这里插入图片描述

基本趋近于0.25

比较结论:

三种算法时间花费上基本一致,但其中DDA不利于硬件实现。

在误差分析上,DDA随着点数增大,有误差越来越大的趋势,而MidPoint和Bresenham平均误差为0.25,且不会随点数增大而增大。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值