欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

计算机图形学实验一绘制任意斜率的直线段

程序员文章站 2022-03-22 16:24:52
...

一、实验目的

(1)掌握任意斜率直线段的重点 Bresenham 扫描转换算法;

(2)掌握 Cline 直线类的设计方法;

(3)掌握状态栏编程方法。

二、实验步骤

(1)创建MFC应用程序

(2)定义CLine类

计算机图形学实验一绘制任意斜率的直线段计算机图形学实验一绘制任意斜率的直线段

 

  1. 添加消息处理的处理程序

计算机图形学实验一绘制任意斜率的直线段

 

三、实验结果

计算机图形学实验一绘制任意斜率的直线段

 

四、实验体会

在本次实验中,通过不断的探索和实践,我学会了如何创建一个MFC应用程序,将理论运用于实践,掌握了直线类的设计方法,学会了如何绘制任意斜率的方法,虽然过程很艰辛,遇到了许多困难,但是最终通过不断的努力将实验完成了,收获良多。

附录:源代码

 

 CLine.cpp
// 隐函数F(x,y)=y-kx-b,计算误差项
double CLine::getDistance(double x, double y)
{
	return y - m_k * x - m_b;
}


// 调用CDC对象的MoveTo(),移动到起点
void CLine::moveTo(CDC *&pDC)
{
	pDC->MoveTo(m_start);
}


// 使用直线扫描算法绘制直线
void CLine::lineTo(CDC *&pDC)
{
	//如果直线为垂线或是平行线或是k=1的直线
	if ((m_end.x - m_start.x) == 0 || (m_end.y - m_start.y) == 0 ||
		(m_end.x - m_start.x) == (m_end.y - m_end.y) ||
		(m_end.x - m_start.x) == -(m_end.y - m_end.y))
		pDC->LineTo(m_end);
	else
	{
		m_k = ((double)(m_end.y - m_start.y)) / (m_end.x - m_start.x);
		m_b = m_start.y - m_k * m_start.x;
		if (0 < m_k && m_k < 1)
			kOne(pDC);
		else if (m_k > 1)
			kTwo(pDC);
		else if (-1 < m_k && m_k < 0)
			kThree(pDC);
		else if (m_k < -1)
			kFour(pDC);
	}
}


// 设置直线起点
void CLine::setStartPoint(CPoint point)
{
	this->m_end = point;
}


// 设置直线终点
void CLine::setEndPoint(CPoint point)
{
	this->m_start = point;
}


// 绘制直线斜率在0<k<1范围
void CLine::kOne(CDC *&pDC)
{
	//始终保持起点X坐标小于Y坐标
	if (m_start.x > m_end.x)
	{
		CPoint tmp = m_start;
		m_start = m_end;
		m_end = tmp;
	}
	double d = 0;
	COLORREF color = RGB(0, 0, 0);    //设置直线的颜色
	CPoint next = m_start;  //记录起始点
	pDC->SetPixelV(next, color);    //绘制起始点
	for (int i = m_start.x + 1; i <= m_end.x; i++)
	{
		next.x++;    //以X轴为主位移方向
		if (d <= 0)    //直线位于中点误差上方
			next.y++;    //取上面那个点
		pDC->SetPixelV(next, color);    //绘制点
		d = getDistance((double)next.x + 1, next.y + 0.5);    //下一个中点
	}
}


// 绘制直线斜率在k>1范围
void CLine::kTwo(CDC *&pDC)
{
	if (m_start.y > m_end.y)
	{
		CPoint tmp = m_start;
		m_start = m_end;
		m_end = tmp;
	}
	double d = 0;
	COLORREF color = RGB(0, 0, 0);
	CPoint next = m_start;
	pDC->SetPixelV(next, color);
	for (int i = m_start.y + 1; i <= m_end.y; i++)
	{
		next.y++;
		if (d > 0)
			next.x++;
		pDC->SetPixelV(next, color);
		d = getDistance(next.x + 0.5, (double)next.y + 1);
	}
}


// 绘制直线斜率在-1<k<0范围
void CLine::kThree(CDC *&pDC)
{
	if (m_start.x < m_end.x)
	{
		CPoint temp = m_start;
		m_start = m_end;
		m_end = temp;
	}
	double d = 0;
	COLORREF color = RGB(0, 0, 0);
	CPoint next = m_start;
	pDC->SetPixelV(next, color);
	for (int i = m_start.x - 1; i >= m_end.x; i--)
	{
		next.x--;
		if (d < 0)
			next.y++;
		pDC->SetPixelV(next, color);
		d = getDistance((double)next.x - 1, next.y + 0.5);
	}
}


// 绘制直线斜率在k<-1范围
void CLine::kFour(CDC *&pDC)
{
	if (m_start.y < m_end.y)
	{
		CPoint tmp = m_start;
		m_start = m_end;
		m_end = tmp;
	}
	double d = 0;
	COLORREF color = RGB(0, 0, 0);
	CPoint next = m_start;
	pDC->SetPixelV(next, color);
	for (int i = m_start.y - 1; i >= m_end.y; i--)
	{
		next.y--;
		if (d < 0)
			next.x++;
		pDC->SetPixelV(next, color);
		d = getDistance(next.x + 0.5, (double)next.y - 1);
	}
}
消息处理程序:
鼠标左键按下
鼠标左键松开
鼠标移动时显示坐标:
void CMFCApplication1View::OnLButtonDown(UINT nFlags, CPoint point)
{
	// 鼠标按下记录起点
	this->line.setStartPoint(point);
	CView::OnLButtonDown(nFlags, point);
}


void CMFCApplication1View::OnLButtonUp(UINT nFlags, CPoint point)
{
	// 鼠标松开记录终点
	this->line.setEndPoint(point);
	CDC *pDC = GetDC();
	this->line.moveTo(pDC);
	this->line.lineTo(pDC);
	CView::OnLButtonUp(nFlags, point);
}


void CMFCApplication1View::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CString stringX, stringY;
	CMainFrame * pFrame = (CMainFrame *)AfxGetMainWnd();
	CMFCStatusBar * pStatus = &pFrame->m_wndStatusBar;
	if (pStatus != NULL)
	{
		//_T是一个宏,作用是让你的程序支持Unicode编码(双字节编码)
		stringX.Format(_T("x=%d"), point.x);
		stringY.Format(_T("y=%d"), point.y);

		CClientDC dc(this);
		CSize sizeX = dc.GetTextExtent(stringX);
		CSize sizeY = dc.GetTextExtent(stringY);
		pStatus->SetPaneInfo(1, nFlags, SBPS_NORMAL, sizeX.cx);
		pStatus->SetPaneText(1, stringX);
		pStatus->SetPaneInfo(2, nFlags, SBPS_NORMAL, sizeY.cx);
		pStatus->SetPaneText(2, stringY);

	}
	CView::OnMouseMove(nFlags, point);
}