计算机图形学——直线扫描转换(中点Bresenham扫描转换算法)

直线扫描转换

一、实验目的

1、 掌握直线段的重点Bresenham扫描转换算法;
2、 掌握直线绘制类的设计实现;
3、 掌握菱形图形的生成方法。

二、实验要求

1、 直线绘制通过设计类似MFC的直线绘制类来实现,有类似的MoveTo()函数设置直线段起点,LineTo()函数设置直线段终点并完成绘制,还要有直线段颜色设置函数;
2、 直线的绘制采用中点Bresenham扫描转换算法进行实现,根据直线斜率k的范围区分5种不同的情况处理;
3、 调用设计实现的直线绘制类,在视觉区绘制如下图2-3所示的菱形线框,并要求每条边的颜色不同。

三、详细设计

1、创建MFC应用程序框架

项目名称:Test
新建源文件:Line.cpp
新建头文件:Line.h

2、设计实现直线绘制类

(1)实验原理

使用中点扫描转换算法进行直线绘制,需要根据斜率k值分别选择不同的误差项和初始值,除垂线外(k = +∞),可分为k < -1,-1 <= k < 0,0 <= k <= 1,k > 1四种情况,对于k = +∞,可直接画出垂线;-1 <= k < 0,0 <= k <= 1时,X轴方向为主移动方向;k < -1,k > 1时,Y轴方向为主移动方向。

(2)"Line.h"头文件具体代码
#pragma once
class CP2
{
public:
	CP2();
	virtual~CP2();
	CP2(double, double);
public:
	double x;
	double y;
};
 
class CLine
{
public:
	CLine();
	virtual~CLine();
	void SetLineColor(COLORREF);
	void MoveTo(CP2);
	void MoveTo(double, double);
	void LineTo(CP2, CDC*);
	void LineTo(double, double, CDC*);
public:
	CP2 P0;
	CP2 P1;
	COLORREF clr;
};
 
(3)"Line.cpp"源文件具体代码
#include"pch.h"
#include"Line.h"
#include"math.h"
#define Round(d) int(floor(d+0.5))
 
CP2::CP2()
{
	x = 0.0;
	y = 0.0;
};
 
CP2::~CP2()
{}
 
CP2::CP2(double x, double y)
{
	this->x = x;
	this->y = y;
};
 
CLine::CLine()
{}
 
CLine::~CLine()
{}
 
void CLine::SetLineColor(COLORREF color)
{
	clr = color;
}
void CLine::MoveTo(CP2 p0)
{
	P0 = p0;
}
void CLine::MoveTo(double x, double y)
{
	P0.x = x;
	P0.y = y;
}
void CLine::LineTo(double x, double y, CDC* pDC)
{
	CP2 p;
	p.x = x;
	p.y = y;
 
 
	LineTo(p, pDC);
}
void CLine::LineTo(CP2 p1, CDC* pDC)
{
	P1 = p1;
	CP2 p, t;
	if (fabs(P0.x - P1.x) < 1e-6)
	{
		if (P0.y > P1.y)
		{
			t = P0; P0 = P1; P1 = t;
		}
		for (p = P0; p.y < P1.y; p.y++)
		{
			pDC->SetPixelV(Round(p.x), Round(p.y), clr);
		}
	}
	else
	{
		double k, d;
		k = (P1.y - P0.y) / (P1.x - P0.x);
		if (k > 1.0)
		{
			if (P0.y > P1.y)
			{
				t = P0; P0 = P1; P1 = t;
			}
			d = 1 - 0.5 * k;
			for (p = P0; p.y < P1.y; p.y++)
			{
				pDC->SetPixelV(Round(p.x), Round(p.y), clr);
				if (d >= 0)
				{
					p.x++;
					d += 1 - k;
				}
				else
					d += 1;
			}
		}
		if (0.0 <= k && k <= 1.0)
		{
			if (P0.x > P1.x)
			{
				t = P0; P0 = P1; P1 = t;
			}
			d = 0.5 - k;
			for (p = P0; p.x < P1.x; p.x++)
			{
				pDC->SetPixelV(Round(p.x), Round(p.y), clr);
				if (d < 0)
				{
					p.y++;
					d += 1 - k;
				}
				else
					d -= k;
			}
		}
 
 
		if (k >= -1.0 && k < 0.0)
		{
			if (P0.x > P1.x)
			{
				t = P0; P0 = P1; P1 = t;
			}
			d = -0.5 - k;
			for (p = P0; p.x < P1.x; p.x++)
			{
				pDC->SetPixelV(Round(p.x), Round(p.y), clr);
				if (d > 0)
				{
					p.y--;
					d -= 1 + k;
				}
				else
					d -= k;
			}
		}
		if (k < -1.0)
		{
			if (P0.y > P1.y)
			{
				t = P0; P0 = P1; P1 = t;
			}
			d = -1 - 0.5 * k;
			for (p = P0; p.y > P1.y; p.y--)
			{
				pDC->SetPixelV(Round(p.x), Round(p.y), clr);
				if (d < 0)
				{
					p.x++;
					d -= 1 + k;
				}
				else
					d -= 1;
			}
		}
	}
	P0 = p1;
}
(4)调用直线类绘制菱形线框图

在CTestView::OnDraw()函数中进行菱形ABCD线框图的绘制,只需要调用四次CLine类对象,分别AB,BC,CD,DA四条边,每条边需要设置两个顶点坐标和颜色即可,具体代码如下:

void CTestView::OnDraw(CDC* pDC)
{
	CTestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
 
	// TODO: 在此处为本机数据添加绘制代码
	CRect rect;
	GetClientRect(&rect);
	pDC->SetMapMode(MM_ANISOTROPIC);
	pDC->SetWindowExt(rect.Width(), rect.Height());
	pDC->SetViewportExt(rect.Width(), -rect.Height());
	pDC->SetViewportOrg(rect.Width() / 2, rect.Height() / 2);
	rect.OffsetRect(-rect.Width() / 2, -rect.Height() / 2);
 
	CLine* line = new CLine;
	line->SetLineColor(RGB(0, 0, 0));
	line->MoveTo(CP2(-rect.Width() / 2, 0));
	line->LineTo(CP2(rect.Width() / 2, 0), pDC);
	line->MoveTo(CP2(0, -rect.Height() / 2));
	line->LineTo(CP2(0, rect.Height() / 2), pDC);
 
	int a = 200;
	CP2 A(0, a);
	CP2 B(a, 0);
	CP2 C(0, -a);
	CP2 D(-a, 0);
 
	line->SetLineColor(RGB(255, 0, 0));
	line->MoveTo(A);
	line->LineTo(B, pDC);
 
	line->SetLineColor(RGB(0, 255, 0));
	line->LineTo(C, pDC);
 
	line->SetLineColor(RGB(0, 0, 255));
	line->LineTo(D, pDC);
 
	line->SetLineColor(RGB(255, 255, 0));
	line->LineTo(A, pDC);
 
	delete line;
 
}

文件总样式:
在这里插入图片描述

四、运行结果

在这里插入图片描述

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值