资源描述
(word完整版)ArcGIS Engine地图查询
地图查询、统计是一个GIS系统的基本的功能模块,实际上统计功能的前提也是通过查询获取结果以文字或者图表等报表的形式展现查询结果数据.
地图查询有两种类型的查询:
1.空间查询:在地图上设置一定范围,查询这一范围内的要素。例如在地图上画一范围查询这一区域内的所有消防栓,这一范围的所有消防栓高亮显示(或者其他显示方式)并展现出所有的消防栓的属性信息。
2.属性查询:通过一定的查询条件获取目标要素。例如我们需要查询中国行政区上人口大于5000万,同时GDP大于1万亿的省份,通过执行查询,符号条件的省份高亮显示(或者其他显示方式)并展现出这些省份的属性信息。
ArcGIS Engine9。3为开发者提供了无需写代码即可进行查询功能的Identify工具,但是这个工具是一个通用的信息查询新工具.而开发者通常需要自己开发一套符合自己业务需求更加灵活的查询功能模块,甚至一些功能不仅仅是查询信息,很多编辑编辑功能以及和业务相结合的功能开发都用到查询功能。所以很有必要了解ArcGIS Engine的查询机制。
5.1目标
1.熟悉Cursor,FeatureCursor对象,使用IFeatureCursor接口
2。熟悉QueryFilter, SpatialFilter对象使用IQueryFilter,ISpatialFilter接口
3。熟悉要素选择集SelectionSet对象,会使用IFeatureSelection,ISelectionSet接口
4.开发一个属性查询小功能Demo, 获取符号查询条件的Feature,并IFeatureLayerDefinition接口创建一个新的要素图层加载到Mapcontrol上
5。开发一个空间多边形查询功能的小Demo, 学会创建内存半透明图层用于显示选择范围
5.2准备工作
1。IDE:Visual Studio 2005/2008
2.ArcGIS Engine Developer kit 9.3
3.准备一份用于查询的的矢量数据(文章内有说明)
5。3Cursor对象
Cursor(游标)本质上是一个指向数据的指针,本身并不包含数据内容,它是连接到Row对象或要素对象的桥梁.
游标有三种类型,即查询游标、插入游标和更新游标。每一种游标都是通过与之相适应的方法来获得的,如Search、Insert和Update方法。更新和插入游标都需要使用一个过滤器(Filter)对象,因为它们首先必须获得需要进行操作的要素。
Cursor对象支持的接口是ICursor,它定义了操作一个Row集合或一个Row对象的属性和方法,下面是获得插入型、更新型和查询型游标的方法:
pCursor = IFeatureClass.Insert()
使用IFeatureClass的Insert方法返回一个插入型游标,它通常用于往表中插入一条记录。
pCursor = IFeatureClass。Update()
使用IFeatureClass的Update方法会返回一个更新型游标,它用于更新或者删除一条记录。
pCursor= IFeatureClass。Search()
使用IFeatureClass的Sarch方法对表进行查询后,可以得到一个查询型Cursor对象,它指向一个或多个Row对象。
以我们这章的内容主要使用查询游标。
FeatureCursor是Cursor的一个子类,指向一个或多个要素,它实现了IFeatureCursor接口,ArcGIS Engine开发所对矢量图层实现查询功能都是实行IFeatureCursor.
5.4QueryFilter对象与SpatialFilter对象
在关系型数据库中,查询条件是通过SQL语句的Where子语句来完成的。在ArcGIS Engine中不能直接使用SQL语句,但ArcGIS Engine提供了QueryFilter和SpatialFilter两个过滤器对象来配合完成查询条件的设置,从而查询到想要的数据.
QueryFilter过滤器主要用于对属性数据查询条件的设置,它主要实现IQueryFilter接口从而实现属性查询功能。
CODE:
IQueryFilter pQueryFilter = new QueryFilterClass();
//设置过滤器对象的属性
pQueryFilter.WhereClause = "人口〉 10000000";
SpatialFilter过滤器主要用于空间范围查询条件的设置,它主要实现ISpatialFilter(继承 IQueryFilter接口)接口从而实现空间查询功能。
CODE:
ISpatialFilter pSpatialFilter = new SpatialFilterClass();
//设置空间过滤器的范围(多边形)
pSpatialFilter.Geometry = pGeometry;
//设置空间过滤器空间关系类型
pSpatialFilter。SpatialRel = esriSpatialRelEnum。esriSpatialRelContains;
空间过滤器空间关系类型主要有以下几种类型如表一所示:
表1
空间过滤器空间关系类型
描述(A是待查询图形,B是过滤条件图形)
esriSpatialRelUndefined
未定义
esriSpatialRelIntersects
A与B图形相交
esriSpatialRelEnvelopeIntersects
A的Envelope和B的Envelope相交
esriSpatialRelIndexIntersects
A与B索引相交
esriSpatialRelTouches
A与B边界相接
esriSpatialRelOverlaps
A与B相叠加
esriSpatialRelCrosses
A与B相交(两条线相交于一点,一条线和一个面相交)
esriSpatialRelWithin
A在B内
esriSpatialRelContains
A包含B
esriSpatialRelRelation
A与B空间关联
5.5SelectionSet要素选择集对象
熟悉ArcGIS Desktop使用的开发者一定会知道当在ArcMap中显示查询结果的时,所有的符号查询调教的要素都以蓝色高亮的形式显示在地图控件上,蓝色高亮显示表示高亮选中,这些高亮显示选中的要素对应一个要素选择集对象中。通过IFeatureSelection的SelectionSet属性可以获取选择集,FeatureLayer对象实现了IFeatureSelection接口。
实现代码如下:
IFeatureLayerpFeatureLayer =this。axMapControl1。get_Layer(0)asIFeatureLayer;
//QI至IFeatureSelection
IFeatureSelectionpFeatureSelection = pFeatureLayerasIFeatureSelection;
//创建过滤器
IQueryFilterpQueryFilter =newQueryFilterClass();
//设置过滤器对象的查询条件
pQueryFilter。WhereClause =”人口> 10000000”;
//选择要素
pFeatureSelection.SelectFeatures(pQueryFilter,esriSelectionResultEnum。esriSelectionResultNew,false);
//获取选择集对象
ISelectionSetpSelectinSet=pFeatureSelection。SelectionSet;
//设置选择集的符号
pFeatureSelection。SelectionSymbol = pSymbol;
5.6属性查询实例
5。6.1程序实现目标:
查询人口大于5000000的城市,并把查询结果创建为一个新的图层,如图1—3所示:
代码片段如下:
CODE:
private void button1_Click(object sender, EventArgs e)
{
IFeatureLayer pFeatureLayer = this.axMapControl1。get_Layer(0) as IFeatureLayer;
//QI到FeatureSelection
IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection;
//创建过滤器
IQueryFilter pQueryFilter = new QueryFilterClass();
//设置过滤器对象的查询条件
pQueryFilter。WhereClause = "人口> 5000000";
//根据查询条件选择要素
pFeatureSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
//QI到ISelectionSet
ISelectionSet pSelectionSet = pFeatureSelection。SelectionSet;
if (pSelectionSet.Count 〉 0)
{
IFeatureLayerDefinition pFDefinition = pFeatureLayer as IFeatureLayerDefinition;
//创建新图层
IFeatureLayer pNewFeatureLayer = pFDefinition。CreateSelectionLayer(”newlayerName", true, null, null);
pNewFeatureLayer。Name = "查询结果城市”;
axMapControl1.AddLayer(pNewFeatureLayer as ILayer);
}
}
5.7空间查询实例
5。7.1目标
实现多边形查询功能
5.7.2功能开发
代码片段如下:
引用的命名空间:
[code]
using System;
using System.Drawing;
using System.Collections;
using System。ComponentModel;
using System。Windows.Forms;
using System.Data;
using System.IO;
using System.Runtime。InteropServices;
using System.Collections。Generic;
using ESRI。ArcGIS.esriSystem;
using ESRI。ArcGIS。Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.ADF;
using ESRI。ArcGIS。SystemUI;
using ESRI。ArcGIS。Display;
using ESRI.ArcGIS.Geodatabase;
using ESRI。ArcGIS。Geometry;
using ESRI。ArcGIS.DataSourcesGDB;
///<summary>///
在程序运行时的内存中创建矢量要素层,并加到地图控件最顶端
///〈/summary〉 ///
〈param name=”pMapCtrl”>地图控件〈/param〉
///〈returns〉IFeatureLayer 新加的要素层</returns〉
private IFeatureLayer AddFeatureLayerByMemoryWS(AxMapControl pMapCtrl,ISpatialReference pSReference)
{
try
{
if (pMapCtrl == null) return null;
#region
创建新的内存工作空间
IWorkspaceFactory pWSF = new InMemoryWorkspaceFactoryClass();
IWorkspaceName pWSName = pWSF.Create(””, "Temp”, null, 0);
IName pName = (IName)pWSName;
IWorkspace pMemoryWS = (IWorkspace)pName.Open();
#endregion
IField Field = new FieldClass();
IFields Fields = new FieldsClass();
IFieldsEdit FieldsEdit = null;
IFieldEdit FieldEdit = null;
IFeatureClass FeatureClass = null;
IFeatureLayer FeatureLayer = null;
try
{
FieldsEdit = oFields as IFieldsEdit;
oFieldEdit = oField as IFieldEdit;
oFieldEdit。Name_2 = "OBJECTID”;
oFieldEdit。Type_2 = esriFieldType。esriFieldTypeOID;
oFieldEdit。IsNullable_2 = false;
oFieldEdit.Required_2 = false;
oFieldsEdit.AddField(oField);
oField = new FieldClass();
oFieldEdit = oField as IFieldEdit;
IGeometryDef pGeoDef = new GeometryDefClass();
IGeometryDefEdit pGeoDefEdit = (IGeometryDefEdit)pGeoDef;
pGeoDefEdit.AvgNumPoints_2 = 5;
pGeoDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolygon;
pGeoDefEdit。GridCount_2 = 1;
pGeoDefEdit。HasM_2 = false;
pGeoDefEdit。HasZ_2 = false;
pGeoDefEdit.SpatialReference_2 = pSReference;
oFieldEdit.Name_2 = ”SHAPE";
oFieldEdit。Type_2 = esriFieldType。esriFieldTypeGeometry;
oFieldEdit.GeometryDef_2 = pGeoDef;
oFieldEdit.IsNullable_2 = true;
oFieldEdit.Required_2 = true;
oFieldsEdit.AddField(oField);
oField = new FieldClass();
oFieldEdit = oField as IFieldEdit;
oFieldEdit。Name_2 = "Code”;
oFieldEdit.Type_2 = esriFieldType.esriFieldTypeSmallInteger;
oFieldEdit。IsNullable_2 = true;
oFieldsEdit。AddField(oField);
//创建要素类
oFeatureClass = (pMemoryWS as IFeatureWorkspace)。CreateFeatureClass(”Temp", oFields, null, null, esriFeatureType。esriFTSimple, "SHAPE", ”");
oFeatureLayer = new FeatureLayerClass();
oFeatureLayer.Name = ”TransTemp”;
oFeatureLayer.FeatureClass = oFeatureClass;
//创建唯一值符号化对象
IUniqueValueRenderer pURender = new UniqueValueRendererClass();
pURender.FieldCount = 1;
pURender。set_Field(0, ”Code");
pURender。UseDefaultSymbol = false;
ISimpleFillSymbol pFillSym = new SimpleFillSymbolClass();
pFillSym。Style. = esriSimpleFillStyle。esriSFSSolid;
//半透明颜色
IRgbColor pColor = new RgbColorClass();
pColor.Red = 255;
pColor。Green = 255;
pFillSym.Color = pColor;
pURender.AddValue("1", "”, pFillSym as ISymbol);
pFillSym = new SimpleFillSymbolClass();
pFillSym。Style. = esriSimpleFillStyle。esriSFSSolid;
//唯一值符号化内存图层
(oFeatureLayer as IGeoFeatureLayer)。Renderer = pURender as IFeatureRenderer;
ILayerEffects pLyrEffect = oFeatureLayer as ILayerEffects;
//透明度
pLyrEffect.Transparency = 80;
}
catch(Exception Err)
{
MessageBox.Show(Err。Message);
}
finally
{
try{
ystem。Runtime.InteropServices.Marshal。ReleaseComObject(oField);
System.Runtime。InteropServices。Marshal。ReleaseComObject(oFields);
System。Runtime。InteropServices。Marshal。ReleaseComObject(oFieldsEdit);
System.Runtime。InteropServices。Marshal.ReleaseComObject(oFieldEdit);
System.Runtime。InteropServices。Marshal。ReleaseComObject(pName);
System。Runtime.InteropServices.Marshal。ReleaseComObject(pWSF);
System。Runtime。InteropServices。Marshal。ReleaseComObject(pWSName);
System.Runtime。InteropServices.Marshal.ReleaseComObject(pMemoryWS);
System.Runtime。InteropServices.Marshal。ReleaseComObject(oFeatureClass);
}
catch
{
}
GC。Collect();
}
return oFeatureLayer;
}
catch (Exception Err)
{
MessageBox.Show(Err。Message, "提示”, MessageBoxButtons。OK, MessageBoxIcon.Information);
return null;}
}
CODE:
/// <summary> 在地图控件上添加透明临时图元/// 〈/summary>
/// 〈param name="pMapCtrl"〉地图控件</param>
/// 〈param name="pGeo”>Envelope或Polygon几何实体</param>
/// <param name=”bAutoClear”〉是否清除原有内容〈/param〉
public void AddTransTempEle(AxMapControl pMapCtrl, IGeometry pGeo, bool bAutoClear)
{
try
{
if (pMapCtrl == null) return;
if (pGeo == null) return;
if (pGeo.IsEmpty) return;
IGeometry pPolygon = null;
if (pGeo is IEnvelope)
{
object Miss = Type。Missing;
pPolygon = new PolygonClass();
IGeometryCollection pGeoColl = pPolygon as IGeometryCollection;
pGeoColl.AddGeometry(pGeo, ref Miss, ref Miss);
}
else if (pGeo is IPolygon)
{
(pGeo as ITopologicalOperator).Simplify();
pPolygon = pGeo;
}
else
{
MessageBox.Show( "几何实体类型不匹配”,”提示" ,MessageBoxButtons。OK, MessageBoxIcon.Information);
return;
}
//获取透明要素层
IFeatureLayer pFlyr = null;
for (int i = 0; i < pMapCtrl.LayerCount; i++)
{
if (pMapCtrl.get_Layer(i)。Name == ”TransTemp”)
{
pFlyr = pMapCtrl。get_Layer(i) as IFeatureLayer;
break;
}
}
//透明临时层不存在需要创建
if (pFlyr == null)
{
pFlyr = AddFeatureLayerByMemoryWS(pMapCtrl,pMapCtrl.SpatialReference);
if (pFlyr == null)
{
MessageBox。Show("创建透明临时图层发生异常", ”提示", MessageBoxButtons.OK, MessageBoxIcon。Information);
return;
}
}
IFeatureClass pFC = pFlyr.FeatureClass;
if (bAutoClear)
{
if (pFC.FeatureCount(null) > 0)
{
IFeatureCursor pFCursor = pFC.Search(null, false);
if (pFCursor != null)
{
IFeature pFeature = pFCursor。NextFeature();
if (pFeature != null)
{
while (pFeature != null)
{
pFeature.Delete();
pFeature = pFCursor.NextFeature();
}
}
System.Runtime。InteropServices.Marshal。ReleaseComObject(pFCursor);
}
}
}
//创建要素
IFeature pNFeature = pFC。CreateFeature();
pNFeature.Shape = pPolygon;
pNFeature.set_Value(pFC.FindField(”Code”),"1");
pNFeature。Store();
pMapCtrl.Refresh(esriViewDrawPhase.esriViewGeography, pFlyr, pFlyr.AreaOfInterest);
}
catch (Exception Err)
{
MessageBox.Show(Err.Message, "提示”, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
CODE:
/// <summary〉
/// 获取查询要素
/// </summary>
/// <param name=”pFeatureLayer”〉要素图层〈/param>
/// 〈param name="pGeometry"〉图形范围参数〈/param〉
/// <returns>符号条件要素集合</returns〉
private List<IFeature> GetSeartchFeatures( IFeatureLayer pFeatureLayer,IGeometry pGeometry)
{
try
{
List〈IFeature〉 pList = new List<IFeature〉();
//创建SpatialFilter空间过滤器对象
ISpatialFilter pSpatialFilter = new SpatialFilterClass();
IQueryFilter pQueryFilter = pSpatialFilter as ISpatialFilter;
//设置过滤器的Geometry
pSpatialFilter。Geometry = pGeometry;
//设置空间关系类型
pSpatialFilter。SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;
//获取FeatureCursor游标
IFeatureCursor pFeatureCursor = pFeatureLayer.Search(pQueryFilter, false);
//遍历FeatureCursor
IFeature pFeature = pFeatureCursor.NextFeature();
while (pFeature != null)
{
//获取要素对象
pList.Add(pFeature);
pFeature = pFeatureCursor.NextFeature();
}
System。Runtime。InteropServices。Marshal.ReleaseComObject(pFeatureCursor);
return pList;
}
catch (Exception Err)
{
MessageBox.Show(Err.Message, ”提示", MessageBoxButtons。OK, MessageBoxIcon。Information);
return null;
}
}
CODE:
bool bSearch = false; //定义bool变量用于启动多边形查询功能
private void button1_Click(object sender, EventArgs e)
{
try
{
//向地图控件添加内存图层
IFeatureLayer pFeatureLayer = this。AddFeatureLayerByMemoryWS(this。axMapControl1,this.axMapControl1.SpatialReference);
this.axMapControl1.AddLayer(pFeatureLayer);
//设置鼠标样式为十字丝
this.axMapControl1。MousePointer = esriControlsMousePointer。esriPointerCrosshair;
//启动范围查询功能
bSearch = true;
}添加一个新的Form在Form上添加一个DataGridView控件用于显示查询结果信息.如图4所示:
CODE:
private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
{
if (bSearch)
{
//设置鼠标样式为十字丝
this.axMapControl
展开阅读全文