ArcEngine 二次开发实习初级讲义
图40 RS查询结果
3.2.3 代码解释
If e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Return) Then
上述代码是一个判断语句,即当用户输入回车的时候,开始进行查询。 下面两行代码是定义查询的范围,默认为上一小节中添加的图层“states”,如果找不到这个图层则自动退出。
pFeatureLayer = Me.AxMapControl1.Map.Layer(0) If Not pFeatureLayer.Name = \ Then Exit Sub
Me.AxMapControl1.Map.ClearSelection()是为了将上一次的查询结果清除。 pFilter = New QueryFilter
pFilter.WhereClause = \ & TextBox1.Text & \ pCursor = pFeatureLayer.Search(pFilter, True) pFeature = pCursor.NextFeature
这一部分是生成一个新的查询器,选择条件(WhereClause)就是检索是否有与用户输入相符的州,并将结果从查询得到的pCursor中读取出来。
If pFeature Is Nothing Then
Me.AxMapControl1.Refresh()
MessageBox.Show(\没有找到名为\ & TextBox1.Text & \的州\, \,
MessageBoxButtons.OK)
Exit Sub Else
Me.AxMapControl1.Map.SelectFeature(pFeatureLayer, pFeature) Me.AxMapControl1.Extent = pFeature.Shape.Envelope End If
这一部分是一个判断语句,若查询得到的结果为空,则刷新地图,弹出对话框通知用户没有查询到结果,并退出程序。如果查询得到的结果不为空,则将这个结果加入地图的选择
- 26 -
ArcEngine 二次开发实习初级讲义
集,并将地图的显示范围定为查询结果的外轮廓,这样得到的州将高亮显示同时居中放大到屏幕中心。 3.2.4 小结
这一部分中,我们接触到了基本的属性查询。但是在这个例子中,我们不能实现对属性表中任意属性字段的查询(在这个程序中,我们只能查询州名——STATE_NAME,而不能对别的字段进行查询),而且这个查询不支持模糊查询。为了使查询变的更加丰富,更加人性化,请您参考IQueryFilter接口中WhereClause属性的设置方法,拓展WhereClause可以得到许多有趣的结果。在书写代码的过程中,对任何有疑问的地方,或者您想要拓展的位置,都可以在帮助系统中查询相关的接口和属性,查看最原始的定义,帮助系统中的解释和定义对于您熟悉ArcObjects,熟悉ArcGIS Engine的二次开发以及后续的工作都是十分重要的,请一定不要忽视这个环节。如果您已经尝试了一些变化,或者对本小节的内容比较熟悉了,则可以进入下一小节的学习。
3.3 空间查询
上一小节我们已经学习了如何进行属性查询,在这一小节中,我们将继续学习GIS中的另一种查询方式——空间查询。 3.3.1 添加控件
如果上一小节的工程已经关闭,则将其打开,如果您之后又在MapControl中添加了一些别的数据,请将其删除,只保留一个“states”图层,请务必注意这一步,这直接关系到您下面的工作能否顺利进行。我们接着上一小节的内容继续完善。在窗体中添加一个Button,将其Text属性修改为“点查询”。
图41 添加“点查询”按钮
3.3.2添加引用和代码
利用上一小节讲的方式,添加引用“ESRI.ArcGIS.Geometry”,并在类中添加一个全局变量nMouseFlag,如下图所示:
- 27 -
ArcEngine 二次开发实习初级讲义
图42 添加引用“ESRI.ArcGIS.Geometry”
之后在类中添加一个公共函数,用来根据屏幕像素计算实际的地理距离。
Public Function ConvertPixelsToMapUnits(ByVal pActiveView As IActiveView, ByVal pixelUnits As Double) As Double
Dim realWorldDisplayExtent As Double Dim pixelExtent As Integer Dim sizeOfOnePixel As Double
pixelExtent = pActiveView.ScreenDisplay.DisplayTransformation.DeviceFrame.Right - pActiveView.ScreenDisplay.DisplayTransformation.DeviceFrame.Left realWorldDisplayExtent =
pActiveView.ScreenDisplay.DisplayTransformation.VisibleBounds.Width sizeOfOnePixel = realWorldDisplayExtent / pixelExtent ConvertPixelsToMapUnits = pixelUnits * sizeOfOnePixel
End Function
此后,双击Button1,进入Button的Click事件,向其中添加如下代码:
nMouseFlag = 1
Me.AxMapControl1.MousePointer
= ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerCrosshair
(注:上两行代码应该书写在一行,由于空间有限,这里写为两行)
最后将MapControl控件的OnMouseDown事件中已有的代码清除,替换为以下代码:
If nMouseFlag = 1 Then
Dim pFeatureLayer As IFeatureLayer Dim pFeatureClass As IFeatureClass Dim pSpatialFilter As ISpatialFilter Dim pFilter As IQueryFilter Dim pActiveView As IActiveView Dim pPoint As IPoint Dim pBuffer As IGeometry Dim length As Double Dim n As Long
Dim pTopo As ITopologicalOperator Dim pCursor As IFeatureCursor
- 28 -
ArcEngine 二次开发实习初级讲义
Dim pFeature As IFeature
pFeatureLayer = Me.AxMapControl1.Map.Layer(0)
If Not pFeatureLayer.Name = \ Then Exit Sub pFeatureClass = pFeatureLayer.FeatureClass If pFeatureClass Is Nothing Then Exit Sub
pActiveView = Me.AxMapControl1.Map
pPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y) length = ConvertPixelsToMapUnits(pActiveView, 2)
pTopo = pPoint
pBuffer = pTopo.Buffer(length) pSpatialFilter = New SpatialFilter pSpatialFilter.Geometry = pBuffer
Select Case pFeatureClass.ShapeType Case esriGeometryType.esriGeometryPoint
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains Case esriGeometryType.esriGeometryPolyline
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelCrosses Case esriGeometryType.esriGeometryPolygon
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects End Select
pSpatialFilter.GeometryField = pFeatureClass.ShapeFieldName pFilter = pSpatialFilter
pCursor = pFeatureLayer.Search(pFilter, False) pFeature = pCursor.NextFeature If pFeature Is Nothing Then Exit Sub
Me.AxMapControl1.Map.ClearSelection()
Me.AxMapControl1.Map.SelectFeature(pFeatureLayer, pFeature) Me.AxMapControl1.Refresh()
n = pFeature.Fields.FindField(\)
MessageBox.Show(pFeature.Value(n), \, MessageBoxButtons.OK)
End If
运行程序,结果如下图所示:
- 29 -
ArcEngine 二次开发实习初级讲义
图43 空间查询运行结果
3.3.3代码解释
距离转换函数请您自行参看帮助系统中对相关接口的具体定义和解释。 Button1的Click事件中是将nMouseFlag设置为1,并将鼠标在MapControl上的形状改变为十字丝状。
pActiveView = Me.AxMapControl1.Map
pPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y)
上述代码是在MapControl的OnMouseDown事件中,当您单击鼠标左键的时候,将屏幕上的点转换成地图上的点(关键在于坐标值的转换),方便后续操作。
length = ConvertPixelsToMapUnits(pActiveView, 2) pTopo = pPoint
pBuffer = pTopo.Buffer(length)
这一部分是将2个像素的距离转换成实际的地理距离,并以这个距离为半径,上一步生成的点为中心,生成一个缓冲区。
pSpatialFilter = New SpatialFilter pSpatialFilter.Geometry = pBuffer Select Case pFeatureClass.ShapeType Case esriGeometryType.esriGeometryPoint
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains Case esriGeometryType.esriGeometryPolyline
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelCrosses Case esriGeometryType.esriGeometryPolygon
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects End Select
pSpatialFilter.GeometryField = pFeatureClass.ShapeFieldName pFilter = pSpatialFilter
上述代码是设置pSpatialFilter的各项参数,供后续查询,包括空间查询的几何形状(之前生成的缓冲区),空间查询的方式(相交,包含等)以及Shape字段。
n = pFeature.Fields.FindField(\)
- 30 -