ArcgisEngine开发总结集锦

更新时间:2023-04-10 20:34:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

1.目录

1. 目录 (1)

2. 用ArcEngine的工具条添加图层要素 (2)

3. ArcEngine中对Feature的编辑 (5)

4. Feature的概念 (7)

5. 如何实现经度纬度到平面坐标的相互转换?(转载) (7)

6. ArcEngine中使用上下左右键移动地图功能的实现 (9)

7. 缓冲区的创建 (11)

8. C#制作鹰眼全过程(引自ESRI中国社区) (13)

9. ArcEngine中拓扑的使用- - (15)

10. 为什么使用接口编程{转载} (17)

11. ArcEngine中闪烁目标 (21)

12. 创建多个ArcSDE实例 (23)

13. 空间查询与空间分析功能 (25)

14. AO中的空间关系 (26)

15. ArcGIS Engine 中的相交分析的实现 (28)

16. GIS基本概念集锦 (30)

17. AE开发中矢量图层叠加求交分析 (34)

18. 矢量数据分析 (38)

19. GIS空间信息基本分析方法 (39)

20. 如何判断图形间的逻辑运算 (42)

21. AE中2种方式overlay (43)

22. ArcEngine中实现捕捉功能 (47)

23. 在LAYER(i)上添加缓冲区 (69)

24. C#编码标准--编码习惯 (69)

25. 基于AE删除选择的要素- - (86)

26. 基于AO/AE获取要素信息 (87)

27. ArcEngine中拓扑的使用- - (90)

28. ArcEngine 渲染的使用 (93)

29. 利用ArcEngin进行空间分析的简单应用- - (100)

30. IfeatureSelection:SelectFeatures方法介绍 (105)

31. 常用数据入sde库的代码 (107)

32. ArcEngine开发感想 (112)

33. Geometry 对象浅析 (114)

34. AE开发中的一些基本方法(1)数据连接 (125)

2.用ArcEngine的工具条添加图层要素

发现AE比起其它的组件GIS来要好用的多

但也有一些bt的地方

比如说AE没有提供图层编辑的工具条

但最近因为程序里要添加图元

必须得开发图层编辑的功能

于是去找了找资料

发现自带的帮助里有一个MapEditing的示例

但是从AO的示例改造而来

需要从按钮写起

想想如果这样搞的话

倒不如直接用AO算了

一直想省点事

在AE自带的工具条上做点文章

其实AE中也有一组相似的编辑按钮,是用于编辑Graphics的

自然就有了一个想法:能不能先生成一个Graphic,然后将其加载进来

代码分享

private void Form1_Load(object sender, System.EventArgs e)

{

//清空图层

this.axMapControl1.Map.ClearLayers();

//加载服务器SDE地图信息

ESRI.ArcGIS.esriSystem.IpropertySet Proset = new ESRI.ArcGIS.esriSystem.PropertySetClass();

//属性集

ESRI.ArcGIS.Geodatabase.IWorkspaceFactory Fact;//工作空间仓库

ESRI.ArcGIS.Geodatabase.IWorkspace Workspace;//工作空间

Proset.SetProperty("Server","服务器名");//服务器名

Proset.SetProperty("Instance","端口");//实例化端口

Proset.SetProperty("user","用户名");//SDE用户名

Proset.SetProperty("password","密码");//密码

Proset.SetProperty("version","sde.DEFAULT");//连接版本

Fact = new ESRI.ArcGIS.DataSourcesGDB.SdeWorkspaceFactoryClass();//实例化为SDE工作空间仓库Workspace = Fact.Open(Proset,Int32.Parse(this.Handle.ToString()));//填入属性集

ESRI.ArcGIS.Geodatabase.IFeatureWorkspace FeatureWorkspace;

FeatureWorkspace = Workspace as ESRI.ArcGIS.Geodatabase.IFeatureWorkspace;//传递给Feature工作空间ESRI.ArcGIS.Geodatabase.IFeatureClass FeatureClass;

FeatureClass = FeatureWorkspace.OpenFeatureClass("SDE.BBBB");//填充所需Feature集合

ESRI.ArcGIS.Carto.FeatureLayer FLayer = new ESRI.ArcGIS.Carto.FeatureLayerClass();

FLayer.FeatureClass = FeatureClass;//将Feature加载到图层

axMapControl1.Map.AddLayer(FLayer);//加载图层

axMapControl1.Update();//更新空白区域

axMapControl1.Refresh();//刷新地图视窗

}

private void Form1_Closed(object sender, System.EventArgs e)

{

ESRI.ArcGIS.esriSystem.IAoInitialize aoi = new ESRI.ArcGIS.esriSystem.AoInitializeClass();

aoi.Shutdown();

}

private void button1_Click(object sender, System.EventArgs e)

{

IGraphicsContainerSelect GraphicsContainerSelect = (IGraphicsContainerSelect)axMapControl1.Map;

if(GraphicsContainerSelect.ElementSelectionCount ==0)//判断是否选中图斑

{

MessageBox.Show("请选中欲导入图斑!");

return;

}

IWorkspaceEdit WorkspaceEdit;

IFeatureLayer FeatureLayer;

IFeatureClass FeatureClass;

IFeature Feature;

IDataset Dataset;

FeatureLayer = (IFeatureLayer)this.axMapControl1.get_Layer(0);//选中导入图层

FeatureClass = FeatureLayer.FeatureClass;//该图层的feature集

Dataset = (IDataset)FeatureClass;//该图层的数据集

WorkspaceEdit = (IWorkspaceEdit)Dataset.Workspace;//关联到编辑空间

WorkspaceEdit.StartEditing(true);//使之可编辑

WorkspaceEdit.StartEditOperation();//开始编辑

Feature = FeatureClass.CreateFeature();//创建空feature

Feature.Shape = GraphicsContainerSelect.SelectedElement(0).Geometry;//仅导入最新选中图斑,即多选时只有一个可以导入Feature.Store();

WorkspaceEdit.StopEditOperation();

WorkspaceEdit.StopEditing(true);//结束编辑并保存

IGraphicsContainer GraphicsContainer = (IGraphicsContainer)GraphicsContainerSelect;

GraphicsContainer.DeleteAllElements();//删除graphic图层

axMapControl1.ActiveView.Refresh();//刷新当前视图

MessageBox.Show("ok");

}

3.ArcEngine中对Feature的编辑

对Feature的编辑分为以下几个部分

1.新建

2.修改

3.删除

涉及到的接口有以下几个

IWorkspaceEdit

IFeatureClass

IFeatureCursor

IFeature

其中IWorkspaceEdit用于启动编辑开始编辑操作结束编辑操作结束编辑

IFeatureClass 是数据的所在地

IFeatureCursor 是一个游标提供访问数据的接口和修改数据的接口

IFeature 是对象的代表我们要编辑的目标

编辑的过程如下:

1.添加一个Feature

//假设space是一个IWorkspaceEdit

//参数表示是否需要使用Undo/Redo功能,该功能的粒度是EditOperator. spaceEdit.StartEditing(false);

spaceEdit.StartEditOperator();

//添加一个Feature

IFeature newFea=feaClass.createFeature();

//为Feature 添加属性设置图形

newFea.Store();//保存属性和图形

spaceEdit.StopEditOperator();//结束编辑操作

//结束编辑过程

//参数表示是否保存编辑

spaceEdit.StopEditing(true);

2.添加多个Feature

添加多个Feature也可以向上面一样使用多次就可以了

当时也可以使用IFeatureCursor来添加数据

3.修改Feature

添加Feature中的修改属性和图形部分就是

每次修改后一定要调用Store方法这样变化才可以保存下来

4.删除

IFeature 有一个方法Delete 可以用于删除当时经过测试发现对Shapefile

会抛出异常来。

IFeatureCuror有一个DeleteFeature方法可以用来删除当前的Feature ,经测试

对所有的数据源类型都可以使用。

注意事项

1.不能设置Feature的OID

2.不能设置Feature的Area

3.不能设置Feature的Lenght

4.不能设置Feature的Shape字段,需要调用单独的方法来给Feature关联几何图形。

4.Feature的概念

Feature是二次开发中最常用的对象,feature是featureclass中一个记录,从object中派生出来的,因此也具有属性和方法,object 又是从row中派生的,所以featureclass其实一张表,featured就是表中的一条记录,feature可以保存空间数据对象,要素中的几何型体对象定义了要素的类型,它可以保存的几何型体对象有点、点集、多边形、多义线。这些都是些简单的要素对象,在有些情况下要素还可以参与拓扑、网络运算。

Feature相关接口

Feature有派生出很多类,如:networkfeature、rastercatalogfeature、coverageannotationfeature、annotationfeature、dimensionfeature。

feature的主要接口是Ifeature,其中的Extent用来返回要素对象的包络线,显示要素的空间范围;Featuretype返回要素的类型;Shape 返回要素的几何型体对象;ShapeCopy得到几何型体对象的一个拷贝。

IfeatureBuffer中的Shape得到缓冲要素的几何型体对象

IfeatureEdit中MoveSet、RotateSet、DeleteSet分别是移动、旋转、删除一个或者是多个要素组成的要素集上。Split主要是用来分割几何型体的,通过点分割线,通过多义线分割多边形,分割后旧的被删除,新的要素自动产生。因为每个要素都有对应的属性,要素改变了,其对应的属性也相应的要改变。Splitattributes就是用来分割要素属性字段中的值。该方法可以在Split方法执行后自动执行。

IfeatureDraw中的InvalidArea属性得到一个绘画的区域。Draw在显示设备上绘制要素

IfeatureChanges中OriginalShape得到要素的最初几何类型,ShapeChanged指示要素的几何类型是否改变。

IfeatureSimplify中SimplifyGeometry按照该元素的拓扑规则进行拓扑一致

5.如何实现经度纬度到平面坐标的相互转换?(转载)

分类:WebGIS网络地理信息系统研究

现在好多人在使用ArcObject的时候都可能需要作经纬度和平面坐标的相互转换。由于经纬度是球面坐标,平面坐标是X-Y的笛卡尔坐标系统,所以这是一个看起来比较难的问题。

好多人一上来就搬出地图学、地图投影学或者测绘学中的投影公式(如高斯投影或墨卡托投影),又是基准坐标又是角度的搞的人头都大了。

实际上要想实现这个功能非常easy。ARC Engine中的IPoint就可以进行投影和反投影运算了。

投影过程(C#):

/// flatref 投影的坐标系统,这里的54013是世界投影,世界投影所有经纬度都可以转换为平面坐标,但是由于投影面积大失真也会比较大(相当于把整个地球劈成一片片的,然后拉伸最后贴到平面上,失真当然大了)。当然也可以选择精度更高的平面如:esriSRProjCS_Beijing1954GK_23N 对应数值21483 仅仅把北京附近的地球平面拉伸铺在平面上,由于投影面积变小,所以投影经度提高。但是由于面积变小,所以有些经度纬度不能转换,比如所美国的精度纬度用北京投影就投不了。

flatref = pfactory.CreateProjectedCoordinateSystem(54013);

//没什么说的,标准大地经纬度,可以将X-Y逆投影为经度和纬度

earthref = pfactory.CreateGeographicCoordinateSystem((int)esriSRGeoCSType.esriSRGeoCS_NAD1983);

/// 将经纬度点转换为平面坐标。

private IPoint GetProject(double x, double y)

{

IPoint pt = new PointClass();

pt.PutCoords(x, y);

IGeometry geo = (IGeometry)pt;

geo.SpatialReference = earthref;

geo.Project(flatref);

return pt;

}

/// 将平面坐标转换为经纬度。

private IPoint GetGeo(double x, double y)

{

IPoint pt = new PointClass();

pt.PutCoords(x, y);

IGeometry geo = (IGeometry)pt;

geo.SpatialReference = flatref;

geo.Project(earthref);

double xx = pt.X;

return pt;

}实际上IPoint的投影和任何地图都没什么大关系,完全可以不用地图,直接调用IPoint进行投影的转换6.ArcEngine中使用上下左右键移动地图功能的实现

//闪烁目标

public static void FlashFeature(AxMapControl mapControl,IFeature iFeature, IMap iMap)

{

IActiveView iActiveView = iMap as IActiveView;

if (iActiveView != null)

{

iActiveView.ScreenDisplay.StartDrawing(0, (short)esriScreenCache.esriNoScreenCache);

//根据几何类型调用不同的过程

switch (iFeature.Shape.GeometryType)

{

case esriGeometryType.esriGeometryPolyline:

FlashLine(mapControl, iActiveView.ScreenDisplay, iFeature.Shape);

break;

case esriGeometryType.esriGeometryPolygon:

FlashPolygon(mapControl, iActiveView.ScreenDisplay, iFeature.Shape);

break;

case esriGeometryType.esriGeometryPoint:

FlashPoint(mapControl, iActiveView.ScreenDisplay, iFeature.Shape);

break;

default:

break;

}

iActiveView.ScreenDisplay.FinishDrawing();

}

}

//闪烁线

static void FlashLine(AxMapControl mapControl,IScreenDisplay iScreenDisplay,IGeometry iGeometry) {

ISimpleLineSymbol iLineSymbol;

ISymbol iSymbol;

IRgbColor iRgbColor;

iLineSymbol = new SimpleLineSymbol();

iLineSymbol.Width = 4;

iRgbColor = new RgbColor();

iRgbColor.Red = 255;

iLineSymbol.Color = iRgbColor;

iSymbol = (ISymbol)iLineSymbol;

iSymbol.ROP2 = esriRasterOpCode.esriROPNotXOrPen;

mapControl.FlashShape(iGeometry, 3, 200, iSymbol);

}

//闪烁面

static void FlashPolygon(AxMapControl mapControl, IScreenDisplay iScreenDisplay, IGeometry iGeometry) {

ISimpleFillSymbol iFillSymbol;

ISymbol iSymbol;

IRgbColor iRgbColor;

iFillSymbol = new SimpleFillSymbol();

iFillSymbol.Style = esriSimpleFillStyle.esriSFSSolid;

iFillSymbol.Outline.Width = 12;

iRgbColor = new RgbColor();

iRgbColor.RGB = System.Drawing.Color.FromArgb(100, 180, 180).ToArgb();

iFillSymbol.Color = iRgbColor;

iSymbol = (ISymbol)iFillSymbol;

iSymbol.ROP2 = esriRasterOpCode.esriROPNotXOrPen;

iScreenDisplay.SetSymbol(iSymbol);

mapControl.FlashShape(iGeometry, 3, 200, iSymbol);

}

//闪烁点

static void FlashPoint(AxMapControl mapControl, IScreenDisplay iScreenDisplay, IGeometry iGeometry)

{

ISimpleMarkerSymbol iMarkerSymbol;

ISymbol iSymbol;

IRgbColor iRgbColor;

iMarkerSymbol = new SimpleMarkerSymbol();

iMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSCircle;

iRgbColor = new RgbColor();

iRgbColor.RGB = System.Drawing.Color.FromArgb(0, 0, 0).ToArgb();

iMarkerSymbol.Color = iRgbColor;

iSymbol = (ISymbol)iMarkerSymbol;

iSymbol.ROP2 = esriRasterOpCode.esriROPNotXOrPen;

mapControl.FlashShape(iGeometry, 3, 200, iSymbol);

}

7.缓冲区的创建

蓝蓝的小志发表于2005-6-5 10:07:08

本文以面图层为例,并且把创建的缓冲区就存储在面图层中,当然也可以把创建的缓冲区另存为一个新的图层。程序运行环境(.NET+AO)

代码如下:

Private Sub ITopologicalOperator_Buffer(ByVal pFeatLyr As ESRI.ArcGIS.Carto.IFeatureLayer, ByVal distance As Double, Optional ByVal pFeatClass As ESRI.ArcGIS.Geodatabase.IFeatureClass = Nothing)

'pFeatLyr 为面图层

'distance缓冲距离

Dim pFeatureClass As ESRI.ArcGIS.Geodatabase.IFeatureClass

Dim pTopoOper As ESRI.ArcGIS.Geometry.ITopologicalOperator

Dim pBufferPoly As ESRI.ArcGIS.Geometry.IPolygon

Dim pFeatCursor As ESRI.ArcGIS.Geodatabase.IFeatureCursor

Dim pFeature As ESRI.ArcGIS.Geodatabase.IFeature

Try

pFeatureClass = pFeatLyr.FeatureClass

pFeatCursor = pFeatureClass.Search(Nothing, False)

pFeature = pFeatCursor.NextFeature

Do

If Not (pFeature Is Nothing) Then

pTopoOper = pFeature.Shape()

pBufferPoly = pTopoOper.Buffer(distance)

'pFeature = pFeatClass.CreateFeature

pFeature.Shape = pBufferPoly

pFeature.Store()

pFeature = pFeatCursor.NextFeature()

End If

Loop Until (pFeature Is Nothing)

Catch

MsgBox(Err.Description, MsgBoxStyle.OKOnly, "错误提示")

pFeature = Nothing

pFeatCursor = Nothing

pBufferPoly = Nothing

pTopoOper = Nothing

pFeatureClass = Nothing

pFeatLyr = Nothing

End Try

pFeature = Nothing

pFeatCursor = Nothing

pBufferPoly = Nothing

pTopoOper = Nothing

pFeatureClass = Nothing

pFeatLyr = Nothing

End Sub

8.C#制作鹰眼全过程(引自ESRI中国社区)

1.axMapControl1是主控件,axMapControl2是鹰眼控件

2. 1.鹰眼地图资源载入

3.private void axMapControl1_OnMapReplaced(object sender, IMapControlEvents2_OnMapReplacedEvent e)

4. {

5.//当主地图显示控件的地图更换时,鹰眼中的地图也跟随更换

6. axMapControl2.LoadMxFile(axMapControl1.DocumentFilename);

7. axMapControl2.Extent = axMapControl2.FullExtent;

8. }

9. 2.绘制鹰眼矩形框

10.private void axMapControl1_OnExtentUpdated(object sender, IMapControlEvents2_OnExtentUpdatedEvent e)

11. {

12.// 得到新范围

13. IEnvelope pEnv = (IEnvelope)e.newEnvelope;

14. IGraphicsContainer pGra = axMapControl2.Map as IGraphicsContainer;

15. IActiveView pAv = pGra as IActiveView;

16.//在绘制前,清除axMapControl2中的任何图形元素

17. pGra.DeleteAllElements();

18. IRectangleElement pRectangleEle = new RectangleElementClass();

19. IElement pEle = pRectangleEle as IElement;

20. pEle.Geometry = pEnv;

21.//设置鹰眼图中的红线框

22. IRgbColor pColor = new RgbColorClass();

23. pColor.Red = 255;

24. pColor.Green = 0;

25. pColor.Blue = 0;

26. pColor.Transparency = 255;

27.//产生一个线符号对象

28. ILineSymbol pOutline = new SimpleLineSymbolClass();

29. pOutline.Width = 2;

30. pOutline.Color = pColor;

31.//设置颜色属性

32. pColor = new RgbColorClass();

33. pColor.Red = 255;

34. pColor.Green = 0;

35. pColor.Blue = 0;

36. pColor.Transparency = 0;

37.//设置填充符号的属性

38. IFillSymbol pFillSymbol = new SimpleFillSymbolClass();

39. pFillSymbol.Color = pColor;

40. pFillSymbol.Outline = pOutline;

41. IFillShapeElement pFillShapeEle = pEle as IFillShapeElement;

42. pFillShapeEle.Symbol = pFillSymbol;

43. pGra.AddElement((IElement)pFillShapeEle, 0);

44. pAv.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);

45. }

46.3. 实现互动

47.private void axMapControl2_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)

48. {

49. IPoint pPt=new PointClass ();

50. pPt.PutCoords (e.mapX ,e.mapY );

51.//改变主控件的视图范围

52. axMapControl1 .CenterAt (pPt );

53. }

9.ArcEngine中拓扑的使用- -

拓扑(ITopology)的使用包括

1.建立拓扑

2.验证拓扑

3.编辑过程中保证拓扑的正确

4.查询系统中存在的拓扑

1.首先来看看建立拓扑

Topology实现了ITopology这个接口但是给类是不能用来创建对象的。

必须要通过调用ITopologyContainer::CreateTopology这个方法来建立一个Topology FeatureDataset 实现了ITopologyContainer这个接口。那么这就是说拓扑只能在一个FeatureDataset的范围内建立。而不能独立存在于Workspace中。这样做的原因是需要保证参与同一个拓扑的FeatureClass具有同一个投影坐标系统。建立拓扑后需要将ObjectClass 加入到拓扑中去。这样这个拓扑就可以用来验证这几个ObjectClass 的对象之间的关系了。验证关系就要有规则,规则是由ITopologyRule来表达的。ITopologyRule必须要被

加入到一个ITopologyRuleContainer中去。而Topology实现了这个接口。

一个ITopologyRule用来表达两个ObjectClass的对象之间的某个关系。

具体代码参看接口就可以了。

2.验证拓扑

ITopology有一个方法ValidateTopology 用来验证指定区域内的拓扑。需要注意没有版本的拓扑可以在任何时候验证。而有版本的拓扑必须在编辑回话中验证。

3.拓扑编辑

1.移动共用点

1.首先需要打开拓扑建立拓扑图(ITopologyGraph)

代码如下:

//topoLayer 是一个打开的拓扑图层

ITopologyGraph pTG=topoLayer.Topology.Cache;

pTG.Build(pA.Extent,false);

2.然后需要获得当前节点或者边这个操作要使用拓扑图的点击测试

ITopologyElement topeEle

pTG.HitTest(... ref topeEle);

这个方法在点击测试成功的时候返回true.而且会通过topeEle这个ref 参数将选中的元素(点或者边) 返回.

3.还有一种获取节点的方法

首先调用拓扑图的Select方法选中点击测试的元素(pTG.Select)

然后可以查询拓扑图的选中节点集合就可以找到该节点(pTG.NodeSelection)

4.为该元素使用一个Feedback.

//其中pNode 就是当前节点sr 是参考坐标系可以使用null

//还有给Feedback设置Display

m_pNodeFeedback =pTG.GetSplitMoveNodeFeedback(pNode,false,sr);

m_pNodeFeedback.Display= activeView.ScreenDisplay;

5.在鼠标移动的时候调用Feedback的MoveTo 方法。

if(m_pNodeFeedback!=null)

{

//activeView 是活动的试图

//首先要把将点坐标转换为地图中的坐标。

//然后调用MoveTo 方法

IPoint pt=activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(X,Y);

m_pNodeFeedback.MoveTo(pt);

}

6.在鼠标释放的时候

//获取拓扑图

ITopologyGraph pTG=topoLayer.Topology.Cache;

//转换坐标

IPoint pt=pA.ScreenDisplay.DisplayTransformation.ToMapPoint(X,Y);

//获得正在做拓扑编辑的元素

ITopologyNode pTN=(ITopologyNode)m_pTopoElement;

//实施拓扑编辑

pTG.SplitMoveNode(pTN,pt,false);

//提交拓扑编辑结果

IEnvelope pE;

pTG.Post(out pE);

4.查询系统中的拓扑

还是ITopologyContainer 这个接口这个接口有FeatureDataset这个唯一的实现。

CreateTopology 建立一个新的拓扑

DefaultClusterTolerance The default cluster tolerance as per the topology engine.

MaximumClusterTolerance The maximal cluster tolerance as per the topology engine.

MinimumClusterTolerance The minimal cluster tolerance as per the topology engine.

Topology 通过索引打开拓扑.

TopologyByID 通过ID打开拓扑.

TopologyByName 通过名字打开拓扑

TopologyCount 拓扑的数目

10.为什么使用接口编程{转载}

进行接口的介绍,必须介绍一下程序语言发展的历史才行,鲁迅先生说过“治学先治史”,明白了程序语言发展的前世今生,才能知道为什么这么多语言为什么会这样,为什么么会那样?

计算机出现以后,科学家相继开发了多种语言,从smalltalk,Pascal,Basic,C语言,C++,java,.net等等,这些语言的发展步伐,可以看作是从面向过程向面向对象发展的一段历史。很多面向对象的书在介绍自己的历史的时候,都会给读者介绍这一段历史,并鼓吹OO编程是多么多么的优异。问题是,很多刚开始学程序的人根本不知道为什么要有这个转变,他们也很难理解OO语言中的虚函数,接口等概念到底为了什么而提出来。

我们在了解这一段历史以前,首先给大家介绍一个概念??“粒度”,什么是粒度?作者认为所谓粒度其实就是一个程序中使用代码单元的组合尺度,我们可以举一个例子,沙砾??砖块??房屋模板,我们设想去修建一座房子,其实有很多中修筑方法,如果你不闲麻烦,可以使用沙砾一点点地建筑,或者将沙砾烧制为砖块,用砖块来砌,甚至直接从工厂购买房屋的门,窗,墙组件来堆砌。这三种不同的方法代表了三种不同的组合尺度。沙砾是最小的单位,使用它搭建小的房子说不定还可以,但是毫无疑问,我们必须使用很多很多“沙砾”,不便于管理;砖块比沙砾聚合了一层,可以用来修建较大的房子了;房屋模板是最高的尺寸,使用它可以快速地搭建大规模的房屋。这三种尺度的区别和联系,与我们编写程序概念是有很大的相似之处的。

在早期学习Pascal,老师告诉我们这种面向过程语言的最基本的单元是过程和函数,它们是程序中的最小的组件。过程和函数可以实现最基本的代码重用,当我们把某些固定功能的代码使用过程和函数编写后,我们可以在程序中调用它们而不必在任何需要的地方都写上这样一段代码,这样的好处是显而易见的。在一些小型的程序里面,使用过程和函数是合适的,但是在大中型程序中,它们的弊端就显示出来,过程和函数的粒度太低了,如果我们一个系统,有10000个函数和过程,我们的程序员将不得不花费大量的时间去寻找和维护它们,10000个没有任何关系的函数和过程的管理难度是显而易见的,就好像10000个人的企业一样,如果没有部门和职务,这还不乱了套?!

面向对象语言的出现,就是为了解决这个问题,别听OO语言吹的天花乱坠,其实它出现就为一个理由??提高编程的粒度。面向对象语言的基本单位是类CLASS,类封装了很多数据成员和成员函数,过程,将最小组件的提高了一个等级,我们需要直接操作的不是过程和函数了,而是一个个更高层次上的类。我们把10000人分了很多部门,不同的部门负责不同的事宜,这样公司终于可以走上正轨了。

做成了类CLASS是否就万事大吉了呢?不一定,新的问题随之而来,也许我们有一个部门的人很多,可以做很多事情,如何在部门内部实现更好的管理呢?好比我们有一个类,它提供了很多种方法和属性,这些方法和属性其实可以分为一堆堆,为不同的功能服务,但是我们的类并没有做这个管理。在AO种,map对象拥有很多功能,比如管理图层,管理元素,管理选择集,进行地图显示,每种不同的功能都有好多方法和属性,现在这些属性和方法是杂乱无章,没有任何区别堆积在一个类里面的,当我们的程序员需要寻找一个方法的时候,不得不一个个去寻找,很不方便。

这个时候,接口interface出现了,C++的发明者第一次提出纯虚函数(其实就是接口)概念的时候,遭到了很多抵制,很多人都不明白接口的意义何在,我们用虚函数好好的,何必又出来个啥东西都没有的空架子?说它是类吧,又不能实现产生一个对象;说它是对象吧,又没有方法体来使用。接口出来干了一件好事,就是将类内部进行分类。对于map对象,我们可以做好几个接口,这些接口中定义不同功能的方法,函数和属性,map类实现这些接口,这样我们可以使用接口定义,实现对象。因此,所谓接口就是一系列相关方法与属性集合的定义。

Dim pGraphicsContainer as iGraphicsContainer

pGraphicsContainer=application.document.ActiveView.focusMap

pGraphicsContainer可以使用的属性和方法就只能是它定义的那部分了,而不能使用管理元素等的接口定义的方法和属性,那我们如何使用其它的功能呢?这就是所谓的QI(Query Interface)功能。从一个接口查询另一个接口。

Dim pGeoFeatureLayer as iGeofeatureLayer

pGeoFeatureLayer= pGraphicsContainer QI

好了,我们罗嗦了这么多,已经走进了COM的概念了,在正式介绍COM以前我们得最后罗嗦一点:计算机语言的发展历史,其实就是一部不断提高组件粒度的历史,不断提高代码重用的历史。以前我们使用过程和函数,后来我们使用类,现在我们使用接口,都是为了一个目的,让我们操作的组件在具体和抽象之间寻找一个平衡点。太具体了,如过程和函数,就没有了框架;太抽象,如类,就无法分别。

一个代码示例:

public interface IForm

{

void Show();

void ShowDialog();

}

public class A:IForm

{

public void Show()

{

}

public void ShowDialog()

{

}

}

public class B:IForm

{

public void Show()

{

}

public void ShowDialog()

{

}

}

public class FormFactory

{

public static IForm CreateInstance(string parm) {

if (parm == "A")

{

return new A();

else if (parm == "B")

return new B();

}

return null;

}

}

这是逻辑的抽象

这是方法的具体

这就是编写程序的哲学.

11.ArcEngine中闪烁目标

//闪烁目标

public static void FlashFeature(AxMapControl mapControl,IFeature iFeature, IMap iMap)

{

IActiveView iActiveView = iMap as IActiveView;

if (iActiveView != null)

{

iActiveView.ScreenDisplay.StartDrawing(0, (short)esriScreenCache.esriNoScreenCache);

//根据几何类型调用不同的过程

switch (iFeature.Shape.GeometryType)

{

case esriGeometryType.esriGeometryPolyline:

FlashLine(mapControl, iActiveView.ScreenDisplay, iFeature.Shape);

break;

case esriGeometryType.esriGeometryPolygon:

FlashPolygon(mapControl, iActiveView.ScreenDisplay, iFeature.Shape);

break;

case esriGeometryType.esriGeometryPoint:

FlashPoint(mapControl, iActiveView.ScreenDisplay, iFeature.Shape);

break;

default:

break;

}

本文来源:https://www.bwwdw.com/article/89rl.html

Top