基于 C++ MFC 实现二维变换的画图软件【100010873】 您所在的位置:网站首页 excel做图形变换 基于 C++ MFC 实现二维变换的画图软件【100010873】

基于 C++ MFC 实现二维变换的画图软件【100010873】

2023-06-04 19:39| 来源: 网络整理| 查看: 265

基于 MFC 和二维变换的画图软件 摘 要

本文描述了二维复合变换的基本方法和思想,根据鼠标位置坐标获取起始点 pStart 和终止点 pEnd 的坐标,设计实现每个基本图形的画图方法,根据 pStart 和 pEnd 即可确定基本图形的控制点,进而绘制对应图形。规范化齐次坐标以后,图形几何变换可以表示为图形控制点点集合的规范化齐次坐标矩阵与二维变换矩阵相乘的形式,分别设置二维变换矩阵的参数信息,设计实现对应的方法,即可实现图形的二维变换功能。

设 计

“基于二维复合变换的动画制作软件”的设计中包括以下几个部分:(1) 程序结构设计,(2)鼠标消息映射,(3) 图形绘制实现,(4) 图形变换,(5)动画扩展实现,(6)信息保存,(7)程序交互设计。

1 程序总体结构 1.1 总体结构设计 1.1.1 绘图设计

基本图形包括点,直线,曲线,自由画笔,矩形,圆形,椭圆,三角形,左箭头,上箭头,五角星,四角形,五边形共 12 钟类型,每个基本图形都有自己的编号,用户在选择基本图形后,被选择图形的编号信息保存到 dstyle 变量中,绘图模块即可根据 dstyle 中的编号绘制相应的图形。图形大小,位置信息由全局变量 pStart 和 pEnd 控制,pStart 和 pEnd 分别为用户在窗口内拖动鼠标时的起点坐标和终点坐标。根据两个坐标确定一个矩形,按照比例,设置相应的控制点,再根据控制点即可绘制相应图形。绘图流程图见图 1.1。

1.1.2 变换设计

图形变换包括图形移动,图形旋转,图形放缩。绘图模块绘制图形结束后,会将 pStart,pEnd,style 等基本信息存入图表中。例如,选择旋转类型后,执行对应函数,将图表中所有图形的位置信息修改,再执行重绘函数,按照点表内容依次重绘变换之后的图形,即可实现图形的旋转变换。变换流程图见图 1.2。

图 1.1 绘图流程图

图 1.2 变换流程图

2 程序实现 2.1 鼠标绘图的消息映射

为了实现基本图形的绘制和组合,需要在项目的视图 View 类中定义鼠标左键按下 OnLButtonDown,鼠标移动 OnMouseMove,以及鼠标左键抬起 OnLButtonUp 的消息映射,以实现拖动鼠标绘图功能。当鼠标左键按下时,设置一个变量为 true 保存绘图状态并且记录按下时的点,记为 pStart,只有当该变量为 true 时,鼠标移动时才会将绘图,当鼠标左键抬起时,该变量赋值为 false,并保存此时的点,记为 pEnd。 其中,在鼠标左键按下并移动时,使用橡皮筋技术,即移动过程中选用画笔颜色取反模式(SetROP2(R2_NOT)),即可消除移动过程中不断绘制的图形,在鼠标左键抬起时,设置画笔为颜色覆盖模式(SETROP2(R2_COPYPEN)),绘制最终的图形,并保存 pStart 点和 pEnd 点,以及笔的粗细,形状,颜色等其他信息。

2.2 图形绘制实现 2.2.1 点

由于单个点的像素太小,不利于在图形绘制中使用与观察。这里使用了画一个微型填充圆的方法代替原始像素点。

2.2.2 直线

从直线起的以下图形的绘制均为根据外接矩形绘制内部图形。绘制图形时,当点击鼠标左键时获取矩形起点,按住不放拖动鼠标直至放开左键,放开鼠标左键的位置记录为矩形的终点。直线的绘制则根据矩形起始点使用 MoveTo()和 LineTo()函数绘制。

2.2.3 等腰和直角三角形

在使用鼠标拉取的矩形中选取点位置并用画线函数连接点实现。三角形包括 3 个顶点。拉取矩形的起点坐标为(pStart.x,pStart.y),终点坐标为(pEnd.x,pEnd.y)。根据两种三角形在矩形中绘制时的对应比例,等腰三角形 3 个顶点坐标分别为: P1 (pStart.x+pEnd.x)/2,pStart.y); P2 (pStart.x,pEnd.y); P3 (pEnd.x,pEnd.y); 直角三角形的三个顶点坐标为: P1 (pStart.x,pStart.y); P2 (pEnd.x,pEnd.y); P3 (pStart.x,pEnd.y);

2.2.4 矩形和填充矩形

在使用鼠标拉取的矩形中获取了起始点和终止点后用矩形函数实现。拉取矩形的起点坐标为(pStart.x,pStart.y),终点坐标为(pEnd.x,pEnd.y)。要绘制矩形由绘制矩形的函数实现 pdc->Rectangle(pStart.x , pStart.y , pEnd.x, pEnd.y)。绘制填充矩形则在绘制前使用画刷以填充内部。

2.2.5 圆形和填充圆

在使用鼠标拉取的矩形中获取了起始点后。将两点间的距离作为要画圆的半径 r。使用绘制圆函数进行绘制 pdc->Ellipse(pStart.x-r,pStart.y-r , pStart.x+r , pStart.y+r)。绘制填充矩形则在绘制前使用画刷以填充内部。

2.2.6 自由画笔

在鼠标左键按下,并且移动的过程中,通过不断触发 OnMouseMove 消息映射,在移动中的点的位置和上一个位置间连线,即可实现自由画笔功能。

2.2.7 左箭头

在使用鼠标拉取的矩形中选取点位置并用画线函数连接点实现。左箭头包括 7 个顶点。拉取矩形的起点坐标为(pStart.x,pStart.y),终点坐标为(pEnd.x,pEnd.y)。根据左箭头在矩形中绘制时的对应比例,7 个顶点坐标为: P1 (pStart.x, pStart.y-dy/2); P2 (pStart.x+dx/2),pStart.y); P3 (pStart.x+dx/2), pStart.y-dy/4); P4 (pEnd.x, pStart.y-dy/4); P5 (pEnd.x, pStart.y-3dy/4); P6 (pStart.x+dx/2), pStart.y-3dy/4); P7 (pStart.x+dx/2),pEnd.y); 其中 dy=pStart.y-pEnd.y;dx= pEnd.x-pStart.x

2.2.8 上箭头

在使用鼠标拉取的矩形中选取点位置并用画线函数连接点实现。上箭头包括 7 个顶点。拉取矩形的起点坐标为(pStart.x,pStart.y),终点坐标为(pEnd.x,pEnd.y)。根据上箭头在矩形中绘制时的对应比例,7 个顶点坐标为: P1 (pStart.x, pStart.y-dy0/2); P2 ( (pStart.x+dx0/2,pStart.y); P3 (pEnd.x, pStart.y-dy0/2); P4 (pStart.x+3dx0/4, pStart.y-dy0/2); P5 (pStart.x+3dx0/4,pEnd.y); P6 (pStart.x+dx0/4,pEnd.y); P7 (pStart.x+dx0/4, pStart.y-dy0/2); 其中 dy0=pStart.y-pEnd.y;dx0=pEnd.x-pStart.x

2.2.9 五角星

在使用鼠标拉取的矩形中选取点位置并用画线函数连接点实现。五角星绘制包括 5 个顶点。拉取矩形的起点坐标为(pStart.x,pStart.y),终点坐标为(pEnd.x,pEnd.y)。根据五角星在矩形中绘制时的对应比例,5 个顶点坐标为: P1(pStart.x+pEnd.x)/2),pStart.y); P2(pStart.x+RX*(sin(72pi/180)cos(54pi/180))/2/sin(72pi/180)),pEnd.y); P3(pEnd.x, pStart.y+RY(1-cos(72pi/180))/(1+sin(54pi/180))); P4(pStart.x, pStart.y+RY*(1-cos(72pi/180))/(1+sin(54pi/180))); P5(pStart.x+RX*(sin(72pi/180)+cos(54pi/180))/2/sin(72*pi/180),pEnd.y); 其中 pi = 3.1415926;RX = -(pStart.x-pEnd.x);RY = -(pStart.y-pEnd.y);

2.2.10 五边形

在使用鼠标拉取的矩形中选取点位置并用画线函数连接点实现。五边形包括 5 个顶点。拉取矩形的起点坐标为(pStart.x,pStart.y),终点坐标为(pEnd.x,pEnd.y)。根据五边形在矩形中绘制时的对应比例,5 个顶点坐标为: P1 (pStart.x+pEnd.x)/2,pStart.y); P2 (pStart.x,(pEnd.y-pStart.y)*0.41+pStart.y); P3 (pStart.x+(pEnd.x - pStart.x)*0.19,pEnd.y); P4 (pStart.x+(pEnd.x - pStart.x)*0.81,pEnd.y); P5 (pEnd.x, (pEnd.y-pStart.y)*0.41+pStart.y);

2.2.11 四角星

在使用鼠标拉取的矩形中选取点位置并用画线函数连接点实现。四角星包括 8 个顶点。拉取矩形的起点坐标为(pStart.x,pStart.y),终点坐标为(pEnd.x,pEnd.y)。根据四角星在矩形中绘制时的对应比例,8 个顶点坐标为: P1 ((pStart.x+pEnd.x)/2,pStart.y) P2 (pStart.x+(pEnd.x-pStart.x)3/8,(pEnd.y-pStart.y) 3/8+pStart.y); P3 (pStart.x,(pStart.y+pEnd.y)/2); P4 (pStart.x+(pEnd.x-pStart.x)* 3/8,(pEnd.y-pStart.y)6/8+pStart.y); P5 ((pStart.x + pEnd.x)/2),pEnd.y); P6 (pStart.x+(pEnd.x-pStart.x) 6/8,(pEnd.y-pStart.y)*6/8+pStart.y); P7 (pEnd.x,(pStart.y+pEnd.y)/2); P8 (pStart.x+(pEnd.x-pStart.x)*6/8,(pEnd.y-pStart.y)*3/8+pStart.y);

2.2.12 弧线

在使用鼠标拉取的矩形中获取了起始点后,使用绘制椭圆弧线函数进行绘制 pdc->Arc(pStart.x,pStart.y,pEnd.x,pEnd.y,int((pStart.x+pEnd.x)/2),pStart.y,pEnd.x,int((pStart.y+pEnd.y)/2));

2.3 图形变换实现 2.3.1 图形移动

图形移动包括包括左移,右移和上移,下移,点表中存有每个图形的 pStart 点,pEnd 点和其他样式信息,绘图函数可根据这些信息重新绘制对应图形,所以只要调用 transform.tranlate()函数将 pStart,pEnd 的 x,y 坐标同时增加减少相同数值即可完成图形的上下左右移动。

2.3.2 图形旋转

图形旋转包括顺时针旋转和逆时针旋转。与其他的变换不同的是,旋转需要定义一个旋转中心,默认为坐标系原点。如果没有设置旋转中心,旋转变换可能会导致图形变换到窗口之外,所以设置坐标点(pStart+pEnd)/2 为旋转中心,调用 Transform.Rotate()函数,即可实现在原位置旋转变换。

2.3.3 图形放缩

图形放大和缩小是由 pStart 和 pEnd 坐标的等比变换实现的。每次放大,将 pStart 和 pEnd 的 x,y 坐标放大两倍,每次缩小将 pStart 和 pEnd 的 x,y 坐标设置为原来的 1/2。经过多次放缩后,可能导致图形太大或者太小而不能正常显示的问题,所以每次放缩判断 pStart 和 pEnd 之间的距离,如果距离大于窗口距离,或距离小于 5 个像素则终止放缩并给出相应提示。

2.4 图形变换扩展 2.4.1 动画设计

通过自定义文本对话框类(Cchoosedig),实现通过输入框输入获取复合图形变换运动时间的功能,基于原有的图形变化函数,增加根据输入时间循环移动以及延时(Sleep())的功能,即实现了自定义动画时间的动画制作。

2.4.2 自定义点表结构

由于动画制作需要修改组合复杂图形的所有点的信息,因此需要遍历点集,再重绘所有图形,因此,自定义了一个结构体,用来存储每一个图形的信息,其中信息包括:起始点,终止点,图形类型,画笔类型,画笔粗细,画笔颜色,结构体如图 2.1,然后为这个结构体创建链表,再修改文档类的串行化 Serialize 函数即可。

图 2.1 自定义结构体

2.4.3 运动时间设置

为了自定义运动时间,采用了文本对话框,通过输入运动时间,从对话框获取信息,保存到变量,再传递到 View 类,实现动画制作功能。时间设置效果如图 2.2 所示。

图 2.2 运动时间设置

2.4.4 图形重绘

对于图形重绘,先暂存当前所选择的图形类型,画笔,颜色等信息,再获取点表的长度,然后循环遍历点表,取出点表中的数据,赋值给 CDC 类的指针对象 pdc,根据图形类型和其他信息画出所有对应的图形。最后恢复之前暂存的信息,即可实现图形重绘功能,且不影响当前选择的样式。

2.5 程序交互实现 2.5.1 绘图类型选择

通过点击菜单栏的图标按钮,如图 2.3 所示,可以设置绘制图形的类型。具体实现是,当按钮被点击,调用相应的响应函数设置 dstyle,并设置 cclick 为 false 即可。

图 2.3 菜单栏中选择绘图类型的按钮

2.5.2 画笔颜色选择

颜色设置是调用系统自带的颜色对话框(CColorDialog)完成对画笔、画刷颜色的选择,同时选用该对话框能够实现自定义颜色。颜色选择对话框如图 2.4 所示。

图 2.4 颜色选择对话框

2.5.3 画笔类型选择

在菜单栏中,有画笔形状和画笔粗细可以选择。其中,画笔形状包含包含直线(PS_SOLID),点线(PS_DOT),虚线(PS_DASH),画笔粗细包括粗线,标准线和细线。根据选择的画笔类型,设置 type 和 thickness 的值即可。其中,画笔形状中的虚线和点线只有在画笔粗细为细线的时候才能正常显示,当画笔粗细为标准或者粗线时,画出来的都是实线。

2.5.4 清屏

在清屏时,首先会有弹窗提示是否确定清屏,点击“否”则取消操作,点击“是”则进行清屏。清屏功能的具体操作是先调用 RedrawWindow()函数清屏,然后清空点表 MyList 并设置 dstyle 和 cclick 分别为初始值 0 和 false 即可。

2.5.5 回退

由于本项目把每个图形外接矩形的一对顶点保存在了点表 MyList 中的一个自定义的节点结构体中,所以在回退时,我们只需要删除点表中的最后一个节点,然后根据点表重新绘图即可。

3 程序运行效果 3.1 基本图形实现

设计实现了包含点,直线段,椭圆弧线,矩形,填充矩形,等腰三角形,直角三角形,椭圆,圆,填充圆,五边形,五角星,四角星,箭头等多种基础图形,并且实现画图以及选择画笔类型功能,初始窗口如图 3.1 所示,基础图形效果如图 3.2 所示。

图 3.1 初始窗口

图 3.2 基础图形效果

3.2 组合复杂图形以及整体变换

实现了基本图形组合成复杂图形的功能,并且具有回退,清空画布,颜色等功能,具有包含平移,旋转,放大缩小,输入动画时长的功能。

♻️ 资源

在这里插入图片描述

大小: 28.9MB ➡️ 资源下载:https://download.csdn.net/download/s1t16/87472192 注:如当前文章或代码侵犯了您的权益,请私信作者删除!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有