版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
学科分类号0812本科学生毕业论文〔设计〕基于VC的根本矢量图形系统的开发与实现DevelopmentandImplementationofBasicVectorGraphicsSystemUnderVC学号院〔系〕计算机与通信工程系计算机科学与技术2007级指导教师目录第一章绪论11.1选题背景及意义11.2国内外研究现状11.3论文内容及结构安排21.4本章小结3第二章矢量图形系统的分析与设计42.1开发思路42.2开发模式42.3功能分析52.4功能模块设计62.5本章小结6第三章矢量图形系统的坐标转换73.1Windows环境下的坐标系73.1.1设备坐标73.1.2逻辑坐标73.2设备坐标与逻辑坐标83.2.1设备坐标与逻辑坐标的关系83.2.1设备坐标及逻辑坐标的转换83.3窗口与视口93.4本章小结9第四章实现矢量图形系统的文档和视图104.1矢量图形系统的图形元素类104.1.1图形元素基类104.1.2直线类104.1.3连续直线或封闭多边形类104.1.4圆类104.1.5圆弧类114.1.6标注文本类114.1.7图形参数类114.2矢量图形系统的文档114.2.1面向对象的文档管理机制114.2.2创立图形元素对象指针114.2.3矢量图形系统的文档124.2.4实现文档的管理功能124.3矢量图形系统的视图134.3.1建立坐标系134.3.2实现各类图形元素的绘制功能144.3.3实现视图的绘制144.4鼠标交互绘图154.4.1要解决的主要问题154.4.2交互绘制各类图形元素154.5本章小结17第五章矢量图形系统的操作功能185.1图形操作菜单管理185.1.1增加菜单资源185.1.2添加消息处理函数185.2图形操作的具体实现195.2.1图形重画195.2.2图形放大和移动205.2.3重画上屏和重画首屏225.2.4显示全图245.2.5图形重画速度的提升255.3图形的点选与撤销275.3.1鼠标点选图形元素275.3.2各种图形元素的点选判断函数285.3.3实现点选图形元素功能295.3.4选中图形元素的特殊显示315.3.5撤销选中的图形元素325.4图形元素的删除325.5本章小结35第六章总结与展望366.1总结366.2展望36参考文献37致谢38基于VC的根本矢量图形系统的开发与实现摘要矢量图形系统作为GIS系统组成的一局部,随着GIS系统用户的不同,对于矢量图形系统的要求也不同,现有GIS矢量图形绘制系统功能全面,但是针对性差,所以有针对性的从底层自主开发符合自己需要的矢量图形系统是十分必要的。论文利用面向对象的程序设计和C++类的组织方法,在VC6.0下实现了一个根本的矢量图形系统,能够实现鼠标绘制直线、圆、圆弧、圆形区域等功能。通过对矢量图形系统坐标系的建立及其与Windows坐标系之间的转换关系的探讨,实现了图形的无级缩放、漫游、全图显示等操作功能。通过对点选图形元素的原理的研究,实现了图形的选中、图形删除、放弃选中等功能。此外,就矢量图形的显示速度等问题进行了探讨,并提出了加快图形显示速度的根本方法:在显示一个图形元素前,对这个图形元素进行判断,判断这个图形元素是否在视图屏幕中,如果这个图形元素不在当前的视图屏幕中,就不用对这个图形元素进行绘制,以此节省绘制时间。 系统具有比拟完善的图形绘制功能,可应用于城市信息管理系统中。【关键词】矢量图形;鼠标绘图;无极缩放DevelopmentandImplementationofBasicVectorGraphicsSystemUnderVCAbstractVectorgraphicssystemasacomponentpartoftheGISsystem,GISsystemuserswithdifferentrequirementsforthevectorgraphicssystemisdifferent,andtheexistingfull-featuredGISgraphicsrenderingsystem,buttargetedpoor,ittargetedindependentfromtheunderlyingdevelopmentinlinewiththeirvectorgraphicssystemneedsisessential.Byusingobject-orientedprogrammingandC++classmethodoforganization,theorganizationimplementsabasicvectorgraphicssystemthatenablesthemousetodrawastraightline,circle,arc,circleandsoon.VectorgraphicssystemthroughtheestablishmentofthecoordinatesystemanditsWindowscoordinatesystemconversionrelationshipbetweenstudyandrealizethesteplesszoomgraphics,roaming,fullmapdisplayandotheroperationsfunctions.Clickthroughontheprinciplesofgraphicelementstoachievetheselectedgraphic,graphics,remove,abandonselectedfunctions.Inaddition,vectorgraphicsdisplayspeedoftheotherissuesdiscussed,Andproposedtoacceleratethespeedofthebasicmethodofgraphicaldisplay,whichisagraphicalelementinthedisplaybeforethejudgeonthegraphicelementstodeterminewhetherthegraphicelementsintheviewscreen,ifthegraphicelementisnotthecurrentviewofthescreen,theydonotdrawonthegraphicelementsinordertosaverenderingtime.Systemhasarelativelycompletegraphicsrenderingcapabilities,mainlyusedforurbaninformationmanagementsystem.【Keywords】vectorgraphic;Mousedrawing;PromiseZoom第一章绪论1.1选题背景及意义一个根本的GIS系统包括管理空间坐标数据的矢量图形系统和管理属性信息的数据库管理系统,以及实现矢量图形系统与数据库管理系统双向连接的连接系统三个局部1]。 矢量图形系统面向地理对象,是地理实体抽象和完整表达的主要方式,因而是GIS系统中重要的组成局部,也是开发一个GIS系统的重点所在2]。 一些专业的商品化GIS软件都提供了比拟完善的图形系统的功能,利用这些专业的工具软件进行开发,虽然开发难度不高,简单易学,但也普遍存在着一些弊端3]:⑴不易扩展。专业的GIS工具软件提供的接口复杂,难于修改,不能够很好的扩展;⑵软硬件要求高。专业的GIS软件开发工具通常比拟庞大,对系统软硬件的要求高;⑶软件不易升级。利用GIS专业软件工具所进行的图形系统的开发,实质上只是在这些专业软件根底上做一些简单的应用开发,开发完成的产品同样需要这些专业软件工具的支撑,因此,软件的升级就要受到制约;⑷代价高。商品化的GIS软件要面向最广的用户,所以软件和系统还是作为一个整体而存在,开发者必须要购置整个的GIS软件,代价较高,而且购置的平台中真正需要的功能可能只是很少的一局部,造成了软件资源的浪费。 此外,在实际的应用中,我们对系统的需求往往主要集中在某些特定功能上,如本论文结合信息平台的需求,所需要的功能主要是图形的绘制、显示、查询、缩放等。然而,商品化的GIS软件致力于提供解决方案,它提供了全面的GIS功能,因此,面向实际应用的针对性必然要差一些。 综合以上分析,对于有特定需求的用户来说,有针对性的从底层自主开发符合自己需要的矢量图形系统是十分必要的。1.2国内外研究现状 矢量图形系统作为GIS系统最重要的组成局部,应用领域也不断扩大,已进入了普通管理信息系统(MIS)[4],GIS矢量图形系统与普通管理信息系统相结合,克服了MIS系统的局限性,大大提高了系统的直观性和可操作性,同时提高了MIS系统所不能解决的如空间信息统计、属性信息计算等功能。 专业的GIS软件大都提供了较为完善的矢量图形的开发功能。借助这些专业的开发工具软件,出现了大量GIS系统的研究和开发成果。 文献[5]提出了一种小型GIS矢量图形系统的设计方案,利用GIS、面向对象及数据库等技术,以VC++6.0开发平台,底层开发实现了一个具有图形编辑功能,且有与第三方GIS软件数据接口功能的GIS矢量图形系统,并已在生产中得到了应用。 文献[6]提出了一种基于MFC的动态交互的矢量图形系统的快速开发方法,设计实现的矢量图形系统已成功应用于测绘数据处理等专门问题的解决中。 文献[7]同样利用VC++6.0,基于面向对象技术的软件工程思想开发实现了一个用于煤矿平安分析可视化研究的矢量图形系统。 综上所述,从底层开发实现的GIS矢量图形系统以其较好的灵活性和可操作性已经在很多领域得到了推广应用。1.3论文内容及结构安排本文主要研究如何基于VC++从底层开发实现一个能够满足信息平台需求的矢量图形系统。主要对图形元素的组织和存储、图形对象的绘制、图形的操作、图形与属性的双向查询、图层管理等方面进行研究,具体包括以下几个方面的工作:⑴采用面向对象的方法完成矢量图形数据对象类的组织和存储,实现包括圆形,直线,点,标注文本等图形元素的绘制;⑵能够实现鼠标交互绘图的功能;⑶研究矢量图形系统坐标系的建立及坐标转换关系,并在此根底上实现图形的无级缩放、移动、全图显示等操作功能;⑷能够对图形进行选中、删除等功能。论文的结构安排: 第一章是绪论,主要对课题的研究背景、矢量图形系统开发研究的现状进行了探讨,并简要介绍了本文的研究内容; 第二章是对本系统的分析与设计,主要介绍系统的开发思路、开发模式的选择、系统功能模块设计等内容; 第三章是矢量图形系统坐标系的设计。介绍和分析了Windows环境下的逻辑坐标系和设备坐标系,在此根底上建立了系统的实际坐标系以及三种坐标之间的转换关系; 第四章是实现图形系统的文档和视图,这一章主要是真对在系统实现过程中所用到的一些文档与视图的管理; 第五章矢量图形系统的操作功能,这一章是论文的重点,主要对系统各功能模块的实现技术、实现过程进行了详细的研究和阐述; 第六章主要是对全文进行的一个总结。1.4本章小结 本章主要是对GIS系统的研究背景、研究现状进行了简单的描述,从而表达出选题的意义及其目的,在确定了系统需要的功能后,对整个系统的功能进行了简单的描述,并对系统预期实现的功能进行了分析,最后列出了整篇论文的根本构架。第二章矢量图形系统的分析与设计2.1开发思路 一个根本的矢量图形系统包含两个局部:矢量图形元素以及对图形元素的各种操作。基于这两个组成局部,本文将从以下两方面组织确立系统的开发思路。 开发工具的选择:从底层开发GIS矢量图形系统的首要问题是要选择适宜的可视化编程语言9]。适用的有Delphi,VC++等。目前比拟流行的GIS专业软件平台多是用C++开发完成的。在Windows下VC++是一个很好的底层开发工具。VC++通过微软根底类MFC〔MicrosoftFoundationClass〕把WIN32API封装起来,使得在MFC根底上用C++编写Windows平台下面的程序更为方便。此外,VC++的MFC提供了很多与图形操作有关的类,使得VC++结合GDI对象可以简单的实现图形图像的显示。因此使用VC++开发图形系统,具有开发灵活、功能强等特点。最重要的一点是MFC在简化编程的同时,并没有限制对系统的控制,设计出的程序也稳定、高效。所以两者的结合有利于矢量图形系统的开发。因此,系统选用MicrosoftVisualC++6.0〔简称VC6.0〕作为开发平台,VC++作为程序设计语言。2.2开发模式 当前的软件开发模式有面向过程和面向对象两种。面向过程的方法 面向过程的方法也就是传统的结构化方法10],包括结构化系统分析、系统设计及程序设计方法,是以系统中的数据及对数据进行处理的过程为研究中心的。面向过程的方法构建一个系统的流程是:从需求出发,制定方案,编写代码,测试代码,维护系统。面向对象的方法 面向对象的方法〔Object-OrientedParadigm,简称O-O方法〕是目前软件开发的主流方法11]。面向对象的方法以对象为中心,对象是属性〔数据〕和操作〔处理数据的函数〕的封装体。面向对象方法有如下三大特性12]:⑴封装性:封装性(Encapsulation)是指对象将其属性的实现细节隐藏在内部,外界只有通过函数才能对其访问和利用。因此保证了面向对象软件的可构造性和易维护性;⑵继承性:继承性(Inheritance)是指下层对象能够拥有上层对象的特征〔属性和操作〕的能力。继承性是面向对象方法中最重要的机制,可以通过继承机制扩充和完善旧的程序设计以适应新的需求;⑶多态性:多态性(Polymorphism)是指发出同样的消息被不同类型的对象接收时导致完全不同的行为。这里所说的消息主要是指对对象函数的调用,而不同的行为是指不同的实现。多态性表达了对象行为的扩充能力,使程序的动态链接方便易行。面向对象方法的这三大特性是相互关联的,封装性是根底,继承性是关键,多态性是补充,而多态性又必须存在于继承的环境中。两种开发模式的比拟 应用于不同领域的GIS系统,对矢量图形系统功能的要求是有差异的12]。用户的需求也可能是逐步提出的,如果考虑系统的所有功能,那么在构建时会很困难。而面向过程的方法在做需求分析、制定方案阶段都需要用户的参与,开发人员对这些需求的理解也会存在差异,这就导致开发人员将不断地修改这些面向过程的代码,陷入代码的泥潭。面向对象技术很好地解决了这种问题。在需求分析阶段,如果用户对需求不十分清楚,正如在此系统中,那么开发人员无须考虑将要构建的矢量图形系统会应用于哪一类实际应用,可以先从一般的需求出发,构造实现这种需求的对象,把系统看做是一组相对独立的对象的集合,规定其操作13],由多个对象抽象为类,由类构造派生类,由这些类派生出实例,逐步构造系统。由于对象的数据与其操作〔处理数据的函数〕是封装的,并通过函数与外部进行联系,这是一种自下向上的开发方法,在对某个对象修改时只涉及该对象、该类的细节,不影响整个系统。这使建立一个根本图形系统来满足不同图形应用系统开发的需要具有了可行性。将面向对象技术应用于矢量图形系统的设计当中,可以根据应用系统本身的需求来实现功能,使软件易于扩充。面向对象的方法在GIS中的应用,己经成为GIS开展的方向。这是因为空间信息较之传统数据库处理的一维信息更为复杂、繁琐,面向对象的方法为描述复杂的空间信息提供了一条直观、结构清晰、组织有序的方法。 基于以上分析,确定本系统的开发思路是:在Windows下选用VC6.0作为开发平台,VC++作为程序设计语言,采用面向对象的软件开发模式,从底层开发独立于其他任何专业GIS开发平台的软件产品。2.3功能分析 一个根本的GIS矢量图形系统,一般应具备如下根本功能10]:⑴比拟完善的图形元素。具备处理点、线、面等根本图形元素的能力;⑵比拟完善的图形绘制功能,能够绘制图形系统的各种图形元素;⑶比拟完善的图形操作功能。具备图形的放缩、漫游、全屏等功能;⑷图层管理功能。根据图形元素的属性不同,分图层进行管理;⑸具有颜色、线型、线宽、填充色等参数的设置功能;⑹图形对象的各种选取功能。根据需要选定图形对象,如点选、框选等。 但不同的行业对GIS矢量图形系统的需求是有差异的[14]。建立一个城市信息管理系统,要求矢量图形系统具有丰富的图形元素、丰富的线型、巨大的存储容量、完整的输入和输出、强大的地图编辑功能等;而建立一个地图查询系统,那么只需要地图显示和操作的根本功能。根据以上功能分析,本系统将以矢量图形系统所应具备的根本功能为根底,从城市信息管理系统的需求出发进行系统功能的设计。2.4功能模块设计 本系统对功能结构的设计采用的是完全面向对象的模块化方式,“模块化的设计方式,使得系统能够易于维护和扩展。系统主要包含以下能模块:图形绘制模块、图形操作模块、查询模块、矢量数据的输入及输出模块。下面分别对各模块功能作简要说明。图形绘制模块 该模块主要实现对根本图形元素类〔点、线、圆、圆形区域、标注文本等〕的绘制功能。2.图形操作模块 该模块要实现的主要操作功能有:⑴图形无级缩放:图形能够以任意比例尺放大缩小;⑵漫游:通过调整视图屏幕来显示图形的其他局部进行浏览;⑶全图显示:在视图屏幕中显示所有图形元素;⑷点选:通过鼠标点击选取当前视图屏幕中的图形元素并查询其属性数据。2.5本章小结 本章主要对系统开发的思路进行了简单的阐述,包括矢量图形系统的构成、开发工具的选择等方面;开发模式的选择,包括对两种开发模式的简单介绍,并对两种开发模式进行了比拟,选出了适合本系统的开发模式,即面向对象开发模式;阐述了组本钱系统的几个模块,并对各个模块的功能进行了分析与介绍。第三章矢量图形系统的坐标转换3.1Windows环境下的坐标系3.1.1设备坐标 设备坐标是指在Windows环境下的各种输出设备所使用的坐标4,5]。它所对应的对象是具体的设备,如:键盘、显示器及打印机等。设备坐标是建立在笛卡尔直角坐标系上的,以像素为单位。一个实际物理屏幕就是由像素组成的,如平常所说的分辨率1024*768指的就是显示器屏幕的实际宽度和高度的像素数目。由于不同的设备分辨率不同,相同坐标值的物理位置就可能不同。逻辑坐标 逻辑坐标也是建立在笛卡尔坐标系上的,即是指Windows系统各种映射模式下的坐标。Windows系统为了方便程序开发,为我们提供了如表3.1所示的8种映像模式:表3.1Windows映像模式映射模式映射识别码逻辑单元X和Y轴正向MM_TEXT1Pixel右下MM_LOMETRIC20.1mm右上MM_HIMETRIC30,01mm右上MM_LONGLISH40.1inch右上MM_HIENGLISH50.01inch右上MM_TWIPS61/440inch右上MM_ISOTROPIC7Variable变化的MM_ANISOTROPIC8Variable变化的 其中MM_TEXT方式宇DOS文本方式很相似,MM_Text方式允许应用程序利用设备像素工作,而DOS是在字符状态下操作。在此模式下,窗口〔屏幕〕的原点是在坐上角,X的正方向为向右,Y的正方向为向下。 而MM_LOMETRIC、MM_LONGLISH、MM_HIENGLISH、MM_HIMETRIC四种映像方式默认的原点即是窗口的左上角,X的正方向为向右,Y的正方向为向上。坐标用英尺(inch)或毫米(mm)表示,对于绘图程序来说很方便,不用进行坐标转换。MM_ISOTROPIC与MM_ANISOTROPIC映像方式都是用笛卡尔坐标,且提供可变的逻辑单位和可变的原点。在MM_ISOTROPIC方式下,X轴和Y轴坐标的刻度是相同的,而MM_ANISOTROPIC方式下X轴和Y轴坐标的刻度是可以设置为不同的。 MM_TWRIPS方式下,TWIPS是对“一个点的1/20”3.2设备坐标与逻辑坐标设备坐标与逻辑坐标的关系逻辑坐标不同于设备坐标,它不需要考虑具体的设备类型,其中面向的对象是设备环境,在内存中建立的一种虚拟坐标系。虽然逻辑坐标的取值同设备坐标一样都是整数,但是采用的坐标单位是不同的,而且坐标轴的方向也是随着映射模式的改变而不同。在矢量图形系统中,应根据实际需要使用特定的逻辑坐标系。 逻辑坐标和设备坐标一起为Windows提供了设备无关性,设备无关性指的是只要设定了映射模式,不管是在何种输出设备上,一个图形显示出同样的效果。但对于MM_TEXT映射模式来说,因为其坐标单位是像素,而一个像素所占的实际长度随着设备的不同而不同,长度是不固定的,所以在不同的输出设备上不能保证所显示图形的大小相同。 设备坐标系和逻辑坐标系均是由Windows系统定义的,因此统称为Windows坐标系3]。Windows下列图形的绘制是在逻辑坐标系中进行的,用户在各种绘图设备上的绘制操作使用的是逻辑坐标值,然后Windows再根据所设定的映射模式,将逻辑坐标值转换成设备坐标值,最后将图形输出到实际的显示设备或打印设备上。设备坐标及逻辑坐标的转换Windows下的绘图是在逻辑坐标系中进行的,而任何图形的显示和输出都必须在一定的设备上实现,因此,在图形系统的开发中,逻辑坐标到设备坐标的转换常被大量用到。另外,当系统和用户之间进行交互时,系统需要知道用户输入焦点的位置坐标,而这个坐标是设备坐标,必须将其转换为逻辑坐标后才能进行识别和操作。 逻辑坐标与设备坐标转换之前,首先要对映射模式进行设置,也就是要确立系统开发所采用的逻辑坐标系。在MFC中,不同的映射模式其对应的逻辑坐标单位是不同的,设定了映射模式,就规定了逻辑单位的大小和增量的方式。所以实现逻辑坐标与设备坐标转换的第一步就是确定系统所使用的映射模式14]。 在MFC应用程序中可以通过调用CDC类的函数SetMapMode(intnMapMode)来设置,其中参数nMapMode代表的即是表1中的映射模式识别码,用来指定新的映射模式,可以取Windows八种映射模式中的任意一种。 本系统在视图类CMapView的OnDraw函数中设置映射模式如下:pDC->SetMapMode(MM_TEXT); 为了完成Windows各种映射模式下从逻辑坐标到设备坐标的转换,VC++提供了两个转换功能函数:DPtoLP(LPPOINTlpPoints)//从设备坐标到逻辑坐标的转换LPtoDP(LPPOINTlpPoints)//从逻辑坐标到设备坐标的转换3.3窗口与视口 窗口是虚拟存在的一个屏幕视口〔也称视图〕是设备坐标系〔通常屏幕〕中定义的一个矩形区域,就是在屏幕上看到的视图客户区,即绘图的区域,用来确定显示内容,窗口是图形的可见局部。窗口的坐标是逻辑坐标,与设备无关5]。视口是与设备相关的一个矩形区域,坐标单位是与设备相关的。视口决定了窗口中的图形显示在屏幕上的位置和大小。窗口坐标的原点与视口坐标的原点始终对应于同一点。 窗口和视口的划分与Windows下列图形绘制的机制有关。Windows下的绘图并不是把图形直接绘制到设备屏幕上,而是先在Windows预先定义好的坐标系统〔映射模式〕中选择一个作为绘图参考系,在此映射模式下将图形绘制到虚拟的内存窗口中去。然后再将窗口中的图形映射到视口中。如果映射到屏幕上就实现了图形的显示;如果映射到打印机等输出设备上就实现了图形的打印输出。 窗口原点和视口原点指的是同一点分别在窗口坐标系和视口坐标系中的坐标值,它们决定了图形由窗口映射到视口时的相对位置。3.4本章小结要实现矢量图形的绘制、显示及无级缩放等功能,首先要确立和实现矢量图形系统所采用的坐标系,坐标系是整个图形系统开发的根底。本系统建立了自己的图形坐标系,称之为实际坐标系,来维护矢量数据的地理坐标,并实现了实际坐标与Windows坐标——逻辑坐标和设备坐标的相互转换。因此本章对矢量图形系统坐标系的建立过程及其与Windows坐标系的相互关系进行了介绍,并对设备坐标与实际坐标的转换方法进行了阐述,最后还简单的介绍了窗口与视口及其他们之间的关系。第四章实现矢量图形系统的文档和视图4.1矢量图形系统的图形元素类 面向对象的程序设计,是目前程序设计的主流方法,在本设计中,将利用面向对象的程序设计和C++类的组织方法,组织建立一个根本矢量图形的图形元素类。组织实现的矢量图形系统,能够处理点类、线类、面类等类别的图形元素,其中点类图形元素有包括直线,圆,圆弧,标注文本等图形元素,针对每类图形元素组织建立起对其进行管理的C++类,并把每个图形元素作为一个独立的对象来管理。图形元素基类对各类图形元素进行分析,可以发现各类图形元素具有一些相同的属性和操作功能,如图形元素的颜色、线型线宽所在层等属性和得到一个图形元素是否做了删除标志等操作。把这些图形元素中共性的东西〔属性和操作〕,组织存放在一个图形元素基类(CDraw)中,具体的图形元素由这个基类来派生。直线类直线类Cline是从CDraw派生而来,在直线类的构造函数中,共有包括11个参数,并利用前7个参数从CDraw派生而来,并在构造函数中对其余的四个参数〔直线的起点与终点〕进行了初始化。用来标识直线类的特殊属性,也在类中进行了定义。连续直线或封闭多边形类连续直线除了具有图形元素基类所具有的属性外,从图形的几何特征上,连续直线是由很多顶点组成的,而且顶点数目是不确定的。一条连续直线可能只有两个顶点,也可能有几千个顶点。所以,需要定义一个结构来存储连续直线的一个顶点坐标。定义一个成员变量m_Numble用来记录点的个数,定义一个b_Fill来标识是连续直线还是封闭多边形。圆类 对圆类CCircle的创立方法与直线类CLine类似,圆除了具有图形元素的根本特征外,还有自身的几何特性。在CCircle类中定义了m_CircleX,m_CircleY,m_CircleR用来记录圆心与圆的半径,并定义了b_Fill用来标识此图形元素是圆还是圆形区域。圆弧类圆是圆弧的一个特例,当圆弧的弧度等于2时就是圆。所以可以从一个圆类派生得到一个圆弧类。在圆弧类中定义了m_Angle1,m_Angle2用来表示圆弧的起始弧度与终点的弧度。标注文本类矢量图形中可以有大量的标注文本,标注文本除了具有图形元素的根本特性外,还具有位置、字体及标注内容等自身的信息。CText类也有两个构造函数,第二个构造参数有多个参数,并利用多个参数对类的成员变量进行初始化。在构造函数中,调用了基类CDraw的构造函数对基类CDraw的成员变量进行初始化。图形参数类在矢量图形系统中,图形参数是集中存储的。在图形元素基类中成员变量m_ColorPen,m_ColorBrush分别用来存储画笔的颜色与画刷的颜色序号,m_Layer中存储的是在图层列表中的序列号。用m_ColorList,m_LayerList两个数组来分别存储颜色和涂层,并在构造函数中进行初始化。4.2矢量图形系统的文档面向对象的文档管理机制管理矢量图形系统图形数据的方法即文档管理机制。在本设计的开发中,采用一套完全面向对象的文档组织机制。这种机制就是通过图形元素类创立很多图形元素对象,每个图形元素对象作为一个整体来组织存储空间的分配、存取等各种管理功能。然后通过建立一种存储机制,来管理指向所有图形元素对象的指针,到达管理所有图形元素对象的目的。这种文档管理机制具有组织简单结构化和移植性好,以及比拟容易利用VC++程序设计语言的开发功能等优点。缺点是需要较大的内存空间。创立图形元素对象指针管理一个矢量图形系统文档的思路是:每个图形元素是图形元素类创立的一个对象,在创立这个对象时得到指向这个对象的指针,建立一个对象指针数组来管理这些指针,以到达管理所有图形元素对象的目的。 在VC++下可以较容易地实现对指向图形元素对象的指针的组织和管理。在MFC中有一个类模板CTypedPtrArray,可以用它来创立一个管理类指针的对象。例如,可以定义一个管理CLine类指针的对象如下:CTypedPtrArray<CObArray,Cline*>m_LineArray;矢量图形系统的文档在应用程序Draw中,可以派生几个CObArray对象来分别管理基类图形元素。在文档类CDrawDoc中创立用来管理各类图形元素的对象指针,创立的CObArray对象如下: private: CTypedPtrArray<CObArray,CLine*>m_LineArray; //管理直线对象指针的对象 CTypedPtrArray<CObArray,CPline*>m_PLineArray;//管理连续直线对象指针对象 CTypedPtrArray<CObArray,CCircle*>m_CircleArray;//管理圆对象指针的对象 CTypedPtrArray<CObArray,CArc*>m_ArcArray; //管理圆弧对象指针的对象 CTypedPtrArray<CObArray,CText*>m_TextArray; //管理文字对象指针的对象实现文档的管理功能⑴增加图形元素。在应用程序Draw中增加一个图形元素对象〔如一条直线〕时,需要进行以下两个步骤的操作:首先需要创立一个图形元素对象,并用图形元素的实际数据初始化这个图形元素对象。如增加一条直线时,需要创立一个CLine对象,并用这条直线的实际数据〔起终点、所在图层、颜色等〕初始化这个CLine对象的成员变量。然后需要把指向新创立的图形元素对象的指针,增加到文档类中管理图形元素对象指针的对象中。如增加一条CLine对象后,需要把指向这个CLine对象的指针增加到文档类的m_LineArray对象中。 为了实现增加各类图形元素的功能,在文档类CDrawDoc中定义几个函数,分别来完成增加各类图形元素的操作功能 CLine*AddLine(shortColorPen,shortColorBrush,floatLineWide,shortLineType,shortLayer,intid_only,floatX1,floatY1,floatX2,floatY2); CCircle*AddCircle(shortColorPen,shortColorBrush,floatLineWide,shortLineType,shortLayer,intid_only,floatCircleX,floatCircleY,floatCircleR,BOOLbFill); CArc*AddArc(shortColorPen,shortColorBrush,floatLineWide,shortLineType,shortLayer,intid_only,floatCircleX,floatCircleY,floatCircleR,floatAngle1,floatAngle2); CText*AddText(shortColorPen,shortColorBrush,floatLineWide,shortLineType,shortLayer,intid_only,floatStartX,floatStartY,floatAngle1,floatAngle2,floatTextHeight,floatTextWide,floatOffWide,unsignedcharTextFont,intTextLong,CStringText); CTag*AddTag(shortColorPen,intLayer,floatxInsert,floatyInsert,floatxScale,floatyScale,floatangle,intonly_id,intidBlock); CPline*AddPLine(shortColorPen,shortColorBrush,floatLineWide,shortLineType,shortLayer,intid_only,intNumble,PointStruct*PointList); 这6个函数分别用来实现增加一条直线、一个圆、一个圆弧、一个标注文本、一条连续直线或一个多边形区域的功能。函数返回指向新增图形元素对象的指针。⑵实现对图形元素的操作。为了实现对图形元素的操作,为此,在文档类CDrawDoc中定义一些Public成员函数,并在实现文件drawdoc.cpp中,参加函数的具体实现代码。函数具体定义如下:CDraw*GetGraph(shortLb,intindex);//得到指向图形元素对象的指针VoidDeleteGraph(shortLb,intindex);//删除图形元素对象IntGetGraphNumb(shortLb);//各类图形元素的数目IntGetGraphUpperBound(shortLb);//存储各类图形元素CObArray对象数组的最大下标IntGetGraphIndex(shortLb,intID);//某个识别号的图形元素对象指针在CObArray数组中的存放位置4.3矢量图形系统的视图建立坐标系⑴建立坐标系 该坐标系取屏幕的左下角点作为图形屏幕的基点。客户区的左下角的坐标定义为(m_xStart,m_yStart),并确定一个变量blc作为逻辑坐标和实际坐标的比例关系。⑵实际坐标与逻辑坐标的转换 为了实现实际坐标与逻辑坐标的转换,在视图类CDrawDoc中定义如下的四个转换函数: Public: VoidDPtoVP(floatx,floaty,int*X,int*Y); VoidVPtoDP(intx,inty,float*X,float*Y); IntDLtoVL(floatl); FloatVLtoDL(intl); 函数VPtoDP用来将逻辑坐标转换成实际坐标,参数(x,y)是一个点的逻辑坐标,参数(*X,*Y)返回转换后的实际坐标值。 函数DLtoVL用来将实际坐标长度转换成逻辑坐标长度,参数l是一个实际坐标长度,函数返回逻辑坐标表示的长度值。 四个转换函数中用到的成员变量,在视图类CDrawView中定义: Privated: Floatm_xStart,m_yStart,blc; Intm_wScreen,m_hScreen; 为了在应用程序Draw的其他类中能够使用四个坐标转换函数,可以将四个转换函数定义成四个全局函数来实现转换操作功能,在实现文件drawview.cpp中,定义四个全局函数。且四个全局函数利用视图类指针p_View调用视图类的四个坐标转换函数,来完成坐标和长度的转换功能,p_View指向当前激活的视图对象。如果在某个实现文件中使用这四个全局转换函数,只需在这个实现文件中的开始处参加全局函数的外部引用。实现各类图形元素的绘制功能利用虚函数实现各种图形元素的绘制功能。在图形元素基类CDraw中,抽象定义一个进行绘制操作的虚函数。因为在应用程序Draw中,不用CDraw类直接来创立对象,所以可以将虚函数定义成纯虚函数: VirtualvoidDraw(CDC*pDC,intm_DrawMode,intm_DrawModel,shortBackColor)=0;在各种图形元素类CLineCCircleCArcCTextCTagCPlineCPlineRgnCLinkNet中,重载虚函数Draw:virtualvoidDraw(CDC*pDC,intm_DrawMode,intm_DrawModel,shortBackColor);实现视图的绘制 为了实现应用程序Draw的图形绘制工作,在文档类CDrawDoc中定义Draw函数如下: voidDraw(CDC*pDC,intm_DrawMode,intm_DrawModel,shortBackColor);4.4鼠标交互绘图要解决的主要问题⑴捕获鼠标操作消息 VC++提供了足够的窗口消息和已经保护的消息处理函数解决这个问题.在应用程序Draw中实现鼠标交互绘制图形元素时,将主要用到以下三个鼠标操作: OnMouseMove(UINTnFlags,CPointpoint)WM_MOUSEMOVE//鼠标移动 OnRButtonDown(UINTnFlags.CPointpoint)WM_RBUTTONDOWN//按下右键 OnLButtonDown(UINTnFlags.CPointpoint)WM_LBUTTONDOWN//按下左键⑵捕捉所有的鼠标输入 在用鼠标交互绘制一个图形元素时,在已经开始绘图的情况下,不希望还能进行别的操作,以防止造成系统流程和变量初始化等方面的错误.VC++提供了两个成员函数来满足以上的功能需求: CWnd::SetCapture(); CWnd::ReleaseCapture();⑶在屏幕上拖动图形 在用鼠标交互绘制图形元素时,为了直观的看到所绘制的图形,一般采用拖动图形的方法;⑷保存图形数据到文档 用鼠标在屏幕上交互绘制的图形元素,要创立一个图形元素对象并将指向这个图形元素对象的指针保存起来;⑸将图形以实际的形态重画 用鼠标交互绘制一个图形元素后,要在屏幕上马上显示出这个图形元素的实际形态,必须将图形元素以实际的形态重画。在矢量图形系统设计中,一般采用CClientDC对象,在交互绘制图形元素操作完成后,即时在视图中重画这个新增的图形元素。交互绘制各类图形元素本设计主要实现交互绘制直线、圆、填充圆、圆弧、标注文本、连续直线、多边形区域的实现过程.⑴增加菜单资源. 在应用程序Draw的菜单资源中,增加一个菜单〞鼠标绘图〞,.在这个菜单中包含直线、圆、填充圆、圆弧、标注文本、连续直线及多边形区域菜单项。参加的菜单如图4-1所示:图4-1鼠标绘图菜单⑵为每个操作添加消息处理函数 选中其中的一个菜单项,单击鼠标右键,选择“建立类向导……〞,在Classname中选择CDrawView,在Messages中选择COMMAND,点击AddFunction,即可为菜单先增加一个响应函数。点击Edit即可在实现文件drawview.cpp中增加消息处理函数的实现代码.操作界面如图4-2所示:图4-2MFCClassWisard获得图形元素的唯一识别号: 在一个矢量图形系统中,对于任何一个图形元素,必须有一个能够与其他图形元素区分开来的属性,因此,在此系统中,在Draw类中为每类图形元素创立一个惟一识别号变量m_id_only.为了得到每类图形元素的识别号,在CDrawDoc中定义一个成员函数GetGraphID来实现。具体函数定义如下: intGetGraphID(shortLb).其中参数Lb用来表示图形类别,具体的实现代码在drawdoc.cpp文件中。当单击标注文本时出现文本对话框如图4-3:图4-3标注信息窗口当单击字体参数时出现的对话框如图4-4:图4-4标注字体参数4.5本章小结本章主要是对直线、连续直线及封闭多边形区域、圆、圆弧、标注文本等根本的图形元素的数据组织和绘制方法做了简单的介绍,并对具体的实现过程也做了简要的概述。对于鼠标绘图操作的完成提供了有效的方法。第五章矢量图形系统的操作功能5.1图形操作菜单管理增加菜单资源 在应用程序Draw的菜单资源中,增加“图形操作〞及“图形选中〞两个菜单,.并分别在两个菜单下参加菜单项如图5-1与图5-2所示:图5-1图形操作菜单图5-2图形选中菜单添加消息处理函数按照4.3节中介绍的方法为两个菜单下的所有菜单项添加消息处理函数。添加后,可以在视图类CDrawView中找到如下定义:afx_msgvoidOnGraphRedraw();afx_msgvoidOnGraphZoom(); afx_msgvoidOnGraphSmall();afx_msgvoidOnGraphPan();afx_msgvoidOnGraphUp();afx_msgvoidOnGraphFirst();afx_msgvoidOnGraphAll();可以在视图类drawView.cpp中找到如下定义: ON_COMMAND(ID_GRAPH_REDRAW,OnGraphRedraw) //图形重画 ON_COMMAND(ID_GRAPH_ZOOM,OnGraphZoom) //图形放大 ON_COMMAND(ID_GRAPH_SMALL,OnGraphSmall)//图形缩小 ON_COMMAND(ID_GRAPH_PAN,OnGraphPan) //图形摇动 ON_COMMAND(ID_GRAPH_UP,OnGraphUp) //重画上屏 ON_COMMAND(ID_GRAPH_FIRST,OnGraphFirst) //重画首屏 ON_COMMAND(ID_GRAPH_ALL,OnGraphAll) //重画全屏 ON_COMMAND(ID_SELECT_MOUSE,OnSelectMouse)//图形选中 ON_COMMAND(ID_SELECT_CLEAR,OnSelectClear) //放弃选中 ON_COMMAND(ID_SELECT_DELETE,OnSelectDelete)//删除选中图形5.2图形操作的具体实现图形重画所谓图形重画,就是把当前视图屏幕重新绘制一次,实际上也就是让视图类的函数OnDraw(CDC*pDC)重新执行一次。根据需要重画区域的不同,图形重画可以分为全屏重画和局部重画。⑴全屏重画 在有些情况下,需要将当前视图屏幕全屏重画。全屏重画有两种方法,一种是使用函数UpdateAllViews,使属于当前文档对象的所有视图重画。另外一种方法即是用函数Invalidate,使当前视图屏幕的客户区失效,从而激活图形重画。两种方法的不同点为:Invalidate函数它只能使当前视图重画,而与其同文档的其他视图并不重画。对视图类CDrawView的OnGraphRedraw函数进行修改。具体代码如下:VoidCDrawView::OnGraphRedraw() { CDrawDoc*pDoc=GetDocument(); pDoc->UpdateAllViews(this); Invalidate(); } OnGraphRedraw函数首先得到指向当前文档对象的指针,然后调用UpdateAllViews函数重画此文档对象所有的视图,参数this是指向当前视图对象的指针。⑵局部重画 如果只希望将当前视图屏幕的一局部区域重画,即进行局部重画。在VC++中,Invalidate与RectInvalidateRgn两个函数可以完成此功能。两个函数的定义如下:VoidInvalidateRect(LPCRECTlpRect,BOOLbErase=TRUE); //lpRect中存储着视图中需要重画的区域,参数bErase用于指定当区域重画时,背景是否擦除voidInvalidateRgn(CRgn*pRgn,BOOLbErase=TRUE);图形放大和移动1.图形放大 图形放大指的是通过调整视图屏幕,使当前视图屏幕中的一局部区域放大显示到整个视图屏幕中15]。矢量图形系统应具有无级放缩的功能。所谓“无级〞,指的是图形能以任何的比例进行显示。在应用程序Draw已经建立的坐标系根底上,可以很容易实现图形的无级放大。实现图形放大的操作方法很多:如可以进行固定比例的图形放大;再如可以通过窗口放大。本设计将涉及到用窗口放大图形的操作方法和具体实现步骤。在此根底上,可以轻而易举的实现其他方法的图形放大操作功能。实现图形放大、移动后的效果图分别如图5-3、图5-4所示:图5-3图形绘制〔放大前〕图5-4图形绘制〔放大后〕2.图形移动 图形移动指的是将图形元素在横向和纵向上移动一定的偏移量,得到移动后图形元素的坐标。图形移动操作功能的机理非常简单,只需将各类图形元素的特征点做相应的坐标移动即可。⑴各类图形元素的移动操作 为了实现图形元素的移动功能,同样需要在图形元素基类CDraw中定义一个纯虚函数:virtualvoidMove(floatx_Move,floaty_Move)=0; 在各个图形元素类中增加这个虚函数的重载定义,在各个图形元素类的实现文件中,参加这个重载函数的实现代码。⑵实现图形移动操作功能 图形移动功能的操作步骤如下:首先用“鼠标点中〞操作选中要移动的图形元素,按下鼠标左键点中移动操作的基点,再按下鼠标左键点中移动操作的目标点,各个图形元素将以这两个点为根底进行相对移动。在OnEditMove函数中,对图形移动操作进行了标识,为了实现具体的移动操作,需要对各个鼠标消息处理函数进行修改。在实现文件drawview.cpp的消息处理函数OnLButtonDow、OnMouseMoven、OnRButtonDown中参加相应的实现代码。图形移动的效果图如图5-5、图5-6所示:图5-5图形绘制〔移动前〕图5-6图形绘制〔移动后〕重画上屏和重画首屏图形经过放大、移动操作后,还要有把图形屏幕再恢复到前一屏幕〔重画上屏〕或者直接使图形回到第一屏〔重画首屏〕的功能。要实现重画上屏和重画首屏的功能,就需要记录下每一屏幕的状态,并时刻跟踪着当前的状态。记录屏幕状态: 一个图形屏幕是由三个参数来确定的:屏幕左下角原点的坐标m_xStart、m_yStart和显示比例blc,在文档类CDrawDoc中定义一个结构数组来存储历史图形屏幕。在CDrawDoc类中定义以下几个变量:Public: intm_CurrentScreen;//当前屏幕的序号 intm_MaxScreen;//最多能存储的屏幕数 ScreenStruct*m_Screen;//记录屏幕参数的结构数组结构ScreenStruct在头文件drawdoc.h中CDrawDoc类定义前定义:Typedefstruct {Floatblc;//显示比例Floatsx;//屏幕左下角横坐标Floatsy;//屏幕左下角纵坐标 }ScreenStruct;在文档类CDrawDoc中定义一个函数,来完成存储一个图形屏幕状态的操作功能:Public:VoidAddScreen(floatStartX,floatStartY,floatblc); 在实现文件drawdoc.cpp中,参加函数的实现代码。⑴重画上屏 要实现重画上屏操作功能,只需把m_CurrentScreen的值减去1,从结构数组m_Screen中取出屏幕参数重画图形即可。在实现文件drawview.cpp中,将“重画上屏〞菜单项的消息处理函数OnGraphUp的实现代码修改如下:voidCDrawView::OnGraphUp(){CDrawDoc*pDoc=(CDrawDoc*)GetDocument();if(pDoc->m_CurrentScreen>0)//如果当前不是首屏,当前图形屏幕序号减1pDoc->m_CurrentScreen--;//得到上一屏幕的图形参数并重画图形m_xStart=p_Screen[pDoc->m_CurrentScreen].sx;m_yStart=p_Screen[pDoc->m_CurrentScreen].sy;blc=p_Screen[pDoc->m_CurrentScreen].blc;Invalidate();//重画图形}p_Screen是CDrawView类中定义的指向文档对象中的结构数组m_Screen的指针,它在 视图类CDrawView中定义ScreenStruct*p_Screen; 在实现文件drawview.cpp中,在重载的虚函数OnActiveView中对p_Screen进行初始化,将它指向当前文档对象中的结构数组m_Screen:voidCDrawView::OnActivateView(BOOLbActivate,CView*pActivateView,CView*pDeactiveView){p_View=this;CDrawDoc*pDoc=(CDrawDoc*)GetDocument();p_Screen=pDoc->m_Screen;CView::OnActivateView(bActivate,pActivateView,pDeactiveView);}⑵重画首屏 对于重画首屏功能来说,只要取出存储在结构数组m_Screen中的首屏参数,并对视图重画即可。修改实现文件drawview.cpp中的消息处理函数OnGraphFirst,得到实现代码如下:voidCDrawView::OnGraphFirst()//重画首屏{//TODO:AddyourcommandhandlercodehereCDrawDoc*pDoc=GetDocument();if(pDoc->m_CurrentScreen==0)return;m_xStart=p_Screen[0].sx;m_yStart=p_Screen[0].sy;blc=p_Screen[0].blc;pDoc->AddScreen(m_xStart,m_yStart,blc);Invalidate();}显示全图在矢量图形系统中,随着一些图形元素通过外部接口或者系统本身的绘制功能的参加,图形首屏可能包含不了所有的图形元素;还有一种情况是,图形中所有的图形元素都在视图屏幕的一个角上,只占图幅的一小局部。这是就需要一个操作功能,调整视图屏幕左下角原点的实际坐标(m_xStart,m_yStart)和显示比例blc,使所有的图形元素正好能够绘制到视图屏幕中〔在屏幕上留有一局部边界区域〕,显示全图功能就是为完成此功能而设置的。实现显示全图功能的思路是,通过得到每一类图形元素〔如直线、连续直线〕的边界矩形,然后根据视图屏幕的大小〔逻辑坐标〕进行计算,得到屏幕的参数m_xStart,m_yStart,blc.所以,解决问题的关键在于得到各类图形元素的边界矩形。各类图形元素的边界矩形计算: 在图形元素基类CDraw中定义一个纯虚函数:VirtualvoidGetRect(float*minx,float*minY,float*maxX,float*maxY)=0; 函数GetRect用来计算图形元素的边界矩形,〔*minX,*minY〕和〔*maxX,*maxY〕这四个指针参数用来返回边界矩形的最小和最大坐标。 在由CDraw类派生的各个图形元素类中重载虚函数GetRect,即在各个类中参加以下定义代码:VirtualvoidGetRect(float*minx,float*minY,float*maxX,float*maxY);并在各个图形元素类中实现代码,以完成计算各类图形元素边界矩形的功能。实现显示全图功能:⑴得到所有图形元素的边界矩形 把所有图形元素的边界矩形坐标进行比拟,就可以得到所有图形元素的边界矩形。为了实现这个功能,在文档类CDrawDoc中定义一个Public函数:BOOLGetRect(float*m_Xmin,float*m_Ymin,float*m_Xmax,float*m_Ymax); 指针参数用来返回边界矩形的最小和最大坐标,当能计算得到边界矩形时,函数返回TRUE,否那么,函数返回FALSE.在实现文件drawdoc.cpp中,参加这个函数的实现代码在函数GetRect中,首先对记录最小值和最大值的变量初始化,然后对所有的直线连续直线圆圆弧标注文本多边形区域网络点等类图形元素进行循环,得到每个图形元素的边界矩形,并比拟运算得到所有图形元素的边界矩形。当至少有一个图形元素时,函数返回TRUE,没有任何图形元素时,函数返回FALSE.⑵实现显示全图功能 在得到所有图形元素的边界矩形后,就可以调整视图屏幕的基点和比例,使当前视图正好能够绘制下所有的图形元素。在实现文件drawview.cpp中,对菜单项“重画全屏〞的消息处理函数OnGraphAll进行修改:voidCDrawView::OnGraphAll(){//TODO:Addyourcommandhandlercodeherefloatminx,miny,maxx,maxy,bl1;CDrawDoc*pDoc=GetDocument();SetCapture();SetCursor(LoadCursor(NULL,IDC_WAIT));BOOLpb=pDoc->GetRect(&minx,&miny,&maxx,&maxy);SetCursor(LoadCursor(NULL,IDC_ARROW));ReleaseCapture();if(!pb)return;bl1=(maxx-minx)/(m_wScreen-20);blc=(maxy-miny)/(m_hScreen-20);if(bl1>blc)blc=bl1;m_xStart=minx-10*blc;m_yStart=miny-10*blc;p_Screen[0].sx=m_xStart;p_Screen[0].sy=m_yStart;p_Screen[0].blc=blc;pDoc->m_CurrentScreen=0;Invalidate();}图形重画速度的提升⑴提高图形重画速度的方法 一个根本的方法就是在显示一个图形元素前,对这个图形元素进行判断,判断这个图形元素是否在视图屏幕中,如果这个图形元素不在当前的视图屏幕中,就不用对这个图形元素进行绘制,以此节省绘制时间。 我们采用的计算方法应该是计算简单且允许不太严密。这里所谓的不太严密,指的是用这种方法判断是在视图屏幕中的图形元素,实际也可能不在视图屏幕中,而经过判断不在视图屏幕中的图形元素一定不在视图屏幕中。这种判断一般采用这个图形元素的边界矩形和屏幕边界矩形是否相交的方法。 在提高图形重画速度时,首先要得到视图屏幕即客户区的大小。在应用程序Draw中,在视图类CDrawView中有两个变量m_hScreen和m_wScreen分别用来存储当前视图的高度和宽度〔逻辑坐标〕。在进行图形绘制前,把视图屏幕矩形有逻辑坐标转换成实际坐标。定义以下四个全局变量,用来传递要绘制视图的左下角和右上角的实际坐标。在实现文件drawdoc.cpp中,增加全局变量的定义:FloatxMinScreen,yMinScreen,xMaxScreen,yMaxScreen;为了在实现文件drawview.cpp中使用这些变量,在实现文件drawview.cpp中增加对这些全局变量的引用:ExternfloatxMinScreen,yMinScreen,xMaxScreen,yMaxScreen这四个全局变量在每次调用OnDraw函数实现视图的绘制功能前被初始化。在实现文件drawview.cpp中的绘制函数CDrawView::OnDraw(CDC*pDC)中参加代码,实现在每次绘制前得到视图屏幕边界的实际坐标:voidCDrawView::OnDraw(CDC*pDC){CDrawDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);//TODO:adddrawcodefornativedataherexMinScreen=m_xStart;yMinScreen=m_yStart;xMaxScreen=xMinScreen+blc*m_wScreen;yMaxScreen=yMinScreen+blc*m_hScreen;DrawBack(pDC);pDoc->Draw(pDC,0,0,m_bColor);m_MapMode=pDC->SetMapMode(1);}这样在以当前的屏幕参数〔m_xStart,m_yStart,blc〕绘制图形前,把视图屏幕的左下角和右上角的实际坐标计算出来。 为判断一个矩形区域与视图屏幕矩形是否相交,在drawdoc.cpp中定义一个全局函数:BOOLIsRectCross(floatminx,floatminy,floatmaxx,floatmaxy);函数的实现代码如下:BOOLIsRectCross(floatminx,floatminy,floatmaxx,floatmaxy){if(minx>xMaxScreen||maxx<xMinScreen||miny>yMaxScreen||maxy<yMinScreen) returnFALSE;//如两个矩形不相交else returnTRUE;}IsRectCross函数在一个矩形区域与视图屏幕区域相交时返回TRUE,否那么返回FALSE.⑵提高图形元素的绘制速度 对各类图形元素的绘制函数Draw进行修改,使其能够先判断图形元素的边界矩形是否与图形屏幕区域相交,来决定是否需要对图形元素进行绘制。在直线类CLine的绘制函数Draw中,参加完整实现代码,对于CCircle、CArc、CText、CPline、CPlineRgn、CTag、CLinkNet等图形元素类,同样也需要在其绘制函数Draw中参加相同的代码。5.3图形的点选与撤销鼠标点选图形元素为了实现图形的删除和恢复等操作功能,首先应该在矢量图形系统中实现图形的选中操作。对于一个矢量图形系统来说,不但要能够实现交互图形绘制、放缩操作等,还应有一项根本的功能,就是能够选中图形元素。选中图形元素是对图形进行修改删除直接从图形上得到信息〔在GIS中〕,以及在GIS中实现空间统计和分析功能等操作的根底。各种图形元素的选中区域:⑴直线和连续直线 因为直线是没有宽度的,所以,这种选中判断实际上是要判断一个点与一条直线的距离是否在一定的距离范围之内。问题的实质就是,如何确定这个判断选中的距离范围和怎样计算一个点与一条直线的距离。点与直线距离的计算方法 为了完成计算点到直线距离的功能,需要定义一个函数,为了在直线和连续直线类中都能够使用这个函数,在图形元素基类CDraw中定义一个Public函数:floatPointLine(floatxx,floatyy,floatx1,floaty1,floatx2,floaty2);函数的参数分别是选中点与直线两个顶点的实际坐标,函数返回计算得到的距离值。在实现文件draw.cpp中,参加函数实现代码。在上述函数中,调用了一个在CDraw类中定义的计算两点距离的函数CalDisp,:FloatCalDisp(floatx1,floaty1,floatx2,floaty2);⑵圆和填充圆 圆的选中区域非常简单,如果有效距离为j1,计算得到的鼠标按中点到圆心的距离为jl1;选中区域就是: |jl1-circle.r|<jl;即按中点到圆的距离小于jl.对于填充圆,选中区域那么是:Jl1<=jl;⑶圆弧 圆弧的选中区域同圆类似,首先要确定按中点是否在圆弧所在的圆上。即按中点到圆心的距离jl1符合: |jl1-circle.r|<jl;因为圆弧不是封闭的,还要确定按中点相对于圆心的弧度是否在圆弧的弧度范围内,可以通过CArc类中的成员函数IsInArc函数来确定。⑷多边形区域 图形元素多边形区域和标注文本〔四边形〕都属于这种情况。最简单的多边形区域就是没有旋转的矩形〔如水平标注的文本就是这种情况〕,判断一个点是否在这种矩形中的算法非常简单。VC++的CRgn类提供了一个成员函数来实现这个操作功能。CRgn类封装了一些进行区域操作的函数,可以直接解决按中点是否在多边形区域中的问题。以下是操作步骤:首先定义一个CRgn对象;把CRgn初始化成一个具有n个顶点的多边形区域;建立一个多边形区域后,调用PtInRegion函数来判断一个点是否在区域内。函数PtInRegion是CRgn类的成员函数,它可以判断点是否在初始化区域内。在CDraw类中建立一个函数完成这个操作:Public: BOOLPointRgn(floatx,floaty,intNumble,PointStruct*PointList,floatblc); //判断点是否在初的区域内在实现文件draw.cpp中,参加函数的实现代码各种图形元素的点选判断函数首先,在图形基类CDraw中定义一个纯虚函数:Public:VirtualBOOLIsPoint(floatx,floaty,floatjl,floatblc)=0; 在各个图形元素类CLineCCircleCArcCTextCPlineCPlineRgnCLinkNet中重载虚函数IsPoint,即在这些类中参加这个函数的重载定义:Pubic:VirtualBOOLIsPoint(floatx,floaty,floatjl,floatblc);然后实现各个图形元素类重载的IsPoint函数的实现代码,实现各个图形元素类的点选判断功能。实现点选图形元素功能⑴增加一个菜单及消息处理函数⑵保存选中的图形元素 要实现数据保存,就需要建立数据结构来存储选中的图形元素。在文档类CDrawDoc中,定义一个结构数组和一个变量:Protected: GraphSelectStruct*GraphSelect;//存储选中的图形元素Intn_GraphSelect;//选中图形元素的数目结构GraphSelectStruct在头文件drawdoc.h中〔CDrawDoc类前〕定义为:Typedefstruct{ShortintLb;IntIndex;Intid_only;}GraphSelectStruct; 将选中的图形元素存储在结构数组GraphSelect中,成员变量Lb存储选中图形元素的类别;成员变量Index存储图形元素的序列号,即图形元素在指针数组中的下标;成员变量id_only存储这个图形元素惟一的识别号,即图形元素中的成员变量m_id_only。在实现文件drawdoc.cpp中,在CDrawDoc文档类的构造函数内动态分配结构数组GraphSelect: CDrawDoc::CDrawDoc() { GraphSelect=newGraphSelectStruct[10000]; }在CDrawDo类的析构函数中,删除动态分配的结构数组: CDrawDoc::~CDrawDoc() {DeleteGraphSelect; } 为了将一个选中的图形元素存储到结构数组GraphSelect中,在文档类CDrawDoc中定义一个函数:Public: BOOLAddSelectList(intLb,intindex,intid_only); 函数AddSelectList实现在结构数组GraphSelect中增加一个选中的图形元素,增加成功是返回TRUE,否那么函数返回FALSE.函数的实现代码如下:BOOLCDrawDoc::AddSelectList(intLb,intindex,intid_only){for(inti=0;i<n_G
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025~2026学年河南省安阳市滑县人教版六年级上册12月月考数学试卷【附答案】
- 2025~2026学年安徽合肥市庐江县苏教版第二册四年级数册末质量检测试卷(A卷)【附答案】
- 2025-2026学年四川省攀枝花市初中历史九年级期末下册自我评估黑金试卷(附答案)
- Photoshop二级考试试题及详细答案
- 2025-2026学年山东省新泰市初中历史七年级期末下册提升黑金试题(详细参考解析)
- PC电脑基础知识测试题(含详细答案)
- 围绝经期潮热睡眠联合干预实操方案共识
- 杠杆专题-新疆哈密市第四中学2027届七上数学期末教学质量检测模拟试题含解析
- PAP全国公共英语二级考试模拟试题(完整版)
- (2026年)仓库保管员(初级工)理论考试题库(含答案)
- 2026“外研社·国才杯”“理解当代中国”外语能力国际传播综合能力赛项真题及答案解析(10月11日上午场次)
- 2026年七年级数学竞赛试题及答案
- 老年患者呼吸困难护理
- 2026年物流师职业能力等级认证考试(中级)考前冲刺试题及答案
- 小学英语外研版 (三年级起点)六年级下册Unit 1 He spent about twenty-one hours in space.教案
- Unit 6 Enjoy Cycling Topic 3 Bicycle riding is good exercise Section A 教学设计 -仁爱版英语八年级下册
- 2026胸腔闭式引流护理团体标准
- 建筑工程竣工验收报告贵州版
- ASD辩证行为疗法(DBT)青少年方案
- 《允许一切发生》读书感悟
- 邮轮餐饮服务双语实训指导-西餐宴会服务常见问题
评论
0/150
提交评论