AE开发实例代码总结
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1、AE开发技术文档
一、数据加载问题
1、加载个人数据库
个人数据库是保存在Access中的数据库。
加载方式有两种:通过名字和通过属性加载(也许不只是这两种,AE中实现同一功能可以有多种方式)
A、通过设置属性加载个人数据库
首先通过IPropertySet接口定义要连接数据库的一些相关属性,在个人数据库中为数据库的路径,例如:
IPropertySet Propset= new PropertySetClass();
Propset.SetProperty(“DATABASE”,@”D:\test\Ao\data\sh\Mapdata.mdb”);
当定义完属性并设置属性后就可以进行打开数据库的操作了,在ArcEngine 开发中存在IWorkspaceFactory 、IFeatureWorkspace 、IFeatureClass 、IFeatureLayer等几个常用的用于打开和操作数据空间地物的接口。
IWorkspaceFactory是一个用于创建和打开工作空间的接口,它是一个抽象的接口,我们在具体应用时要用对应的工作空间实例化它,如下:
IWorkspaceFactory Fact = new AccessWorkspaceFactoryClass (); 如果我们打开的是SDE数据库就要用SdeWorkspaceFactoryClass 实例化Fact。
当我们完成了工作空间的实例化后就可以根据上边设置的属性打开对应的Access 数据库了。
打开方式如下:
IFeatureWorkspace Workspace = Fact.Open( Propset,0) as IFeatureWorkspace;
打开Access 工作空间后接下来的事情是做什么了,很简单,找到对应的地物类,赋给相应的层,通过MapControl 控件添加对应的层,然后刷新地图。
以下为添加某一层的代码:
IFeatureClass Fcls = Workspace.OpenFeatureClass("District");//找到对应的地物类IFeatureLayer Fly = new FeatureLayerClass();//建立新图层
Fly.FeatureClass = Fcls; //将地物赋给相应的层
MapCtr.Map.AddLayer (Fly);//添加层
MapCtr.ActiveView.Refresh();//刷新地图
其中District 为地物类的名字,MapCtr 为AE中MapControl 的对象。
上边的通过属性设置加载数据空间的方式还可以用于SDE 数据库,在SDE 数据库加载时会介绍。
以下为通过设置属性加载Access 数据库的完整C#代码:
public void AddAccessDBByPro()
{
IPropertySet Propset = new PropertySetClass();
Propset.SetProperty("DATABASE",@"D:\test\Ao\data\sh\MapData.mdb" );
IWorkspaceFactory Fact = new AccessWorkspaceFactoryClass ();
IFeatureWorkspace Workspace= Fact.Open(Propset,0) as IFeatureWorkspace;
IFeatureClass Fcls = Workspace.OpenFeatureClass ("District");
IFeatureLayer Fly = new FeatureLayerClass();
Fly.FeatureClass = Fcls;
MapCtr.Map.AddLayer(Fly);
MapCtr.ActiveView.Refresh();
}
B、通过数据库名字加载个人数据库
public void AddAccessDBByName()
{
IworkspaceName pWorkspaceName = new WorkspaceNameClass();
pWorkspaceName.WorkspaceFactoryProgID= “esriDataSourcesGDB.AccessWorkspaceFactory”;
pWorkspaceName.PathName =@“D:\test\Ao\data\sh\MapData.mdb”;
IName n=pWorkspaceName as IName;
IFeatureWorkspace Workspace= n.Open() as IFeatureWorkspace;
IFeatureClass Fcls = Workspace.OpenFeatureClass ("District");
IFeatureLayer Fly = new FeatureLayerClass();
Fly.FeatureClass = Fcls;
MapCtr.Map.AddLayer(Fly);
MapCtr.ActiveView.Refresh();
}
首先创建一个个人数据库工作空间名,再指定工作空间名的ProgID,以确定打开的是什么类型的工作空间,例如在打开Access个人数据库时,使用下面代码;
IworkspaceName pWorkspaceName = new WorkspaceNameClass();
pWorkspaceName.WorkspaceFactoryProgID= “esriDataSourcesGDB.AccessWorkspaceFactory”;
pWorkspaceName.PathName =@“D:\test\Ao\data\sh\MapData.mdb”;
属性WorkspaceFactoryProgID可以确保工作空间是AccessWorkspaceFactory,即个人数据库,同时要指定打开数据库路径。
为了打开数据库,打开工作空间必须使用IName接口(思考有没有其他办法),,所以接着定义IName、对象,并把工作空间名转换成IName类型,并赋值给IName对象,然后通过IName对象的open方法打开相应的工作空间,代码如下:
IName n=pWorkspaceName as IName;
IFeatureWorkspace Workspace= n.Open() as IFeatureWorkspace;
2、AE开发编辑功能
数据编辑问题
1.需要了解的概念
长事务短事务编辑空间抽象类,类,和组件对象类
2、最基本的添加点线面功能
添加点(方法有多种,基本思路一样,只是少量的接口有变化)
通过FeatureClass的CreatFeature函数来添加地物。
public void AddPointByStore()
{
//得到要添加地物的图层
IFeatureLayer l=MapCtr.Map.get_Layer(0) as IFeatureLayer;
//定义一个地物类,把要编辑的图层转化为定义的地物类
IFeatureClass fc= l.FeatureClass;
//先定义一个编辑的工作空间,然后把它转化为数据集,最后转化为编辑工作空间,
IWorkspaceEdit w=(fc as IDataset).Workspace as IWorkspaceEdit; IFeature f;
IPoint p;
//开始事务操作
w.StartEditing(false); //////????????????????????????
//开始编辑
w.StartEditOperation();
for(int i=0;i<100;i++)
{
//创建一个地物
f=fc.CreateFeature();
p=new PointClass();
//设置点的坐标
p.PutCoord(i,i);
//确定图形类型
f.Shape=p;
//保存地物
f.Store()
}
//结束编辑
w.StopEditOperation();
//结束事务操作
w.StopEditing(true);
}
二、添加线
方法跟添加点一样,不同的只是地物类型不一样而已,
AE中各类库的介绍
1、问题一:什么是UI组件?
2、类库介绍
空间拓扑运算
1、高级几何对象:点(point)、多点(multipoint)、线(polyline)、面(polygon)、multipatch 等。
(multipatch:多片,三维地形图中的地图符号包括点状符号、线状符号、面状符号、体状符号以及多片(MultiPatch)符号等)
2、拓扑:空间拓扑描述的事自然界地理对象的空间位置关系,即相邻、重合、连通等。
是在同一个要素集下的要素类之间的关系的集合,所以要参与一个拓扑的所有要素类,必须在同一个要素集内(也就是具有同一个空间参考),这样进行的拓扑检查才是精确的。
3、一个要素集可以有多个拓扑,但每个要素类最多只能参与一个拓扑,一个拓扑中可以定义多个规则,是地理对象空间属性的一部分,在目前ESRI提供的数据存储方式中,Coverage 和GeoDatabase能够建立拓扑,而Shape格式的数据不能建立拓扑。
4、esriTRTAny————任何拓扑规则,查询拓扑的时候用(ESRI提供的拓扑关系)
5、AE中提供了ITopologicalOperator接口用于拓扑运算,ITopologicalOperator接口用来通过对已存在的几何对象做空间拓扑运算,以产生新的集合对象。
ITopologicalOperator接口在GIS开发中的使用非常广泛,通常GIS系统中的缓冲区分析、裁剪几何图形、几何图形差分操作、几何图形合并操作等都需要此接口。
Boundary 方法用于几何图形对象的边界。
Polygon的几何对象的Boundary是组成它的Polyline几何对象,Polyline几何对象的Boundary是组成它的顶点Point几何对象,而Point 的几何对象的Boundary是空对象。
Buffer 用于集合对象缓冲区分析拓扑操作,该方法用于给一个高级几何对象产生一个缓冲区,无论是Polygon、Polyline、还是Point,他们的缓冲区都是具有面积的几何对象。
Clip 用于对几何对象进行裁剪空间拓扑操作。
Clip方法可用一个Envelope对象对一个几何对象进行裁剪,结果是几何对象被Envelope对象所包围的部分。
ConstructUion用于将多个枚举对象与单个几何对象合并为单个几何对象。
ConvexHull 用于构建几何对象的凸多边形。
ConvexHull方法用于产生一个几何图形的最小的边框凸多边形(没有凹面包含几何图形的最小多边形)
Cut 用于切割几何对象,不支持GeometryBags几何对象,它可以指定一条切割曲线和一个几何图形,经过切割运算后把几何图形分为左右两部分,左右两部分是相对曲线的方向而
言的。
点与多点不可被分割。
Polyline和Polygon只有与切割曲线相交时才能执行Cut方法。
Difference 用于从一个几何图形中减去其与另一个图形相交的部分,产生两个几何对象的差集。
Intersection方法用于两个同纬度几何对象的交集部分。
Simplify用于使几何对象拓扑一致。
SymmetricDifference对称差分可将两个几何图形的并集部分减去两个几何图形交集的部分。
开发实例
一、鹰眼功能的实现:
分析:鹰眼图的操作主要由以下几个动作,当在一个控件中移动一幅图的时候另一控件中的图也发生变化,当在主控件中重新加载一幅图的时候,另外一个控件的图也发生相应的变化,同时我们在鸟瞰的控件中加入一红色边框,注意这个其实是一个面,只是填充的颜色是透明的而已。
通过分析我们知道,我们要添加两个MapControl控件,名字分别是axMapControl1和axMapControl2,其中axMapControl1为主图,而axMapControl2为鸟瞰图。
方法:步骤一:对于名称为axMapControl1的MapControl控件,只需要在axMapControl1的OnExtentUpdated和OnMapReplaced 中分别添加以下代码:
private void axMapControl1_OnExtentUpdated(object sender,
IMapControlEvents2_OnExtentUpdatedEvent e)
{
// 得到新范围
IEnvelope pEnvelope = (IEnvelope)e.newEnvelope;
IGraphicsContainer pGraphicsContainer = axMapControl2.Map as IGraphicsContainer; IActiveView pActiveView = pGraphicsContainer as IActiveView;
//在绘制前,清除axMapControl2中的任何图形元素
pGraphicsContainer.DeleteAllElements();
IRectangleElement pRectangleEle = new RectangleElementClass();
IElement pElement = pRectangleEle as IElement;
pElement.Geometry = pEnvelope;
//设置鹰眼图中的红线框
IRgbColor pColor = new RgbColorClass();
pColor.Red = 255;
pColor.Green = 0;
pColor.Blue = 0;
pColor.Transparency = 255;
//产生一个线符号对象
ILineSymbol pOutline = new SimpleLineSymbolClass();
pOutline.Width = 3;
的属性
IFillSymbol pFillSymbol = new SimpleFillSymbolClass();
pFillSymbol.Color = pColor;
pFillSymbol.Outline = pOutline;
IFillShapeElement pFillShapeEle = pElement as IFillShapeElement;
pFillShapeEle.Symbol = pFillSymbol;
pGraphicsContainer.AddElement((IElement)pFillShapeEle,0);
pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics,null,null);
}
private void axMapControl1_OnMapReplaced(object sender,
IMapControlEvents2_OnMapReplacedEvent e)
{
if (yerCount > 0)
{
axMapControl2.Map = new MapClass();
for (int i = 0; i <= yerCount - 1; i++)
{
axMapControl2.AddLayer(axMapControl1.get_Layer(i));
}
axMapControl2.Extent = axMapControl1.Extent;
axMapControl2.Refresh();
}
}
步骤二:对于名称为axMapControl2的MapControl控件,只需要在axMapControl2的OnMouseMove和OnMouseDown中分别添加以下代码:
private void axMapControl2_OnMouseMove(object sender,
IMapControlEvents2_OnMouseMoveEvent e)
{
if (e.button == 1)
{
IPoint pPoint = new PointClass();
pPoint.PutCoords(e.mapX,e.mapY);
axMapControl1.CenterAt(pPoint);
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography,null,null);
}
}
private void axMapControl2_OnMouseDown(object sender,
IMapControlEvents2_OnMouseDownEvent e)
{
if (yerCount > 0)
{
if (e.button == 1)
{
IPoint pPoint = new PointClass();
pPoint.PutCoords(e.mapX,e.mapY);
axMapControl1.CenterAt(pPoint);
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography,null,null);
}
else if (e.button == 2)
{
IEnvelope pEnv = axMapControl2.TrackRectangle();
axMapControl1.Extent = pEnv;
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography,null,null);
}
}
}
二、显示属性表的信息
我们知道ArcMap中的Table of Contents有很多功能,
如下图:
而ArcGIS Engine提供的TOCControl控件几乎没有提供,那么这些都是需要自己开发的,在这里我做一个显示属性表的功能。
分析:要显示某一个图层的属性表,首先要将这个图层选中,然后在另外一个Form中将选中的这个图层的属性信息进行显示。
方法:添加一个上下文菜单,添加一个新的Form窗体,在这个新的
窗体上添加GridView控件,并在TOCControl控件的OnMouseDown 事件下添加如下代码(pGlobalFeatureLayer是我定义的一个全局变量):
private void axTOCControl1_OnMouseDown(object sender,
ESRI.ArcGIS.Controls.ITOCControlEvents_OnMouseDownEvent e)
{
if (yerCount > 0)
{
esriTOCControlItem pItem = new esriTOCControlItem();
pGlobalFeatureLayer = new FeatureLayerClass();
IBasicMap pBasicMap = new MapClass();
object pOther = new object();
object pIndex = new object();
axTOCControl1.HitTest(e.x,e.y,ref pItem,ref pBasicMap,ref pGlobalFeatureLayer,ref pOther,ref pIndex);
}
if (e.button == 2)
{
context.Show(axTOCControl1,e.x,e.y);
}
}
在上下文菜单的打开属性表的Click事件中添加如下代码:
private void 打开属性表ToolStripMenuItem_Click(object sender,EventArgs e)
{
FormTable Ft = new FormTable(pGlobalFeatureLayer as IFeatureLayer);
Ft.Show();
}
在新的窗体中添加一个将属性表显示到GridView控件中的函数,如下:
public void Itable2Dtable()
{
IFields pFields;
pFields = pFeatureLayer.FeatureClass.Fields;
dtGridView.ColumnCount = pFields.FieldCount;
for (int i = 0; i < pFields.FieldCount;i++ )
{
string fldName = pFields.get_Field(i).Name;
dtGridView.Columns[i].Name = fldName;
dtGridView.Columns[i].ValueType =
System.Type.GetType(ParseFieldType(pFields.get_Field(i).Type));
}
IFeatureCursor pFeatureCursor;
pFeatureCursor = pFeatureLayer.FeatureClass.Search(null,false);
IFeature pFeature;
pFeature = pFeatureCursor.NextFeature();
while (pFeature != null)
{
string[] fldValue = new string[pFields.FieldCount];
for (int i = 0; i < pFields.FieldCount; i++)
{
string fldName;
fldName = pFields.get_Field(i).Name;
if (fldName==pFeatureLayer .FeatureClass .ShapeFieldName)
{
fldValue[i] = Convert.ToString(pFeature.Shape.GeometryType);
}
else
fldValue[i] = Convert.ToString(pFeature.get_Value(i));
}
dtGridView.Rows.Add(fldValue);
pFeature = pFeatureCursor.NextFeature();
}
}
数据库知识:
数据库打开方式以及方法:
1、打开个人数据库:
public IWorkspace GetMDBWorkspace(String _pGDBName)
{
IWorkspaceFactory pWsFac = new AccessWorkspaceFactoryClass(); IWorkspace pWs = pWsFac.OpenFromFile(_pGDBName,0); return pWs;
}
2、打开文件数据库:
public IWorkspace GetFGDBWorkspace(String _pGDBName)
{
IWorkspaceFactory pWsFac = new FileGDBWorkspaceFactoryClass(); IWorkspace pWs = pWsFac.OpenFromFile(_pGDBName,0);
return pWs;
}
3、打开SDE数据库:
打开SDE数据库我们使用的是Open方法,要用这个方法,我们就要对IPropertySet对象设置,要打开SDE数据库,我们要获取SDE数据库的服务器地址,数据库实例,数据库,用户,密码等参数。
而IPropertySet就好比一个Key-Value 的对象,用来帮组我们设置这些,然后传到Open方法中。
public IWorkspace GetSDEWorkspace(String _pServerIP,String _pInstance,String _pUser,String _pPassword,String _pDatabase,String _pVersion)
{
ESRI.ArcGIS.esriSystem.IPropertySet pPropertySet = new
ESRI.ArcGIS.esriSystem.PropertySetClass();
pPropertySet.SetProperty("SERVER",_pServerIP);
pPropertySet.SetProperty("INSTANCE",_pInstance);
pPropertySet.SetProperty("DATABASE",_pDatabase);
pPropertySet.SetProperty("USER",_pUser);
pPropertySet.SetProperty("PASSWORD",_pPassword);
pPropertySet.SetProperty("VERSION",_pVersion);
ESRI.ArcGIS.Geodatabase.IWorkspaceFactory2 workspaceFactory;
workspaceFactory = (ESRI.ArcGIS.Geodatabase.IWorkspaceFactory2)new
ESRI.ArcGIS.DataSourcesGDB.SdeWorkspaceFactoryClass();
return workspaceFactory.Open(pPropertySet,0);
}
注意,打开SDE数据库需要用到ArcGIS Engine运行时的企业级许可。
(即此时的License 需要特别设置——ArcEngine的Lisence应使用企业数据库类型,在From1_Load事件中初始化lisence,不能使用lisence控件设置,否则提示没有许可lisence。
)
具体的解决代码如下:
private void From1_Load(object sender,EventArg e)
{
IAoInitialize pao=new AoInitializeClass();
pao.Initialize(esriLisenceProductCode.esriLisenceProductCodeEngineGeoDB);
}
4.4.2 获取数据库中的要素类
在ArcGIS Engine中,要得到某一个类,首要要获取工作空间,然后进入工作空间再得到相应的东西,也就是以下两个步骤:
获取工作空间;
获取相应的要素类。
我们定义一个函数用来获取个人数据库的路径
public string WsPath()
{
string WsFileName="";
OpenFileDialog OpenFile = new OpenFileDialog();
OpenFile.Filter = "个人数据库(MDB)|*.mdb";
DialogResult DialogR = OpenFile.ShowDialog();
if (DialogR == DialogResult.Cancel)
{
}
else
{
WsFileName = OpenFile.FileName;
}
return WsFileName;
}
要获取要素类,首先获取工作空间,然后对工作空间中的要素类进行遍历,代码如下:
private void button2_Click(object sender,EventArgs e)
{
string WsName = WsPath();
if (WsName != "")
{
IWorkspaceFactory pWsFt = new AccessWorkspaceFactoryClass();
IWorkspace pWs = pWsFt.OpenFromFile(WsName,0);
IEnumDataset pEDataset =pWs.get_Datasets(esriDatasetType.esriDTAny);
IDataset pDataset = pEDataset.Next();
while (pDataset != null)
{
if (pDataset.Type ==esriDatasetType.esriDTFeatureClass)
{
FeatureClassBox.Items.Add();
}
//如果是数据集
else if (pDataset.Type == esriDatasetType.esriDTFeatureDataset)
{
IEnumDataset pESubDataset = pDataset.Subsets;
IDataset pSubDataset = pESubDataset.Next();
while (pSubDataset != null)
{
FeatureClassBox.Items.Add();// ----这是从哪里来的???------------ pSubDataset = pESubDataset.Next();
}
}
pDataset = pEDataset.Next();
}
}
FeatureClassBox.Text = FeatureClassBox.Items[0].ToString();
}
判断要素是否被编辑:
ArcGIS Engine 提供了一个IDatasetEdit的接口用来判断我们的数据是否处于编辑状态,该接口只有一个方法,如下:
示例代码如下:
public bool ISEdit (IFeatureClass pFeatureClass)
{
IDatasetEdit pDataEdit = pFeatureClass as IDatasetEdit;
return pDataEdit.IsBeingEdited();
}
如何删除要素类:
IFeatureWorkspace这个接口主要是用于管理基于矢量数据的,如表,要素类,要素数据集等。
要想删除一个要素类,那么必须先得到这个。
,如要打开一个名称为PointTest的要素类,只需要在OpenFeatureClass中传入这个要素类的名称,代码如下:
IWorkspaceFactory pWsFt = new AccessWorkspaceFactoryClass();
IWorkspace pWs = pWsFt.OpenFromFile(WsName,0);
IFeatureWorkspace pFWs = pWs as IFeatureWorkspace;
IFeatureClass pFClass = pFWs.OpenFeatureClass("PointTest");
如果是在ArcMap中,我们会切换到Catalog中然后进入相应的数据库,然后删除相应的要素类,这种操作会让我们想到FeatureClas这个对象会提供删除的方法,其实不然,这个删除的方法是定义在Dataset这个对象中。
private void button1_Click(object sender,EventArgs e)
{
string WsName = WsPath();
if( WsName !="")
{
IWorkspaceFactory pWsFt = new AccessWorkspaceFactoryClass();
IWorkspace pWs = pWsFt.OpenFromFile(WsName,0);
IFeatureWorkspace pFWs = pWs as IFeatureWorkspace;
IFeatureClass pFClass = pFWs.OpenFeatureClass("PointTest");
IDataset pDatset = pFClass as IDataset;
pDatset.Delete();
}
}
删除前:
删除后:
创建要素类
创建要素类用到了IFeatureWorkspace.CreateFeatureClass方法。
所需接口:IField,IFieldEdit,IFields,IFieldsEdit,IGeometryDef,IGeometryDefEdit接口
(注意在NET中,会遇到以“_2”结尾的属性,这些属性是可写的。
)
//定义一个几何字段,类型为点类型
ISpatialReference pSpatialReference = axMapControl1.ActiveView.FocusMap.SpatialReference; IGeometryDefEdit pGeoDef = new GeometryDefClass();
IGeometryDefEdit pGeoDefEdit = pGeoDef as IGeometryDefEdit;
pGeoDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPoint;
pGeoDefEdit.SpatialReference_2 = pSpatialReference;
//定义一个字段集合对象
IFields pFields = new FieldsClass();
IField s Edit pFieldsEdit = (IFieldsEdit)pFields;
//定义单个的字段
IField pField = new FieldClass();
IFieldEdit pFieldEdit = (IFieldEdit)pField;
_2 = "SHAPE";
pFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
pField s Edit.AddField(pField);
pFieldEdit.GeometryDef_2 = pGeoDef;
//定义单个的字段,并添加到字段集合中
pField = new FieldClass();
pFieldEdit = (IFieldEdit)pField;
_2 = "STCD";
pFieldEdit.Type_2 = esriFieldType.esriFieldTypeString;
pField s Edit.AddField(pField);
//定义单个的字段,并添加到字段集合中
pField = new FieldClass();
pFieldEdit = (IFieldEdit)pField;
_2 = "SLM10";
pFieldEdit.Type_2 = esriFieldType.esriFieldTypeString;
pField s Edit.AddField(pField);
//定义单个的字段,并添加到字段集合中
pField = new FieldClass();
pFieldEdit = (IFieldEdit)pField;
_2 = "SLM20";
pFieldEdit.Type_2 = esriFieldType.esriFieldTypeString;
pFieldsEdit.AddField(pField);
//定义单个的字段,并添加到字段集合中
pField = new FieldClass();
pFieldEdit = (IFieldEdit)pField;
_2 = "SLM40";
pFieldEdit.Type_2 = esriFieldType.esriFieldTypeString;
pFieldsEdit.AddField(pField);
IWorkspaceFactory pFtWsFct = new AccessWorkspaceFactory();
IFeatureWorkspace pWs = pFtWsFct.OpenFromFile(@"E:\arcgis\Engine\s.mdb",0) as IFeatureWorkspace;
IFeatureClass pFtClass = pWs.CreateFeatureClass("Test",pFields,null,null,esriFeatureType.esriFTSimple,"SHAPE",null)——————//////?????????????
如何改变字段的别名?
public void ChangeFieldAliasName(ITable pTable,string pOriFieldName,string pDesFieldName) {
IClassSchemaEdit pClassSchemaEdit = (IClassSchemaEdit)pTable;
//给对象加上锁
ISchemaLock pSchemaLock = (ISchemaLock)pTable;
pSchemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);
if (pTable.FindField(pOriFieldName) != -1)
{
pClassSchemaEdit.AlterFieldAliasName(pOriFieldName,pDesFieldName);
pSchemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
使用IFeatureSelection接口高亮显示
在介绍IMap接口那一节,我们用IMap的IMap.SelectFeature方法实现了对查询的要素高亮显示,现在我们用IFeatureSelection接口实现查询高亮显示
IMap pMap = axMapControl1.Map;
IFeatureLayer pFeaturelayer = GetLayer(pMap,"Roads") as IFeatureLayer;
IFeatureSelection pFeatureSelection = pFeaturelayer as IFeatureSelection;
IQueryFilter pQuery = new QueryFilterClass();
pQuery.WhereClause = "TYPE=" +"'paved'";
pFeatureSelection.SelectFeatures(pQuery,esriSelectionResultEnum.esriSelectionResultNew,false); axMapControl1.ActiveView.Refresh();
其中GetLayer函数是我们写的一个根据图层的名称获取图层的方法,代码如下
private ILayer GetLayer(IMap pMap,string LayerName)
{
IEnumLayer pEnunLayer;
pEnunLayer = pMap.get_Layers(null,false);
pEnunLayer.Reset();
ILayer pRetureLayer;
pRetureLayer = pEnunLayer.Next();
while (pRetureLayer != null)
{
if ( == LayerName)
{
break;
}
pRetureLayer = pEnunLayer.Next();
}
return pRetureLayer;
}
提问:以下三种方式的区别在哪里?
axMapControl1.Refresh(esriViewDrawPhase.esriViewGeoSelection, null, null); axMapControl1.ActiveView.Refresh();
axMapControl1.Refresh();
创建符合要求的表:
public ITable CreateTable(string _TablePath,string _TableName)
{
IWorkspaceFactory pWks = new ShapefileWorkspaceFactoryClass();
IFeatureWorkspace pFwk = pWks.OpenFromFile(_TablePath,0) as IFeatureWorkspace;
//用于记录面中的ID;
IField pFieldID = new FieldClass();
IFieldEdit pFieldIID = pFieldID as IFieldEdit;
pFieldIID.Type_2 = esriFieldType.esriFieldTypeInteger;
_2 = "面ID";
//用于记录个数的;
IField pFieldCount = new FieldClass();
IFieldEdit pFieldICount = pFieldCount as IFieldEdit;
pFieldICount.Type_2 = esriFieldType.esriFieldTypeInteger;
_2 = "个数";
//用于添加表中的必要字段
ESRI.ArcGIS.Geodatabase.IObjectClassDescription objectClassDescription = new
ESRI.ArcGIS.Geodatabase.ObjectClassDescriptionClass();
IFields pTableFields = objectClassDescription.RequiredFields;
IFieldsEdit pTableFieldsEdit = pTableFields as IFieldsEdit;
pTableFieldsEdit.AddField(pFieldID);
pTableFieldsEdit.AddField(pFieldCount);
ITable pTable = pFwk.CreateTable(_TableName,pTableFields,null,null,""); return pTable;
}
统计需要的数据:
/// <summary>
/// 第一个参数为面数据,第二个参数为点数据,第三个为输出的表
/// </summary>
/// <param name="_pPolygonFClass"></param>
/// <param name="_pPointFClass"></param>
/// <param name="_pTable"></param>
public void StatisticPointCount(IFeatureClass _pPolygonFClass,IFeatureClass _pPointFClass,ITable _pTable)
{
IFeatureCursor pPolyCursor = _pPolygonFClass.Search(null,false);
IFeature pPolyFeature = pPolyCursor.NextFeature();
while (pPolyFeature != null)
{
IGeometry pPolGeo = pPolyFeature.Shape;
int Count = 0;
ISpatialFilter spatialFilter = new SpatialFilterClass();
spatialFilter.Geometry = pPolGeo;
spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;
IFeatureCursor pPointCur = _pPointFClass.Search(spatialFilter,false);
if (pPointCur != null)
{
IFeature pPointFeature = pPointCur.NextFeature();
while (pPointFeature != null)
{
pPointFeature= pPointCur.NextFeature();
Count++;
}
}
if (Count != 0)
{
IRow pRow = _pTable.CreateRow();
pRow.set_Value(1,pPolyFeature.get_Value(0));
pRow.set_Value(2,Count);
pRow.Store();
}
pPolyFeature = pPolyCursor.NextFeature();
}
}
效果如下:
上面这个例子只是用了空间过滤,没有用到属性过滤,我们将上面的代码稍微改动下,加上一句代码即可,
结果对照:
使用查询图层快速浏览:
我们可以按照以下步骤来执行一个QueryLayer。
1)获取SqlWorkspaceFactory
2)获取SqlWorkspace
3)构造查询语句
4)执行查询
5)获取结果
public IFeatureLayer OracleQueryLayer()
{
// 创建SqlWorkspaceFactory的对象
Type pFactoryType =Type.GetTypeFromProgID("esriDataSourcesGDB.SqlWorkspaceFactory"); IWorkspaceFactory pWorkspaceFactory =
(IWorkspaceFactory)Activator.CreateInstance(pFactoryType);
// 构造连接数据库的参数
IPropertySet pConnectionProps = new PropertySetClass();
pConnectionProps.SetProperty("dbclient","Oracle11g");
pConnectionProps.SetProperty("serverinstance","esri");
pConnectionProps.SetProperty("authentication_mode","DBMS");
pConnectionProps.SetProperty("user","scott");
pConnectionProps.SetProperty("password","arcgis");
// 打开工作空间
IWorkspace workspace = pWorkspaceFactory.Open(pConnectionProps,0);
ISqlWorkspace pSQLWorkspace = workspace as ISqlWorkspace;
//获取数据库中的所有表的名称
IStringArray pStringArray= pSQLWorkspace.GetTables();
for (int i = 0; i < pStringArray.Count; i++)
{
MessageBox.Show(pStringArray.get_Element(i));
}
// 构造过滤条件SELECT * FROM PointQueryLayer
IQueryDescription queryDescription = pSQLWorkspace.GetQueryDescription("SELECT * FROM PointQueryLayer");
ITable pTable = pSQLWorkspace.OpenQueryClass("QueryLayerTest",queryDescription); IFeatureLayer pFeatureLayer = new FeatureLayerClass();
pFeatureLayer.FeatureClass = pTable as IFeatureClass;
return pFeatureLayer;
}
点几何对象:
Point是一个0维的几何图形,具有X,Y坐标值,以及一些可选的属性:如高程值(Z值),度量值(M值) M这个属性在线性参考和动态分段中经常用到和ID号,点对象用于描述精确定位的对象。
同时,点对象还可以有Z和M两个可选属性,。
以下代码演示如何创建一个Point对象:
/// <summary>
/// 获取点
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
private IPoint ConstructPoint(double x,double y)
{
IPoint pPoint = new PointClass();
pPoint.PutCoords(x,y);
return pPoint;
}
MultiPoint对象是一系列无序的点的群集,这些点具有相同的属性信息。
例如可以用一个点集来表示整个城市天然气调压站。
如下图所示:一个Multipoint对象由8个Point对象组成。
以下代码片段演示如何构建Multipoint对象:
private object pMissing = Type.Missing;
public IGeometry GetMultipointGeometry()
{
const double MultipointPointCount = 25;
IPointCollection pPointCollection = new MultipointClass();
for (int i = 0; i < MultipointPointCount; i++)
{
pPointCollection.AddPoint(GetPoint(),ref pMissing,ref pMissing);
}
return pPointCollection as IGeometry;
}
private IPoint GetPoint()
{
const double Min = -10;
const double Max = 10;
Random pRandom = new Random();
double x = Min + (Max - Min) * pRandom.NextDouble();
double y = Min + (Max - Min) * pRandom.NextDouble();
return ConstructPoint(x,y);
}
Segment对象
Segment对象是一个有起点和终点的“线“,也就是说Segement只有两个点,至于两点之间的线是直的,还是曲的,需要其余的参数定义。
所以Segment是由起点,终点和参数三个方面决定的。
Segment有4个子类,它的4个子类(直线,圆弧,椭圆弧,贝赛尔曲线)。
ISegment有两个很有用的方法如下图:
这两个方法用于将该Segment进行分割成小的Segement
Path几何对象
Path是连续的Segment的集合,除了路径的第一个Segment和最后一个Segment外其余的Segment的起始点都是前一个Segment的终止点,即Path对象的中的Segment不能出现分离,Path可以是任意数的Segment 子类的组合。
该Path对象有很多我们经常用到的方法,如平滑曲线,对曲线抽稀等操作
Ring几何对象
Ring是一个封闭的Path即起始和终止点有相同的坐标值,它有内部和外部属性。
Polyline几何对象
Polyline对象是由一个或多个相连或者不相连的path对象的有序集合,通常用来代表线状地物如道路,河流,管线等等.该对象在ArcGIS Engine中的模型图如下:
这并不意味着用户必须按照这种层次去构造polyline,实际上Point集合直接构成Polyline,组成Polyline 的这些路径既可以是连续的,也可以是不连续的。
Polyline是有序path组成的集合,可以拥有M、Z和ID属性值,Polyline对象的IPointCollection接口包含了所有的节点信息,IGeometryCollection接口可以获取polyline的paths,ISegmentCollection接口可以获取polyline的segments。
一个Polyline对象必须满足以下准则:
1.组成Polyline对象的所有Path对象必须是有效的。
2.组成Polyline对象的所有Path对象不能重合,相交或自相交。
3.组成Polyline对象的多个Path对象可以连接与某一点,也可以分离。
4.Path对象的长度不能为0.
IPolyline是Polyline类的主要接口,IPolyline的Reshape方法可以使用一个Path对象为一个Polyline对象整形,IPolyline的SimplifyNetwork方法用于简化网络。
Polyline对象可以使用IGeometryCollection接口添加Path对象的方法来创建,使用该接口需注意以下情况:
1.每一个Path对象必须是有效的,或使用IPath::Simplify方法后有效。
2.由于Polyline是Path对象的有序集合,所以添加Path对象时必须注意顺序和方向。
3.为了保证Polyline是有效的,可以创建完Polyline对象后使用ITopologicalOperator接口的Simplify方法。
下面代码片段演示了一个Polyline的构成:
private object pMissing = Type.Missing;
public IGeometry GetPolylineGeometry()
{
const double PathCount = 3;
const double PathVertexCount = 3;
IGeometryCollection pGeometryCollection = new PolylineClass();
for (int i = 0; i < PathCount; i++)
{
IPointCollection pPointCollection = new PathClass();
for (int j = 0; j < PathVertexCount; j++)
{
pPointCollection.AddPoint(GetPoint(),ref pMissing,ref pMissing);
}
pGeometryCollection.AddGeometry(pPointCollection as IGeometry,ref pMissing,ref pMissing);
}
return pGeometryCollection as IGeometry;
}
private IPoint GetPoint()
{
const double Min = -10;
const double Max = 10;
Random random = new Random();
double x = Min + (Max - Min) * random.NextDouble();
double y = Min + (Max - Min) * random.NextDouble();
return ConstructPoint(x,y);
}
Segment,Path,Ring和Polyline的区别
在这四者当中Segment是最小的单位具体的构成路线可以分为两个条:
Segment-Path-Ring(封闭的Path)
Segment-Path-Polyline
我们可以这样说Segment是Path,只不过是这个Path由一个Segment组成,Ring也是一种Path,只不过是一个起点和终点重合的Path,至于Polyline那就很明显了,他们的区别可以从下图看出:
Polygon对象
Polylgon对象是由一个或多个Ring对象的有序集合,它可以是由单个Ring 对象构成,也可以使用多个Ring 组成。
Polygon通常用来代表有面积的多边形矢量对象,如行政区,建筑物等。
Polygon的组成结构可以看下图:
从这个图上可以看出Polygon是由Rings构成,而Ring又是又Segment构成,但是这并不意味着用户必须按照这种层次去构造Polygon,实际上用Point的集合可以构成Polygon.
/// <summary>
/// 通过点构造面
/// </summary>
/// <param name="pPointCollection"></param>
/// <returns></returns>
public IPolygon CreatePolygonByPoints(IPointCollection pPointCollection)
{
IGeometryBridge2 pGeometryBridge2 = new GeometryEnvironmentClass();
IPointCollection4 pPolygon = new PolygonClass();
WKSPoint[] pWKSPoint = new WKSPoint[pPointCollection.PointCount];
for (int i = 0; i < pPointCollection.PointCount; i++)
{
pWKSPoint[i].X = pPointCollection.get_Point(i).X;
pWKSPoint[i].Y = pPointCollection.get_Point(i).Y;
}
pGeometryBridge2.SetWKSPoints(pPolygon,ref pWKSPoint);
IPolygon pPoly= pPolygon as IPolygon;
pPoly.close();
return pPoly;
}
组成Polygon的是Ring,其中Ring可以分为Outer Ring(外环)和Inner Ring(内环)之分。
外环和内环都是有方向的,它们的区别是外环的方向是顺时针的,内环的方向是逆时针。
Polygon对象实现了一个接口IArea,而该接口用来对Poylgon的中心,重心,以及面积进行访问,下面片段用来获取Polygoe的面积:
IArea pArea = pPolygon as IArea;
Double S= pArea. Area
IGeometryCollection接口
通过IGeometryCollection创建一个Polygon对象的代码片段如下:
private IPolygon ConstructorPolygon(List<IRing> pRingList)
{
try
{
IGeometryCollection pGCollection = new PolygonClass();
object o = Type.Missing;
for (int i = 0; i < pRingList.Count; i++)
{
//通过IGeometryCollection接口的AddGeometry方法向Polygon对象中添加Ring子对象pGCollection.AddGeometry(pRingList[i],ref o,ref o);
}
//QI至ITopologicalOperator
ITopologicalOperator pTopological = pGCollection as ITopologicalOperator;
//执行Simplify操作
pTopological.Simplify();
IPolygon pPolygon = pGCollection as IPolygon;
//返回Polygon对象
return pPolygon;
}
catch (Exception Err)
{
return null;
}
}
private IPolygon MergePolygons(IPolygon firstPolygon,IPolygon SecondPolygon)
{
try
{
//创建一个Polygon对象
IGeometryCollection pGCollection1 = new PolygonClass();
IGeometryCollection pGCollection2 = firstPolygon as IGeometryCollection;
IGeometryCollection pGCollection3 = SecondPolygon as IGeometryCollection;
//添加firstPolygon
pGCollection1.AddGeometryCollection(pGCollection2);
//添加SecondPolygon
pGCollection1.AddGeometryCollection(pGCollection3);
//QI至ITopologicalOperator
ITopologicalOperator pTopological = pGCollection1 as ITopologicalOperator;
//执行Simplify操作
pTopological.Simplify();
IPolygon pPolygon = pGCollection1 as IPolygon;
//返回Polygon对象
return pPolygon;
}
catch (Exception Err)
{
return null;
}
}
唯一值渲染代码:
public UniqueValueRender(AxMapControl pMapcontrol,IFeatureLayer pFtLayer,int pCount,string pFieldName)
{
IGeoFeatureLayer pGeoFeaturelayer = pFtLayer as IGeoFeatureLayer;
IUniqueValueRenderer pUnique = new UniqueValueRendererClass();
pUnique.FieldCount = 1;
pUnique.set_Field(0,pFieldName);
ISimpleFillSymbol pSimFill = new SimpleFillSymbolClass();
//给颜色
IFeatureCursor pFtCursor = pFtLayer.FeatureClass.Search(null,false);。