ArcGIS Engine二次开发——基础篇
不到这个图层则自动退出。
//获取图层
pFeatureLayer = this.axMapControl1.Map.get_Layer(0) as IFeatureLayer; //如果图层名称不是states,程序退出 if (pFeatureLayer.Name != \ bou2_4p \) return;
//清除上次查询结果
this.axMapControl1.Map.ClearSelection();
下面部分是生成一个新的查询器,选择条件(WhereClause)就是检索是否有与用户输
入相符的州,并将结果从查询得到的pCursor中读取出来。
//pQueryFilter的实例化
pQueryFilter = new QueryFilterClass(); //设置查询过滤条件
pQueryFilter.WhereClause = \ + txtStateName.Text + \; //查询
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 + \的省\, \提示\); }
1.2.3 小结
这一部分中,我们接触到了基本的属性查询。但是在这个例子中,我们不能实现对属性表中任意属性字段的查询(在这个程序中,我们只能查询省名——NAME,而不能对别的字段进行查询),而且这个查询不支持模糊查询。为了使查询变的更加丰富,更加人性化,
ArcGIS Engine二次开发——基础篇
请您参考IQueryFilter接口中WhereClause属性的设置方法,拓展WhereClause可以得到许多有趣的结果。在书写代码的过程中,对任何有疑问的地方,或者您想要拓展的位置,都可以在帮助系统中查询相关的接口和属性,查看最原始的定义,帮助系统中的解释和定义对于您熟悉ArcObjects,熟悉ArcGIS Engine的二次开发以及后续的工作都是十分重要的,请一定不要忽视这个环节。如果您已经尝试了一些变化,或者对本小节的内容比较熟悉了,则可以进入下一小节的学习。
1.3 空间查询
上一小节我们已经学习了如何进行属性查询,在这一小节中,我们将继续学习GIS中的另一种查询方式——空间查询,其中有点查询、线查询、矩形查询、圆查询。本节我们将空间查询的方法抽象为一个独立的函数,这个函数中我们将根据不同的空间查询方式,返回查询得到的一个或多个要素的名称并在地图上高亮显示。
1.3.1 添加控件
新建一个C#.Net工程,向工程中添加控件,如下图所示:
图 31 窗体布局
其中包括MapControl,4个Button,一个TextBox。属性设置如下:
窗体及控件属性设置
类型 Form TextBox Button Button Button Name MainForm txtTips btnPointQuery btnLineQuery btnRectQuery Text 空间查询 点查询 线查询 矩形查询 用途 主窗体 点查询 线查询 矩形查询 请在地图上选取地物! 系统操作提示 ArcGIS Engine二次开发——基础篇
Button
btnCircleQuery 圆查询 圆查询 通过在控件属性中添加地图的方法,向Mapcontrol中添加例子数据。(例子数据是位于China文件夹下的bou2_4p)如下图所示:
图 9添加数据
下面我们在MainForm的代码页添加空间查询的函数。本例中我们需要添加ESRI.ArcGIS.Carto、ESRI.ArcGIS.Geometry、ESRI.ArcGIS.Geodatabase、ESRI.ArcGIS.Controls四个个命名空间。
我们仍然需要上节中的ConvertPixelToMapUnits(IActiveView activeView,double pixelUnits)函数,请自行添加。
1.3.2 添加代码
先在类中添加一个公共函数,用来根据屏幕像素计算实际的地理距离。
///
/// 根据屏幕像素计算实际的地理距离 ///
/// /// ///
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;
ArcGIS Engine二次开发——基础篇
}
然后添加空间查询的方法,空间查询函数代码如下:
///
/// /// /// ///
private string QuerySpatial(AxMapControl mapControl, IGeometry geometry, string fieldName) {
//本例添加一个图层进行查询,多个图层时返回 if (mapControl.LayerCount > 1) return null;
//清除已有选择
mapControl.Map.ClearSelection();
//查询得到的要素名称 string strNames=null;
IFeatureLayer pFeatureLayer; IFeatureClass pFeatureClass; //获取图层和要素类,为空时返回
pFeatureLayer = mapControl.Map.get_Layer(0) as IFeatureLayer; pFeatureClass = pFeatureLayer.FeatureClass; if (pFeatureClass == null) return null;
//初始化空间过滤器 ISpatialFilter pSpatialFilter;
pSpatialFilter = new SpatialFilterClass(); pSpatialFilter.Geometry = geometry; //根据图层类型选择缓冲方式 switch (pFeatureClass.ShapeType) {
case esriGeometryType.esriGeometryPoint:
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains; break;
case esriGeometryType.esriGeometryPolyline:
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelCrosses; break;
case esriGeometryType.esriGeometryPolygon:
ArcGIS Engine二次开发——基础篇
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; break; }
//定义空间过滤器的空间字段
pSpatialFilter.GeometryField = pFeatureClass.ShapeFieldName;
IQueryFilter pQueryFilter; IFeatureCursor pFeatureCursor; IFeature pFeature; //利用要素过滤器查询要素
pQueryFilter = pSpatialFilter as IQueryFilter;
pFeatureCursor = pFeatureLayer.Search(pQueryFilter, true); pFeature = pFeatureCursor.NextFeature();
int fieldIndex;
while (pFeature != null) {
//选择指定要素
fieldIndex = pFeature.Fields.FindField(fieldName); //获取要素名称
strNames = strNames + pFeature.get_Value(fieldIndex) + \;\; //高亮选中要素
mapControl.Map.SelectFeature((ILayer)pFeatureLayer, pFeature); mapControl.ActiveView.Refresh(); pFeature = pFeatureCursor.NextFeature(); }
return strNames; }
定义鼠标标记的成员变量mMouseFlag。在设计页面双击点查询按钮,进入点击按钮响应事件填写如下代码。
private void btnPointQuery_Click(object sender, EventArgs e) {
mMouseFlag = 1;
this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair; }
相应的线查询、矩形查询、圆查询添加同样的代码,但nMouseFlag得值要有所改变。 线查询:nMouseFlag=2 矩形查询:nMouseFlag=3 圆查询:nMouseFlag=4