这世界上有很多坑,注定有些坑是要填的。下面我就用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. 010.简单查询、分组统计查询、多表连接查询(sql实例)

    -------------------------------------day3------------ --添加多行数据:------INSERT [INTO] 表名 [(列的列表)] --SEL ...

  2. 洛谷 P2765 魔术球问题 (dinic求最大流,最小边覆盖)

    P2765 魔术球问题 题目描述 «问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2 ...

  3. golang docker kubernetes

    不断共建Golang生态.其中比较有代表性的Golang编写软件作品是Docker和Kubernetes.从目前Golang的发展时间和社区活跃度来看,Golang无疑是一门成功的编程语言.

  4. 《黑白团团》第九次团队作业:Beta冲刺与验收准备

    项目 内容 作业课程地址 任课教师首页链接 作业要求 团队项目 填写团队名称 黑白团团队 填写具体目标 认真负责,完成项目 GitHub链接 Scrum meeting导航 [Beta]Scrum m ...

  5. LNMP原理

    在linux系统中,LNMP是目前网站主流架构之一,LNMP中L指linux系统平台,N是nginx指网站的前端程序,发布静态页面和调用外部程序解析动态页面,M是mysql指网站的后台数据库,P是PH ...

  6. c#使用 NServiceKit.Redis 封装 RedisHelper

    在说StackExchange.Redis 的时候说了,因为我们的项目一直.net4.0不升级,没有办法,我说的不算,哈哈,又查了StackExchange.Redis在.net4.0使用麻烦,所以选 ...

  7. Hive启动报错Terminal initialization failed; falling back to unsupported java.lang.Incomp

    这个报错需要删除hadoop目录下,需要删除下面目录下的文件,重启hadoop和hive即可 $HADOOP_HOME/share/hadoop/yarn/lib/jline-0.9.94.jar

  8. java实现简单的单点登录 (转)

    摘要:单点登录(SSO)的技术被越来越广泛地运用到各个领域的软件系统当中.本文从业务的角度分析了单点登录的需求和应用领域:从技术本身的角度分析了单点登录技术的内部机制和实现手段,并且给出Web-SSO ...

  9. vue中使用v-chart改变柱状图颜色以及X轴Y轴的文字颜色和大小以及标题

    1.html部分 <ve-histogram :tooltip-visible="true" :x-axis="xAxis" :y-axis=" ...

  10. PHP mysqli_kill() 函数

    定义和用法 mysqli_kill() 函数请求服务器杀死一个由 processid 参数指定的 MySQL 线程. 语法 mysqli_kill(connection,processid);   实 ...