【OOP】实验9 GIS矢量图形系统
作者:3sbase | 发布时间:2016/3/19

一、实验类型

    设计型

二、实验目的与要求

1、实验目的

    学习基于VC++ MFC开发环境开发简单GIS矢量图形系统的方法

2、实验要求

能够编写简单的矢量绘图系统:能够画点和直线,课后可以尝试实现图形的放大、缩小和漫游操作及保存等功能。

三、上机准备

1、实验室安装VC++6.0软件。

2、学习VC++相关教程。

3、学习VC++开发GIS矢量图形系统方面的书籍。

四、实验内容

编写简单的矢量绘图系统:能够画点和直线,程序运行界面如下图。

10-1 程序运行界面

1、基于类向导生成图元基类(CFigure)、点类(CMapPoint)和直线类(CLine)

建立单文档应用程序。

B Insert菜单下有一个新建类向导。在其中选择Class typeGeneric ClassName为你要建立的类的名字,Derived From下边写基类的名字。图中建立了一个CFigure类,从CObject类派生。

修改生成两个文件,内容如下:

// Figure.h: interface for the CFigure class.

//

//////////////////////////////////////////////////////////////////////

 

#if !defined(AFX_FIGURE_H__4DBE20D7_A090_4437_8FA5_579EE35F9B55__INCLUDED_)

#define AFX_FIGURE_H__4DBE20D7_A090_4437_8FA5_579EE35F9B55__INCLUDED_

 

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

 

class CFigure:public CObject 

{

protected:

       int m_id_only;

public:

       CFigure();

       CFigure(int id_only)

       {

              m_id_only=id_only;

       }

       int GetID();   

       virtual void Draw(CDC*pDC)=0;

       virtual ~CFigure();

 

};

 

// Figure.cpp: implementation of the CFigure class.

//

//////////////////////////////////////////////////////////////////////

 

#include "stdafx.h"

#include "test.h"

#include "Figure.h"

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif

 

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

 

CFigure::CFigure()

{

}

CFigure::~CFigure()

{

}

int CFigure::GetID()

{

       return m_id_only;

}    

#endif // !defined(AFX_FIGURE_H__4DBE20D7_A090_4437_8FA5_579EE35F9B55__INCLUDED_)

按照这样的方式,建立CMapPoint类和Cline类,源程序如下修改。

CMapPoint类的定义文件

// MapPoint.h: interface for the CMapPoint class.

//

//////////////////////////////////////////////////////////////////////

#include"figure.h"

#if !defined(AFX_MAPPOINT_H__7A0D7F22_260E_4709_849E_A105FE50BBE6__INCLUDED_)

#define AFX_MAPPOINT_H__7A0D7F22_260E_4709_849E_A105FE50BBE6__INCLUDED_

 

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

 

class CMapPoint:public CFigure 

{

public:

       float m_x,m_y;

public:

       CMapPoint();

    CMapPoint(int id_only,float x,float y):CFigure(id_only)

       {

              m_x=x;

              m_y=y;

       }

       void Draw(CDC* pDC)

       {

              pDC->Ellipse(CRect(m_x-5,m_y-5,m_x+5,m_y+5));

       }

       virtual ~CMapPoint();

};

 

#endif // !defined(AFX_MAPPOINT_H__7A0D7F22_260E_4709_849E_A105FE50BBE6__INCLUDED_)

 

CMapPoint类的实现文件

// MapPoint.cpp: implementation of the CMapPoint class.

//

//////////////////////////////////////////////////////////////////////

 

#include "stdafx.h"

#include "test.h"

#include "MapPoint.h"

 

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif

 

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

 

CMapPoint::CMapPoint()

{

}

 

CMapPoint::~CMapPoint()

{

}

 

CLine类的定义文件

// Line.h: interface for the CLine class.

//

//////////////////////////////////////////////////////////////////////

 

#if !defined(AFX_LINE_H__6D15869E_8FC2_455B_94F0_E99153418EE2__INCLUDED_)

#define AFX_LINE_H__6D15869E_8FC2_455B_94F0_E99153418EE2__INCLUDED_

 

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

 

#include "figure.h"

 

class CLine : public CFigure 

{

protected:

       float m_X1,m_X2,m_Y1,m_Y2;

public:

       CLine();

       CLine(int id_only,float x1,float y1,float x2,float y2):CFigure(id_only)

       {

              m_X1=x1;

              m_Y1=y1;

              m_X2=x2;

              m_Y2=y2;

       }

       void Draw(CDC* pDC)

       {

              pDC->MoveTo(m_X1,m_Y1);

              pDC->LineTo(m_X2,m_Y2);

       }

       virtual ~CLine();

 

};

#endif // !defined(AFX_LINE_H__6D15869E_8FC2_455B_94F0_E99153418EE2__INCLUDED_)

 

CLine类的实现文件

// Line.cpp: implementation of the CLine class.

//

//////////////////////////////////////////////////////////////////////

 

#include "stdafx.h"

#include "test.h"

#include "Line.h"

 

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif

 

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

CLine::CLine()

{

}

CLine::~CLine()

{

}

在工具栏上添加两个按钮,如下图。

双击第一个按钮,将其ID改为ID_POINT,如下图。

以同样的方式将第二个按钮的ID改为:ID_LINE

在视图类中添加两个按钮的消息处理函数,方法如下:

启动类向导(在查看菜单下的建立类向导或者按CTRL+W),如下图,在Object IDs中找到ID_POINT,选择Messages下的COMMAND,然后点击Add Function按钮,添加处理函数。以同样的方式完成ID_LINE的消息的添加。这样在视图类中就多了两个函数,如下,并修改其函数体,如下。

void CTestView::OnPoint()

{

       // TODO: Add your command handler code here

       m_DrawCurrent=1;

}

void CTestView::OnLine()

{

       // TODO: Add your command handler code here

              m_DrawCurrent=2;

              PushNum=0;

}

 

在文档类中,加入以下定义。

public:

       CTypedPtrArray<CObArray,CFigure*> m_FigureArray;  

private:

       int* m_Index;

public:

       int GetFigureID();

 

在文档类的实现文件中,定义函数。

修改构造函数和析构函数

CTestDoc::CTestDoc()

{

       // TODO: add one-time construction code here

       m_Index=new int[20000];

}

 

CTestDoc::~CTestDoc()

{

       delete m_Index;

}

实现函数GetFigureID

int CTestDoc::GetFigureID()

{    

       int nFigureNum=m_FigureArray.GetSize();

       for(int i=0;i<20000;i++)

              m_Index[i]=0;

       for(i=0;i<nFigureNum;i++)

       {

              m_Index[m_FigureArray[i]->GetID()]=1;

       }

       for(i=0;i<20000;i++)

       {

              if(m_Index[i]==0)

              {       

                     return i;         

              }

       }

       return -1;

}

在文档类的头文件开头,加入:

#include<afxtempl.h>

#include"figure.h"

F、修改视图类

在类中定义如下变量

private:

       int m_DrawCurrent;

       int PushNum;

       CPoint mPointOrign,mPointOld;

重写视图的左键单击消息处理函数,通过类向导(在查看菜单下的建立类向导或者按CTRL+W),找到视图类的WM_LBUTTONDOWN消息添加该消息的处理函数,如下,并修改里边的代码。

void CTestView::OnLButtonDown(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       CTestDoc *pDoc=GetDocument();

       CClientDC client(this);

       switch(m_DrawCurrent)

       {

       case 1:

              {

                     CMapPoint *pPt=new CMapPoint(pDoc->GetFigureID(),point.x,point.y);                    

                     pDoc->m_FigureArray.Add(pPt);

                     pPt->Draw(&client);

                     break;

              }

    case 2:

              {

                     if(PushNum==0)

                     {

                            PushNum++;

                            mPointOrign=point;

                            mPointOld=point;

                            SetCapture();

                     }

                     else if(PushNum==1)

                     {

              Cline  *pLine=new CLine(1,mPointOrign.x,mPointOrign.y,mPointOld.x,mPointOld.y);                           

                         pDoc->m_FigureArray.Add(pLine);

                         pLine->Draw(&client);

                            PushNum=0;

                            ReleaseCapture();

                     }

              }

       case 0:

              break;

       }

       CView::OnLButtonDown(nFlags, point);

}

以同样的方式实现WM_MOUSEMOVE消息的处理函数,并改写如下。

void CTestView::OnMouseMove(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

 

       if(m_DrawCurrent==2&&PushNum==1)

       {

              CTestDoc* pDOc=GetDocument();

           CClientDC client(this);

           client.SetROP2(R2_NOT);

              if(mPointOld!=point){

              client.MoveTo(mPointOrign);

              client.LineTo(mPointOld);

              client.MoveTo(mPointOrign);

              client.LineTo(point);

              mPointOld=point; 

              }

       }

       CView::OnMouseMove(nFlags, point);

}

 

修改视图类构造函数和OnDraw函数,如下。

CTestView::CTestView()

{

       // TODO: add construction code here

       m_DrawCurrent=0;

}

 

void CTestView::OnDraw(CDC* pDC)

{

       CTestDoc* pDoc = GetDocument();

       ASSERT_VALID(pDoc);

       // TODO: add draw code for native data here

       for(int i=0;i<pDoc->m_FigureArray.GetSize();i++)

       {

              pDoc->m_FigureArray.GetAt(i)->Draw(pDC);

       }

      

}

请同学们按以上的步骤完成程序,将程序调试通过,并分析程序的运行原理,将自己的心得记入实验报告。

程序最终的运行界面如图10-1,用户点击工具栏上的画点和线按钮,用户可以在客户区画点和直线。

五、实验步骤

1VC++ MFC应用程序的建立。

2、编写CFigureCMapPointCline类。

3在工具栏上添加两个按钮,并实现按钮按下的处理处理函数

4、修改文档类。

5、修改视图类。

6、调试程序,看是否那个地方忘记了包含头文件等错误。

六、实验报告

1、怎样通过“插入”菜单下的“新建类”菜单弹出的对话框,创建类,并说明实验中所创建的类之间的关系。

2、在VC中怎样创建工具栏上的按钮及其处理函数。

3、解释在文档类中所添加的语句的意义。

4、解释视图类中各个函数的作用。