这世界上有很多坑,注定有些坑是要填的。下面我就用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. 轻量化模型之MobileNet系列

    自 2012 年 AlexNet 以来,卷积神经网络在图像分类.目标检测.语义分割等领域获得广泛应用.随着性能要求越来越高,AlexNet 已经无法满足大家的需求,于是乎各路大牛纷纷提出性能更优越的 ...

  2. 前端基础(八):Font Awesome(图标)

    一.font awesome简介 目前图标总数共有519个; 不依赖Javascript 矢量图形,无限缩放 免费,可用于商业 CSS控制样式,自定义图标颜色,大小,阴影,一切可能实现的效果 支持re ...

  3. 生成漂亮报告的Go语言代码检查工具

    上篇文章,老司机给各位同学介绍了Go语言的静态代码测试“三板斧”以及Go语言的testing类库. “三板斧”简洁明了,但是缺点也很明显,命令行执行,命令行输出.适合研发攻城狮看,不适合交给领导过目. ...

  4. [USACO19FEB]Cow Dating——找规律

    原题戳这里 题解 显然原题等价于让我们求这个式子\(\prod\limits_{i=l}^{r}(1-p_i)\sum\limits_{i=l}^{r}\frac{p_i}{1-p_i}\)的最大值是 ...

  5. python json模块小技巧

    python的json模块通常用于与序列化数据,如 def get_user_info(user_id): res = {"user_id": 190013234,"ni ...

  6. Codeforces Round #586 (Div. 1 + Div. 2) D. Alex and Julian

    链接: https://codeforces.com/contest/1220/problem/D 题意: Boy Dima gave Julian a birthday present - set ...

  7. [RxJS] RxJS Advanced Patterns Operate Heavily Dynamic UIs

    Check the playground. import {Counter, CountDownState, ConterStateKeys, PartialCountDownState} from ...

  8. sqlite3-python

    官网资料 https://sqlite.org/lang_createtable.html 操作参考: https://www.runoob.com/sqlite/sqlite-insert.html ...

  9. diff:二进制文件内容差异比较

    在Ubuntu 18.04下验证,造冰箱的大熊猫@cnblogs 2019/7/29 假设我们需要以二进制格式比较两个文件file1.bin和file2.bin的差异,一个简单的方法是 1)先使用xx ...

  10. 灰度变换,gama变换,对数,反对数变换

    学习DIP第2天 灰度变换,及按照一定规则对像素点的灰度值进行变换,变换的结果可以增强对比度,或者达到其他的效果(例如二值化,或者伽马变换),由于灰度变换为针对单个像素点的灰度值进行变换,素以算法复杂 ...