GIS系统的开发与设计.docx
《GIS系统的开发与设计.docx》由会员分享,可在线阅读,更多相关《GIS系统的开发与设计.docx(48页珍藏版)》请在冰豆网上搜索。
GIS系统的开发与设计
GIS系统的开发与设计
1 实现图形系统的文档和视图
1.1 组织矢量图形系统的图形元素类
城市的信息化为城市GIS发展带来了机遇。
实际上,城市信息化表现为政府管理与决策的信息化(数字政府),企业管理、决策与服务的信息化(数字企业),市民生活的信息化(数字城市生活),即“数字城市”。
由此可见,城市GIS是“数字城市”最核心的部分,可以分为政府GIS、企业GIS和社会GIS。
“数字城市”的发展,要求政府、企业和社会GIS通过数据通信网络将政府、企业和社会联成一个整体,实现资源的共享。
历史给了我们中国人特殊的超越他人的机遇。
美国人、加拿大人、西欧人在通讯基础设施,政府、企业信息系统建设,信息系统互联互通,以及网络社会、网络社区四个阶段循序渐进的发展中占尽先机。
但是当时的3维GIS技术、VR技术、4D数据融合集成技术、GIS三维表现技术都没有像今天这样成熟和廉价。
访遍美国、西欧、加拿大、澳洲的城市政府网站,基于4D数据、三维表现、借助虚拟现实技术的凤毛麟角。
时间和市场为我们创造了超越的重大历史机会。
这个机会就是数字城市中三维和VR技术的开发和应用。
抓住机遇,我国的数字城市将大放异彩。
我们认为中国的数字城市特色应该定位在:
建设具有4D数据的城市基础地理信息公共平台;建设以3维和VR技术为主的城市规划、建设和管理业务专业应用系统。
集中抢占数字城市“43VR”的技术应用战略制高点,形成中国数字城市“43VR”的特色,开拓中国数字城市独特的市场空间[10]。
面向对象的程序设计,是目前程序设计的主流方法,在本设计中,将利用面向对象的程序设计和C++类的组织方法,组织建立一个基本矢量图形的图形元素类。
组织实现的矢量图形系统,能够处理点类、线类、面类、网络点等类别的图形元素,其中点类图形元素有包括直线,圆,圆弧,子图,标注文本等图形元素,针对每类图形元素组织建立起对其进行管理的C++类,并把每个图形元素作为一个独立的对象来管理。
1.1.1 图形元素基类的组织
对各类图形元素进行分析,可以发现各类图形元素具有一些相同的属性和操作功能,如图形元素的颜色、线型线宽所在层等属性和得到一个图形元素是否做了删除标志等操作。
把这些图形元素中共性的东西(属性和操作),组织存放在一个图形元素基类(CDraw)中,具体的图形元素由这个基类来派生。
1.1.2 点类图形元素组织[5]
对于点类图形元素,其基本特性是各个图形相互独立,且每个图形元素具有有限个固定的特征点。
直线的基类是CDraw.,在直线类的构造函数中,共有包括11个参数,并利用前7个参数调用基类CDraw的构造函数,对基类的成员变量进行初始化,而在本身的构造函数中对直线类CLine自身的四个参数(直线的起点和终点)进行了初始化。
对圆类的创建方法与直线类CLine类似,圆除了具有图形元素的基本特征外,还有自身的几何特性,可以用圆心和半径作为特征参数表示圆的几何特性。
圆是圆弧的一个特例,当圆弧的弧度等于2时就是圆。
所以可以从一个圆类派生得到一个圆弧类。
矢量图形中可以有大量的标注文本,标注文本除了具有图形元素的基本特性外,还具有位置、字体及标注内容等自身的信息。
CText类也有两个构造函数,第二个构造参数有多个参数,并利用多个参数对类的成员变量进行初始化。
在构造函数中,调用了基类CDraw的构造函数对基类CDraw的成员变量进行初始化。
子图是各类图形元素的集合体,是由多个图形元素组成的整体。
为了在图形中插入子图,必须首先建立起管理子图所包含的图形元素的类,形成一个子图定义体,将选定的子图块以一定的横纵比例插入到图形中指定的位置,就形成了一个子图块。
1.1.3 线类图形元素组织
线类图形元素包括很多种,如连续直线、混合线、树状线等,在本设计中,以最简单的连续直线为例进行讨论,对于其他类型线的实现方法,可根据连续直线的实现方法来开发。
连续直线除了具有图形元素基类所具有的属性外,从图形的几何特征上,连续直线是由很多顶点组成的,而且顶点数目是不确定的。
一条连续直线可能只有两个顶点,也可能有几千个顶点。
所以,需要定义一个结构来存储连续直线的一个顶点坐标。
1.1.4 面类图形元素的组织[10]
面类图形元素一般是由闭合线围成的区域。
根据围成面的边界不同,有不同形式的面,如圆形区域椭圆形区域复合线区域多边形区域等。
最常用的面是多边形区域,其边界由一条连续直线组成。
因为另外各种类型面的边界一般都可以用连续直线来近似描述,所以,本设计只讨论多边形区域的实现方法。
在描述多边形区域时,最主要的是要描述边界顶点坐标。
描述面的边界顶点坐标时,有不同的描述方法,一种方法是将边界由几段连续直线来描述。
另外一种描述方法是直接存储区域的边界顶点坐标,即把区域的整个边界作为一条连续直线来存储。
这种方法的缺点是造成坐标的重复存储;优点是具有较强的独立性,不用考虑组成区域的连续直线段。
在本设计中,采用直接存储边界坐标的方式。
用这种方式组织多边形区域时,组织方式与连续直线类似。
所以,可以由连续直线类CPline派生出一个CPlineRgn类,来对多边形区域进行管理。
1.1.5 网络类图形元素的组织
网络分析是GIS的一项非常重要的基本功能,最佳路径分析、最佳游历路径分析、连通分析、资源分配等都需要有网络类图形元素对网络进行描述、显示和分析。
为了能够对网络进行描述和处理,在系统中增加一类图形元素来描述有方向、无转角的网络图。
这类图形元素称为网络点。
1.1.6 图形参数类
在矢量图形系统中,图形参数是集中存储的。
在图形元素基类中成员变量m_ColorPen,m_ColorBrush等存储的是颜色列表的序列号,m_Layer中存储的也是在图层列表中的序列号。
1.2 组织矢量图形系统的文档
1.2.1 组织面向对象的文档管理机制
管理矢量图形系统图形数据的方法即文档管理机制。
在本设计的开发中,采用一套完全面向对象的文档组织机制。
这种机制就是通过图形元素类创建很多图形元素对象,每个图形元素对象作为一个整体来组织存储空间的分配、存取等各种管理功能。
然后通过建立一种存储机制,来管理指向所有图形元素对象的指针,达到管理所有图形元素对象的目的。
这种文档管理机制具有组织简单结构化和移植性好,以及比较容易利用VC++程序设计语言的开发功能等优点。
缺点是需要较大的内存空间。
1.2.2 利用MFC摸板创建管理图形元素对象指针的对象
管理一个矢量图形系统文档的思路是:
每个图形元素是图形元素类创建的一个对象,在创建这个对象时得到指向这个对象的指针,建立一个对象指针数组来管理这些指针,以达到管理所有图形元素对象的目的。
在VC++下可以较容易地实现对指向图形元素对象的指针的组织和管理。
在MFC中有一个类模班CTypedPtrArray,可以用它来创建一个管理类指针的对象。
例如,可以定义一个管理CLine类指针的对象如下:
CTypedPtrArraym_LineArray;[10]
1.2.3 实现矢量图形系统的文档
在应用程序Draw中,可以派生几个CObArray对象来分别管理基类图形元素。
在文档类CDrawDoc中创建几个管理各类图形元素对象指针的CObArray对象如下:
private:
CTypedPtrArraym_LineArray;
CTypedPtrArraym_CircleArray;
CTypedPtrArraym_ArcArray;
CTypedPtrArraym_TextArray;
CTypedPtrArraym_TagArray;
CTypedPtrArraym_PLineArray;
CTypedPtrArraym_PLineRgnArray;
CTypedPtrArraym_NetArray;
1.2.4 实现文档的管理功能
⑴增加图形元素
在应用程序Draw中增加一个图形元素对象(如一条直线)时,需要进行以下两个步骤的操作:
1首先需要创建一个图形元素对象,并用图形元素的实际数据初始化这个图形元素对象。
如增加一条直线时,需要创建一个CLine对象,并用这条直线的实际数据(起终点、所在图层、颜色等)初始化这个CLine对象的成员变量。
2然后需要把指向新创建的图形元素对象的指针,增加到文档类中管理图形元素对象指针的对象中。
如增加一条CLine对象后,需要把指向这个CLine对象的指针增加到文档类的m_LineArray对象中。
为了实现增加各类图形元素的功能,在文档类CDrawDoc中定义几个函数,
分别来完成增加各类图形元素的操作功能[3]
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);
CPlineRgn*AddPLineRgn(shortColorPen,shortColorBrush,floatLineWide,shortLineType,shortLayer,intid_only,intNumble,PointStruct*PointList,BOOLbTransparent,BOOLbFill);
CLinkNet*AddNetPoint(floatx,floaty,floatrRadiu,shortLayer,intid_only,shortColorPen);
这8个函数分别用来实现增加一条直线、一个圆、一个圆弧、一个标注文本、一个子图、一条连续直线、一个多边形区域、一个网络点的功能。
函数返回指向新增图形元素对象的指针。
⑵得到指向图形元素对象的指针
在一个矢量图形系统中,有大量的图形元素,指向图形元素对象的指针被保存在文档类对应的CObArray对象中。
在系统的操作过程中,为了实现对图形元素的各种操作功能,需要得到指向指定图形元素对象的指针,为此,在文档类CDrawDoc中定义一个函数GetGraph如下:
Public:
CDraw*GetGraph(shortLb,intindex);
在实现文件drawdoc.cpp中,加入函数的具体实现代码。
⑶删除图形元素对象
为了能够从CObArray对象中删除一个指定图形元素对象指针,在文档类CDrawDoc中定义一个成员函数:
Public:
VoidDeleteGraph(shortLb,intindex);
在实现文件drawdoc.cpp中,加入函数的具体实现代码。
⑷得到各类图形元素的数目
为了能够随时得到文档中各类图形元素对象的数目,在文档类CDrawDoc中,定义一个成员函数如下:
Public:
IntGetGraphNumb(shortLb);
在实现文件drawdoc.cpp中,加入函数的具体实现代码。
⑸得到存储各类图形元素CObArray对象数组的最大下标
在对各个图形元素类的所有图形元素进行操作时,需要得到存储在各个CObArray对象中的最大数组下标,然后对各个数组项实现遍历操作。
为了得到存储在各个CObArray对象中的最大数组下标,在文档类CDrawDoc中定义一个函数如下:
Public:
IntGetGraphUpperBound(shortLb);
在实现文件drawdoc.cpp中,加入函数的具体实现代码。
⑹得到某个识别号的图形元素对象指针在CObArray数组中的存放位置
Public:
IntGetGraphIndex(shortLb,intID);
在实现文件drawdoc.cpp中,加入函数的具体实现代码。
⑺增加网络连接
对于一个网络点来说,其最主要的特性就是指向其他网络点的连接。
为了增加网络连接,首先在CNet类中定义一个增加网络连接的函数AddLink;
Public:
VoidAddLink(intnID);
函数的参数是连接要指向的网络点的识别号;
在文档类CDrawDoc中定义一个函数AddNetLink,实现在一个网络点中增加一个指向另外一个网络点的连接。
在实现文件drawdoc.cpp中,加入函数的具体实现代码。
1.3 实现矢量图形系统的视图
1.3.1 建立坐标系
⑴建立坐标系
该坐标系取屏幕的左下角点作为图形屏幕的基点。
客户区的左下角的坐标定义为(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中,定义四个全局函数如下:
VoidDPtoVP(floatx,floaty,int*X,int*Y);
VoidVPtoDP(intx,inty,float*X,float*Y);
IntDLtoVL(floatl);
IntVLtoDL(intl);
以上四个全局函数利用视图类指针p_View调用视图类的四个坐标转换函数,来完成坐标和长度的转换功能。
如果在某个实现文件中使用这四个全局转换函数,只需在这个实现文件中的开始处加入全局函数的外部引用:
ExternVoidDPtoVP(floatx,floaty,int*X,int*Y);
ExternVoidVPtoDP(intx,inty,float*X,float*Y);
ExternIntDLtoVL(floatl);
ExternIntVLtoDL(intl);
在四个全局函数中,p_View指向当前激活的视图对象。
p_View是一个在实现文件drawview中全局定义的视图类指针。
1.3.2 实现各类图形元素的绘制功能
利用虚函数实现各种图形元素的绘制功能。
在图形元素基类CDraw中,抽象定义一个进行绘制操作的虚函数。
因为在应用程序Draw中,不用CDraw类直接来创建对象,所以可以将虚函数定义成纯虚函数:
[8]
Public:
VirtualvoidDraw(CDC*pDC,intm_DrawMode,intm_DrawModel,shortBackColor)=0;
在各种图形元素类CLineCCircleCArcCTextCTagCPlineCPlineRgnCLinkNet中,重载虚函数Draw:
public:
virtualvoidDraw(CDC*pDC,intm_DrawMode,intm_DrawModel,shortBackColor);
1.3.3 实现视图
为了实现应用程序Draw的图形绘制工作,在文档类CDrawDoc中定义Draw函数如下:
public:
voidDraw(CDC*pDC,intm_DrawMode,intm_DrawModel,shortBackColor);
1.4 各类图形元素几何属性的计算
以上定义的各类图形元素,除了坐标数据外,还有一些最基本的几何特征,其中最主要的两个特征是长度和面积.为了计算各类图形元素的长度和面积,在图形元素基类CDraw中定义了两个虚函数:
protected:
virtualvoidCalLong();
virtualvoidCalArea();
直线圆圆弧连续直线等图形元素都具有长度属性.在CLineCircleCarcCpline类中重载计算长度的虚函数CalLong:
protected:
virtualvoidCalLong();
图形元素圆和多边形区域具有面积属性.在CCircle类和CPlineRgn类中重载CalArea函数.
2 鼠标交互绘图
2.1 用鼠标绘图要解决的主要问题
2.1.1 捕获鼠标操作消息
VC++提供了足够的窗口消息和已经保护的消息处理函数解决这个问题.在应用程序Draw中实现鼠标交互绘制图形元素时,将主要用到以下三个鼠标操作:
鼠标移动:
OnMouseMove(UINTnFlags,CPointpoint)WM_MOUSEMOVE
按下左键:
OnLButtonDown(UINTnFlags.CPointpoint)WM_LBUTTOND
按下右键:
OnRButtonDown(UINTnFlags.CPointpoint)WM_RBUTTONDOWN
2.1.2 捕捉所有的鼠标输入
在用鼠标交互绘制一个图形元素时,在已经开始绘图的情况下,不希望还能进行别的操作,以避免造成系统流程和变量初始化等方面的错误.VC++提供了两个成员函数来满足以上的功能需求:
CWnd:
:
SetCapture();
CWnd:
:
ReleaseCapture();
2.1.3 在屏幕上拖动图形
在用鼠标交互绘制图形元素时,为了直观的看到所绘制的图形,一般采用拖动图形的方法.
2.1.4 保存图形数据到文档
用鼠标在屏幕上交互绘制的图形元素,要创建一个图形元素对象并将指向这个图形元素对象的指针保存起来.
2.1.5 将图形以实际的形态重画
用鼠标交互绘制一个图形元素后,要在屏幕上马上显示出这个图形元素的实际形态,必须将图形元素以实际的形态重画.因为在VC++的R2_NOT绘制模式下,线条不是彩色的,拖动的图形都不是用图形元素的实际颜色.必须对图形元素以实际形态进行重画.在矢量图形系统设计中,一般采用CClientDC对象,在交互绘制图形元素操作完成后,即时在视图中重画这个新增的图形元素.
2.2 交互绘制各类图形元素
本设计主要实现交互绘制直线、圆、填充圆、圆弧、标注文本、连续直线、多边形区域、网络点的实现过程.
2.2.1 加入绘图菜单
1增加菜单资源.
在应用程序Draw的菜单资源中,增加一个菜单”鼠标绘图”.在这个菜单中包含直线圆填充圆圆弧标注文本连续直线多边形区域网络点网络连接等九个菜单项.
⑵
①增加菜单的消息处理函数
afx_msgvoidOnSize(UINTnType,intcx,intcy);
afx_msgvoidOnMouseMove(UINTnFlags,CPointpoint);
afx_msgvoidOnLButtonDown(UINTnFlags,CPointpoint);
afx_msgvoidOnRButtonDown(UINTnFlags,CPointpoint);
afx_msgvoidOnDrawArc();
afx_msgvoidOnDrawCircle();
afx_msgvoidOnDrawCircle1();
afx_msgvoidOnDrawLine();
afx_msgvoidOnDrawPline();
afx_msgvoidOnDrawPlineRgn();
afx_msgvoidOnDrawText();
afx_msgvoidOnDrawNet();
afx_msgvoidOnDrawNetLink();
②在实现文件drawview.cpp中,增加了函数的消息映射机制:
ON_COMMAND(ID_DRAW_ARC,OnDrawArc)
ON_COMMAND(ID_DRAW_CIRCLE,OnDrawCircle)
ON_COMMAND(ID_DRAW_CIRCLE1,OnDrawCircle1)
ON_COMMAND(ID_DRAW_LINE,OnDrawLine)
ON_COMMAND(ID_DRAW_PLINE,OnDrawPline)
ON_COMMAND(ID_DRAW_RGN,OnDrawPlineRgn)
ON_COMMAND(ID_DRAW_TEXT,OnDrawText)
ON_COMMAND(ID_DRAW_NET,OnDrawNet)
ON_COMMAND(ID_DRAW_NET_LINK,On