GIS暑期实习报告.docx
《GIS暑期实习报告.docx》由会员分享,可在线阅读,更多相关《GIS暑期实习报告.docx(26页珍藏版)》请在冰豆网上搜索。
GIS暑期实习报告
GIS暑期实习
报告
班号:
064081—28
姓名:
任远
完成日期:
2011-07-14
提交日期:
2011-07-14
目录
第一部分1
程序设计思路:
1
程序实现过程:
1
1.定义图形类:
1
2.读取Shape文件并存储在图形类中2
3.文件的显示4
4.图形的放大、缩小和漫游6
5.缓冲区的创建7
6.视图的重绘11
程序运行结果:
11
1.图形的显示:
12
2.缓冲区分析:
12
第二部分12
程序实现过程:
12
1.建立VB工程12
2.通过代码加载数据13
3.图层操作13
4.显示图层要素类型14
5.地图属性的查询15
6.地图信息可视化16
程序运行结果:
17
1.加载图层17
2.图形的放大、缩小、漫游17
3.显示图层要素信息18
4.地图属性的查询18
5.地图信息可视化18
第一部分
程序设计思路:
首先定义图形类,在图形类的定义中编写图形绘制方法和缓冲区创建方法,将缩放倍数与平移坐标作为这些方法的传入参数以适应后面所要实现的种各功能。
然后编写函数将shape文件中的数据读入图形类中,采用图形类基类的指针的结点以链表方式存储。
接下来在视图类中通过调用图形绘制方法来显示图形,改变缩放倍数与平移坐标等传入参数可以实现图形的放大缩小与漫游。
当需要进行缓冲区分析时,则在视图类中调用缓冲区创建方法进行缓冲区的创建。
程序实现过程:
1.定义图形类:
首先定义图形类基类CShape,然后定义派生图形类CSPoint(点类)、CPolyLine(线类)、CPolygon(多边形类):
1)定义图形类基类CShape
classCShape:
publicCObject
{
public:
CShape(){};//构造函数
intShapeType;//图形几何类型
virtualvoidDraw(CDC*pDC,doubleXmin,doubleYmin,doubleYmax,doublemX,doublemY,doublen);//图形绘制方法
virtualvoidCreateBuffer(CDC*pDC,doubleXmin,doubleYmin,doubleYmax,doublemX,doublemY,doublen,doubleBufferRadius,COLORREFColor);//创建缓冲区方法
~CShape(){};//析构函数
};
2)定义派生图形类CSPoint
classCSPoint:
virtualpublicCShape
{
public:
CSPoint(){};
public:
doublex;//点坐标
doubley;
virtualvoidDraw(CDC*pDC,doubleXmin,doubleYmin,doubleYmax,doublemX,doublemY,doublen);//点绘制方法
virtualvoidCreateBuffer(CDC*pDC,doubleXmin,doubleYmin,doubleYmax,doublemX,doublemY,doublen,doubleBufferRadius,COLORREFColor);//点缓冲区创建方法
~CSPoint(){};
};
3)定义派生图形类CPolyLine
classCPolyLine:
virtualpublicCShape
{
public:
CPolyLine(){};
public:
doubleBox[4];//坐标范围
intNumParts;//子线段个数
intNumPoints;//坐标点数
int*Parts;//子线段起始位置数组
double*PointsX;//线上各点X坐标数组
double*PointsY;//线上各点Y坐标数组
virtualvoidDraw(CDC*pDC,doubleXmin,doubleYmin,doubleYmax,doublemX,doublemY,doublen);//线绘制方法
virtualvoidCreateBuffer(CDC*pDC,doubleXmin,doubleYmin,doubleYmax,doublemX,doublemY,doublen,doubleBufferRadius,COLORREFColor);//线缓冲区创建方法
~CPolyLine(){};
};
4)定义派生图形类CPolygon
classCPolygon:
virtualpublicCPolyLine
{
public:
CPolygon(){};
virtualvoidDraw(CDC*pDC,doubleXmin,doubleYmin,doubleYmax,doublemX,doublemY,doublen);//多边形绘制方法
virtualvoidCreateBuffer(CDC*pDC,doubleXmin,doubleYmin,doubleYmax,doublemX,doublemY,doublen,doubleBufferRadius,COLORREFColor);//多边形缓冲区创建方法
~CPolygon(){};
};
2.读取Shape文件并存储在图形类中
在CGISDoc中声明并定义链表和文件读取函数,用来将Shape文件读入图形类并存储在链表中。
这里在链表中保存图形类基类的指针,用图形类基类的指针来指向派生图形类的对象。
在CGISView中响应菜单项【打开】,在消息响应函数中首先调用文件读取函数将shape文件中的数据读入图形类并存储在链表中,然后遍历链表调用图形绘制方法显示图形。
1)菜单项【打开】的消息响应函数
voidCGISView:
:
OnFileOpen()
{
//TODO:
Addyourcommandhandlercodehere
CGISDoc*pDoc=GetDocument();//获取文档类指针
CFileDialogdlg(TRUE,NULL,NULL,0,"(*.shp)|*.shp");//创建文件打开对话框
dlg.m_ofn.lpstrTitle="打开文件";
CStringpath;
if(dlg.DoModal()!
=IDOK)
return;
path=dlg.GetPathName();//获得打开文件路径
FILE*fp=fopen(path,"rb");//打开文件
if(!
fp)
return;
pDoc->ReadShp(fp);//调用文档类中的文件读取函数
//从文档类中获得图幅范围
doubleXmax=pDoc->Xmax;
doubleXmin=pDoc->Xmin;
doubleYmax=pDoc->Ymax;
doubleYmin=pDoc->Ymin;
CClientDCdc(this);//获得客户区
CRectrectClient;
GetClientRect(rectClient);
CSizesizeClient=rectClient.Size();//获得客户区大小
doublenx=(Xmax-Xmin)/(double(sizeClient.cx)-100);
doubleny=(Ymax-Ymin)/(double(sizeClient.cy)-100);
n=(nx>ny)?
nx:
ny;//计算图幅缩放比例
mX=((Xmax-Xmin)/n-sizeClient.cx)/2;
mY=((Ymax-Ymin)/n-sizeClient.cy)/2;//计算图形平移距离
CTypedPtrList&shapeList=pDoc->m_shapeList;//图形类链表
POSITIONpos=shapeList.GetHeadPosition();
while(pos!
=NULL)
{
CShape*m_shape=shapeList.GetNext(pos);
m_shape->Draw(&dc,Xmin,Ymin,Ymax,mX,mY,n);//调用图形绘制方法
}
}
2)Shape文件读取函数
(1)读取完整文件:
完整文件的读取包括头文件的读取与分类型的实体信息读取:
voidCGISDoc:
:
ReadShp(FILE*m_ShpFile_fp)
{
inttype=OnReadShphead(m_ShpFile_fp);//读取头文件并返回图形类型值
switch(type)//根据图形类型值确定实体信息读取方法
{
case1:
OnReadPointShp(m_ShpFile_fp);//读取点实体信息
break;
case3:
OnReadLineShp(m_ShpFile_fp);//读取线实体信息
break;
case5:
OnReadAreaShp(m_ShpFile_fp);//读取多边形实体信息
break;
default:
return;
}
}
(2)头文件的读取
(3)分类型的实体信息读取
由于这里是使用示例代码读取文件,因此对于
(2)、(3)部分的代码这里不再列出。
3.文件的显示
文件的显示是通过在视图类的消息响应函数以及重绘函数中调用图形类中的图形绘制方法来实现的,而图形绘制方法则封装在各图形类中。
在图形绘制中,首先根据客户区的大小进行图形的缩放与平移,然后进行图形的绘制。
在图形绘制方法中,Xmin、Ymin、Xmax、Ymax为图幅坐标范围,mX、mY为平移坐标大小,n为缩放比例。
1)点类的图形绘制方法
voidCSPoint:
:
Draw(CDC*pDC,doubleXmin,doubleYmin,doubleYmax,doublemX,doublemY,doublen)
{
doubleX,Y;
//进行坐标转换
X=(x-Xmin)/n-mX;
Y=((Ymax+Ymin)-y-Ymin)/n-mY;
pDC->Ellipse(int(X)-3,int(Y)-3,int(X)+3,int(Y)+3);
}
2)线类的图形绘制方法
voidCPolyLine:
:
Draw(CDC*pDC,doubleXmin,doubleYmin,doubleYmax,doublemX,doublemY,doublen)
{
inti,j;
intpointNum;
for(i=0;i{
//绘制子线段
if(i!
=NumParts-1)
pointNum=Parts[i+1]-Parts[i];
else
pointNum=NumPoints-Parts[i];
//将线上原始点的坐标进行转换后存入CPoint数组中
CPoint*point=newCPoint[pointNum];
for(j=Parts[i];j{
doubleX,Y;
X=PointsX[j]-Xmin;
Y=(Ymax+Ymin)-PointsY[j]-Ymin;
point[j-Parts[i]].x=int(X/n-mX);
point[j-Parts[i]].y=int(Y/n-mY);
}
pDC->Polyline(point,PartPoints);
delete[]point;
}
}
3)多边形类的图形绘制方法
voidCPolygon:
:
Draw(CDC*pDC,doubleXmin,doubleYmin,doubleYmax,doublemX,doublemY,doublen)
{
inti,j;
doubleYmid=(Ymin+Ymax)/2;
intpointNum;
for(i=0;i{
//绘制子线段
if(i!
=NumParts-1)
pointNum=Parts[i+1]-Parts[i];
else
pointNum=NumPoints-Parts[i];
//将多边形边界上原始点的坐标进行转换后存入CPoint数组中
CPoint*point=newCPoint[pointNum];
for(j=Parts[i];j{
doubleX,Y;
X=PointsX[j]-Xmin;
Y=(Ymax+Ymin)-PointsY[j]-Ymin;
point[j-Parts[i]].x=int(X/n-mX);
point[j-Parts[i]].y=int(Y/n-mY);
}
pDC->Polygon(point,PartPoints);
delete[]point;
}
}
4)显示窗口大小的调整
为了更好的显示图形,这里在创建窗口前对窗口的大小进行设定,在创建窗口时设置窗口大小为800*800。
具体的做法为在CMainFrame.cpp文件中的CMainFrame:
:
PreCreateWindow(CREATESTRUCT&cs)函数加入如下代码:
cs.style&=~WS_EX_CLIENTEDGE;
CRectrect(0,0,800,800);
AdjustWindowRectEx(&rect,cs.style,TRUE,cs.dwExStyle);
cs.cx=rect.right-rect.left;
cs.cy=rect.bottom-rect.top;
4.图形的放大、缩小和漫游
在菜单中添加菜单项【视图】并为其添加子菜单项【放大】、【缩小】、【漫游】,并分别为其添加消息响应函数。
在视图类中添加变量m_zoom和m_wander作为指标值本别指示当前状态是否为放大、缩小和漫游。
在消息响应函数中只改变当前状态指标值,真正的功能实现放在对鼠标事件的响应中。
主要的相应步骤为首先判断当前状态,然后根据当前状态调整缩放比例与平移坐标,最后强制视图重绘。
1)鼠标左键按下
voidCGISView:
:
OnLButtonDown(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
start=point;
if(m_zoom==1)//放大
{
n*=0.5;//调整缩放比例
nout++;
//计算平移坐标
mX+=(pow(2,nout)-pow(2,nout-1))*(start.x+mX)/pow(2,nout-1);
mY+=(pow(2,nout)-pow(2,nout-1))*(start.y+mY)/pow(2,nout-1);
Invalidate();//强制视图重绘
}
if(m_zoom==2)//缩小
{
n*=2;//调整缩放比例
nin++;
//计算平移坐标
mX+=(pow(0.5,nin)-pow(0.5,nin-1))*(start.x+mX)/pow(0.5,nin-1);
mY+=(pow(0.5,nin)-pow(0.5,nin-1))*(start.x+mX)/pow(0.5,nin-1);
Invalidate();//强制视图重绘
}
if(m_wander==1)//漫游
{
prepoint=point;
nextpoint=point;
}
CView:
:
OnLButtonDown(nFlags,point);
}
2)鼠标移动
voidCGISView:
:
OnMouseMove(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
if(m_wander==1)//漫游
{
nextpoint=point;
mX+=prepoint.x-nextpoint.x;
mY+=prepoint.y-nextpoint.y;//计算平移坐标
Invalidate();//强制视图重绘
prepoint=point;
}
CView:
:
OnMouseMove(nFlags,point);
}
5.缓冲区的创建
在菜单中添加菜单项【分析】并为其添加子菜单项【缓冲区分析】,在消息响应函数中首先唤起缓冲区分析对话框由用户输入缓冲区半径,然后改变当前状态指标值,最后强制视图重绘,此时在重绘函数中调用各图形类的缓冲区创建方法。
在各图形类的缓冲区创建方法方法的各传入参数中,Xmin、Ymin、Xmax、Ymax为图幅坐标范围,mX、mY为平移坐标大小,n为缩放比例,BufferRadius为缓冲区半径,Color为缓冲区颜色。
各图形类的缓冲区创建方法如下:
1)点类的缓冲区创建方法
点的缓冲区创建比较简单,直接以各点为圆心、以输入缓冲区半径为半径画圆即可。
voidCSPoint:
:
CreateBuffer(CDC*pDC,doubleXmin,doubleYmin,doubleYmax,doublemX,doublemY,doublen,doubleBufferRadius,COLORREFColor)
{
//创建点类缓冲区
doubleX,Y;
X=(x-Xmin)/n-mX;
Y=((Ymax+Ymin)-y-Ymin)/n-mY;
doublem_nBuffer=BufferRadius/n;
//创建新画刷
CBrush*newBrush=newCBrush(Color);
CBrush*oldBrush;
oldBrush=pDC->SelectObject(newBrush);
pDC->Ellipse(int(X-m_nBuffer),int(Y-m_nBuffer),int(X+m_nBuffer),int(Y+m_nBuffer));
newBrush=pDC->SelectObject(oldBrush);
deletenewBrush;
}
2)线类的缓冲区创建方法
由于每一个线类的对象都是由多条子线段组成的,在创建线类缓冲区时对其进行分段处理,即为每个子线段创建缓冲区,具体过程为在子线段中间部分创建多边形区域,其中多边形区域的顶点需要根据线上的下一个子线段端点来计算,在子线段边缘创建圆形区域,然后将其合并。
voidCPolyLine:
:
CreateBuffer(CDC*pDC,doubleXmin,doubleYmin,doubleYmax,doublemX,doublemY,doublen,doubleBufferRadius,COLORREFColor)
{
inti;
CPoint*point=newCPoint[NumPoints];
doubleYmid=(Ymin+Ymax)/2;
for(i=0;i{
doubleX,Y;
X=PointsX[i]-Xmin;
Y=(Ymax+Ymin)-PointsY[i]-Ymin;
point[i].x=int(X/n-mX);
point[i].y=int(Y/n-mY);
}
doublem_nBuffer=BufferRadius/n;
doublearctangent;//记录角度和点位坐标
CPointpointBuffer[4];
CRgnpNewRgn,pRgn;
pRgn.CreateEllipticRgn(point[0].x-m_nBuffer,point[0].y-m_nBuffer,point[0].x+m_nBuffer,point[0].y+m_nBuffer);
for(i=0;i{
//计算角度
arctangent=atan2(-(point[i].x-point[i+1].x),(point[i].y-point[i+1].y));
//计算坐标
pointBuffer[0].x=long(point[i].x+m_nBuffer*cos(arctangent));
pointBuffer[0].y=long(point[i].y+m_nBuffer*sin(arctangent));
pointBuffer[1].x=long(point[i].x-m_nBuffer*cos(arctangent));
pointBuffer[1].y=long(point[i].y-m_nBuffer*sin(arctangent));
pointBuffer[2].x=long(point[i+1].x-m_nBuffer*cos(arctangent));
pointBuffer[2].y=long(point[i+1].y-m_nBuffer*sin(arctangent));
pointBuffer[3].x=long(point[i+1].x+m_nBuffer*cos(arctangent));
pointBuffer[3].y=long(point[i+1].y+m_nBuffer*sin(arctangent));
//创建多边形区域
pNewRgn.CreatePolygonRgn(pointBuffer,4,WINDING);
pRgn.CombineRgn(&pRgn,&pNewRgn,RGN_OR);//合并区域
pNewRgn.DeleteObject();
//