《ArcGIS-Engine二次开发——提高篇(共77页).doc》由会员分享,可在线阅读,更多相关《ArcGIS-Engine二次开发——提高篇(共77页).doc(77页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、精选优质文档-倾情为你奉上ArcGIS Engine二次开发提高篇专心-专注-专业1 缩略图(鹰眼)鹰眼功能是GIS的主要功能之一,当地图范围很大时,它可以很好的为用户指明当前地图的范围。在本小节中我们将学习如何制作这种鹰眼。1.1 添加控件新建一个C#.Net项目,项目名称为OverView,将Form1的名字设置为MainForm,并添加ToolbarControl 、两个MapControl和LicenceControl等四个控件。布局如下图所示。左边的axMapControl1用于地图数据显示和操作,右边axMapControl2用于鹰眼显示。图 1 界面布局在ToolbarContr
2、ol 加载添加数据按钮和地图浏览的功能按钮,如下图所示,并将ToolbarControl的伙伴控件设为axMapControl1。图 2添加按钮1.2 代码添加及解释鹰眼用来显示主窗体当前视图范围在全景视图中的位置,在ArcMap中使用一个线框在鹰眼视图中标识。当主视图中的视图范围改变时,鹰眼中的线框随之改变,当拖动鹰眼视图中的红线框时,主视图中的视图范围也随之改变。下面开始实现鹰眼功能,添加using ESRI.ArcGIS.Carto、using ESRI.ArcGIS.Geometry、using ESRI.ArcGIS.Display三个引用。首先在axMapControl1中视图范围
3、改变时鹰眼窗体要做出对应的响应,即绘制线框并显示,在OnExtentUpdated事件中添加代码如下:private void axMapControl1_OnExtentUpdated(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnExtentUpdatedEvent e) /创建鹰眼中线框 IEnvelope pEnv = (IEnvelope)e.newEnvelope; IRectangleElement pRectangleEle = new RectangleElementClass(); IElement pEl
4、e = pRectangleEle as IElement; pEle.Geometry = pEnv; /设置线框的边线对象,包括颜色和线宽 IRgbColor pColor = new RgbColorClass(); pColor.Red = 255; pColor.Green = 0; pColor.Blue = 0; pColor.Transparency = 255; / 产生一个线符号对象 ILineSymbol pOutline = new SimpleLineSymbolClass(); pOutline.Width = 2; pOutline.Color = pColor;
5、 / 设置颜色属性 pColor.Red = 255; pColor.Green = 0; pColor.Blue = 0; pColor.Transparency = 0; / 设置线框填充符号的属性 IFillSymbol pFillSymbol = new SimpleFillSymbolClass(); pFillSymbol.Color = pColor; pFillSymbol.Outline = pOutline; IFillShapeElement pFillShapeEle = pEle as IFillShapeElement; pFillShapeEle.Symbol =
6、 pFillSymbol; / 得到鹰眼视图中的图形元素容器 IGraphicsContainer pGra = axMapControl2.Map as IGraphicsContainer; IActiveView pAv = pGra as IActiveView; / 在绘制前,清除 axMapControl2 中的任何图形元素 pGra.DeleteAllElements(); / 鹰眼视图中添加线框 pGra.AddElement(IElement)pFillShapeEle, 0); / 刷新鹰眼 pAv.PartialRefresh(esriViewDrawPhase.esri
7、ViewGraphics, null, null); 当鼠标点击鹰眼窗体时,主窗体Extent随之改变。在axMapControl2的OnMouseDown事件中添加代码如下:private void axMapControl2_OnMouseDown(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseDownEvent e) if (this.axMapControl2.Map.LayerCount != 0) / 按下鼠标左键移动矩形框 if (e.button = 1) IPoint pPoint = new Po
8、intClass(); pPoint.PutCoords(e.mapX, e.mapY); IEnvelope pEnvelope = this.axMapControl1.Extent; pEnvelope.CenterAt(pPoint); this.axMapControl1.Extent = pEnvelope; this.axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null); / 按下鼠标右键绘制矩形框 else if (e.button = 2) IEnvel
9、ope pEnvelop = this.axMapControl2.TrackRectangle(); this.axMapControl1.Extent = pEnvelop; this.axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null); 当鼠标在鹰眼窗体移动时,主窗体Extent随之改变。在axMapControl2的OnMouseMove事件中添加代码如下: private void axMapControl2_OnMouseMove(object sender
10、, ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseMoveEvent e) / 如果不是左键按下就直接返回 if (e.button != 1) return; IPoint pPoint = new PointClass(); pPoint.PutCoords(e.mapX, e.mapY); this.axMapControl1.CenterAt(pPoint); this.axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, nu
11、ll); 下面代码用于实现axMapControl2与axMapControl1的数据的同步更新,获取主视图中视图范围最大的图层作为鹰眼中的视图。这个更新由两部分组成,一个是对axMapControl1添加地图文档(mxd文件)的响应,通过axMapControl1的OnMapReplace事件实现,一个是对axMapControl1添加单个图层的响应,通过axMapControl1的OnFullExtentUpdated事件实现。我们获取主视图中的视图范围最大的图层写成一个独立的函数,方便调用。 private ILayer GetOverviewLayer(IMap map) /获取主视图
12、的第一个图层 ILayer pLayer = map.get_Layer(0); /遍历其他图层,并比较视图范围的宽度,返回宽度最大的图层 ILayer pTempLayer = null; for (int i = 1; i map.LayerCount;i+ ) pTempLayer = map.get_Layer(i); if (pLayer.AreaOfInterest.Width pTempLayer.AreaOfInterest.Width) pLayer = pTempLayer; return pLayer; 然后在axMapControl1的OnMapReplaced事件中调
13、用。 private void axMapControl1_OnMapReplaced(object sender, IMapControlEvents2_OnMapReplacedEvent e) /获取鹰眼图层 this.axMapControl2.AddLayer(this.GetOverviewLayer(this.axMapControl1.Map); / 设置 MapControl 显示范围至数据的全局范围 this.axMapControl2.Extent = this.axMapControl1.FullExtent; / 刷新鹰眼控件地图 this.axMapControl2
14、.Refresh(); 在axMapControl1的OnFullExtentUpdated添加代码,用于实现在主视图添加图层时,实现对鹰眼视图的更新。代码如下: private void axMapControl1_OnFullExtentUpdated(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnFullExtentUpdatedEvent e) /获取鹰眼图层 this.axMapControl2.AddLayer(this.GetOverviewLayer(this.axMapControl1.Map); / 设置
15、MapControl 显示范围至数据的全局范围 this.axMapControl2.Extent = this.axMapControl1.FullExtent; / 刷新鹰眼控件地图 this.axMapControl2.Refresh(); 本例的示例数据无特别要求,使用前面章节实例数据即可。运行程序,添加地图数据,可以在主视图进行相关操作,鹰眼视图同步响应,在鹰眼视图可以移动红线框可以同步更新主视图的视图范围,在鹰眼视图单击右键拉框可以重新绘制红线框,效果如下:图 3鹰眼效果1.3 MyGIS中添加鹰眼在上一讲中的最后一节,我们创建了一个简单的GIS系统MyGIS,这里,我们讲鹰眼功能
16、嵌入到我们的系统中。在这里我们对实现的思路做一个介绍,请您自己动手完善MyGIS。首先需要修改一下MyGIS窗体的控件布局,我们讲鹰眼视图放到图层管理器的下方,需要在控件容器SpliterContainer1的Panel1中添加一个水平分隔的SpliterContainer,然后将图层管理器空间TOCControl和鹰眼视图MapControl分别置于上下的容器中,并将其属性Dock分别设为Fill。另外,在此种窗体布局情况下,直接在TOCControl控件属性中设置伙伴控件无效,如图所示。我们需要在MainForm的Load事件中为TOCControl设置伙伴控件为axMapControl1
17、。添加代码如下: private void Form1_Load(object sender, EventArgs e) /设置axTOCControl1的伙伴控件 this.axTOCControl1.SetBuddyControl(axMapControl1.Object); 图 4 TOCControl控件属性中设置伙伴控件然后依次添加本例中的代码,即可完成,运行效果如下图所示:图 5 MyGIS中鹰眼的运行效果1.4 小结在本小节中,我们实现了鹰眼功能并讲鹰眼加入了MyGIS,这部分的重点是鹰眼视图和主视图之间的事件交互。推荐您仔细结合例子程序查看代码,如果需要获得进一步的信息,请查看
18、帮助系统。如果您对这一小节的内容比较熟悉了,就可以开始学习本章最后一小节的内容了。在下一小节中,我们将尝试添加缓冲区分析功能。2 缓冲区分析缓冲区分析指为了识别某一地理实体或空间物体对其周围地物影响度而在其周围建立的具有一定宽度的区域,以确定哪些实体落在了被影响的区域范围之内。缓冲区分析与缓冲区查询不同,缓冲区查询是不破坏原有空间目标的关系,只是检索到该缓冲区范围内涉及到的目标。而缓冲区分析是根据设定的距离条件对一类地物建立缓冲区多边形,存储到一个新的图层中。然后再将新的图层与需要进行缓冲区分析的图层进行叠置分析,得到所需要的结果。因此,缓冲区分析实际上进行了两步的操作,第一步是建立缓冲区图层
19、,第二步是进行叠置剪裁分析。缓冲区分析适用于点、线、面对象,如点状的居民点、线状的河流和面状的作物分布区等,只要地理实体能对周围一定区域形成影响即可使用这种分析方法。图 6点、线、面的缓冲区分析ArcGIS的ArcToolBox中的分析工具提供了缓冲区分析的功能,本节实习我们首先使用Geoprocessor方法实现一个简单的缓冲区分析功能,然后将缓冲区分析功能添加到我们的MyGIS项目中。程序运行前首先需要在D盘下新建一个名为Temp的文件夹,存放叠置分析生成的文件。2.1 Geoprocessor实现缓冲区分析为了降低开发难度和提高开发效率,ArcGIS Engine中添加了GeoProce
20、ssor类,使用Geoprocessor能帮助用户直接实现一些简单的工具性的功能,所有在ArcToolBox中的功能,基本都可以用Geoprocessor编程实现。本节我们使用Geoprocessor实现缓冲区分析的功能。2.1.1 添加控件新建一个C#.Net项目,项目名称为Buffer,将Form1的名字设置为MainForm,并添加ToolbarControl 、MapControl、TOCControl、LicenceControl和Button等五个控件。并将ToolbarControl 、TOCControl的伙伴控件设为MapControl,Button控件的Name属性设定为b
21、tnBuffer,Text属性设定为“缓冲区分析”。控件布局效果如下图所示。图 7控件布局效果在ToolbarControl 加载添加数据按钮和地图浏览的功能按钮,如下图所示。图 8添加按钮2.1.2 代码添加及解释首先添加如下四个命名空间的引用。using ESRI.ArcGIS.Carto;using ESRI.ArcGIS.Geoprocessor;using ESRI.ArcGIS.Geoprocessing;using ESRI.ArcGIS.esriSystem;在使用Geoprocessor工具实现缓冲区分析时,需要首先定义一个Geoprocessor对象,因为命名空间“ESRI
22、.ArcGIS.Geoprocessing”也包含Geoprocessor类,为了避免混淆,我们使用命名空间来定义Geoprocessor,然后设置Geoprocessor中的环境参数,这里我们使用默认参数。然后定义一个操作类Buffer,并设置参数,生成缓冲区的参数包含原始图层,缓冲半径和输出路径,最后使用已定义的Geoprocessor对象执行即可。双击“生成缓存区”按钮,添加代码如下: private void btnBuffer_Click(object sender, EventArgs e) /判断MapControl中是否包含图层 if (this.axMapControl1.L
23、ayerCount = 0) return; /获取MapControl中第一个图层 ILayer pLayer = this.axMapControl1.Map.get_Layer(0); /输出路径,可以自行指定 string strOutputPath = D:Buffer.shp; /缓冲半径 double dblDistace = 1.0; /获取一个geoprocessor的实例,避免与命名空间Geoprocessing中的Geoprocessor发生引用错误 ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Ge
24、oprocessor.Geoprocessor(); /OverwriteOutput为真时,输出图层会覆盖当前文件夹下的同名图层 gp.OverwriteOutput = true; /创建一个Buffer工具的实例 ESRI.ArcGIS.AnalysisTools.Buffer buffer = new ESRI.ArcGIS.AnalysisTools.Buffer(pLayer, strOutputPath, dblDistace); /执行缓冲区分析 IGeoProcessorResult results = null; results = gp.Execute(buffer, n
25、ull) as IGeoProcessorResult; /判断缓冲区是否成功生成 if (results.Status != esriJobStatus.esriJobSucceeded) MessageBox.Show(图层 + pLayer.Name + 缓冲区生成失败!); else MessageBox.Show(缓冲区生成成功!); /将生成图层加入MapControl int index = strOutputPath.LastIndexOf(); this.axMapControl1.AddShapeFile(strOutputPath.Substring(0, index),
26、 strOutputPath.Substring(index); 运行程序,添加一个图层(多个图层时本例中默认选择的图层为第一个图层),点击“生成缓冲区”,运行结果如图。图 9缓冲区生成效果2.1.3 小结本例中,我们使用Geoprocessor工具实现了缓冲区分析。从中我们可以得到Geoprocessor工具使用的一般方法,在使用Geoprocessor时,一般需先定义一个Geoprocessor对象,然后设置该对象的参数,如本例中的OverwriteOutput,再定义一个具体的操作类,如本例中的Buffer类,在设置完操作类的参数后,则通过Geoprocessor的Excute函数来执行
27、。至此,我们已经实现了一个简单的缓冲区分析的功能,从中我们学习了Geoprocessor的使用方法。下一节我们讲对缓冲区份分析功能做进一步的改进,使其具有更强的适用性,并将这个功能添加到MyGIS中。2.2 MyGIS中添加缓冲区分析我们在使用缓冲区分析时,需要设定原始的图层,缓冲半径以及生成缓冲区的保存路径。本节我们将在上一节的基础上进一步实现缓冲区分析,实现缓冲图层,缓冲半径和保存路径的可选设置。2.2.1 添加控件打开项目MyGIS,在MyGIS的主菜单添加一个新的菜单项“空间分析”,并添加子菜单“缓冲区分析”,Name属性修改为“menuBuffer”。项目中添加一个新的窗体,名称为“
28、BufferForm”,Name属性设为“缓冲区分析”,添加四个Label、一个ComboBox、两个TextBox、三个Button控件,控件属性设置如下:表 1控件属性设置控件类型Name属性Text属性控件说明Label选择图层:Label缓冲半径:LabellblUnit地图单位标示当前地图的地图单位Label输出图层:ComboBoxcboLayers所有图层的名称TextBoxtxtBufferDistance1.0生成缓冲区的缓冲半径TextBoxtxtOutputPath缓冲区文件的输出路径,其ReadOnly属性设为TrueButtonbtnOutputLayer选择缓冲区文
29、件的输出路径ButtonbtnBuffer分析进行缓冲区分析ButtonbtnCancel取消取消2.2.2 代码添加及解释该项目需添加如下引用:using ESRI.ArcGIS.Controls;using ESRI.ArcGIS.Geoprocessor;using ESRI.ArcGIS.Carto;using ESRI.ArcGIS.Geoprocessing;using ESRI.ArcGIS.esriSystem;首先声明两个成员变量,用于保存地图数据和输出文件的路径。 /接收MapControl中的数据 private IHookHelper mHookHelper = new
30、 HookHelperClass(); /缓冲区文件输出路径 public string strOutputPath;重写BufferForm的构造函数,添加一个参数,用于接收MapControl中的数据。 /重写构造函数,添加参数hook,用于传入MapControl中的数据 public BufferForm(object hook) InitializeComponent(); this.mHookHelper.Hook = hook; 添加一个自定义函数,用于根据图层名称获取要素图层并返回。 private IFeatureLayer GetFeatureLayer(string la
31、yerName) IFeatureLayer pFeatureLayer = null; /遍历图层,获取与名称匹配的图层 for (int i = 0; i this.mHookHelper.FocusMap.LayerCount; i+) ILayer pLayer = this.mHookHelper.FocusMap.get_Layer(i); if (pLayer.Name = layerName) pFeatureLayer = pLayer as IFeatureLayer; if (pFeatureLayer != null) return pFeatureLayer; els
32、e return null; BufferForm在载入时需要加载当前MapControl中的图层名称到cboLayers,读取当前地图的地图单位,设置缓冲区文件的默认输出路径,这里我们将默认输出路径设为“D:Temp”。 private void BufferForm_Load(object sender, EventArgs e) /传入数据为空时返回 if (null = mHookHelper | null = mHookHelper.Hook | 0 = mHookHelper.FocusMap.LayerCount) return; /获取图层名称并加入cboLayers for
33、(int i = 0; i 0) cboLayers.SelectedIndex = 0; /设置生成文件的默认输出路径和名称 string tempDir = D:Temp; txtOutputPath.Text = System.IO.Path.Combine(tempDir, (string)cboLayers.SelectedItem + _buffer.shp); /设置默认地图单位 lblUnits.Text = Convert.ToString(mHookHelper.FocusMap.MapUnits); 双击路径设置按钮,进入代码编辑界面,添加如下代码: private vo
34、id btnOutputLayer_Click(object sender, EventArgs e) /定义输出文件路径 SaveFileDialog saveDlg = new SaveFileDialog(); /检查路径是否存在 saveDlg.CheckPathExists = true; saveDlg.Filter = Shapefile (*.shp)|*.shp; /保存时覆盖同名文件 saveDlg.OverwritePrompt = true; saveDlg.Title = 输出路径; /对话框关闭前还原当前目录 saveDlg.RestoreDirectory = t
35、rue; saveDlg.FileName = (string)cboLayers.SelectedItem + _buffer.shp; /读取文件输出路径到txtOutputPath DialogResult dr = saveDlg.ShowDialog(); if (dr = DialogResult.OK) txtOutputPath.Text = saveDlg.FileName; 双击“分析”按钮,添加代码如下: private void btnBuffer_Click(object sender, EventArgs e) /缓冲距离 double bufferDistance
36、; /输入的缓冲距离转换为double double.TryParse(txtBufferDistance.Text.ToString(),out bufferDistance); /判断输出路径是否合法 if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(txtOutputPath.Text) | .shp != System.IO.Path.GetExtension(txtOutputPath.Text) MessageBox.Show(输出路径错误!); return; /判断图层个数 if (mHookHelp
37、er.FocusMap.LayerCount = 0) return; /获取图层 IFeatureLayer pFeatureLayer = GetFeatureLayer(string)cboLayers.SelectedItem); if (null = pFeatureLayer) MessageBox.Show(图层 + (string)cboLayers.SelectedItem + 不存在!rn); return; /获取一个geoprocessor的实例 Geoprocessor gp = new Geoprocessor(); /OverwriteOutput为真时,输出图层会覆盖当前文件夹下的同名图层 gp.OverwriteOutput = true;