半径较小的缓冲区,进而分析目标图层中是否有与该缓冲区相交的要
素:若没有,返回空值;若有,则遍历该要素的所有字段值,并显示
出来。
代码:
public static int Flag; // 定义整型公有变量“Flag”
private void axMapControl1_OnMouseDown(object sender,
AxESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseDownEvent e)
{
IPoint pPoint;
ITopologicalOperator pTopo;
IGeometry pGeometry;
IFeature pFeature;
IFeatureLayer pFeatureLayer;
IFeatureCursor pCursor;
ISpatialFilter pFilter;
if ((e.button ==1) && (Flag ==1)) //在MapControl 控件中单
击左键, 且已点击
“iDentify”按钮
{
pPoint = new PointClass();
pPoint.PutCoords(e.mapX,e.mapY);
pTopo = pPoint as ITopologicalOperator;
pGeometry = pTopo.Buffer(Length); // Length 为缓冲区距
离,自行设置
pFilter = new SpatialFilterClass();
pFilter.GeometryField = "shape";
pFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
pFilter.Geometry = pGeometry;
pFeatureLayer = axMapControl1.Map.get_Layer(2) as
IFeatureLayer ; // 将第3 个图层作为目标图层
//MessageBox.Show(pFeatureLayer.Name);
pCursor = pFeatureLayer.Search(pFilter,false );
pFeature = pCursor.NextFeature();
if (pFeature != null) // 要素非空
{
// 此处仅仅显示该要素的第4 个属性值若想逐一遍历所
有属性,可参照最下面的代码
MessageBox.Show(pFeature.get_Value(3).ToString());
}
else
{
MessageBox.Show("没有对应的要素!");
}
}
}
private void i查询ToolStripMenuItem_Click(object sender, EventArgs e)
{
Flag = 1;
}
/* 以下代码为遍历选中要素的所有属性值
int k = pFeatureLayer.FeatureClass.Fields.FieldCount;
this.listBox1.Items.Clear();
for (int i = 0; i < k; i++)
{
if (i == 1) continue;
this.listBox1.Items.Add(pFeatureLayer.FeatureClass.Fields.get_Fi
eld(i).AliasName + " = " + pFeature.get_Value(i).ToString());
}
可将上述信息以表格的形式表现出来,使其更像ArcMap 中的“iDentify”
*/
point.X = e.mapX; //在axMapControl_OnMouseDown事件中
point.Y = e.mapY;
Geometry = point as IGeometry;
axMapControl1.Map.SelectByShape(Geometry, null, true);
axMapControl1.Refresh(esriViewDrawPhase.esriViewGeoSelection, null, null); //选中要素高亮显示
ILayer layer = axMapControl1.Map.get_Layer(0); //获取layer,这里只有一个图层所以直接写了
IMap map = axMapControl1.Map;
IFeatureLayer FeatureLayer = layer as IFeatureLayer;
IFeatureSelection featureSelection;
featureSelection = FeatureLayer as IFeatureSelection;
long id = featureSelection.SelectionSet.IDs.Next(); //获取选中要素的ID值。
IQueryFilter queryFilter = new QueryFilterClass(); //创建一个查询筛选
queryFilter.WhereClause = "OBJECTID =" + id; //查询条件,即选中获取的ID
queryFilter.SubFields = "SHAPE_Area";
int fieldPosition = featureClass.FindField("SHAPE_Area"); //获取字段(这里是SHAPE_Area),其他字段同理
IFeatureCursor featureCursor = featureClass.Search(queryFilter, true);
IFeature feature = null;
while ((feature = featureCursor.NextFeature()) != null)
{
MessageBox.Show(feature.get_Value(fieldPosition).ToString()); //获取字段的值。
}
开运动会之前,就实现了这个功能,开了运动会后主要学习c#和准备六级了,接近两个月没有看过AE了,看来又要再过很久才能成为菜鸟了。。。。
考完六级,准备开始继续学习AE,由于以前做的Indentify功能使用的是IFeatureIdentifyObj和IIdentifyObj.Flash来完成对要素的属性查询和要素的闪烁。但是IIdentifyObj.Flash闪烁只能一个一个要素的闪烁,速度可想而知。。。考完六级后也准备继续把这个功能改进一下,顺带复习一下以前所学到的知识。
在改进的过程中,先是使用的mapcontrol.FlashShape()方法,但是最后只是成功了一半。此方法其实挺不错的,可以使所有选择的元素同时闪烁,可以控制闪烁的次数和间隔时间,并且可以自己设置闪烁的样式。但是比较笨,只完成了对点集的闪烁。线和面却没有实现。。。
对于点集,使用IpointCollection 定义一个MultiPoint就能很简单的实现了,但是在做线和面的时候我使用IGeometryCollection却不行,网上查了下,说对于IGeometryCollection添加点用AddGeometry(),添加线和面用AddGeometryCollection(),试了下没实现,自己也嫌麻烦,并且听说该方法在执行过程中什么也做不了(不是很清楚),于是就没做了。
后来试了下GeometryBag类,最开始程序运行不出错,但是不闪烁,断点查之,貌似添加了一个就不添加了,查了下MSDN,好像要先给GeometryBag定义空间参考,再添加要素,也没实现,哎,还真是挺笨的,o(╯□╰)o。。。
后来就使用了IHookActions.DoActionOnMultiple()方法。不能自定闪烁方式,但是可以通过自己编写代码来控制显示次数和间隔时间。这个方法可以实现点线面同时闪烁,挺方便的
本来想写个地图文档属性查看器的,但是这几天太热了,又得复习考试,想想还是算了,本来所有功能也都实现了,只是重新组合下就行了,也没什么可做的了。况且老是重复做过的东西,进步也不会太大。
趁着今晚睡不着,把这次改进的主要代码总结下:
主要实现的是对可见图层的框选显示属性:
1、框选要素高亮显示
private void axMapControl1_OnMouseDown(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseDownEvent e)
{
IGeometry pGeo = axMapControl1.TrackRectangle();
ISpatialFilter pSpatialFilter = new SpatialFilterClass();
pSpatialFilter.Geometry = pGeo;
pSpatialFilter.GeometryField = "SHAPE";
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;
IArray geoArray = new ArrayClass();
IMap pMap = axMapControl1.Map;
for (int i = 0; i < pMap.LayerCount; i++)
{
IFeatureLayer pFeatureLayer = pMap.get_Layer(i) as IFeatureLayer;
if(pFeatureLayer.Visible!=true)
continue;
IFeatureCursor pFeatureCursor = pFeatureLayer.Search(pSpatialFilter, false);
IFeature pFeature = pFeatureCursor.NextFeature();
while (pFeature != null)
{
geoArray.Add(pFeature);
pFeature = pFeatureCursor.NextFeature();
}
}
FlashAndIdentify(geoArray);
}
/// <summary>
/// 对所选择要素集进行高亮显示并打开属性查询窗口
/// </summary>
/// <param name="inArray">所选择的要素集</param>
private void FlashAndIdentify(IArray inArray)
{
try
{
if (inArray == null)
return;
HookHelperClass hookHelper = new HookHelperClass();
hookHelper.Hook = axMapControl1.Object;
IHookActions hookAction = (IHookActions)hookHelper;
hookAction.DoActionOnMultiple(inArray, esriHookActions.esriHookActionsFlash);
frmIdentify newFrm = frmIdentify.CreatIdentify((IHookHelper)hookHelper, inArray);
newFrm.Show();
newFrm.ShowProperty(inArray);
}
catch (Exception exc) { MessageBox.Show(exc.Message); }
}
2、Identify窗体中
/// <summary>
/// 打开Identify对话框,并显示所选择的要素集
/// </summary>
/// <param name="array">要素集</param>
public void ShowProperty(IArray array)
{
tvFeature.Nodes.Clear();
lvProperty.Items.Clear();
int geoCount = array.Count;
if (geoCount > 0)
{
toolStripStatusLabel1.Text = "共选择" + geoCount + "条记录";
for (int count = 0; count < geoCount; count++)
{
IFeature pFeature = array.get_Element(count) as IFeature;
IFields pFields = pFeature.Fields;
int FieldIndex = pFields.FindField("OBJECTID");
TreeNode newNode = new TreeNode(pFeature.get_Value(FieldIndex).ToString());
tvFeature.Nodes.Add(newNode);
}
IFeature pF = array.get_Element(0) as IFeature;
listview = IdentifyFeature.getFeaturePorperty(pF);
for (int index = 0; index < listview.Items.Count; index++)
{
lvProperty.Items.Add(listview.Items[index].Clone() as ListViewItem);//ListViewItem只能添加到一个ListView中,此处使用Clone方法
}
}
else
toolStripStatusLabel1.Text = "共选择0条记录";
}
/// <summary>
/// 高亮显示所点击节点代表的要素及其属性
/// </summary>
/// <param name="lvIndex">节点索引</param>
/// <param name="FeatureArray">所选择的要素集</param>
private void NodeClicktoFeature(int lvIndex, IArray FeatureArray)
{
IFeature pFeature = FeatureArray.get_Element(lvIndex) as IFeature;
listview = IdentifyFeature.getFeaturePorperty(pFeature);
lvProperty.Items.Clear();
for (int index = 0; index < listview.Items.Count; index++)
{
lvProperty.Items.Add(listview.Items[index].Clone() as ListViewItem);//ListViewItem只能添加到一个ListView中,此处使用Clone方法
}
IHookActions hookAction = pHookHelper as IHookActions;
hookAction.DoAction(pFeature.ShapeCopy, esriHookActions.esriHookActionsFlash);
}
3、把每个要素的信息显示到listview中
/// <summary>
/// 显示每个要素信息
/// </summary>
/// <param name="pFeature">选择的要素</param>
/// <returns></returns>
public static ListView getFeaturePorperty(IFeature pFeature)
{
ListView listview = new ListView();
listview.View = System.Windows.Forms.View.Details;
IFields pFields = pFeature.Fields;
for (int index = 0; index < pFields.FieldCount; index++)
{
string strValue, strField;
strField = pFields.get_Field(index).Name.ToString();
if (pFields.get_Field(index).Type == esriFieldType.esriFieldTypeGeometry)
{
strValue = pFeature.Shape.GeometryType.ToString();
switch (strValue)
{
case "esriGeometryPoint":
strValue = "点";
break;
case "esriGeometryPolyline":
strValue = "线";
break;
case "esriGeometryPolygon":
strValue = "面";
break;
}
}
else
{
strValue = pFeature.get_Value(index).ToString();
if (strValue == "")
strValue = "<null>";
}
ListViewItem item = new ListViewItem();
item.SubItems[0].Text = strField;
item.SubItems.Add(strValue);
listview.Items.Add(item);
}
return listview;
}
(四)用AE实现点击查看属性
关于ARCGIS中IDENTIFY功能的实现
一:功能实现的基本思路是这样的:
1. 点击时,先获取点击位置的屏幕坐标,然后转换到地图坐标;
2. 定义一个图层对象(Identify),调用相应的Identify方法生成点对象;
3. 提取图层中点击处的图形,提取属性,填充到事先设计好的窗口中;
4. 显示窗口。
二:代码
IIdentify pIdentify; //IIdentify接口(要素图层下的一个接口)定义了获得要素图层单个要素的属性的捷径方法。它有一Identify方法,返回一个IArray数组对象。
IPoint pPoint;
IArray pIDArray;
IFeatureIdentifyObj pFeatIdObj;//定义一个要素对象
IIdentifyObj pIdObj;
IMap pMap = axMapControl1.Map;//将当前地图赋给地图对象pMap
pIdentify = pMap.get_Layer(0) as IIdentify;//将图层赋给图层对象pIdentify
pPoint = new PointClass();//定义了一个实现IPoint接口的点对象
pPoint.PutCoords(e.mapX, e.mapY);//pPoint.PutCoords用来设置点的X,Y值从而创建一个点对象。
pPoint.SpatialReference = pMap.SpatialReference;
pIDArray = pIdentify.Identify(pPoint);//Identify方法返回一个Array数组对象
if (pIDArray != null)
{
pFeatIdObj = pIDArray.get_Element(0) as IFeatureIdentifyObj;//获得要素集数组中的第一个元素
pIdObj = pFeatIdObj as IIdentifyObj;
pIdObj.Flash(axMapControl1.ActiveView.ScreenDisplay);//选中要素闪烁
MessageBox.Show("Layer˖ + pIdObj.Layer.Name +
System.Environment.NewLine + "Feature˖ + pIdObj.Name);//显示要素所在图层的名字,要素的的名字
}
else
MessageBox.Show("没有要素选中");
程序的运行结果如图,说明Identify方法生成的数组为空,如下图;
三:程序调试
问题分析:
出现上述问题的原因是IPoint没有和图层建立关系,即无论你有没有点到图层中的点,程序都会通过pPoint.PutCoords(e.MapX,e.MapY)生成点对象,但是pIdentify.identify()方法对参数(pPoint)的传递无响应,该方法只会识别图层中的元素,因此返回的数组始终是空NULL;
问题解决:
参考AE帮助中的DEMO,在此不用point对象,建立一个Envelop对象pEnv(相当于缓冲区), 将该对象作为参数传递给Identify方法就可以了
最终运行结果
四:相关理论知识总结
用到的相关对象 方法 接口:
IMap接口 是开始多数GIS任务的起点,它主要用于管理Map对象中的layer对象,要素选择集、MapSourround对象、标注引擎和空间参考等对象。IMap接口中定义了大量的方法来操作它其中的图层对象(如:AddLayer 、ClearLayers)。
IIdentify接口定义了获得要素图层单个要素的属性的捷径方法。它有一个Identify方法,返回一个IArray数组对象。
IPoint接口定义了Point对象的属性和方法,ID属性可以返回点队形的ID号。使用IPoint::X和IPoint::Y用户可以获得一个点的X和Y的坐标值。
IPoint::PutCoords用于设置一个点的X、Y坐标值,当用户new完成一个Point后,可以用这个方法来建立一个实际的点对象。
包络线Envelop:
Envelop通过它的最大和最小X,Y坐标来定义一个矩形形状,因此包络线对象相对于它的空间参考而言总是直角的。包络线也定义了最大的和最小的Z值、M值,这两个值分别通过IZAware,IMAware接口来定义。
IEnvelope::PutCoords:提供了一种构造了包络线的方法,它通过传入XMin,YMin,XMax,YMax四个点对象而返回一个包络线;IEnvelop::Query则可以返回一个包络线的四个值。
五:
该程序的属性显示用了一个MESSAGEBOX,功能过于简单,没法对元素所有属性字段的显示,需要找一个合适的控件对其属性进行展示。
关于ARCGIS中IDENTIFY功能的实现
一:功能实现的基本思路是这样的:
1. 点击时,先获取点击位置的屏幕坐标,然后转换到地图坐标;
2. 定义一个图层对象(Identify),调用相应的Identify方法生成点对象;
3. 提取图层中点击处的图形,提取属性,填充到事先设计好的窗口中;
4. 显示窗口。
二:代码
IIdentify pIdentify; //IIdentify接口(要素图层下的一个接口)定义了获得要素图层单个要素的属性的捷径方法。它有一Identify方法,返回一个IArray数组对象。
IPoint pPoint;
IArray pIDArray;
IFeatureIdentifyObj pFeatIdObj;//定义一个要素对象
IIdentifyObj pIdObj;
IMap pMap = axMapControl1.Map;//将当前地图赋给地图对象pMap
pIdentify = pMap.get_Layer(0) as IIdentify;//将图层赋给图层对象pIdentify
pPoint = new PointClass();//定义了一个实现IPoint接口的点对象
pPoint.PutCoords(e.mapX, e.mapY);//pPoint.PutCoords用来设置点的X,Y值从而创建一个点对象。
pPoint.SpatialReference = pMap.SpatialReference;
pIDArray = pIdentify.Identify(pPoint);//Identify方法返回一个Array数组对象
if (pIDArray != null)
{
pFeatIdObj = pIDArray.get_Element(0) as IFeatureIdentifyObj;//获得要素集数组中的第一个元素
pIdObj = pFeatIdObj as IIdentifyObj;
pIdObj.Flash(axMapControl1.ActiveView.ScreenDisplay);//选中要素闪烁
MessageBox.Show("Layer˖ + pIdObj.Layer.Name +
System.Environment.NewLine + "Feature˖ + pIdObj.Name);//显示要素所在图层的名字,要素的的名字
}
else
MessageBox.Show("没有要素选中");
程序的运行结果如图,说明Identify方法生成的数组为空,如下图;
三:程序调试
问题分析:
出现上述问题的原因是IPoint没有和图层建立关系,即无论你有没有点到图层中的点,程序都会通过pPoint.PutCoords(e.MapX,e.MapY)生成点对象,但是pIdentify.identify()方法对参数(pPoint)的传递无响应,该方法只会识别图层中的元素,因此返回的数组始终是空NULL;
问题解决:
参考AE帮助中的DEMO,在此不用point对象,建立一个Envelop对象pEnv(相当于缓冲区), 将该对象作为参数传递给Identify方法就可以了
最终运行结果
四:相关理论知识总结
用到的相关对象 方法 接口:
IMap接口 是开始多数GIS任务的起点,它主要用于管理Map对象中的layer对象,要素选择集、MapSourround对象、标注引擎和空间参考等对象。IMap接口中定义了大量的方法来操作它其中的图层对象(如:AddLayer 、ClearLayers)。
IIdentify接口定义了获得要素图层单个要素的属性的捷径方法。它有一个Identify方法,返回一个IArray数组对象。
IPoint接口定义了Point对象的属性和方法,ID属性可以返回点队形的ID号。使用IPoint::X和IPoint::Y用户可以获得一个点的X和Y的坐标值。
IPoint::PutCoords用于设置一个点的X、Y坐标值,当用户new完成一个Point后,可以用这个方法来建立一个实际的点对象。
包络线Envelop:
Envelop通过它的最大和最小X,Y坐标来定义一个矩形形状,因此包络线对象相对于它的空间参考而言总是直角的。包络线也定义了最大的和最小的Z值、M值,这两个值分别通过IZAware,IMAware接口来定义。
IEnvelope::PutCoords:提供了一种构造了包络线的方法,它通过传入XMin,YMin,XMax,YMax四个点对象而返回一个包络线;IEnvelop::Query则可以返回一个包络线的四个值。
五:
该程序的属性显示用了一个MESSAGEBOX,功能过于简单,没法对元素所有属性字段的显示,需要找一个合适的控件对其属性进行展示。