资源描述
,单击此处编辑母版标题样式,2,*,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,Wuhan University,School of Remote Sensing and,Information Engineering,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,Wuhan University,School of Remote Sensing and,Information Engineering,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,GIS,工程设计开发综合实习,张文,、黄长青,武汉大学遥感信息工程学院,基于,C#.NET,和,AO/AE,的,GIS,设计与开发,1,2024年8月16日,GIS工程设计开发综合实习张文、黄长青基于C#.NET和,2,Part 5,:,ArcGIS Engine,二次开发入门,2024年8月16日,2Part 5:ArcGIS Engine二次开发入门 2,ArcGIS Engine,二次开发入门,3,5.1 ArcGIS Engine,简介,5.2 ArcGIS Engine,开发起步,5.3,属性查询,5.4,空间查询,5.5 BaseCommand,开发实例,5.6 BaseTool,开发实例,5.7,通过代码添加图层,5.8,构建一个简单的,GIS,应用,5.9,问题解决方法及帮助文档的使用,2024年8月16日,ArcGIS Engine二次开发入门 35.1 Arc,5.1 ArcGIS Engine,简介,ArcGIS Engine,的功能十分强大。作为,ArcGIS Engine,开发者,您可以实现以下列出的和其他更多的功能,这包括:,用多个图层来显示地图,例如道路、水系、边界等,地图的漫游和缩放,地图上要素的确认,地图上要素的查询和定位,根据属性值显示注记,根据航片或者卫片显示图像,绘制几何图形,例如点、线、弧、多边形,添加描述性的文字,4,2024年8月16日,5.1 ArcGIS Engine简介ArcGIS En,沿着线选择或者选择矩形、某一范围内、多边形等内部的要素,选择距离在某一范围内的要素,利用,SQL,语言来寻找和选择要素,利用专题地图来渲染要素,如唯一值法、分级法和点状密度法,动态显示实时地图或者时序数据,根据地理编码来寻找位置,转换您地图的坐标系,根据几何操作来生成缓冲区、计算差值,或者进行求交、求并等运算,编辑要素形状或者旋转地图,创建并更新要素的几何形状及其属性,5,2024年8月16日,沿着线选择或者选择矩形、某一范围内、多边形等内部的要素520,编辑要素(,Editing Features,),ArcGIS Engine,开发包让您构建出能创建、修改和删除,geodatabase,中矢量要素或者,shapefile,文件的应用程序。标准的,ArcGIS Engine Runtime,能够让编辑,shapefile,文件或者,personal geodatabase,中简单要素的程序运行。然而,要构建企业级,geodatabase,的全部功能,就需要,ArcGIS Engine Runtime,中的,Geodatabase Update,选项。,6,2024年8月16日,编辑要素(Editing Features)ArcGIS E,空间建模和分析,空间建模和通过增加,ArcGIS Engine Runtime,中的,Spatial,选项,您能够扩展,ArcGIS Engine,的功能。这个选项(,Spatial,选项)能提供一系列强劲的空间建模和分析功能。您能够创建、查询、表达和分析基于象元的栅格数据,能够集成栅格和矢量数据进行分析,能够从已有数据挖掘出新的信息,能够从多层数据中查询信息,能够在,ArcGIS Engine,应用程序中完美集成基于象元的栅格数据和矢量数据。,7,2024年8月16日,空间建模和分析空间建模和通过增加ArcGIS Engine,三维可视化等,ArcGIS Engine Runtime,中的,3D,选项让您通过使用,Scene,和,Globe,控件来有效的表达和分析区域及全球数据。,例如,您能够:,显示,Scene,和,Globe,文档,展示交互性的透视图,包括漫游、缩放、旋转、倾斜、模拟飞行以便于表达和分析,显示真实世界的表面要素,例如楼房,展示视域和可见范围分析、场景高度内插、剖面分析和最短距离分析,8,2024年8月16日,三维可视化等ArcGIS Engine Runtime中的3,这个例子将引导您创建第一个简单的地图显示程序,并添加基本的缩放和漫游功能。如果您之前没有接触过,ArcGIS Engine,的开发,那么这个例子是您迈入,ArcGIS Engine,二次开发大门的极好例子,如果您之前没有接触,C#.NET,,也无需担心,这个例子将从零开始引导您一步一步完成任务。,5.2 ArcGIS Engine开发起步第一个简单的地图显示程序,9,2024年8月16日,这个例子将引导您创建第一个简单的地图显示程序,并添加基本的缩,首先打开,Microsoft Visual Studio 2005,,点击菜单栏中的“文件”,“,新建项目”,在弹出的对话框中选择新建一个,C#,的,Windows,应用程序,之后更改项目名称为“,MapView”,,更改文件的路径为个人实习文件夹,点击“确定”即可。,创建一个新的工程,图,23,新建项目对话框,10,2024年8月16日,首先打开Microsoft Visual Studio 20,点击编译器最左侧的“工具箱”,在弹出的选择项中找到“,ArcGIS Windows Forms”,项,单击其中的,MapControl,,之后在,Form1,的空白处单击鼠标左键不放并拖拽鼠标,直到调整,MapControl,到合适的大小再松开鼠标(您也可以直接在工具箱中双击,MapControl,,该控件则会自动加入到,Form1,中)。用同样的方法,再将,LicenseControl,添加到,Form1,中。,添加控件及引用,图,24,工具箱,11,2024年8月16日,点击编译器最左侧的“工具箱”,在弹出的选择项中找到“ArcG,如果您在工具箱中找不到,MapControl,,则请依次尝试以下两种解决方案。首先单击工具栏,待工具箱弹出之后,在工具箱的任意位置上单击鼠标右键,从弹出菜单中选择“重置工具箱”。如果这一步操作之后仍然无法看到,MapControl,,则请滑动工具栏右侧的滚动条至最底部,找到“常规”选项卡,然后在“常规”选项卡上单击鼠标右键,在弹出菜单中单击“选择项(,I,),”,,在弹出的对话框中找到“,AxLicenseControl”,和“,AxMapControl”,,将这两项前的复选框打上勾,最后点击确定即可(如果在“,.NET Framework,组件”这个面板中找不到这两项,则选择“,COM,组件”面板,在“,ESRI LicenseControl”,和“,ESRI MapControl”,前面打勾)。,图,25,重置工具箱,12,2024年8月16日,如果您在工具箱中找不到MapControl,则请依次尝试以下,图,26,选择项,图,27,选择工具箱项,13,2024年8月16日,图26 选择项图27 选择工具箱项132023年8月26,图,28,选择工具箱项,14,2024年8月16日,图28 选择工具箱项142023年8月26日,添加好,MapControl,和,LicenseControl,之后,调整,Form1,和,MapControl,的位置与大小,如下图所示:,图,29,窗体布局,15,2024年8月16日,添加好MapControl和LicenseControl之后,在,MapControl,上单击鼠标右键,选择“属性”,则会弹出,MapControl,的属性设置面板,在之前也介绍过,通过这个面板可以完成许多简单的工作。,如图所示,点击“,Map”,面板,之后点击 按钮,在弹出的对话框中选择下图所示的路径(注:笔者的,ArcGIS,安装在,D,盘,若您的,ArcGIS,装在别的盘符,请做相应修改),再在此路径下选择“,States”,,点击“,Open”,。之后在,MapControl,的属性页上点击“确定”即可。,添加地图,图,30,文件添加路径,16,2024年8月16日,在MapControl上单击鼠标右键,选择“属性”,则会弹出,至此,我们已经完成了一个最简单的地图显示程序,下面一起来看一下成果吧。点击“启动调试”按钮(或者在“调试”菜单下选择相应命令,或者按键盘的,F5,键),可以得到如下的运行结果。,图,31 “,启动调试”按钮,17,2024年8月16日,至此,我们已经完成了一个最简单的地图显示程序,下面一起来看一,图,32,初次运行结果,18,2024年8月16日,图32 初次运行结果182023年8月26日,我们没有书写任何代码,就得到了一个最简单的地图显示程序。但这个程序还不能与用户交互,下一步我们需要添加一些代码,让程序能响应用户的鼠标,完成放大和全图显示的功能。,添加基本的代码,图,33 MapControl,控件支持的所有方法,19,2024年8月16日,我们没有书写任何代码,就得到了一个最简单的地图显示程序。但这,双击,MapControl,控件,可以进入代码编辑界面。从窗口上方的下拉列表框中,我们能够看到,MapControl,能够响应的所有事件(关于每个事件的详细使用方法等请参见帮助系统,第六章对帮助系统有更加详细的介绍)。双击,MapControl,进入代码编辑界面的时候,默认的是“,OnMouseDown”,事件,下一步就需要在这个事件中添加响应鼠标的相关代码。,请您在,Private Sub AxMapControl1_OnMouseDown,函数中添加如下代码:,if (e.button = 1),this.axMapControl1.Extent = this.axMapControl1.TrackRectangle();,else if (e.button = 2),this.axMapControl1.Extent = this.axMapControl1.FullExtent;,20,2024年8月16日,双击MapControl控件,可以进入代码编辑界面。从窗口上,再次运行程序,鼠标左键在地图上拉框可以实现地图的放大功能,而右键单击地图则会还原地图的全图显示。,图,34,任意比例尺放大功能,21,2024年8月16日,再次运行程序,鼠标左键在地图上拉框可以实现地图的放大功能,而,如果将代码替换如下,则能实现左键放大,右键漫游的功能。,if (e.button = 1),this.axMapControl1.Extent = this.axMapControl1.TrackRectangle();,else if (e.button = 2),this.axMapControl1.Pan();,22,2024年8月16日,如果将代码替换如下,则能实现左键放大,右键漫游的功能。222,下面我们依次来看看这些代码都代表什么意思。首先看来第一段:,if (e.button = 1),this.axMapControl1.Extent = this.axMapControl1.TrackRectangle();,else if (e.button = 2),this.axMapControl1.Extent = this.axMapControl1.FullExtent;,这个代码是一个,If Else,条件语句,关于“,e”,的详细定义及其中包含的各参数,请参考帮助中与“,IMapControlEvents2, OnMouseDownEventHandler delegate”,关键字相关的内容。,代码解释,23,2024年8月16日,下面我们依次来看看这些代码都代表什么意思。首先看来第一段:代,可以根据,e,中包含的“,button”,值来判断鼠标的单击操作是来自何处,若,button,值为,1,,则为鼠标左键,,2,代表鼠标右键,,4,代表鼠标中键。当判断得到是鼠标左键单击时,执行“,AxMapControl1.Extent = AxMapControl1.TrackRectangle”,这条语句,其中,等号右侧是调用了“,TrackRectangle”,方法,这个方法是在地图上拖拽出一个矩形,之后将这个矩形赋值给当前地图的显示区域(,Extent,),这样就实现了地图的放大功能。类似的,若鼠标右键单击,则将全图范围赋值给当前的显示范围,实现了地图的全图显示功能。,第二段代码与第一段结构一样,只是在右键的相应事件上略有不同,这是调用了“,Pan”,方法,实现了地图的漫游功能。,24,2024年8月16日,可以根据e中包含的“button”值来判断鼠标的单击操作是来,通过这个例子,我们制作出了一个最简单的地图浏览程序,MapView,,并能响应一些基本的鼠标操作。在,MapControl,的属性页中,其实还有许多内容您可以尝试,例如在“,General”,面板中可以直接加入地图文件(*,.mxd,或者*,.mxt,),您也可以利用刚才的方式一次性多加入一些图层而不仅仅加入“,States”,一个,同时可以更改各图层的叠放次序,也可以在“,Data”,面板中设置地图的旋转角度(,Rotation,)等,您还可以设置,MapControl,的显示方式,是否支持地图的预览功能,边框样式等等。您可以做一些尝试,看看能得到哪些有趣的结果,这些尝试对您今后熟悉,ArcGIS Engine,的开发是有一定帮助的。如果需要重置,MapControl,,只需要点击“,Data”,面板中的“,Reset”,按钮。当您完成了这个例子,并做了一些积极的尝试之后,您就可以接着学习下一个小节的内容了。,小结,25,2024年8月16日,通过这个例子,我们制作出了一个最简单的地图浏览程序MapVi,查询是,GIS,中非常重要的一个功能,下面将分别介绍属性查询和空间查询的制作方法。,5.3,属性查询,添加控件,如果上一小节的工程已经关闭,则将其打开,如果您之后又在,MapControl,中添加了一些别的数据,请将其删除,只保留一个“,states”,图层,请务必注意这一步,这直接关系到您下面的工作能否顺利进行。用之前讲过的方式,在窗体中添加一个,Label,和一个,TextBox,。将,Label,的“,Text”,属性修改为“,StateName”,,结果如下:,图,35 Label,控件和,TextBox,控件,26,2024年8月16日,查询是GIS中非常重要的一个功能,下面将分别介绍属性查询和空,首先添加引用。点击菜单栏上的“项目”,“,添加引用”,在弹出的对话框中同时选择“,ESRI.ArcGIS.Carto”,和“,ESRI.ArcGIS.Geodatabase”,(选择的时候按下,Ctrl,键以同时选择多个),点击确定。,之后双击,TextBox1,控件,进入代码编辑界面。在代码编辑区域的最上方输入以下内容:,using ESRI.ArcGIS.Carto;,using ESRI.ArcGIS.Geodatabase;,如下图所示:,添加引用和代码,图,36,引用添加位置,27,2024年8月16日,首先添加引用。点击菜单栏上的“项目”“添加引用”,在弹出,图,37,添加引用对话框,28,2024年8月16日,图37 添加引用对话框282023年8月26日,之后在控件,TextBox,的事件中选择,KeyUp,,在,KeyUp,事件中添加以下代码:,图,38 KeyPress,方法,29,2024年8月16日,之后在控件TextBox的事件中选择KeyUp,在KeyUp,if (e.KeyCode=Keys.Enter),/,定义图层,要素游标,查询过滤器,要素,IFeatureLayer pFeatureLayer;,IFeatureCursor pFeatureCursor;,IQueryFilter pQueryFilter;,IFeature pFeature;,/,获取图层,pFeatureLayer = this.axMapControl1.Map.get_Layer(0) as IFeatureLayer;,/,如果图层名称不是,states,,程序退出,if (pFeatureLayer.Name != states),return;,/,清除上次查询结果,this.axMapControl1.Map.ClearSelection();,/pQueryFilter,的实例化,pQueryFilter = new QueryFilterClass();,/,设置查询过滤条件,pQueryFilter.WhereClause = STATE_NAME= + txtStateName.Text + ;,30,2024年8月16日,302023年8月26日,/,查询,pFeatureCursor = pFeatureLayer.Search(pQueryFilter, true);,/,获取查询到的要素,pFeature = pFeatureCursor.NextFeature();,/,判断是否获取到要素,if (pFeature!=null),/,选择要素,this.axMapControl1.Map.SelectFeature(pFeatureLayer, pFeature);,/,放大到要素,this.axMapControl1.Extent = pFeature.Shape.Envelope;,else,/,没有得到,pFeature,的提示,MessageBox.Show(,没有找到名为, + txtStateName.Text + ,的州, ,提示,);,31,2024年8月16日,/查询 312023年8月26日,运行程序,分别向编辑框中输入“,Texas”,和“,RS”,,键入回车,如下图所示:,图,39 Texas,州查询结果,32,2024年8月16日,运行程序,分别向编辑框中输入“Texas”和“RS”,键入回,图,40 RS,查询结果,33,2024年8月16日,图40 RS查询结果332023年8月26日,if (e.KeyCode=Keys.Enter),上述代码是一个判断语句,即当用户输入回车的时候,开始进行查询。,下面两行代码是定义查询的范围,默认为上一小节中添加的图层“,states”,,如果找不到这个图层则自动退出。,/,获取图层,pFeatureLayer = this.axMapControl1.Map.get_Layer(0) as IFeatureLayer;,/,如果图层名称不是,states,,程序退出,if (pFeatureLayer.Name != states),return;,/,清除上次查询结果,this.axMapControl1.Map.ClearSelection();,这一部分是生成一个新的查询器,选择条件(,WhereClause,)就是检索是否有与用户输入相符的州,并将结果从查询得到的,pCursor,中读取出来。,代码解释,34,2024年8月16日,if (e.KeyCode=Keys.Enter)代码解,/,判断是否获取到要素,if (pFeature!=null),/,选择要素,this.axMapControl1.Map.SelectFeature(pFeatureLayer, pFeature);,/,放大到要素,this.axMapControl1.Extent = pFeature.Shape.Envelope;,else,/,没有得到,pFeature,的提示,MessageBox.Show(,没有找到名为, + txtStateName.Text + ,的州, ,提示,);,这一部分是一个判断语句,若查询得到的结果为空,则刷新地图,弹出对话框通知用户没有查询到结果,并退出程序。如果查询得到的结果不为空,则将这个结果加入地图的选择集,并将地图的显示范围定为查询结果的外轮廓,这样得到的州将高亮显示同时居中放大到屏幕中心。,35,2024年8月16日,/判断是否获取到要素352023年8月26日,这一部分中,我们接触到了基本的属性查询。但是在这个例子中,我们不能实现对属性表中任意属性字段的查询(在这个程序中,我们只能查询州名,STATE_NAME,,而不能对别的字段进行查询),而且这个查询不支持模糊查询。为了使查询变的更加丰富,更加人性化,请您参考,IQueryFilter,接口中,WhereClause,属性的设置方法,拓展,WhereClause,可以得到许多有趣的结果。在书写代码的过程中,对任何有疑问的地方,或者您想要拓展的位置,都可以在帮助系统中查询相关的接口和属性,查看最原始的定义,帮助系统中的解释和定义对于您熟悉,ArcObjects,,熟悉,ArcGIS Engine,的二次开发以及后续的工作都是十分重要的,请一定不要忽视这个环节。如果您已经尝试了一些变化,或者对本小节的内容比较熟悉了,则可以进入下一小节的学习。,小结,36,2024年8月16日,这一部分中,我们接触到了基本的属性查询。但是在这个例子中,我,上一小节我们已经学习了如何进行属性查询,在这一小节中,我们将继续学习,GIS,中的另一种查询方式,空间查询。,如果上一小节的工程已经关闭,则将其打开,如果您之后又在,MapControl,中添加了一些别的数据,请将其删除,只保留一个“,states”,图层,请务必注意这一步,这直接关系到您下面的工作能否顺利进行。我们接着上一小节的内容继续完善。在窗体中添加一个,Button,,将其,Text,属性修改为“点查询”。,5.4,空间查询,添加控件,图,41,添加“点查询”按钮,37,2024年8月16日,上一小节我们已经学习了如何进行属性查询,在这一小节中,我们将,利用上一小节讲的方式,添加引用“,ESRI.ArcGIS.Geometry”,,并在类中添加一个全局变量,nMouseFlag,,如下图所示:,添加引用和代码,图,42,添加引用“,ESRI.ArcGIS.Geometry”,38,2024年8月16日,利用上一小节讲的方式,添加引用“ESRI.ArcGIS.Ge,之后在类中添加一个公共函数,用来根据屏幕像素计算实际的地理距离,private double ConvertPixelToMapUnits(IActiveView activeView,double pixelUnits),double realWorldDiaplayExtent;,int pixelExtent;,double sizeOfOnePixel;,double mapUnits;,/,获取设备中视图显示宽度,即像素个数,pixelExtent=activeView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().right- activeView.ScreenDisplay.DisplayTransformation.get_DeviceFrame().left;,/,获取地图坐标系中地图显示范围,realWorldDiaplayExtent = activeView.ScreenDisplay.DisplayTransformation.VisibleBounds.Width;,/,每个像素大小代表的实际距离,sizeOfOnePixel = realWorldDiaplayExtent / pixelExtent;,/,地理距离,mapUnits = pixelUnits * sizeOfOnePixel;,return mapUnits;,39,2024年8月16日,之后在类中添加一个公共函数,用来根据屏幕像素计算实际的地理距,此后,双击,Button1,,进入,Button,的,Click,事件,向其中添加如下代码:,/,标记点查询,mMouseFlag = 1;,/,设置鼠标形状,this.axMapControl1.MousePointer = ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerCrosshair;,(注:上两行代码应该书写在一行,由于空间有限,这里写为两行),最后将,MapControl,控件的,OnMouseDown,事件中已有的代码清除,替换为以下代码:,if (mMouseFlag=1),IFeatureLayer pFeatureLayer;,IFeatureClass pFeatureClass;,/,获取图层和要素类,为空时返回,pFeatureLayer = this.axMapControl1.Map.get_Layer(0) as IFeatureLayer ;,if (pFeatureLayer.Name != states),return;,pFeatureClass = pFeatureLayer.FeatureClass;,if (pFeatureClass = null),return;,IActiveView pActiveView;,IPoint pPoint;,double length;,40,2024年8月16日,此后,双击Button1,进入Button的Click事件,,/,获取视图范围,pActiveView = this.axMapControl1.ActiveView;,/,获取鼠标点击屏幕坐标,pPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);,/2,个像素大小的屏幕距离转换为地图距离,length = ConvertPixelToMapUnits(pActiveView, 2);,ITopologicalOperator pTopoOperator;,IGeometry pGeoBuffer;,ISpatialFilter pSpatialFilter;,/,根据缓冲半径生成空间过滤器,pTopoOperator = pPoint as ITopologicalOperator;,pGeoBuffer = pTopoOperator.Buffer(length);,pSpatialFilter = new SpatialFilterClass();,pSpatialFilter.Geometry = pGeoBuffer;,/,根据图层类型选择缓冲方式,switch (pFeatureClass.ShapeType),case esriGeometryType.esriGeometryPoint:,pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;,break;,case esriGeometryType.esriGeometryPolyline:,pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelCrosses;,break;,case esriGeometryType.esriGeometryPolygon:,pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;,break;,41,2024年8月16日,/获取视图范围412023年8月26日,/,定义空间过滤器的空间字段,pSpatialFilter.GeometryField = pFeatureClass.ShapeFieldName;,IQueryFilter pQueryFilter;,IFeatureCursor pFeatureCursor;,IFeature pFeature;,/,利用要素过滤器查询要素,pQueryFilter = pSpatialFilter as IQueryFilter;,pFeatureCursor = pFeatureLayer.Search(pQueryFilter, true);,pFeature = pFeatureCursor.NextFeature();,int fieldIndex;,if(pFeature!=null),/,选择指定要素,this.axMapControl1.Map.ClearSelection();,this.axMapControl1.Map.SelectFeature(ILayer)pFeatureLayer, pFeature);,this.axMapControl1.Refresh();,fieldIndex = pFeature.Fields.FindField(STATE_NAME);,MessageBox.Show(,查找到“, + pFeature.get_Value(fieldIndex) + ”, ,提示,);,42,2024年8月16日,422023年8月26日,运行程序,,结果如右图所示:,图,43,空间查询运行结果,43,2024年8月16日,图43 空间查询运行结果432023年8月26日,距离转换函数请您自行参看帮助系统中对相关接口的具体定义和解释。,Button1,的,Click,事件中是将,nMouseFlag,设置为,1,,并将鼠标在,MapControl,上的形状改变为十字丝状。,/,获取视图范围,pActiveView = this.axMapControl1.ActiveView;,/,获取鼠标点击屏幕坐标,pPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);,/,屏幕距离转换为地图距离,length = ConvertPixelToMapUnits(pActiveView, 2);,上述代码是在,MapControl,的,OnMouseDown,事件中,当您单击鼠标左键的时候,将屏幕上的点转换成地图上的点(关键在于坐标值的转换),方便后续操作。,/,根据缓冲半径生成空间过滤器,pTopoOperator = pPoint as ITopologicalOperator;,pGeoBuffer = pTopoOperator.Buffer(length);,pSpatialFilter = new SpatialFilterClass();,pSpatialFilter.Geometry = pGeoBuffer;,代码解释,44,2024年8月16日,距离转换函数请您自行参看帮助系统中对相关接口的具体定义和解释,这一部分是将,2,个像素的距离转换成实际的地理距离,并以这个距离为半径,上一步生成的点为中心,生成一个缓冲区。,45,2024年8月16日,这一部分是将2个像素的距离转换成实际的地理距离,并以这个距离,上述代码是设置,pSpatialFilter,的各项参数,供后续查询,包括空间查询的几何形状(之前生成的缓冲区),空间查询的方式(相交,包含等)以及,Shape,字段。,这两句代码是找出“,STATE_NAME”,所在的列数,并将其显示出来。,46,2024年8月16日,上述代码是设置pSpatialFilter的各项参数,供后续,在本节中我们完成更多的空间查询功能,其中有点查询、线查询、矩形查询、圆查询,新建一个,C#.Net,工程,向工程中添加控件,如下图所示:,其中包括,MapControl,,,4,个,Button,,一个,TextBox,进一步完善空间查询,47,2024年8月16日,在本节中我们完成更多的空间查询功能,其中有点查询、线查询、矩,通过在控件属性中添加地图的方法,向,Mapcontrol,中添加例子数据。(例子数据是位于,World,文件夹下的,Continents.lyr,)如下图所示:,下面我们在,MainForm,的代码页添加空间查询的函数。本例中我们需要添加,ESRI.ArcGIS.Carto,、,ESRI.ArcGIS.Geometry,、,ESRI.ArcGIS.Geodatabase,、,ESRI.ArcGIS.Controls,四个个命名空间,并且我们仍然需要上节中的,ConvertPixelToMapUnits(IActiveView activeView,double pixelUnits),函数,请自行添加。,空间查询函数代码如下:,/ ,/,空间查询,/ ,/ MapControl,/ ,空间查询方式,/ ,字段名称,/ ,查询得到的要素名称,48,2024年8月16日,通过在控件属性中添加地图的方法,向Mapcontrol中添加,private string QuerySpatial(AxMapControl mapControl, IGeometry geometry, string fieldName),49,2024年8月16日,private string QuerySpatial(Ax,50,2024年8月16日,502023年8月26日,51,2024年8月16日,512023年8月26日,在设计页面双击点查询按钮,进入点击按钮响应事件填写如下代码。,相应的线查询、矩形查询、圆查询添加同样的代码,但,nMouseFlag,得值要有所改变。,线查询:,nMouseFlag=2,矩形查询:,nMouseFlag=3,圆查询:,nMouseFlag=4,为,MapControl,控件添加,OnMouseDown,事件,填入以下代码,52,2024年8月16日,在设计页面双击点查询按钮,进入点击按钮响应事件填写如下代码。,53,2024年8月16日,532023年8月26日,54,2024年8月16日,542023年8月26日,点击运行,运行效果如下图所示:,55,2024年8月16日,点击运行,运行效果如下图所示:552023年8月26日,仔细研读代码,您会发现,在这部分中我们并没有用到什么新的知识,只是在结构上做了调整,应为空间查询都是需要使用一个,IGeometry,对象进行空间求交进行查询的。所以我们将公共的代码放在公共的模块中进行调用。有心的同学可能发现,我们为了判断用户在,MapControl,上的操作,我们引入了一个全局变量,nMouseFlag,,程序中多一个全局变量,对程序的结构的封闭性就有所破坏,能不能去掉这个全局变量而是,Mapcontrol,自主判断是哪个功能进行操作呢?答案是肯定的,我们可以使用,BaseCommand,和,BaseTool,来完成这个工作,详细的用法在,3.4,和,3.5,小节将会介绍。,56,2024年8月16日,仔细研读代码,您会发现,在这部分中我们并没有用到什么新的知识,小结,在这一小节中,我们学习了如何进行简单的空间查询。空间查询不仅包括点查询,还包括线查询,矩形查询,多边形查询等(为了实现这些功能,可以参考,MapControl,中的,TrackRectangle,等方法)。对于这一小节的代码,强烈建议您参看帮助系统中对相关接口的解释和定义,以进一步熟悉接口的使用,这对后面的学习以及掌握,ArcGIS Engine,二次开发是极有好处的。如果您对这一部分比较熟悉了,可以进入下一小节。在第四章中,我们介绍了控件命令(,Control Commands,),并提到,ArcGIS Engine,允许用户自定义开发一些控件命令,在下两小节中,我们将具体学习如何开发。,57,2024年8月16日,小结在这一小节中,我们学习了如何进行简单的空间查询。空间查,5.5 BaseCommand,开发实例,在这一小节中,我们将学习,BaseCommand,的开发步骤。,BaseCommand,的功能与,Button,的功能类似,是当鼠标点击按钮的时候,,MapControl,控件会对其中的命令做出相应而无需额外的操作。在这一小节中,我们将制作一个“定比例尺放大”的按钮,当鼠标单击按钮时,地图将居中放大一倍。,添加控件,如果上一小节的程序已经关闭,则重新打开,同时保证,MapControl,控件中加载了至少一个图层。在主窗体(,frmMain,)中添加一个,Button,,将其,Text,属性更改为“居中放大”。,3.3.5,小结,58,2024年8月16日,5.5 BaseCommand开发实例3.3.5小结582,添加,BaseCommand,59,2024年8月16日,添加BaseCommand592023年8月26日,60,2024年8月16日,602023年8月26日,添加代码,61,2024年8月16日,添加代码612023年8月26日,62,2024年8月16日,622023年8月26日,63,2024年8月16日,632023年8月26日,小结,64,2024年8月16日,小结642023年8月26日,End,Thanks!,65,2024年8月16日,End,652023年8月26日,
展开阅读全文