这世界上有很多坑,注定有些坑是要填的。下面我就用VS2017使用MFC对这个课堂实验进行填坑。


一、实验目的

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

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

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

二、实验步骤

打开Visual Studio2017,文件->新建->项目,VC++/MFC/MFC应用程序,弹出设置框选择单文档,点击完成。

首先说一下目录结构,让大家对此有个清晰的了解:

           初始项目类结构                                                      项目最后的类结构

                                            

在添加函数和变量时,有两种规范的方式:

使用类视图的类向导,点击CLine类,右键菜单,类向导,这个方式一次性可添加CLine类的所有函数和变量。

②点击CLine类,右键菜单:添加->添加函数/添加变量,这个方式虽然要多次添加,但是可以添加注释。


步骤一:新建CLine类

代码如下:

CLine类

C

#pragma once
class CLine
{
public:
CLine();
virtual ~CLine();
private:
// 直线斜率
double m_k;
// 直线系数
double m_b;
//直线起点
CPoint m_start;
//直线终点
CPoint m_end; public:
// 隐函数F(x,y)=y-kx-b,计算误差项
double getDistance(double x,double y);
// 调用CDC对象的MoveTo(),移动到起点
void moveTo(CDC *&pDC);
// 使用直线扫描算法绘制直线
void lineTo(CDC *&pDC);
// 设置直线起点
void setStartPoint(CPoint point);
// 设置直线终点
void setEndPoint(CPoint point);
// 绘制直线斜率在0<k<1范围
void kOne(CDC *&pDC);
// 绘制直线斜率在k>1范围
void kTwo(CDC *&pDC);
// 绘制直线斜率在-1<k<0范围
void kThree(CDC *&pDC);
// 绘制直线斜率在k<-1范围
void kFour(CDC *&pDC);
};

Line.h

CLine类的方法的具体实现( 使用Bresenham 扫描转换算法)。

#include "stdafx.h"
#include "CLine.h" CLine::CLine()
{
} CLine::~CLine()
{
} // 隐函数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) == || (m_end.y - m_start.y) == ||
(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 ( < m_k && m_k < )
kOne(pDC);
else if (m_k > )
kTwo(pDC);
else if (- < m_k && m_k < )
kThree(pDC);
else if (m_k < -)
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 = ;
COLORREF color = RGB(, , ); //设置直线的颜色
CPoint next = m_start; //记录起始点
pDC->SetPixelV(next, color); //绘制起始点
for (int i = m_start.x + ; i <= m_end.x; i++)
{
next.x++; //以X轴为主位移方向
if (d <= ) //直线位于中点误差上方
next.y++; //取上面那个点
pDC->SetPixelV(next, color); //绘制点
d = getDistance((double)next.x + , 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 = ;
COLORREF color = RGB(, , );
CPoint next = m_start;
pDC->SetPixelV(next, color);
for (int i = m_start.y + ; i <= m_end.y; i++)
{
next.y++;
if (d > )
next.x++;
pDC->SetPixelV(next, color);
d = getDistance(next.x + 0.5, (double)next.y + );
}
} // 绘制直线斜率在-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 = ;
COLORREF color = RGB(, , );
CPoint next = m_start;
pDC->SetPixelV(next, color);
for (int i = m_start.x - ; i >= m_end.x; i--)
{
next.x--;
if (d < )
next.y++;
pDC->SetPixelV(next, color);
d = getDistance((double)next.x - , 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 = ;
COLORREF color = RGB(, , );
CPoint next = m_start;
pDC->SetPixelV(next, color);
for (int i = m_start.y - ; i >= m_end.y; i--)
{
next.y--;
if (d < )
next.x++;
pDC->SetPixelV(next, color);
d = getDistance(next.x + 0.5, (double)next.y - );
}
}

CLine.cpp


步骤二:MFCApplication1View视图类中用类向导添加消息的处理程序:

①当左键鼠标按钮按下时,记录直线起点位置      void OnLButtonDown(UINT nFlags, CPoint point)

②当左键鼠标按钮松开时,记录直线终点位置并绘制直线    void OnLButtonUp(UINT nFlags, CPoint point)

③当鼠标移动时,在窗口用户区显示鼠标的x坐标和y坐标    void OnMouseMove(UINT nFlags, CPoint point)

④ 添加CLine类为成员变量

添加后,显示如下:


步骤三:CMainFrame类中CMFCStatusBar状态栏控件更改为public成员变量。


步骤四:MFCApplication1View添加类的具体实现是方法。

MFCApplication1View如图位置添加代码,

代码如下:

//当左键鼠标按钮按下时,记录直线起点位置
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);
} //当鼠标移动时,在窗口用户区显示鼠标的x坐标和y坐标
void CMFCApplication1View::OnMouseMove(UINT nFlags, CPoint point)
{
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(, nFlags, SBPS_NORMAL, sizeX.cx);
pStatus->SetPaneText(, stringX);
pStatus->SetPaneInfo(, nFlags, SBPS_NORMAL, sizeY.cx);
pStatus->SetPaneText(, stringY); }
CView::OnMouseMove(nFlags, point);

CMainFrame类的消息处理程序

最后,点击本地Windows测试器运行程序,等待一段时间,这个坑就被填好了!

三、实验结果

运行后的实验结果如下:

①在空白Pane内可通过点击鼠标左键并移动鼠标松开左键的方式绘制直线

②右下角有显示鼠标的X坐标和Y坐标

图片1-1

实验一 绘制任意斜率的直线段 | 使用VS2017工具的更多相关文章

  1. [ACM_暴力][ACM_几何] ZOJ 1426 Counting Rectangles (水平竖直线段组成的矩形个数,暴力)

    Description We are given a figure consisting of only horizontal and vertical line segments. Our goal ...

  2. Liang-Barsky直线段裁剪算法

    Liang-Barsky直线段裁剪算法 梁友栋与Barsky提出的裁剪算法以直线的参数方程为基础,把判断直线段与窗口边界求交的 二维裁剪问题转化为求解一组不等式,确定直线段参数的一维裁剪问题.设起点为 ...

  3. [原创]K8_C段旁注查询工具5.0 30款国外主流CMS识别+智能识别未知CMS

    8_C段旁注查询工具V5.0 20161214作者:K8拉登哥哥 唯一QQ:396890445平台: Windows + .NET Framework 4.0 简介:K8_C段 提供4种方式查询子域名 ...

  4. 实验 1:Mininet 源码安装和可视化拓扑工具

    实验 1:Mininet 源码安装和可视化拓扑工具 一.实验目的 掌握 Mininet 的源码安装方法和 miniedit 可视化拓扑生成工具. 二.实验任务 使用源码安装 Mininet 的 2.3 ...

  5. Bresenham画直线,任意斜率

    function DrawLineBresenham(x1,y1,x2,y2) %sort by x,sure x1<x2. if x1>x2 tmp=x1; x1=x2; x2=tmp; ...

  6. 《图形学》实验三:DDA算法画直线

    开发环境: VC++6.0,OpenGL 实验内容: 使用DDA算法画直线. 实验结果: 代码: #include <gl/glut.h> #include <math.h> ...

  7. js调用百度地图接口绘制任意多边形并获取每个点的经纬度等

    来自:https://blog.csdn.net/u013239236/article/details/52213977 侵删 <!DOCTYPE html> <html> & ...

  8. [ActionScript 3.0] AS3 绘制任意三角形任意顶点到对边的高

    注:顶点坐标可以点击 package { import flash.display.Shape; import flash.display.Sprite; import flash.events.Mo ...

  9. 大厂前端工程师教你如何使用css3绘制任意角度扇形+动画

    这里只是做下原理解释,原理:使用两个半圆做角度拼接.比如想绘制一个缺口朝右,缺口弧度30度角的扇形 资源网站搜索大全https://55wd.com 那么将由一个旋转65度角的半圆A+一个旋转-65度 ...

随机推荐

  1. (备忘)Python字符串、元组、列表、字典互相转换的方法

    #1.字典 dict = {'name': 'Zara', 'age': 7, 'class': 'First'} #字典转为字符串,返回:<type 'str'> {'age': 7, ...

  2. 集合篇-----ArrayList与LinkedList之间的那些小事

    各自特性: ArrayList  : 是一由连续的内存块组成的数组,范围大小可变的,当不够时增加为原来1.5倍大小,数组. :调用trimToSize方法,使得存储区域的大小调整为当前元素数量所需要的 ...

  3. IDEA设置左侧边栏修改代码后变色

    首先声明,此功能是基于版本控制的,不管是基于git或者是svn, 都要有版本控制方可使用. 平常情况下,IDEA左边栏是没有颜色的,如下图所示 当我们修改了代码,左侧就会有颜色显示, 右侧滚动条处也有 ...

  4. 上传时excel类型accept的MIMI类型

    1.excel文件类型 accept='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/v ...

  5. 【CF1218E】Product Tuples

    题目大意:给定一个长度为 \(N\) 的序列,求从序列中选出 \(K\) 个数的集合乘积之和是多少. 题解: 由于是选出 \(K\) 个数字组成的集合,可知对于要计算的 \(K\) 元组来说是没有标号 ...

  6. DTcmsV4.0分析学习——(3)URL重写

    3.URL重写 3.1 控制流程 通过IHttpModule控制所有页面请求,具体流程如下 (1)真实路径可正常访问 (2)前台页面通过URL重写映射aspx目录,后台页面通过URL重写映射admin ...

  7. Apache、nginx 、lighttpd性能比较

    Apache.nginx .lighttpd性能比较 1. web服务器简介 1. lighttpd Lighttpd是一个德国人领导的开源软件,其根本的目的是提供一个专门针对高性能网站,安全.快速. ...

  8. add(expr|ele|html|obj[,con]) 把与表达式匹配的元素添加到jQuery对象中。

    add(expr|ele|html|obj[,con]) 概述 把与表达式匹配的元素添加到jQuery对象中.这个函数可以用于连接分别与两个表达式匹配的元素结果集. jQuery 1.4 中, .ad ...

  9. [51nod1666] 最大值

    题面 题解 毒瘤题浪费我大好青春 容易知道, 如果\(l\)和\(r\)位数不一样, 直接选形似\(99..99\)的数, 输出答案即可 \(l\)和\(r\)位数一样的话, 当位数确定的时候, 由于 ...

  10. log4j.properties log4j.xml 路径问题