ArcGIS Engine 的空间查询功能是其最大的一个特色,本文主要介绍一下空间查询的流程。
首先,新建一个对话框用于选择查询的图层与查询方式。
添加三个Label控件,两个ComboBox,两个Button和一个TextBox。各控件属性设置如下:
名称(Name) |
Text属性 |
描述 |
lblLayer |
选择图层: |
标签 |
lblField |
字段名称: |
标签 |
lblFind |
查找内容: |
标签 |
cboLayer |
MapControl中的图层名称 |
|
cboField |
cboLayer选中图层的所有字段名称 |
|
txtValue |
输入的查询对象名称 |
|
btnOk |
查找 |
查询按钮 |
btnCancel |
取消 |
取消查询按钮 |
进入窗体的代码编辑界面。
1、添加成员变量,重写构造函数,用于在函数构造时获取主窗体的mapControl 控件对象。代码如下:
public SpatialQueryForm(ESRI.ArcGIS.Controls.AxMapControl mapControl)
{
InitializeComponent();
this.m_mapControl = mapControl;
}
#region Class Numble
//获取主窗体mapControl对象
private ESRI.ArcGIS.Controls.AxMapControl m_mapControl;
//查询方式
public int mQueryModel;
//图层索引
public int mLayerIndex;
#endregion
定义两个变量,用于存储查询方式与图层索引。
2、在窗体的Load消息响应函数中初始化当前的图层信息和查询方式,代码如下:
private void SpatialQueryForm_Load(object sender, EventArgs e)
{
//MapControl没有图层返回
if (m_mapControl.LayerCount <= 0)
return;
//获取MapControl中的全部图层名称,并加入ComboBox
for (int i = 0; i < m_mapControl.LayerCount; ++i)
{
cobLayer.Items.Add(m_mapControl.get_Layer(i).Name);
}
//加载查询方式
this.cobSearchStyle.Items.Add("矩形查询");
this.cobSearchStyle.Items.Add("线查询");
this.cobSearchStyle.Items.Add("点查询");
this.cobSearchStyle.Items.Add("圆查询");
//初始化ComboBox默认值
cobLayer.SelectedIndex = 0;
cobSearchStyle.SelectedIndex = 0;
}
3、查询按钮的响应函数,用于获取所选择的图层与查询方式。代码如下:
private void btnOK_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
//判断图层数量
if (this.cobLayer.Items.Count <= 0)
{
MessageBox.Show("当前MapControl没有添加图层!", "提示");
return;
}
//获取选中的查询方式和图层索引
this.mLayerIndex = cobLayer.SelectedIndex;
this.mQueryModel = cobSearchStyle.SelectedIndex;
}
4、在主窗体的菜单栏里建立一个空间分析项,在按钮的响应函数中调用空间查询对话框。并且新建两个成员变量,用于在主窗体中记录查询方式与状态代码如下:
#region 空间查询变量
//查询方式
public int mQueryModel;
//图层索引
public int mLayerIndex;
#endregion
private void menuSpatialQuery_Click(object sender, EventArgs e)
{
//初始化空间查询窗体
SpatialQueryForm pspatialQueryForm = new SpatialQueryForm(axMapControl1);
if (pspatialQueryForm.ShowDialog() == DialogResult.OK)
{
this.mTool = "SpatialQuery";
//获取查询方式和图层信息
this.mQueryModel = pspatialQueryForm.mQueryModel;
this.mLayerIndex = pspatialQueryForm.mLayerIndex;
//设置鼠标形状
this.axMapControl1.MousePointer = ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerCrosshair;
}
}
在该函数中是通过string 类型的mTool变量记录函数状态。然后在鼠标按下(OnMouseDown)的消息响应中实现查询。
5、在Form的窗口设计中添加一个Panel控件,设置控件的visible属性为false。在Panel控件中添加一个datagridview 控件用于显示查询结果,以表单的形式显示,和一个取消按钮。如下图:
6、在主窗体中建立一个独立函数,用于实现查询结果。代码如下:
private DataTable LoadQueryResult(ESRI.ArcGIS.Controls.AxMapControl mapControl, ESRI.ArcGIS.Carto.IFeatureLayer featureLayer, ESRI.ArcGIS.Geometry.IGeometry geometry)
{
ESRI.ArcGIS.Geodatabase.IFeatureClass pFeatureClass = featureLayer.FeatureClass;
//根据图层属性字段初始化DataTable
ESRI.ArcGIS.Geodatabase.IFields pFields = pFeatureClass.Fields;
DataTable pDataTable = new DataTable();
for (int i = 0; i < pFields.FieldCount; ++i)
{
pDataTable.Columns.Add(pFields.get_Field(i).AliasName);
}
//空间过滤器
ESRI.ArcGIS.Geodatabase.ISpatialFilter pSpatialFilter = new ESRI.ArcGIS.Geodatabase.SpatialFilterClass();
pSpatialFilter.Geometry = geometry;
//根据图层类型选择缓冲方式
switch (pFeatureClass.ShapeType)
{
case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryMultipoint:
pSpatialFilter.SpatialRel = ESRI.ArcGIS.Geodatabase.esriSpatialRelEnum.esriSpatialRelContains;
break;
case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline:
pSpatialFilter.SpatialRel = ESRI.ArcGIS.Geodatabase.esriSpatialRelEnum.esriSpatialRelCrosses;
break;
case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolygon:
pSpatialFilter.SpatialRel = ESRI.ArcGIS.Geodatabase.esriSpatialRelEnum.esriSpatialRelIntersects;
break;
}
//定义空间过滤器的空间字段
pSpatialFilter.GeometryField = pFeatureClass.ShapeFieldName;
ESRI.ArcGIS.Geodatabase.IQueryFilter pQueryFilter;
ESRI.ArcGIS.Geodatabase.IFeatureCursor pFeatureCursor;
ESRI.ArcGIS.Geodatabase.IFeature pFeature;
//利用要素过滤器查询要素
pQueryFilter = pSpatialFilter as ESRI.ArcGIS.Geodatabase.IQueryFilter;
pFeatureCursor = featureLayer.Search(pQueryFilter, true);
pFeature = pFeatureCursor.NextFeature();
while (pFeature != null)
{
string strFldValue = null;
DataRow dr = pDataTable.NewRow();
//遍历图层属性表字段值,并加入pDataTable
for (int i = 0; i < pFields.FieldCount; i++)
{
string strFldName = pFields.get_Field(i).Name;
if (strFldName == "Shape")
{
strFldValue = Convert.ToString(pFeature.Shape.GeometryType);
}
else
strFldValue = Convert.ToString(pFeature.get_Value(i));
dr[i] = strFldValue;
}
pDataTable.Rows.Add(dr);
//高亮选择要素
mapControl.Map.SelectFeature((ESRI.ArcGIS.Carto.ILayer)featureLayer, pFeature);
mapControl.ActiveView.Refresh();
pFeature = pFeatureCursor.NextFeature();
}
return pDataTable;
}
代码注释:该函数中根据输入的mapcontrol 、FeatureLayer和Geometry三个参数返回DataTable类型的查询结果。
注意,其中需要根据图层类型选择,点类型为包含、线类型为Cross、面类型为intersect。
7、在鼠标按下的响应函数中获取选择的区域,并进行查询。代码如下:
private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
{
//清空上次选择的结果
this.axMapControl1.Map.ClearSelection();
switch (mTool)
{
case"SpatialQuery":
//获取当前视图
ESRI.ArcGIS.Carto.IActiveView pActiveView = this.axMapControl1.ActiveView;
//获取鼠标点
ESRI.ArcGIS.Geometry.IPoint pPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);
panel1.Visible = true;
ESRI.ArcGIS.Geometry.IGeometry pGeometry = null;
switch (this.mQueryModel)
{
case 0: //矩形查询
pGeometry = this.axMapControl1.TrackRectangle();
break;
case 1: //线查询
pGeometry = this.axMapControl1.TrackLine();
break;
case 2: //点查询
ESRI.ArcGIS.Geometry.ITopologicalOperator pTopo;
ESRI.ArcGIS.Geometry.IGeometry pBuffer;
pGeometry = pPoint;
pTopo = pGeometry as ESRI.ArcGIS.Geometry.ITopologicalOperator;
//根据点位创建缓冲区,缓冲半径设为0.1,可自行修改
pBuffer = pTopo.Buffer(0.1);
pGeometry = pBuffer.Envelope;
break;
case 3: //圆查询
pGeometry = this.axMapControl1.TrackCircle();
break;
}
ESRI.ArcGIS.Carto.IFeatureLayer pFeatureLayer = this.axMapControl1.Map.get_Layer(this.mLayerIndex) as ESRI.ArcGIS.Carto.IFeatureLayer;
DataTable pDataTable = this.LoadQueryResult(axMapControl1, pFeatureLayer, pGeometry);
this.dataGridView1.DataSource = pDataTable.DefaultView;
this.dataGridView1.Refresh();
break;
default :
break;
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.panel1.Visible = false;
this.axMapControl1.ActiveView.FocusMap.ClearSelection();
this.axMapControl1.Refresh();
}
最终结果如下图:
----------------------------------------------------------------------------------end-----------------------------------------------------------------------------