实验一 绘制任意斜率的直线段 | 使用VS2017工具
这世界上有很多坑,注定有些坑是要填的。下面我就用VS2017使用MFC对这个课堂实验进行填坑。
一、实验目的
(1)掌握任意斜率直线段的重点 Bresenham 扫描转换算法;
(2)掌握 Cline 直线类的设计方法;
(3)掌握状态栏编程方法。
二、实验步骤
打开Visual Studio2017,文件->新建->项目,VC++/MFC/MFC应用程序,弹出设置框选择单文档,点击完成。
首先说一下目录结构,让大家对此有个清晰的了解:
初始项目类结构 项目最后的类结构
在添加函数和变量时,有两种规范的方式:
①使用类视图的类向导,点击CLine类,右键菜单,类向导,这个方式一次性可添加CLine类的所有函数和变量。
②点击CLine类,右键菜单:添加->添加函数/添加变量,这个方式虽然要多次添加,但是可以添加注释。
步骤一:新建CLine类:
代码如下:
CLine类
#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工具的更多相关文章
- [ACM_暴力][ACM_几何] ZOJ 1426 Counting Rectangles (水平竖直线段组成的矩形个数,暴力)
Description We are given a figure consisting of only horizontal and vertical line segments. Our goal ...
- Liang-Barsky直线段裁剪算法
Liang-Barsky直线段裁剪算法 梁友栋与Barsky提出的裁剪算法以直线的参数方程为基础,把判断直线段与窗口边界求交的 二维裁剪问题转化为求解一组不等式,确定直线段参数的一维裁剪问题.设起点为 ...
- [原创]K8_C段旁注查询工具5.0 30款国外主流CMS识别+智能识别未知CMS
8_C段旁注查询工具V5.0 20161214作者:K8拉登哥哥 唯一QQ:396890445平台: Windows + .NET Framework 4.0 简介:K8_C段 提供4种方式查询子域名 ...
- 实验 1:Mininet 源码安装和可视化拓扑工具
实验 1:Mininet 源码安装和可视化拓扑工具 一.实验目的 掌握 Mininet 的源码安装方法和 miniedit 可视化拓扑生成工具. 二.实验任务 使用源码安装 Mininet 的 2.3 ...
- Bresenham画直线,任意斜率
function DrawLineBresenham(x1,y1,x2,y2) %sort by x,sure x1<x2. if x1>x2 tmp=x1; x1=x2; x2=tmp; ...
- 《图形学》实验三:DDA算法画直线
开发环境: VC++6.0,OpenGL 实验内容: 使用DDA算法画直线. 实验结果: 代码: #include <gl/glut.h> #include <math.h> ...
- js调用百度地图接口绘制任意多边形并获取每个点的经纬度等
来自:https://blog.csdn.net/u013239236/article/details/52213977 侵删 <!DOCTYPE html> <html> & ...
- [ActionScript 3.0] AS3 绘制任意三角形任意顶点到对边的高
注:顶点坐标可以点击 package { import flash.display.Shape; import flash.display.Sprite; import flash.events.Mo ...
- 大厂前端工程师教你如何使用css3绘制任意角度扇形+动画
这里只是做下原理解释,原理:使用两个半圆做角度拼接.比如想绘制一个缺口朝右,缺口弧度30度角的扇形 资源网站搜索大全https://55wd.com 那么将由一个旋转65度角的半圆A+一个旋转-65度 ...
随机推荐
- Centos7安装dig命令
作者: jwj 时间: 2018-10-17 分类: 服务器 最近做一个项目,需要用到Gmail邮箱发送邮件,但发现发送不出去.排查问题时,需要用到dig命令,但使用时,却提醒我dig命令不存在~那就 ...
- DNSMASQ 部分选项 设置
--local-service 仅接受地址位于本地子网上的主机(即服务器上存在接口的子网)的DNS查询.仅当没有--interface,-- except-interface,--listen-add ...
- Collection 和 Collections 有什么区别?(未完成)
Collection 和 Collections 有什么区别?(未完成)
- 说说lock到底锁谁(II)?
摘要 今天在园子里面有园友反馈关于[C#基础]说说lock到底锁谁?文章中lock(this)的问题.后来针对文章中的例子,仔细想了一下,确实不准确,才有了这篇文章的补充,已经对文章中的demo进行修 ...
- python+Appium自动化:元素等待时间
元素等待时间 为什么要设置等待时间呢?主要是因为界面加载时,为了防止元素还未出现影响后续的操作. 主要有三种方式:强制(线性)等待.隐式等待.显式等待 适用于appium和selenium 强制(线性 ...
- Oracle中dual表的用途
dual是一个虚拟表,用来构成select的语法规则,oracle保证dual里面永远只有一条记录.我们可以用它来做很多事情,如下: 1.查看当前用户,可以在 SQL Plus中执行下面语句 sele ...
- 在laravel5.8中集成swoole组件----用协程实现的服务端和客户端(nginx配置篇章)
laravel项目中的配置 原文出处:https://laravelacademy.org/post/19700.html,感谢原文作者让laravel这款可爱的php框架,进入了高并发的殿堂 如果 ...
- 题解 [BZOJ4368][IOI2015]boxes纪念品盒
题面 解析 可以发现,发纪念品有三种方式: 从左边走再原路返回. 从右边走再原路返回. 走一圈. 注意到,第三种走法最多只会走一次, 因为如果走了多次,那发放的物品数量就会>=\(2k\), 那 ...
- 简单了解学习PHP(针对前端开发)
1.服务器(服务器系统) 通常是指较强的计算能力能够同时服务多人的计算机 常见的服务器操作系统: 1.各个版本的Linux操作系统 2.乌班图.centos 3.mac os(苹果) 4.windo ...
- Java基础知识学习01
0 项目,包,文件,类 Mytest是自己建的java工程,包含src和JRE System Libery.其中src是存放自己的代码的地方,JRE包含程序运行时所需要的各种文件:在src下包含Tes ...