arcgis engine基础开发教程(c#)


ArcGIS Engine 基础开发教程 1.创建第一个ArcGIS Engine桌面应用程序...............................................................................3 1.1 目标.....................................................................................................................................3 1.2 准备工作.............................................................................................................................3 1.3 设计流程图.........................................................................................................................4 1.4 制作地图文档....................................................................................................................4 1.5 创建第一个ArcGIS Engine桌面应用程序......................................................................5 1.6 加载MXD地图文档数据......................................................................................................7 1.7 为应用程序添加编辑功能................................................................................................8 1.8 体验使用编辑功能............................................................................................................9 2.学习几何对象与空间参考.......................................................................................................10 2.1 目标...................................................................................................................................10 2.2 准备工作...........................................................................................................................11 2.3Geometry主要几何对象模型图........................................................................................11 2.4 几何对象...........................................................................................................................12 2.4.1Point和MultiPoint几何对象.............................................................................12 2.4.2Segment几何对象.................................................................................................13 2.4.3Path和Ring几何对象...........................................................................................14 2.4.4Polyline和Polygon几何对象 ..................................................................................14 2.4.5Envelope几何对象..................................................................................................17 2.4.6Curve对象几何对象...............................................................................................18 2.4.7 Triangle Strip和Trangle Fan, Trangle,Ring几何对象.........................................19 2.4.8Multipatch几何对象 ...............................................................................................21 2.4.9Geometry集合接口.................................................................................................26 2.4.10 几何对象总结......................................................................................................31 2.5 空间参考..........................................................................................................................32 2.5.1 空间参考简介........................................................................................................32 2.5.2 修改空间参考........................................................................................................33 2.6 开发野外测量点构建一个Polygon几何要素程序..........................................................34 2.6.1 功能情景描述........................................................................................................34 2.6.2 功能开发代码........................................................................................................35 2.6.3 运行程序................................................................................................................40 2.6.4 Demo总结..............................................................................................................41 3.学习地图和地图布局...............................................................................................................41 3.1 地图...................................................................................................................................42 3.1.1Map对象 .................................................................................................................42 3.1.2 图层对象................................................................................................................44 3.1.3FeatureLayer对象 ...................................................................................................45 3.1.4 矢量图层操作实例................................................................................................46 3.2 地图布局...........................................................................................................................49 3.2.1PageLayout对象......................................................................................................49 3.2.2Page对象.................................................................................................................50 3.2.3SnapGrid对象 .........................................................................................................50 3.2.4SnapGuides对象 .....................................................................................................50 3.2.5RulerSettings对象...................................................................................................52 3.2.6Element对象 ...........................................................................................................52 3.2.7MapGrid对象..........................................................................................................53 3.2.8MapSurround对象...................................................................................................57 4.学习图层符号化.......................................................................................................................61 4.1 目标...................................................................................................................................62 4.2 准备工作...........................................................................................................................62 4.3 符号化Color(颜色)体系...................................................................................................62 4.3.1ArcGIS颜色模型 ....................................................................................................62 4.3.2ColorRamp对象......................................................................................................63 4.3.3 生成颜色带实例....................................................................................................64 4.4 符号化Symbol(符号)体系................................................................................................67 4.4.1MarkerSymbol对象.................................................................................................68 4.4.2LineSymbol对象.....................................................................................................70 4.4.3FillSymbol对象.......................................................................................................71 4.4.4TextSymbol对象 .....................................................................................................74 4.4.5 3DChartSymbol对象..............................................................................................75 4.5 使用ServerStyle ................................................................................................................76 4.5.1 获取符号库中符号................................................................................................77 4.6SymbologyControl控件.....................................................................................................78 4.7 符号化之Renderer( 渲染)体系 .......................................................................................79 4.7.1FeatureRender对象 .................................................................................................79 4.7.2RasterRender对象...................................................................................................81 4.8 利用ESRI自带的符号库进行唯一值符号化一图层开发实例 ......................................84 4.8.1 目的........................................................................................................................84 4.8.2 步骤........................................................................................................................85 4.8.3 功能开发................................................................................................................86 4.9 设计GIS系统符号化模块 ................................................................................................90 4.9.1 通过系统符号化配置表存储图层符号化信息符号化图层。 ............................91 4.9.2 通过ArcEngine提供的Represatation存储要素符号化.........................................91 5. 学习地图查询............................................................................................................................93 5.1 目标...................................................................................................................................94 5.2 准备工作...........................................................................................................................94 5.3Cursor对象.........................................................................................................................94 5.4QueryFilter对象与SpatialFilter对象 .................................................................................95 5.5SelectionSet要素选择集对象............................................................................................96 5.6 属性查询实例...................................................................................................................96 5.6.1 程序实现目标:....................................................................................................96 5.7 空间查询实例...................................................................................................................99 5.7.1 目标........................................................................................................................99 5.7.2 功能开发................................................................................................................99 5.7.3 功能演示..............................................................................................................108 5.7.4 Demo总结:........................................................................................................109 5.8 附IFeatureClass.Search(IQuery Filter,bool Recycling)参数说明 ..................................109 6.学习空间分析.........................................................................................................................111 1.1 目标.................................................................................................................................112 1.2 准备工作.........................................................................................................................112 1.1 ITopologicalOperator接口 ..............................................................................................113 1.1.1 ITopologicalOperator接口简介 ...........................................................................113 6.3.2 简化几何对象功能开发......................................................................................123 6.4 IRelationalOperator接口.................................................................................................124 6.4.1 IRelationalOperator接口简介..............................................................................124 6.4.2 判断几何对象包含关系功能开发......................................................................124 6.5 IProximityOperator接口 .................................................................................................125 6.5.1 IProximityOperator接口简介 ..............................................................................125 6.5.2 最近点查询功能开发.........................................................................................125 7. 学习地图输出..........................................................................................................................126 7.1 目标.................................................................................................................................127 7.2Printer类...........................................................................................................................128 7.3 打印输出.........................................................................................................................129 7.3.1PageLayoutControl控件打印出图........................................................................129 7.3.2 地图转换输出......................................................................................................130 1.创建第一个 ArcGIS Engine 桌面应用程序 ArcGIS Engine9.3 提供了丰富的 GIS 组件方便用户快速的定制开发一个 GIS 应用程序,无需写代码即可实现 GIS 数据加载,地图操作等功能甚至可以实现 高级编辑以及空间分析功能。接下来使用 ArcGIS Engine9.3 提供了 MapControl Application 模块来创建第一个 ArcGIS Engine 桌面应用程序,并为桌面应用应用 程序提供编辑功能。 1.1 目标 1.创建第一个 ArcGIS Engine 桌面应用程序 2.为应用程序添加编辑功能。 1.2 准备工作 1.IDE:Visual Studio 2005/2008 2.ArcGIS Engine Developer kit 9.3 3.制作 ArcGIS 实验数据地图文档 MXD 1.3 设计流程图 1.4 制作地图文档 在 ArcMap 中加载数据后,点击保存生成一个*.mxd 地图文档,如图1所示: 图1 1.5 创建第一个 ArcGIS Engine 桌面应用程序 在 Visual Studio2008 中新创建项 à 选择 àArcGISàEngineàMapControl Application,点击确定,如图2所示: 图2 可以看到在 Visual Studio 中看到在新创建的项目中自动加载了 ToolBarControl、TocControl、LicenseControl、MapControl 四个 ArcGIS Engine 控件以及一个.NET ToolStripMenuItem 菜单控件,如图 3 所示: 图3 1.6 加载 MXD 地图文档数据 单击 F5 键运行程序,然后单击打开 MXD 地图文档按钮打开 MXD 地图文 档,如图 4 所示: 图4 可以看到应用程序把 MXD 地图文档加载到 MapControl 地图上,可以使用 ToolbarControl 提供的常用 GIS 功能如:放大,缩小,信息查询等功能。如图5 所示: 图5 1.7 为应用程序添加编辑功能 在应用程序设计模式下右键单击 ToolbarControl,单击属性选项弹出 ToolbarControl 属性对话框,单击 Items 选项卡,单击 Add…按钮弹出 Controls Commands 对话框,单击 Toolset 选项卡,选择 Feature Editors 选项,拖动到属性 对话框工具栏的指定位置。如图6所示 图6 1.8 体验使用编辑功能 运行应用程序,可见工具条多了一个和 ArcMap 中功能类似的编辑工具集,开始 对面图层进行编辑创建一个新的面图元,如图7所示。 图7 综上 GIS 应用开发人员通过使用 ArcGIS Engine 可以快速创建自定义 GIS 应 用程序。 2.学习几何对象与空间参考 2.1 目标 1.熟悉 ArcGIS Engine Geometry 模型,通过程序构建常用几何对象 2.熟悉空间参考 3.通过野外测量点构建一个 polygon shapefile 功能开发 2.2 准备工作 1.IDE:Visual Studio 2005/2008 2.ArcGIS Engine Developer kit 9.3 3.自造一份包含 X,Y 坐标的*.txt 文本文档数据(即野外测量点) 2.3Geometry 主要几何对象模型图 图 1 Geometry 是 ArcGIS Engine 中使用最为广泛的对象集之一,用户在创建、删 除、编辑和进行地理分析的时候,就是处理一个包含几何形体的矢量对象;除了 显示要素意外,控件对象选择,要素符号化,标注要素,编辑要素都需要 Geometry 参与。图 1 是 Geometry 的主要几何对象模型图,接下来将一一介绍这些几何对 象。 2.4 几何对象 2.4.1Point 和 MultiPoint 几何对象 2.4.1.1Point 几何对象 Point:是一个0维的几何图形,具有 X,Y 坐标值,以及一些可选的属性: 如高程值(Z 值),度量值(M 值) 和 ID 号,点对象用于描述精确定位的对象,例 如一个电话亭在一个城市的精确位置以下代码演示如何创建一个 Point 对象: IPoint pPoint = new PointClass(); pPoint.X = 100; pPoint.Y = 100; 2.4.1.2MultiPoint 几何对象 MultiPoint:点集对象是一系列无序的点的群集,这些点具有相同的属性信 息。例如可以用一个点集来表示整个城市天然气调压站。如下图所示:一个 Multipoint 对象由6个 Point 对象组成。 图 2 以下代码片段演示如何构建 Multipoint 对象: //定义第一个点 IPoint pPoint1 = new PointClass(); pPoint1.X = 100; pPoint1.Y = 100; //定义第二个点 IPoint pPoint2 = new PointClass(); pPoint2.X = 200; pPoint2.Y = 200; ……//构建其他点 IPointCollection pMultipoint = new MultipointClass(); object o=Type.Missing; //添加第一个点,不需要设置点的顺序,参数设置为 Type.Missing pMultipoint.AddPoint(pPoint1, ref o, ref o); //添加第二个点,不需要设置点的顺序,参数设置为 Type.Missing pMultipoint.AddPoint(pPoint2, ref o, ref o); ……//添加其他点 2.4.2Segment 几何对象 2.4.3Path 和 Ring 几何对象 2.4.3.1Path 几何对象 Path 是连续的 Segment 的集合,除了路径的第一个 Segment 和最后一个 Segment 外其余的 Segment 的起始点都是前一个 Segment 的终止点,即 Path 对象 的中的 Segment 不能出现分离,Path 可以是任意数的 Line,CircularArc,EllipticArc 和 BezierCurve 的组合。 图 4 一个或多个 Path 组成一个 Polyline 对象。 2.4.3.2Ring 几何对象 Ring 是一个封闭的 Path 即起始和终止点有相同的坐标值。它有内部和外部 属性。 图 5 一个或多个 Ring 对象组成一个 Polygon 对象。 2.4.4Polyline 和 Polygon 几何对象 2.4.4.1Polyline 几何对象 Polyline 对象是由一个或多个相连或者不相连的 path 对象的有序集合,它可 以是单个 Path 对象组成,也可以是多个相连的 Path 对象组成,或者是多个分离 的 Path 组成,如下图所示。Polyline 通常用来代表线状地物如道路,河流,管线 等等。 图 6 一个 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 方法。 以下代码片段为使用 IGeometryCollection 接口创建一个 Polyline 对象: //定义第一个点 IPoint pPoint1 = new PointClass(); pPoint1.X = 100; pPoint1.Y = 100; //定义第二个点 IPoint pPoint2 = new PointClass(); pPoint2.X = 200; pPoint2.Y = 200; //创建一个 Line 对象 ILine pLine= new LineClass(); //设置 Line 对象的起始终止点 pLine.PutCoords(pPoint1,pPoint2); //QI 到 ISegment ISegment pSegment= pLine as ISegment; //创建一个 Path 对象 SegmentCollection pPath= new PathClass(); object o=Type.Missing; //通过 ISegmentCollection 接口为 Path 对象添加 Segment 对象 pPath.AddSegment(pSegment,ref o,ref o); //创建一个 Polyline 对象 IGeometryCollection pPolyline = new PolylineClass(); //通过 IGeometryCollection 为 Polyline 对象添加 Path 对象 pPolyline.AddGeometry(pPath as IGeometry, ref o, ref o); 2.4.4.2Polylgon 几何对象 2Polylgon对象是由一个或多个Ring对象的有序集合,它可以是由单个Ring 对 象构成,也可以使用多个 Ring 组成如下图所示。其中 Ring 可以分为 Outer Ring(外 环)和 Inner Ring(内环)之分。外环和内环都是有方向的,它们的区别是外环的 方向是顺时针的,内环的方向是逆时针。Polygon 通常用来代表有面积的多边形 矢量对象,如行政区,建筑物等。 图 7 以下代码片段演示如何构建一个 Polygon: //创建一个 Ring 对象,通过 ISegmentCollection 接口向其中添加 Segment 对象 ISegmentCollection pSegCollection = new RingClass(); object o = Type.Missing; pSegCollection.AddSegment(pSegment1, ref o, ref o); pSegCollection.AddSegment(pSegment2, ref o, ref o); //QI 到 IRing 接口封闭 Ring 对象,使其有效 IRing pRing = pSegCollection as IRing; pRing.Close(); //使用 Ring 对象构建 Polygon 对象 IGeometryCollection pGeometryColl = new PolygonClass(); pGeometryColl.AddGeometry(pRing, ref o, ref o); 2.4.5Envelope 几何对象 Envelope 是所有几何对象的外接矩形,用于表示几何对象的最小边框,所有 的几何对象都有一个 Envelope 对象,IEnvelope 是 Envelope 对象的主要接口,通 过它可以获取几何对象的 XMax,XMin,YMax,YMin,Height,Width 属性。通过 IEnvelope 的 Expand 方法还可以按比例缩放 Envelope 对象的范围,如下图所示: 2.4.6Curve 对象几何对象 除去 Point,MultiPoint 和 Envelope 外,其他所有的几何体都可以看做是 Curve( 曲线) 。 Line,Polyline,Polygon,CircularArc,BezierCurve,EllipticArc 和 CircularArc 都是曲线的一种,它们都实现了 ICurve 接口。 ICurve 接口的 Length 属性用于返回一个 Curve 对象的长度。 ICurve 接口的 FromPoint 和 ToPoint 属性可以获得 Curve 对象的起止点。 ICurve 接口的 Reverseorientation 方法可以改变一个 Curve 对象的节点次序即调动 Curve 对象的起始点和终止点互相调换。 ICurve 接口的 IsClosed 属性则可以判断一个 Curve 对象起始点和终止点是否在一 个位置上。 ICurve 接口的 GetSubcurve 方法可以复制一条 Curve 对象的特定部分,例如一条 10 千米公路的 Curve 对象,获取 2-5 千米处的公路的曲线代码片段如下所示: //QI 到 ICurve 接口 ICurve pCurve = pPolyline as ICurve; //创建一个 Polyline 对象 ICurve pNewCurve = new PolylineClass(); bool btrue= true; //获取-5 千米间的曲线对象 pCurve.GetSubcurve(2, 5, btrue, out pNewCurve); 此外 ICurve 的 QueryTangent 和 QueryNormal 方法分别用于获取 Curve 对象上某 一点的曲线的切线和法线。 2.4.7 Triangle Strip 和 Trangle Fan, Trangle,Ring 几何对象 Triangle Strip 和 Trangle Fan, Trangle,Ring 是构成 MultiPatch 几何对象的构建 对象。 2.4.7.1Triangle Strip 几何对象 TriangelStrip 对象是由一系列点定义的曲面片组成,而曲面片是有若干个三 角形所组成,所以这个曲面可以定义为:(0,1,2) ,(2, 1, 3), (2, 3, 4), (4, 3, 5)。 图 9 2.4.7.2Trangle Fan 几何对象 一个 Trangle Fan 对象由一系列点定义的曲面片组成,所不同的是所有的三 角形共享一个顶点。如下图所示,所以这个曲面可以定义为:(0,1,2) ,(0,2, 3), (0, 3, 4), (0, 4, 5)。 图 10 2.4.7.3Triangle 几何对象 Triangle 由三个点所确定如下图,一个 Triangle 可定义为(0,1,2)等。 图 11 2.4.7.4Ring 几何对象 Ring 和前边介绍的组成 Polygon 的 Ring 一样,例如下边一个房屋组成它的墙 是个 OutRing 对象,而窗户和门是 InnerRing 对象。 图 12 2.4.8Multipatch 几何对象 Multipatch 几何对象用于描述 3D 图形,可以由 TriangleStrip, TriangleFan, Triangle 和 ring 对象组合构成组成。Multipatch 可以通过多种方式创建,一种是 通过导入外部 3D 格式数据文件(3D Studio Max .3ds files, OpenFlight .flt files, COLLADA .dae files, Sketchup .skp files, VRML .wrl files),另外 ArcGIS Engine 提 供了多种创建 Multipatch 几何对象的方法: 如果创建没有贴图纹理,没有法向,没有组成部分信息的 Multipatch 时,只 需创建好组成的 Multipatch 的各个部分即可,然后通过 MultiPatch 的 IGeometryCollection 接口添加各个组成部分即可。 如果要为 Multipatch 每个组成部分添加纹理信息,法向信息,属性信息就必 须使用 GeneralMultiPatchCreator 对象来创建,通过其 IGeneralMultiPatchInfo 接 口来为 MultiPatch 各个组成部分定义法向,材质,属性信息。通过 IGeneralMultiPatchInfo 接口可以获取这些 MultiPatch 的各个组成部分的信息。 通过 IConstructMultiPatch 接口和 IExtrude 接口操作 GeometryEnvironment 对象可 以通过拉伸 Polyline 对象(拉伸为墙)和 Polygon 对象(拉伸为多面体)来创建 MultiPatch. 通过访问 3D 符号库,获取 3DSymbol 来渲染点,把三维符号放置在点的位 置从而生成 Multipatch. 下图为 MultiPatch 对象的贴图原理: 图 13 接下来给大家介绍通过 GeneralMultiPatchCreator 创建一个有纹理 MultiPatch 的方法:需要使用以下三个对象: GeometryMaterial:用于构建材质,通过 IGeometryMaterial 创建的材质可以作 为 TextureLineSymbol 或者 TextureFillSymbol 属性用来创建这些符号,也可以把 它添加到 GeometryMaterialList 对象中,用于 GeneralMultipatchCreator 对象构建 Multipatch 对象。 GeometryMaterialList:材质对象的容器用于 GeneralMultiPatchCreator 对象调 用 Init 方法时使用。 GeneralMultiPatchCreator:用于创建有纹理的贴图的 Multipatch.。 以下代码片段演示如何创建一个 MultiPatch 对象 /// ///构建 Multipatch 几何对象 /// ///返回 Multipatch 几何对象 public IMultiPatch CreateMultipatch() { try { //创建图形材质对象 IGeometryMaterial texture = new GeometryMaterialClass(); texture.TextureImage = @"C:\Temp\MyImage.jpg"; //创建材质列表对象 IGeometryMaterialList materialList = new GeometryMaterialListClass(); //向材质列表添加材质 materialList.AddMaterial(texture); //创建 GeneralMultiPatchCreator 对象 IGeneralMultiPatchCreator multiPatchCreator = new GeneralMultiPatchCreatorClass(); multiPatchCreator.Init(4, 1, false, false, false, 4, materialList); //设置 Part:可以使三角扇或环 multiPatchCreator.SetPatchType(0, esriPatchType.esriPatchTypeTriangleStrip); multiPatchCreator.SetMaterialIndex(0, 0); multiPatchCreator.SetPatchPointIndex(0, 0); multiPatchCreator.SetPatchTexturePointIndex(0, 0); //创建真实 points. WKSPointZ upperLeft = new WKSPointZ(); WKSPointZ lowerLeft = new WKSPointZ(); WKSPointZ upperRight = new WKSPointZ(); WKSPointZ lowerRight = new WKSPointZ(); upperLeft.X = 0; upperLeft.Y = 0; upperLeft.Z = 0; upperRight.X = 300; upperRight.Y = 0; upperRight.Z = 0; lowerLeft.X = 0; lowerLeft.Y = 0; lowerLeft.Z = -100; lowerRight.X = 300; lowerRight.Y = 1; lowerRight.Z = -100; multiPatchCreator.SetWKSPointZ(0, ref upperRight); multiPatchCreator.SetWKSPointZ(1, ref lowerRight); multiPatchCreator.SetWKSPointZ(2, ref upperLeft); multiPatchCreator.SetWKSPointZ(3, ref lowerLeft); //设置贴图的点 WKSPoint textureUpperLeft = new WKSPoint(); WKSPoint textureLowerLeft = new WKSPoint(); WKSPoint textureUpperRight = new WKSPoint(); WKSPoint textureLowerRight = new WKSPoint(); textureUpperLeft.X = 0; textureUpperLeft.Y = 0; textureUpperRight.X = 1; textureUpperRight.Y = 0; textureLowerLeft.X = 0; textureLowerLeft.Y = 1; textureLowerRight.X = 1; textureLowerRight.Y = 1; multiPatchCreator.SetTextureWKSPoint(0, ref textureUpperRight); multiPatchCreator.SetTextureWKSPoint(1, ref textureLowerRight); multiPatchCreator.SetTextureWKSPoint(2, ref textureUpperLeft); multiPatchCreator.SetTextureWKSPoint(3, ref textureLowerLeft); //创建 MultiPatch 对象 IMultiPatch multiPatch = multiPatchCreator.CreateMultiPatch() as IMultiPatch; return multiPatch; } catch (Exception Err) { MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } 2.4.9Geometry 集合接口 通过前边对于具体的 Geometry 对象的介绍可知,除了 Point 对象之外,其 他几何对象都是通过其他几何对象集合构建而成。如 MultiPoint 对象是点的集 合,Path 对象是 Segment 对象的集合,Polyline 对象是 Path 对象的集合,Polygon 对象是 Ring 对象的集合,Multipatch 对象是 Triangle Strip 和 Trangle Fan, Trangle,Ring 对象的集合。 ArcGIS Engine 提供了三个主要的几何图形集合接口用于对几何对象的操 作,分别是 IPointCollection,ISegmentCollection 和 IGeometryCollection,这些接 口揭示出 ArcGIS Engine 的几何模型的实质——它们是一种组合构成的模式,这 种组合并不一定按照严格的层次结构组织。 在前面介绍一些几何对象的时候,也给大家演示了部分使用功能,这三个接 口在程序开发中经常使用到,接下来简单阐述以下这三个接口的使用方法。 2.4.9.1IGeometryCollection 接口 IGeometryCollection 接口被 Polygon,Polyline, Multipoint, Multipatch, Trangle,T rangle Strip,Trangle Fan 和 GeometryBag 所实现。IGeometryCollection 接口提供的方法可以让开发者对一个几何对象的组成元素即子对象进行添加,改 变和移除。例如: 组成 Polyline 对象的子对象是 Path 对象。 组成 Polygon 对象的子对象是 Ring 对象。 组成 Multipoint 对象的子对象是 Point 对象。 组成 MultiPatch 对象的子对象是 TrangleFan TrangleStrip,Triangle 或 Ring 对 象。 组成 GeometryBag 对象的是任何类型的几何体对象,实际上 GeometryBag 是一个可以容纳任何类型几何对象的容器。 IGeometryCollection 的 Geometry 属性可以通过一个索引值返回一个组成该 几何对象的某个子对象,而 GeometryCount 返回组成该几何对象的子对象的数 目。 IGeometry 的 AddGeometry 和 AddGeometries 方法都用于向一个几何对象添 加子对象,它们的区别是前者一次只能添加一个几何对象,而后者可以一次添加 一个几何对象数组。除此之外,AddGeometry 方法可以将子对象添加到几何的指 定索引值的位置,而 AddGeometries 方法将子对象数组添加到集合的最后。 在使用 AddGeometry 方法添加子对象到 Polygon 对象的过程中,如果子对象即 Ring出现覆盖现象,那么多边形就没有封闭或出现了包含关系,那么这个Polygon 就不是简单 Polygon,因此通过 IGometryCollection 来创建一个 Polygon 时,需要 使用 ITopologicalOperator 的 Simplify 方法保证其有效性。 通过 IGeometryCollection 创建一个 Polygon 对象的代码片段如下: /// /// 构造 Polygon 对象 /// /// Ring 对象集合 /// 返回一个 Polygon 对象 private IPolygon ConstructorPolygon(List pRingList) { try { //创建一个 Polygon 对象 IGeometryCollection pGCollection = new PolygonClass(); object o = Type.Missing; //遍历 Ring 集合 for(int i=0;i /// 合并两个 Polygon /// /// 第一个 Polygon /// 第二个 Polygon /// 返回合并后的 Polygon 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) { MessageBox.Show(Err.Message," 提示 ",MessageBoxButtons.OK,,MessageBoxIcon.Information); return null; } } 2.4.9.2ISegmentCollection 接口 ISegmentCollection 接口被 Path,Ring,Polyline 和 Polygon 四个类所实现,它 们被称作是 Segment 集合对象,使用这个接口可以处理组成 Segment 集合对象中 的每一个子 Segment 对象。使用 ISegmentCollection 接口可以为一个 Segment 集 合对象添加,插入,删除 Segment 子对象。ISegmentCollection 接口 SetCircle 和 SetRectangle 方法提供了一种简单不需要添加 Segment 的情况下构建一个完成的 Path,Ring,Polyline 和 Polygon 的方法。 2.4.9.3IPointCollection 接口 IPointCollection 可以被多个几何对象类所实现,这些对象都是由多个点构成如: Mullipoint,Path,Ring,Polyline,Polygon,TriangleFan,TrangleStrip,Trangle,Multipatch 等,它们都可以称作 PointCollection 对象,通过 IPointCollection 接口定义的方法 可以获取,添加,插入,查询,移除几何对象中的某个顶点。同以上两个接口一 样它也定义了操作一个点集合对象的方法,例如通过 AddPoint 方法可以向 PointCollection 对象中的特定索引位添加一个点对象,如果不指定位置,则添加 到最后。通过 IPointCollection 的 Point 属性通过顶点索引可以得到某一顶点。 在本章节最后的 Demo 实例将为大家演示 IPointCollection 提供的功能。 2.4.10 几何对象总结 在 Geometry 模型中的几何对象分为两种类型,一类是用来直接构建要素类 的称为高级几何对象,一类用来构建高级几何对象相对低一级的几何对象成为构 建几何对象如下表所示: 几何对象名 称 所属类别 构成子几何对象 用于创建和编辑的接口 Polyline 高级 Path IGeometryCollection, IPointCollection Polygon 高级 Ring IGeometryCollection, IPointCollection MultiPoint 高级 Point IGeometryCollection, IPointCollection MultiPatch 高级 TrangleFan,Ring TrangleStrip ,Trangle, IGeometryCollection, IPointCollection Ring 低级 Segment ISegmentCollection, IPointCollection Path 低级 Segment ISegmentCollection, IPointCollection Segment 低级 Point IPoint,ILine, ICurve TriangleFan 低级 Point IGeometryCollection, IPointCollection TriangleStrip 低级 Point IGeometryCollection, IPointCollection Triangle 低级 Point IGeometryCollection, IPointCollection Point 高级/低级 无 IPoint 2.5 空间参考 2.5.1 空间参考简介 空间参考(Spatial Reference)是 GIS 数据的骨骼框架,能够将我们的数据 定位到相应的位置,为地图中的每一点提供准确的坐标。 在同一个地图上显示 的地图数据的空间参考必须是一致的,如果两个图层的空间参考不一致,往往会 导致两幅地图无法正确拼合,因此开发一个 GIS 系统时,为数据选择正确的空 间参考非常重要。 ArcGIS Engine 提供了一系列对象供开发者管理 GIS 系统的坐标系统。对大 部分开发者而言了解 ProjectedCoordinateSystem, GeographicCoordinateSystem, SpatialReference Environment 这三个组件类是非常有必要的,对于高级开发者而 言,可能需要自定义坐标系统可以使用这些对象 Projection,Datum,AngularUnit,Spheriod,PrimeMeridian 和 GeoTransformation 等。 2.5.2 修改空间参考 以下代码片段演示了如何改变一个图层的空间参考。 /// /// 改变图层的空间参考 /// /// 图层 /// 空间参考类型 private void ChangeLayerRef(IFeatureLayer pFeatureLayer, int gcsType) { try { IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass; //QI 到 IGeoDataset IGeoDataset pGeoDataset = pFeatureClass as IGeoDataset; //QI 到 IGeoDatasetSchemaEdit IGeoDatasetSchemaEdit pGeoDatasetSchemaEdit = pGeoDataset as IGeoDatasetSchemaEdit; if (pGeoDatasetSchemaEdit.CanAlterSpatialReference == true) { //创建 SpatialReferenceEnvironmentClass 对象 ISpatialReferenceFactory2 pSpaRefFactory = new SpatialReferenceEnvironmentClass(); //创建地理坐标系对象 IGeographicCoordinateSystem pNewGeoSys = pSpaRefFactory.CreateGeographicCoordinateSystem(gcsType);//4214 代表 Beijing1954 pGeoDatasetSchemaEdit.AlterSpatialReference(pNewGeoSys); } } catch (Exception Err) { MessageBox.Show(Err.Message, " 提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } 2.6 开发野外测量点构建一个 Polygon 几何要素程序 2.6.1 功能情景描述 现有一存储为*.txt 格式文本文件存储野外测量几个建筑物的坐标信息,如图 所示,我们需要通过开发一个功能能够读取这些这些坐标信息并根据坐标点建筑 物属性来构建建筑物,并创建成一个 ShapeFile 加载到 MapControl 上。 步骤一:添加一个 Form,并添加 4 个 Button,2 个标签,2 个文本框如下图所示: 2.6.2 功能开发代码 private AxMapControl buddyMap; /// /// 关联地图控件 /// public AxMapControl BuddyMap { get { return buddyMap; } set { buddyMap = value; } } /// /// 要保存的 ShapeFile 全路径名称 /// string shapeFileFullName = string.Empty; /// /// 测量数据全路径名称 /// string surveyDataFullName = string.Empty; List pColumns = new List(); List pCPointList = new List(); struct CPoint { public double x; public double y; public string name; } private void OpenBtn_Click(object sender, EventArgs e) { OpenFileDialog pOFD = new OpenFileDialog(); pOFD.Multiselect = false; pOFD.Title = "打开本地测量坐标文件"; pOFD.InitialDirectory = System.IO.Directory.GetCurrentDirectory(); pOFD.Filter = "测量坐标文件(*.TXT)|*.TXT"; if (pOFD.ShowDialog() == DialogResult.OK) { surveyDataFullName = pOFD.FileName; this.textBox1.Text = surveyDataFullName; } } private void Savebtn_Click(object sender, EventArgs e) { SaveFileDialog saveFileDialog = new SaveFileDialog(); saveFileDialog.Filter = "Shape 文件(*.shp) |*.shp"; DialogResult dialogResult = saveFileDialog.ShowDialog(); if (dialogResult == DialogResult.OK) { shapeFileFullName = saveFileDialog.FileName; } else { shapeFileFullName = null; return; } this.textBox2.Text = shapeFileFullName; } /// /// 获取点数据 /// /// 测量数据全路径名称 /// private List GetAllPoint(string surveyDataFullName) { try { List pList = new List(); if (surveyDataFullName == null || surveyDataFullName == string.Empty) { MessageBox.Show("选择野外测量数据"); return null; } if (!System.IO.File.Exists(surveyDataFullName)) { MessageBox.Show("野外测量数据不存在!"); return null; } string strLine; char[] charArray = new char[] {','}; string[] strArray; System.IO.FileStream aFile = new System.IO.FileStream(surveyDataFullName, FileMode.Open); StreamReader sr = new StreamReader(aFile,Encoding.Default); strLine = sr.ReadLine(); strArray = strLine.Split(charArray); if (strArray.Length > 0) { for (int x = 0; x < strArray.Length; x++) { pColumns.Add(strArray[x]); } } else { return null; } strLine = sr.ReadLine(); while (strLine != null) { strArray = strLine.Split(charArray); CPoint pCPoint= new CPoint(); pCPoint.x = Convert.ToDouble(strArray[0]); pCPoint.y = Convert.ToDouble(strArray[1]); pCPoint.name = strArray[2].Trim(); pList.Add(pCPoint); strLine = sr.ReadLine(); } sr.Close(); return pList; } catch (Exception Err) { MessageBox.Show(Err.Message); return null; } } private IFeatureLayer CreateShpFromPoints(string outfileNamePath) { int index = outfileNamePath.LastIndexOf('\\'); string folder = outfileNamePath.Substring(0, index); shapeFileFullName = outfileNamePath.Substring(index + 1); IWorkspaceFactory pWSF = new ShapefileWorkspaceFactoryClass(); IFeatureWorkspace pFWS = (IFeatureWorkspace)pWSF.OpenFromFile(folder, 0); //如果 shapefile 存在替换它 if (File.Exists(outfileNamePath)) { IFeatureClass featureClass = pFWS.OpenFeatureClass(shapeFileFullName); IDataset pDataset = (IDataset)featureClass; pDataset.Delete(); } IFields pFields = new FieldsClass(); IFieldsEdit pFieldsEdit; pFieldsEdit = (IFieldsEdit)pFields; IField pField = new FieldClass(); IFieldEdit pFieldEdit = (IFieldEdit)pField; pFieldEdit.Name_2 = "Shape"; pFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry; IGeometryDef pGeometryDef = new GeometryDefClass(); IGeometryDefEdit pGDefEdit = (IGeometryDefEdit)pGeometryDef; pGDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolygon; pFieldEdit.GeometryDef_2 = pGeometryDef; pFieldsEdit.AddField(pField); pField = new FieldClass(); pFieldEdit = (IFieldEdit)pField; pFieldEdit.Length_2 = 20; pFieldEdit.Name_2 = pColumns[2]; pFieldEdit.Type_2 = esriFieldType.esriFieldTypeString; pFieldsEdit.AddField(pField); IFeatureClass pFeatureClass; pFeatureClass = pFWS.CreateFeatureClass(shapeFileFullName, pFields, null, null, esriFeatureType.esriFTSimple, "Shape", ""); List pBuildingList = new List(); for(int i=0;i0) { IClone pClone = pPointColl.get_Point(0) as IClone; IPoint pEndPoint = pClone.Clone() as IPoint; pPointColl.AddPoint(pEndPoint, ref o, ref o); } IFeature pFeature = pFeatureClass.CreateFeature(); pFeature.Shape = pPointColl as IPolygon; pFeature.Store(); pFeature.set_Value(pFeature.Fields.FindField(pColumns[2]), pBuildingList.Trim()); pFeature.Store(); } IFeatureLayer pFeaturelayer = new FeatureLayerClass(); pFeaturelayer.FeatureClass = pFeatureClass; return pFeaturelayer; } private void Createbtn_Click(object sender, EventArgs e) { pCPointList = this.GetAllPoint(surveyDataFullName); IFeatureLayer pFeatureLayer = CreateShpFromPoints(shapeFileFullName); pFeatureLayer.Name = "建筑物"; this.buddyMap.Map.AddLayer(pFeatureLayer); } 2.6.3 运行程序 点击打开按钮加载自造的“建筑物测量.txt 数据,点击”保存”按钮选择创建的 Shapefile 路径和名称,如图所示,点击创建按钮运行程序如图所示。通过文本坐 标创建为三个 Polygon 对象如图所示。 2.6.4 Demo 总结 在本 Demo 中大家学习了如下主要内容: 1. 通过 IWorkspaceFactory 接口和 IFeatureWorkspace 以及 Shapefile WorkspaceFactory 对象创建一个存储在硬盘上的 Shapefile 文件。 2.通过 IFields , IFieldsEdit,IField 等接口为创建的 ShapeFile 创建属性字段 3.通过 IGeometryDef 和 IGeometryDefEdit 接口为 ShapeFile 创建图形类型 4.通过 IPointCollection 来构建 Polygon 对象。 3.学习地图和地图布局 本章是 ArcGIS Engine 基础开发教程的第三章,主要给大家大致讲解了,地 图和地图布局的相关对象。这些对象非常重要,如果这些基本对象都不熟悉就开 始搞 ArcGIS Engine 开发是不科学的也走不远的。 3.1 地图 3.1.1Map 对象 Map 对象是 ArcGIS Engine 的主要对象,本章将给大家介绍地图组成结构, 如何创建地图,如何对组成地图的对象进行操作,在介绍这些内容时尽量结合 ArcMap 学习效果会更好。 在 Map 对象上能显示的图形有两类一类是地理数据,一类是元素。地理数 据包括矢量类型的要素数据,栅格数据,Tin 等表面数据等,这些数据都保存在 Geodatabase 或数据文件如 shapefile 中,它们是用于 GIS 分析制图的源数据; 图1 而元素是另一种可以显示在 Map 上的对象,它分为两部分一类是图形元素,一 类是框架元素,图形元素可以显示出来,而框架元素充当了“容器”的角色。在 ArcMap 中可以使用“Draw”工具在 Map 上直接绘制一个矩形,圆形,文本等对象, 在布局视图上也可以给地图添加指北针,图例,比例尺等图形对象,这些都是图 形元素。 图2 在 ArcMap 中 Map 对象是由 MXDocument 对象的 MapFrame 对象管理, MapFrame 是一个框架元素。 Map 对象有双重身份,一方面是数据的管理容器,可以加载地理数据和图形 元素,扮演了数据管理器的角色,另一方面它又可以让用户看到这些数据即扮演 了数据显示器的角色,当加载数据到 Map 对象的时候,Map 对象是数据的管理 者;当改变视图范围,刷新地图的时候它是数据的显示者。 Map 对象主要实现的接口由 IMap, IGraphicContainer, IActiveView, IMapBookmarks 等接口。 IMap 接口主要用于管理 Map 对象中的 Layer 对象,要素选择集对象, MapSourround 对象,空间参考等对象。 Map 对象可以显示图形元素(Graphics Element),Map 对象通过 IGraphicsContainer 接口来管理这些元素对象,包括图形元素和框架元素。 IGraphicsContainer 返回的是 Map 对象中处于活动状态的 Graphics layer 引用指 针,它可以是一个 Basicgraphicslayer,也可以是 CompositeGraphicsLayer 中的一个 图层,或者是一个 FDOGraphicsLayer 注记图层。 以下代码片段演示如何添加一个 Element 到 Map 上: /// ///添加临时元素到地图窗口上 /// ///地图控件 ///单个元素 ///元素集合 public static void AddTempElement(AxMapControl pMapCtrl, IElement pEle, IElementCollection pEleColl) { try { IMap pMap = pMapCtrl.Map; IGraphicsContainer pGCs = pMap as IGraphicsContainer; if (pEle != null) pGCs.AddElement(pEle, 0); if (pEleColl != null) if (pEleColl.Count > 0) pGCs.AddElements(pEleColl, 0); IActiveView pAV = (IActiveView)pMap; //需要刷新才能即时显示 pAV.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, pAV.Extent); } catch (Exception Err) { MessageBox.Show(Err.Message, " 提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } IActiveView 接口定义了 Map 对象的数据显示功能。使用该接口可以改变视图的 范围,刷新视图。 IActiveView 的 PartialRefresh(esriViewGeography, pLayer, null)用于刷新指定图层: IActiveView 的 PartialRefresh(esriViewGeography, null, null) 用于刷新刷新所有图 层: IActiveView 的 PartialRefresh(esriViewGeoSelection, null, null) 用于刷新所选择的 对象: IActiveView 的 PartialRefresh(esriViewGraphics, null, null) 用于刷新图形元素: IActiveView 的 PartialRefresh(esriViewGraphics, pElement, null) 用于刷新指定图 形元素 IActiveView 的 PartialRefresh(esriViewGraphics, null, null) 用于刷新所有图形元素 IActiveView 的 PartialRefresh(esriViewGraphicSelection, null, null)用于刷新所选择 的图元。 IMapBookmark 接口用于管理所有的空间书签对象。 3.1.2 图层对象 Map 对象可以装载地理数据,这些数据是以图层的形式加载到地图对象上 的,图层对象 Layer 作为一个数据的“中介”存在,它本身没有转载地理数据,而 仅仅是获得了数据的引用,用于管理数据源的连接。地理数据始终保存在 Geodatabase 或者地理数据文件中。 由于地理数据的类型多样,所以 Layer 类也拥有众多子类(具体查看帮助), 接下来主要给大家介绍要素图层—FeatureLayer 对象。 3.1.3FeatureLayer 对象 FeatureLayer 类实现的常用主要接口如下图所示: IFeatureLayer,IFeatureLayerDefinition,FeatureSelection,IGeoDataset,IGeoFeatureLa yer,IIdentify,ILayerEffects。 图3 IFeatureLayer 接口主要用于设置要素图层的数据源(FeatureClass) , IFeatureLayer 的 DataSourceType 获取 FeatureLayer 对象的数据源类型。此外通过 IFeatureLayer 的 Search 方法可以查询要素图层上符号某一条件的要素集。 IGeoFeatureLayer 接口继承了 ILayer 和 IFeatureLayer 两个接口,用于控制要 素图层的符号化和标注等。 IGeoDataset 接口仅有两个属性,它们用于管理地理要素集。Extent 可以返回 当前数据集的范围,是一个 IEnvelope 类型的对象; SpatialReference 属性则可以让用户获得这个数据集的空间参考。 IFeatureSelection 接口提供管理一个图层中的要素的选择集的方法和属性。 以下代码片段演示如何获取要素图层符合条件获取选择集 /// /// /// 获取要素图层符合条件获取选择集 /// /// 要素图层 /// 过滤条件 /// 返回选择集 private IFeatureSelection SelectLayersFeatures(IFeatureLayer pFeatureLayer, string WhereClause) { IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection; if (pFeatureSelection == null) return null; IQueryFilter pQueryFilter = new QueryFilterClass(); pQueryFilter.WhereClause = WhereClause; pFeatureSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultNew, false); return pFeatureSelection; } IFeatureLayerDefinition 接口定义了 CreateSelectionLayer 方法,可以将一个 图层选择集中的要素转换为一个单独的要素图层。 3.1.4 矢量图层操作实例 以下代码片段演示按行政区加载图层数据的功能,以此理解 IFeatureLayerDefinition 的 CreateSelectionLayer 方法的使用。 比方说整个国土资源部有某一类型专题数据有若干图层,每个图层数据的范 围是整个中国,这时国土资源部开发一套系统可能有这个需求,每个省只能加载 本省的数据。以下函数即为按按行政区范围创建行政区范围的图层。 比方说我想获取河南省的数据只需传入行政区图层中河南省图元的 Geometry 即可。另外如果如果遇到行政区层必须用 esriSpatialRelEnum. esriSpatialRelContains 这个参数,否则行政区这个图层就不能只获取河南这个省 份,它会把河南省的周围省份,河北,湖北,安徽,陕西,山东,山西等省份的 图元也添加创建到新图层。 /// /// 按行政区范围创建行政区范围的图层 /// /// 源数据图层 /// 行政区范围 /// 图层是否为行政区 /// 新创建的图层 private IFeatureLayer GetSelectionLayer(IFeatureLayer pFeatureLayer, IGeometry pGeometry,bool bXZQ) { try { if (pFeatureLayer != null && pGeometry != null) { IQueryFilter pQueryFilter; ISpatialFilter pSpatialFilter = new SpatialFilterClass(); IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection; pSpatialFilter.GeometryField = pFeatureLayer.FeatureClass.ShapeFieldName; pFeatureSelection.Clear(); if (!bXZQ) { pSpatialFilter.Geometry = pGeometry; pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; pQueryFilter = pSpatialFilter; pFeatureSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultNew, false); } else { pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains; pQueryFilter = pSpatialFilter; if(pGeometry is IGeometryCollection) { for (int i = 0; i < (pGeometry as IGeometryCollection).GeometryCount; i++) { pSpatialFilter.Geometry = (pGeometry as IGeometryCollection).get_Geometry(i); pFeatureSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultAdd, false); } } } IFeatureLayerDefinition pFLDefinition = pFeatureLayer as IFeatureLayerDefinition; IFeatureLayer pNewFeatureLayer = pFLDefinition.CreateSelectionLayer(pFeatureLayer.Name ,true, null, null); pNewFeatureLayer.MaximumScale = pFeatureLayer.MaximumScale; pNewFeatureLayer.MinimumScale = pFeatureLayer.MinimumScale; pNewFeatureLayer.Selectable = pFeatureLayer.Selectable; pNewFeatureLayer.Visible = pFeatureLayer.Visible; pNewFeatureLayer.ScaleSymbols = pFeatureLayer.ScaleSymbols; return pNewFeatureLayer; } else { return null; } } catch (Exception Err) { MessageBox.Show(Err.Message, " 获取 SelectionLayer", MessageBoxButtons.OK, MessageBoxIcon.Information); return null; } } IIdentify 接口定义了获得要素图层单个要素的属性的 ILayerFields 接口可以直接获取一个要素图层的要素类字段集合 ILayerEffects 接口用来设置一个要素图层的透明度,对比度,对比度。以下 代码片段演示如何设置要素图层特效: /// /// 设置图层特效 /// /// 要素图层 /// 亮度 /// 对比度 /// 透明度 private static void SetLayerEffects(IFeatureLayer pFeatureLayer, short brightness, short contrast, short transparency) { ILayerEffects pLayerEffect = pFeatureLayer as ILayerEffects; pLayerEffect.Brightness = brightness; pLayerEffect.Contrast = contrast; pLayerEffect.Transparency = transparency; } 3.2 地图布局 3.2.1PageLayout 对象 PageLayout 用以显示地图数据,并通过对地图数据进行整饰以便对地图打印 输出满足不同行业对 GIS 出图功能的需求。PageLayout 和 Map 这两个对象看起 来非常相似,它们都是视图对象,可以显示地图;也都是图形元素的容器,可以 容纳图形元素(Graphics Element)。但是所能够保存的图形类型却是有差别的。 PageLayout 除了保存图形元素外,还可以保存诸如 MapFrame 的框架元素(Frame Element)。PageLayout 控件上的 Map 对象被 PageLayout 的 MapFrame 对象所管 理的。 PageLayout 类主要实现了 IPageLayout 接口,它定义了用于修改页面版式 (layout)的方法和属性。 IPageLayout 的方法 ZoomToWhole 方法可以让 PageLayout 以最大尺寸显示; IPageLayout 的 ZoomToPercent 方法可以按照输入的比例显示; IPageLayout 的 ZoomToWidth 方法可以让视图显示的范围匹配控件对象的宽 度。 IPageLayout 的 Page 属性用以获取 Page 对象 IPageLayout 的 RulerSettings 属性用以获取 RulerSettings 对象 IPageLayout 的 HorizontalSnapGuides 和 VerticalSnapGuides 属性用以获取 SnapGuides 对象 如下图所示: 图4 3.2.2Page 对象 Page对象主要来管理 PageLayout 对象中的页面,它用来加载地理数据,但 不提供分析和查询功能。Page 类的主要接口是 IPage,它除了用于管理 Page 的颜 色,尺寸和方向,还可以管理边框类型和打印区域等。例如通过 IPage 的 FromID 可以直接设置纸张大小类型(A4,A3 等)。 3.2.3SnapGrid 对象 SnapGrid 是 PageLayout 上用于摆放元素而设置的辅助点如图所示,这些点 有规则呈网状排列,便于使用者对其元素,它可以直接通过 IPageLayout 的 SnapGrid 属性获得当前 PageLayout 使用的 SnapGrid 对象的引用。 SnapGrid 类主要实现了 ISnapGrid 接口用于设置 SnapGrid 对象的属性, ISnapGrid 的 HorizontalSpacing 和 VerticalSpacing 属性用于设置网点之间的水平 距离和垂直距离,ISnapGrid 的 Visible 属性决定了这些网点是否可见,Draw 方 法将用于在 Page 对象上绘制一个 SnapGrid 对象。 以下代码片段演示如何在设置 PageLayout 控件上 SnapGrid: /// /// 设置 PageLayout 上 SnapGrid /// /// PangeLayout 对象 private void SetwSnapGridOnPageLayout(IPageLayout pPageLayout) { if(pPageLayout !=null) { ISnapGrid pSnapGrid=pPageLayout.SnapGrid; pSnapGrid.VerticalSpacing =2; pSnapGrid.HorizontalSpacing =2; pSnapGrid.IsVisible =true; IActiveView pActiveView=pPageLayout as IActiveView; pActiveView.Refresh(); } } 3.2.4SnapGuides 对象 SnapGuides 是为了更好的放置地图而在 Pagelayout 上设置的辅助线如图所 示,SnapGuides 分为两种类型一种是水平辅助线通过 IPageLayout 的 HorizontalSnapGuides 属性获得,另一种是垂直辅助线通过 IPageLayout 的 VerticalSnapGuides 属性获得。每个 SnapGuides 都管理着一个 Guide 集合,即不 同的类型的辅助线可以同时存在多条。 SnapGuides 都实现了 ISnapGuides 接口,它定义了管理 SnapGuide 的属性和 方法。 ISnapGuides 的 AreVisible 设定 SnapGuides 是否可见。 ISnapGuides 的 GuideCount 属性返回一个 SnapGuides 对象中的 Guide 的个 数。而使用 ISnapGuides 的 Guide 属性可以按索引值获得某个具体的 Guide 对象。 ISnapGuides 的 AddGuide 方法将一个 Guide 放在指定位置上。 ISnapGuides 的 RemoveAllGuides 和 RemoveGuide 方法分别可以清楚所有的 Guide 和按索引值清除 Guide. 以下代码片段演示如何为 PageLayout 对象添加辅助线: /// /// 向 PageLayout 上指定位置添加辅助线 /// /// PageLayout 对象 /// 位置 /// true 为水平方向辅助线,False 为垂直方 向辅助线 private void AddGuideOnPageLayout(IPageLayout pPageLayout,double pPoistion,bool bHorizontal) { try { if(pPageLayout !=null) { ISnapGuides pSnapGuides=null; //如果是水平辅助线 if(bHorizontal) { pSnapGuides=pPageLayout.HorizontalSnapGuides; } //如果是垂直辅助线 else { pSnapGuides=pPageLayout.VerticalSnapGuides; } if(pSnapGuides!=null) { //向 PageLayout 上添加辅助线 pSnapGuides.AddGuide(pPoistion); } } } catch(Exception Err) { MessageBox.Show(Err.Message,"提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } 3.2.5RulerSettings 对象 标尺对象是为了辅助图形元素的放置而出现在 PageLayout 对象上方和左方 的辅助尺如图所示,通过 IPageLayout 的 RulerSettings 属性可以获得 PageLayout 上的 RulerSettings 对象. RulerSettings 对象主要实现了 IRulerSettings 接口它只有一个 SmallestDivision 属性用于设置 RulerSettings 对象的最小刻度值属性。 3.2.6Element 对象 在 Map 对象和 PageLayout 对象显示的数据除了地理数据之外,另一种即为 元素数据如下图5所示。 图5 Element 是一个非常庞大复杂的对象集合如图 6 所示,它主要分为两大部分: 图形元素(GraphicElement)和框架元素(Frame Element)。 图形元素(GraphicElement) 包 LineElement, MarkerElement, TextElement, GroupElement, FillshapElement,PictureElement,MultiPatchElement 等。它们都是作 为图形的形式而存在,在地图视图或者 PageLayout 视图上时可见的。框架元素 (Frame Element)包括 MapFrameElement, MapSurroundElement 等它们是作为不 可见的容器而存在的。 Map 对象或者 PageLayout 对象可以通过 IGraphicsContainer 接口来管理这些 元素,使用 IGraphicsContainer 接口可以添加,删除和更新位于 Map 或 PageLayout 上的元素。使用 GroupElement 对象还可以将多个元素编组为单个实体来给用户 使用。 IElement 是所有图形元素(GraphicElement)和框架元素(Frame Element)都实 现的接口,通过 IElement 接口可以确定 Element 对象的 Geometry 属性,同时 IElment 接口也提供了用于查找和绘制元素的方法。Element 是个抽象类,在开发 中必须明确指定使用的 Element 的类型。另外 IElement 和 ILineElement, ITextElement 等并不是父子关系,后者没有 Geometry 属性。 图6 3.2.7MapGrid 对象 MapGrid 是布局视图中的一系列参考线和参考点用来帮助地图使用者快速 地确定地图要素的位置如图 7 中的公里格网,MapGridBorder,MapGridLabel。 MapGrid 等。MapGrid 对象由 MapGrids 来管理,一个 MapGrids 可以包含多个 MapGrid 对象。 图7 MapGrid 是一个抽象类,它的子类有 MeasuredGrid,IndexGrid,MgrsGrid,Graticule 和 CustomOverlayGrid 五种,这些子 类的对象由 MapGridFactory 对象创建。MapGride 对象模型图如图8和图9所示 图8 图9 /// /// 为 PageLayout 对象添加格网对象 /// /// private void AddMeasuredGridToPageLayout(IPageLayout pPageLayout) { try { //获取 MapFrame 对象 IActiveView pAcitiveView= pPageLayout as IActiveView; IMap pMap = pAcitiveView.FocusMap; IGraphicsContainer pGraphicsContainer=pAcitiveView as IGraphicsContainer; IMapFrame pMapFrame = pGraphicsContainer.FindFrame(pMap) as IMapFrame; IMapGrids pMapGrids = pMapFrame as IMapGrids; //创建一个 MeasuredGrid 对象 IMeasuredGrid pMeasureGrid = new MeasuredGridClass(); IMapGrid pMapGrid = pMeasureGrid as IMapGrid; pMeasureGrid.FixedOrigin = true; pMeasureGrid.Units = pMap.MapUnits; pMeasureGrid.XIntervalSize = 1000; pMeasureGrid.YIntervalSize = 1000; pMeasureGrid.XOrigin = -180; pMeasureGrid.YOrigin = -90; //设置 MeasuredGride 投影属性 IProjectedGrid pProGrid = pMeasureGrid as IProjectedGrid; pProGrid.SpatialReference = pMap.SpatialReference; pMapGrid.Name = "Measured Grid"; //创建一个 CalibratedMapGridBorder 对象并设置为 pMapGrid 的 Border 属性 ICalibratedMapGridBorder pCalibratedBorder = new CalibratedMapGridBorderClass(); pCalibratedBorder.BackgroundColor = GetRgbColor(255, 255, 255); pCalibratedBorder.ForegroundColor = GetRgbColor(0, 0, 0); pCalibratedBorder.BorderWidth = 0.1; pCalibratedBorder.Interval = 72; pCalibratedBorder.Alternating = true; pMapGrid.Border = pCalibratedBorder as IMapGridBorder; //创建一个 FormattedGridLabel 对象 IFormattedGridLabel pFormattedGridLabel = new FormattedGridLabelClass(); IGridLabel pGridLabel = pFormattedGridLabel as IGridLabel; stdole.StdFont pFont = new stdole.StdFont(); pFont.Name = "Arial"; pFont.Size = 6; pGridLabel.Font = pFont as stdole.IFontDisp; ; pGridLabel.Color = GetRgbColor(0, 0, 0); pGridLabel.LabelOffset = 4; pGridLabel.set_LabelAlignment(esriGridAxisEnum.esriGridAxisLeft, false); pGridLabel.set_LabelAlignment(esriGridAxisEnum.esriGridAxisRight, false); INumericFormat pNumericFormat = new NumericFormatClass(); pNumericFormat.AlignmentOption = esriNumericAlignmentEnum.esriAlignRight; pNumericFormat.RoundingOption = esriRoundingOptionEnum.esriRoundNumberOfSignificantDigits; pNumericFormat.RoundingValue = 0; pNumericFormat.ShowPlusSign = false; pNumericFormat.ZeroPad = true; pFormattedGridLabel.Format = pNumericFormat as INumberFormat; //设置 pMapGrid 的 LabelFormat 属性 pMapGrid.LabelFormat = pGridLabel; //添加格网 pMapGrids.AddMapGrid(pMapGrid); } catch(Exception Err) { MessageBox.Show(Err.Message," 提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } 3.2.8MapSurround 对象 MapSurround 对象是与一个地图对象关联的用于修饰地图的辅助图形元素 对象如图所示。它的形状或内容会随着 Map 属性的变化而自动改变。如 Map 视 图范围改变后比例尺(ScaleBar)也会自动调整比例,比例尺文本(ScaleBarText)也 会相应改变它的比例值。 MapSurround 对象由 MapSurroundFrame 对象管理,所有的 MapSurround 对 象添加在布局视图上,每一个 MapSurround 对象可以通过 IMap 接口的 MapSurrounds 属性的索引值所获取。也可以通过 IMap 接口的 MapSurroundCount 来遍历布局视图上的所有 MapSurround 对象。 所有的 MapSurround 对象都实现 IMapSurround 接口,使用 IMapSurround 接 口的 Name 属性可以获得 MapSurround 对象的名称,通过 IMapSurround 的 FitToBound 方法可以设置一个 MapSurround 对象的大小。 同时 MapSurround 类也实现了 IMapSurroundEvents 接口,可以用来触发 MapSounrround 相关事件如:AfterDraw,BeforeDraw,ContensChanged。 图 10 下图是 MapSurround 对象模型 图 11 如下代码演示如何为 PageLayout 添加 Legend: /// /// 为 PageLayout 对象添加图例对象 /// /// PageLayout 对象 /// 图例添加的位置 private void AddLegendToPageLayout(IPageLayout pPageLayout,IEnvelope pEnvelope) { try { IActiveView pActiveView=pPageLayout as IActiveView; IMap pMap = pActiveView.FocusMap; IGraphicsContainer pGraphicsContainer=pActiveView as IGraphicsContainer; IMapFrame pMapFrame = pGraphicsContainer.FindFrame(pMap) as IMapFrame; UID pUID = new UID(); pUID.Value = "{7A3F91E4-B9E3-11d1-8756-0000F8751720}"; ISymbolBackground pSymbolBackground = new SymbolBackgroundClass(); IFillSymbol pFillSymbol = new SimpleFillSymbolClass(); ILineSymbol pLineSymbol = new SimpleLineSymbolClass(); pFillSymbol.Color = GetRgbColor(255, 255, 255); pLineSymbol.Color = GetRgbColor(255, 255, 255); pFillSymbol.Outline = pLineSymbol; pSymbolBackground.FillSymbol = pFillSymbol; IMapSurroundFrame pMapSurroundFrame = pMapFrame.CreateSurroundFrame(pUID, null); pMapSurroundFrame.Background = pSymbolBackground; IElement pElement = pMapSurroundFrame as IElement; pElement.Geometry = pEnvelope; IMapSurround pMapSurround = pMapSurroundFrame.MapSurround; ILegend pLegend = pMapSurround as ILegend; pLegend.ClearItems(); pLegend.Title = "图例"; ITextSymbol pTextSymbol = new TextSymbolClass(); pTextSymbol.Size = 10; pTextSymbol.HorizontalAlignment = esriTextHorizontalAlignment.esriTHALeft; ILegendItem pLegendItem = null; for (int i = 0; i < pActiveView.FocusMap.LayerCount; i++) { ILayer pLayer = pActiveView.FocusMap.get_Layer(i); if (pLayer is IFeatureLayer) { IFeatureLayer pFLayer = pLayer as IFeatureLayer; IFeatureClass pFeatureClass = pFLayer.FeatureClass; if (pFeatureClass.FeatureType == esriFeatureType.esriFTAnnotation) { continue; } else { pLegendItem = new HorizontalLegendItemClass(); pLegendItem.Layer = pLayer; pLegendItem.Columns = 1; pLegendItem.ShowDescriptions = false; pLegendItem.ShowHeading = false; pLegendItem.ShowLabels = true; pLegendItem.LayerNameSymbol = pTextSymbol; pLegend.AddItem(pLegendItem); } } } } catch(Exception Err) { } } 结果如下图所示: 图 12 4.学习图层符号化 地图符号不仅具有确定的空间位置以及空间地物的性质:例如在一个城市管 线系统中不同的线符号表示不同类型的管线,不同的点符号表示不同类型的设备 等等,而且地图符号也可以表达与空间位置相关的丰富信息:例如人口密度符号 可以直观的表示人口数量的空间分布情况。所以地图数据的符号化决定着地图以 何种“面目”展现给地图的使用者,自此空间数据的符号化对 GIS 开发有非常重要 的意义。 ArcGIS Engine9.3 提供了丰富的控件和组件库来实现图层符号化的相关功 能。ArcGIS Engine9.3 提供了 SymbologyControl 控件用于显示 ArcGIS 符号库中 的符号(关于 ArcGIS 符号请查找相关文档),而组件库中的组件对象分为 Color , Symbol, Renderer 三大系列,图层符号化就是通过多个组件对象来合作完成。 4.1 目标 1.熟悉 ArcGIS Engine 符号化之 Color(颜色)体系 2.熟悉 ArcGIS Engine 符号化之 Symbol(符号)体系 3.熟悉 ArcGIS Engine 符号化之 Renderer( 渲染)体系 4.利用 ESRI 自带的符号库进行符号化图层 4.2 准备工作 1.IDE:Visual Studio 2005/2008 2.ArcGIS Engine Developer kit 9.3 3.自造一份用于唯一值符号化的点数据(文章内有说明) 4.3 符号化 Color(颜色)体系 4.3.1ArcGIS 颜色模型 ArcGIS 提供 Color(颜色)的模型有多种分别是: RGB 颜色模型:最常用,所有颜色都是通过红色(Red)、绿色(Green)、蓝色(Blue) 这三原色的混合来显示。 CMY 颜色模型:青(Cyan)、洋红(Magenta)和黄(Yellow)三种颜色的 简写,是相减混色模式,用这种方法产生的颜色之所以称为相减色,主要用于印 刷中。 HSV 颜色模型:色彩(H),纯度(S),明度(V)。 Gray 模型:没有彩色的,灰度图像由8位信息组成,并使用 256 级的灰色来模 拟颜色层次。 HLS 模型: Hue( 色相) 、 Luminance( 亮度) 、 Saturation( 饱和度) 。 图1 如上图所示 Color 对象是一个抽象类,它包括5个子类:它有 5 个颜色子类, 即 CmykColor、RGBColor、HSVColor、HLSColor 和 GrayColor,它们可以使用 IColor 接口定义的方法设置颜色对象的基本属性。在 ArcGIS engine 中最常使用 的两种颜色模型是 RGB 和 HSV,RGB 类实现 IRgbColor 接口,而 HSV 类则实 现 IHsvColor 接口,两个接口分别定义了设置一个 RGBColor 对象和 RGBColor 对象需传递的值。 接下来以一个函数来通过 R,G,B 值来构建一个 RGBColor 对象 private IRgbColor GetRGB(int r,int g,int b) { IRgbColor pRgbColor= new RgbColorClass();//构建一个 RgbColorClass pRgbColor.Red = r;//设置 Red 属性 pRgbColor.Green = g;//设置 Green 属性 pRgbColor.Blue = b;//设置 Blue 属性 return pRgbColor; } 4.3.2ColorRamp 对象 地图符号化的过程中,需要的颜色常常不是一种,而是随机或有序产生的一 组颜色。如果对某一个图层进行符号化需要上百种颜色如图2所示,程序开发者 肯定不能逐个产生出来。ArcGIS Engine 提供了 ColorRamp 对象: 图2 ColorRamp 类的对象可以产生颜色带,这个类实现了 IColorRamp 接口,它 定义了一系列颜色带的属性,如 Size(产生多少种颜色),Colors(颜色带 IEnumColor)。 ColorRamp 类是一个抽象类,它包括 4 个子类分别是:RandomColorRamp (随机颜色带)、PresetColorRamp(预设颜色带)、AlgorithmicColorRamp(起止 颜色带)、MultiPartColorRamp(叠加颜色带),它们的说明如表一所示。 表一 RandomColorRamp 使用 HSV 颜色模型来确定一串颜色 PresetColorRamp 预设的颜色模式,可存储 13 种颜色 AlgorithmicColorRamp 用起始颜色、终止颜色确定一个颜 色带,起始、终止颜色使用 HSV 模 型 MultiPartColorRamp 叠加产生颜色带 在 GIS 应用开发中用到比较多得是 RandomColorRamp(随机颜色带)和 AlgorithmicColorRamp(起止颜色带)接下来详细介绍一下这两个颜色带。 AlgorithmicColorRamp 是通过起止颜色来确定多个在这两个颜色之间的色带。 AlgorithmicColorRamp 类实现了两个接口:IColorRamp 和 IAlgorithmicColorRamp,两个接口之间是接口继承关系,后者包含了前者所有的 方法和属性。 4.3.3 生成颜色带实例 接下来制作一个实例演示 AlgorithmicColorRamp(起止颜色带)的 Demo: 1.创建一个窗体,在窗体上添加 5 个 Picturebox 用于分别显示产生的包含 5 个颜色的起始颜色带中的颜色,如图 3 所示 图 3 2.在“生成颜色带”Button 的 Click 事件中生成颜色带,代码片段如下所示: private void button1_Click(object sender, EventArgs e) { //创建一个新 AlgorithmicColorRampClass 对象 IAlgorithmicColorRamp algColorRamp = new AlgorithmicColorRampClass(); //创建起始颜色对象 IRgbColor startColor = new RgbColor(); startColor.Red = 255; startColor.Green = 0; startColor.Blue = 0; //创建终止颜色对象 IRgbColor endColor = new RgbColor(); endColor.Red = 0; endColor.Green = 255; endColor.Blue = 0; //设置 AlgorithmicColorRampClass 的起止颜色属性 algColorRamp.ToColor = startColor; algColorRamp.FromColor = endColor; //设置梯度类型 algColorRamp.Algorithm = esriColorRampAlgorithm.esriCIELabAlgorithm; //设置颜色带颜色数量 algColorRamp.Size = 5; //创建颜色带 bool bture = true; algColorRamp.CreateRamp(out bture); //使用 IEnumColors 获取颜色带 IEnumColors pEnumColors = null; pEnumColors = algColorRamp.Colors; //设置5个 picturebox 的背景色为产生颜色带的5个颜色 this.pictureBox1.BackColor = ColorTranslator.FromOle(pEnumColors.Next().RGB); this.pictureBox2.BackColor = ColorTranslator.FromOle(pEnumColors.Next().RGB); this.pictureBox3.BackColor = ColorTranslator.FromOle(pEnumColors.Next().RGB); this.pictureBox4.BackColor = ColorTranslator.FromOle(pEnumColors.Next().RGB); this.pictureBox5.BackColor = ColorTranslator.FromOle(pEnumColors.Next().RGB); } 运行点击 Button 结果如图 4 所示: 图 4 RandomColorRamp 对象产生随机颜色带,RandomColorRamp 也需要设定一 个范围,但是这个范围是 HSV 颜色模型的,颜色将在这个范围内随机出现。 RandomColorRamp 类实现了 IRandomColorRamp 接口 以下是生成 RandomColorRamp 的代码片段 IRandomColorRamp pRandomColorRamp = new RandomColorRampClass(); //** 制作一系列介于橘黄色和蓝绿色之间的随机颜色 pRandomColorRamp.StartHue = 40; pRandomColorRamp.EndHue = 120; pRandomColorRamp.MinValue = 65; pRandomColorRamp.MaxValue = 90; pRandomColorRamp.MinSaturation = 25; pRandomColorRamp.MaxSaturation = 45; pRandomColorRamp.Size = 20; pRandomColorRamp.Seed = 23; bool bture = true; pRandomColorRamp.CreateRamp(out bture); IEnumColors pEnumColors = pRandomColorRamp.Colors //** 对 pEnumColors 进行操作 4.4 符号化 Symbol(符号)体系 ArcGIS Engine9.3 为开发人员提供了 32 种符号,主要分为三大类符号 MarkerSymbol(点符号)、 LineSymbol(线符号)和 FillSymbol(填充符号)来绘制地 理要素的几何图形。此外还有两种特殊类型的符号:一种是 TextSymbol 用于文 字标注;另一种是 3D Chart 符号,用于显示饼图等三维对象,如需详细了解请 查找帮助文档。 4.4.1MarkerSymbol 对象 MarkerSymbol 用于修饰点对象的符号,它拥有十三个子类如表2所示,其 中不同的子类可以产生不同类型的点符号。所有的 MarkerSymbol 类都实现了 IMarkerSymbol 接口,这个接口定义了标记符号的公共方法和属性,如角度、颜 色、大小和 X,Y 偏移量等。 表二 点符号类型 描述 ArrowMarkerSymbol 预定义的肩头符号 BarChartSymbol 柱状图符号 CharacterMarker3DSymbol 三维字体符号 CharacterMarkerSymbol 字体符号 Marker3DSymbol 3D 符号 MultiLayerMarkerSymbol 多个符号叠加产生新点符号 PictureMarkerSymbol 图片符号(bmp 或 emf) PiechartSymbol 饼图符号 SimpleMarker3DSymbol 简单 3D 符号 SimpleMarkerSymbol 简单符号 StackedChartSymbol 堆叠符号 TextMarkerSymbol 文字符号用来符号化点 常用的有以下 5 种 类型: 图5 如何创建 MarkerSymbol?接下来以 SimpleMarkerSymbol 构建为例演示如何 创建一个点符号: //创建 SimpleMarkerSymbolClass 对象 ISimpleMarkerSymbol pSimpleMarkerSymbol = new SimpleMarkerSymbolClass(); //创建 RgbColorClass 对象为 pSimpleMarkerSymbol 设置颜色 IRgbColor pRgbColor = new RgbColorClass(); pRgbColor.Red = 255; pSimpleMarkerSymbol.Color = pRgbColor as IColor; //设置 pSimpleMarkerSymbol 对象的符号类型,选择钻石 pSimpleMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSDiamond; //设置 pSimpleMarkerSymbol 对象大小,设置为5 pSimpleMarkerSymbol.Size = 5; //显示外框线 pSimpleMarkerSymbol.Outline = true; //为外框线设置颜色 IRgbColor pLineRgbColor = new RgbColorClass(); pLineRgbColor.Green = 255; pSimpleMarkerSymbol.OutlineColor = pLineRgbColor as IColor; //设置外框线的宽度 pSimpleMarkerSymbol.OutlineSize = 1; 如何使用这个符号,在接下来介绍 Renderer 对象的时候将为大家演示如何用创 建的点符号去符号化一个图层。 4.4.2LineSymbol 对象 LineSymbol 对象是用于修饰线型几何对象的符号,它拥有八个子类如表3 所示,其中不同的子类可以产生不同类型的线符号,所有的 LineSymbol 类都实 现了 ILineSymbol 接口, ILineSymbol 定义了两个公共属性:Color 和 Width。 表三 线符号类型 描述 CartographicLineSymbol 实心或者虚线线符号 HashLineSymbol 离散线符号 MarkerLineSymbol 点线符号 MultiLayerLineSymbol 多符号叠加产生新线符号 PictureLineSymbol 图片线符号 SimpleLine3DSymbol 3D 线符号 SimpleLineSymbol 预定义风格的线符号 TextureLineSymbol (3DAnalyst) 纹理贴 图线符号 常用的 LineSymbol 如下图所示: 图 6 如何创建 LineSymbol?接下来以 MarkerLineSymbol 构建为例演示如何创建 一个线符号: IArrowMarkerSymbol pArrowMarker = new ArrowMarkerSymbolClass(); IRgbColor pRgbColor = new RgbColorClass(); pRgbColor.Red = 255; pArrowMarker.Color = pRgbColor as IColor; pArrowMarker.Length = 10; pArrowMarker.Width = 8; pArrowMarker.Style = esriArrowMarkerStyle.esriAMSPlain; IMarkerLineSymbol pMarkerLine = new MarkerLineSymbolClass(); pMarkerLine.MarkerSymbol = arrowMarker; IRgbColor pLineColor = new RgbColorClass(); pLineColor.Blue = 255; pMarkerLine.Color = pLineColor as IColor; 4.4.3FillSymbol 对象 FillSymbol 是用来修饰如多边形等具有面积的几何形体的符号对象,它拥有 十一个子类如表 4 所示它实现了 IFillSymbol,这个接口定义了两个属性 Color 和 OutLine,以满足所有类型的 FillSymbol 对象的公共属性设置。 表四 填充符号类型 描述 ColorRampSymbol (Carto) 用于渲染 Raster 数据的颜色带 ColorSymbol (Carto) 用于渲染 Raster 数据的颜色符号 DotDensityFillSymbol 点密度填充符号 GradientFillSymbol 渐变填充符号 LineFillSymbol 包含线符号的填充符号 MarkerFillSymbol 包含点符号的填充符号 MultiLayerFillSymbol 多符号叠加产生新填充符号 PictureFillSymbol 图片填充符号 RasterRGBSymbol 用于渲染 Raster 数据 RGBSymbol SimpleFillSymbol 简单填充符号 TextureFillSymbol 纹理贴图填充符号 常用的 FillSymbol 如下图所示: 图7 如何创建 FillSymbol?接下来以 MarkerLineSymbol 构建为例演示如何创建一 个线符号: //为填充符号创建外框线符号 IColor pLineColor = new RgbColorClass(); ICartographicLineSymbol pCartoLineSymbol = new CartographicLineSymbolClass(); pCartoLineSymbol.Width = 2; pCartoLineSymbol.Color = pLineColor; //创建一个填充符号 ISimpleFillSymbol pSmplFillSymbol = new SimpleFillSymbol(); //设置填充符号的属性 IColor pRgbClr = new RgbColorClass(); IFillSymbol pFillSymbol = pSmplFillSymbol; pFillSymbol.Color = pRgbClr; pFillSymbol.Outline = pCartoLineSymbol; 如果没有 ArcGIS Desktop 使用经验的开发看了以上代码片段会一头雾水, 不明白填充符号的创建为什么还要创建线符号等等,如果有 ArcGIS Desktop 使 用经验就会非常容易理解这些符号的创建的机制,如图 8 是 SimpleFillSymbol 设 置信息。所以熟悉 ArcGIS Desktop 的使用对开发人员进行 ArcGIS Engine 开发非 常有用。 图 8 4.4.4TextSymbol 对象 TextSymbol 对象是用于修饰文字元素的,文字元素在要素标注等方面很有 用处。TextSymbol 符号最重要的设置对象是它的字符,它实现了三个主要的接 口来设置字符:ITextSymbol 、 ISimpleTextSymbol 和 IFormattedTextSymbol 。 ITextSymbol 接口是定义文本字符样式的主要接口,它定义的 ITextSymbol::Font 属性是产生一个 TextSymbol 符号的关键。可以使用 IFontDisp 接口来设置字体的大小和是否是粗体、倾斜等属性。使用 ITextSymbol 接口还可 以定义 TextSymbol 对象的颜色、角度、水平排列方式、垂直排列方式和文本等 内容。 以下是一个构建 TextSymbol 的函数: /// ///生成文本符号 /// ///文本符号 ///字体名称 ///字体大小 ///字体颜色 public static void MakeTextSymbol(ref ITextSymbol pTxtSymbol, string sFontName, int iFont, int iColor) { try { pTxtSymbol.Font.Name = sFontName; pTxtSymbol.Font.Size = (decimal)iFont; IRgbColor pRGBColor = new RgbColorClass(); pRGBColor.RGB = iColor; pTxtSymbol.Color = (IColor)pRGBColor; pTxtSymbol.Angle = 0; pTxtSymbol.RightToLeft = false; pTxtSymbol.HorizontalAlignment = esriTextHorizontalAlignment.esriTHACenter; pTxtSymbol.VerticalAlignment = esriTextVerticalAlignment.esriTVABaseline; } catch (Exception Err) { MessageBox.Show(Err.Message, " 提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } 4.4.5 3DChartSymbol 对象 3DChartSymbol 是一个抽象类,它拥有三个子类:BarChart、PieChart 和 StackedChart。如图 9 所示: 图 9 BarChartSymbol 是最常用的三维着色符号,它使用不同类型的柱子来代表一 个要素类中不同的属性,而柱子的高度取决于属性值的大小。 PieChartSymbol 符号进行着色的方法是使用一个饼图来显示不同要素类中 的不同属性,不同的属性按照它们的数值大小占有一个饼图中的不同比例的扇形 区域。 PieChartSymbol 符号进行着色的方法是使用一个饼图来显示不同要素类中 的不同属性,不同的属性按照它们的数值大小占有一个饼图中的不同比例的扇形 区域。 至于如何创建这些 3DChartSymbol 符号这里不再提供代码片段演示,读者可 以根据前边学习的知识,自己操作 ArcGIS Desktop 使用 3DChartSymbol 制作专 题图,然后根据 ArcGIS Engine 的帮助文档开发创建 3DChartSymbol。 4.5 使用 ServerStyle 如果熟悉 ArcGIS Desktop 的使用,就会对 Style 符号库文件有所了解,相对 应的在 ArcGIS Engine 开发中对应的是 ServerStyle 符号库,它的结构体系如图 10 所示。可以通过专门的转换程序把 ArcGIS Desktop Style 符号库转换为 ArcGIS Engine 所能够使用的 ServerStyle 符号库。 用于获取 ServerStyle 符号库中的符号主要涉及到以下接口如表所示: 表 接口名称 功能描述 IStyleGallery 用于管理 Style Gallery IStyleGalleryStorage 管理 Style Gallery 中的符号库文件 IStyleGalleryClass 控制符号库中 Style Gallery Class IEnumStyleGalleryItem 枚举一组 Style Gallery items IStyleGalleryItem 定义 Style Galle ry itme 图 10 4.5.1 获取符号库中符号 如何获取到一个符号库中符号?接下来以获取 ESRI 符号库中名称为 Rose 的 符号的流程: 1.首先构建一个 ServerStyleGallery 对象 2.其次使用 IStyleGalleryStorage 接口的 AddFile 方法加载 ServerStyle 文件 3.遍历 ServerGallery 中的 Class,如果是 FillSymbol 使用 IStyleGallery 的 GetItems 方法返回一个可枚举的包含一系列 StyleGalleryItem 的 EnumStyleGalleryItem 对象。 4.遍历 EnumServerStyleGalleryItme 枚举对象中的 StylegalleryItme 如果名称是 Rose 即可获取 ESRI 符号库中名称为 Rose 的 StylegalleryItme,然后通过 IStyleGalleryItem 的 Item 属性即可转换为 ISymbol。 整个流程图如图 11 所示: 图 11 4.6SymbologyControl 控件 SymbologyControl 用来显示 ServerStyle 符号库中的符号样式,可以选择在该 控件上选择一个符号用来符号化一个图层或者作为一个 Element 的符号。使用 SymbologyControl 可以再设计的模式下在其属性页中加载 ServerStyle 符号库文 件,同样也可以使用的 LoadStyleFile 和 RemoveFile 方法加载和移除 Serverstyle 符号库文件。运行效果如图 12 所示: 图 12 4.7 符号化之 Renderer( 渲染)体系 ArcGIS Engine9.3 对 GIS 数据的符号化分为矢量数据渲染和栅格数据渲染两 大类。接下来分别介绍 FeatureRender 和 RasterRender。 4.7.1FeatureRender 对象 FeatureRenderer 是一个抽象类,它有 15 个子类负责进行不同类型的着色运 算。它们都实现了 IFeatureRenderer 接口,这个接口定义了进行要素图层符号化 的公共属性和方法。 可以通过 IGeoFeatureLayer::Renderer 属性获得一个要素图层的符号化对象 表四 要素符号化类型 描述 SimpleRender 简单符号化 UniqueValueRender 唯一值符号化 BiUniqueValueRender 双变量唯一值符号化 ChartRender 图表符号化 ClassBreaksRenderer 分类等级符号化 DotDensityRenderer 点密度符号化 ProportionalSymbolRenderer 根据属性值设置符号大小进行符 号化 ScaleDependentRenderer 依比例尺符号化 RepresentationRenderer 制图表达符号化 CoTrackSymbologyRenderer(TrackingAnalyst) 轨迹符号化(应用于 TrackingAnaylyst 扩展模块) EnhancedInfoRenderder(TrackingAnalyst) 增强信息符号化(应用于 TrackingAnaylyst 扩展模块) UniqueValueTextRenderer(TrackingAnalyst) 唯一值文本符号化(应用于 TrackingAnaylyst 扩展模块) NAStopRenderer(NetworkAnalyst) 停止符号化(应用于网络分析扩展 模块) FeatureVertexRenderer(SurveyExt) 要素定点符号化(应用于测量分析 扩展模块) SharedEdgeRenderer(EditorExt) 用于绘制拓扑元素 常用的要素符号化类型主要有以下 6 种类型,如图 13 所示: 图 13 由于篇幅有限不再对每一种符号化类型的使用进行讲解,在后边的实例中将 为读者演示如何进行唯一值符号化。 4.7.2RasterRender 对象 RasterRender 是一个抽象类,它有 15 个子类负责进行不同类型的着色运算。 它们都实现了 IRasterRender 接口,这个接口定义了栅格图层符号化的公共属性 和方法。可以通过 IRasterLayer::Renderer 属性获得一个栅格图层的符号化对象。 要素符号化类型 描述 RasterRGBRenderer 栅格 RGB 符号化 RasterUniqueValueRenderer 唯一值符号化 RasterColormapRenderer 双变量唯一值符号化 RasterClassifyColorRampRenderer 图表符号化 RasterStretchColorRampRenderer 分类等级符号化 RasterDiscreteColorRenderer 点密度 符号化 栅格符号化类型结构图如图 14 所示: 图 14 以下代码片段是对一个 RasterLayer 进行 RasterStretchColorRampRenderer 符 号化操作: /// /// StretchColorRamp 符号化 RasterLayer /// ///RasterLayer public void SetStretchColorRampRenderer(IRasterLayer pRasterLayer) { try { //创建 RasterStretchColorRampRendererClass 对象 IRasterStretchColorRampRenderer pRStretchRender= new RasterStretchColorRampRendererClass(); //QI 到 IRasterRenderer IRasterRenderer pRasterRender=pRStretchRender as IRasterRenderer; pRasterRender.Raster = pRasterLayer as IRaster; pRasterRender.Update(); //创建两个起始颜色 IRgbColor pFromRgbColor = new RgbColorClass(); pFromRgbColor.Red = 255; IRgbColor pToRgbColor = new RgbColorClass(); pToRgbColor.Blue = 255; //创建起止颜色带 IAlgorithmicColorRamp pAlgorithmicColorRamp = new AlgorithmicColorRampClass(); pAlgorithmicColorRamp.Size = 255; pAlgorithmicColorRamp.FromColor = pFromRgbColor as IColor; pAlgorithmicColorRamp.ToColor = pToRgbColor as IColor; bool btrue= true; pAlgorithmicColorRamp.CreateRamp(out btrue); //选择拉伸颜色带符号化的波段 pRStretchRender.BandIndex = 0; //设置拉伸颜色带符号化所采用的颜色带 pRStretchRender.ColorRamp = pAlgorithmicColorRamp as IColorRamp; pRasterRender.Update(); //符号化 RasterLayer pRasterLayer.Renderer = pRasterRender; } catch(Exception Err) { MessageBox.Show(Err.Message," 提示 ",MessageBoxButtons.OK,MessageBoxIcon.Information); } } 4.8 利用 ESRI 自带的符号库进行唯一值符号化一图层开发 实例 4.8.1 目的 学会开发唯一值符号化要素图层功能 图 1 5 图 16 图 17 4.8.2 步骤 1.准备点数据,添加属性字段“类别”; 2.并为要素“类别”属性值分别设置为“Hospital2”,“School 1”,“Airport”三种属 性值。 3.实现唯一值符号化功能 4.运行程序实现效果 4.8.3 功能开发 实现唯一值符号化功能代码如下: /// ///获取符号库中符号 /// ///符号库全路径名称 ///GalleryClass 名称 ///符号名称 ///符号 private ISymbol GetSymbol(string sServerStylePath, string sGalleryClassName, string symbolName) { try { //ServerStyleGallery 对象 IStyleGallery pStyleGaller = new ServerStyleGalleryClass(); IStyleGalleryStorage pStyleGalleryStorage = pStyleGaller as IStyleGalleryStorage; IEnumStyleGalleryItem pEnumSyleGalleryItem=null; IStyleGalleryItem pStyleGallerItem = null; IStyleGalleryClass pStyleGalleryClass = null; //使用 IStyleGalleryStorage 接口的 AddFile 方法加载 ServerStyle 文件 pStyleGalleryStorage.AddFile(sServerStylePath); //遍历 ServerGallery 中的 Class for (int i = 0; i < pStyleGaller.ClassCount; i++) { pStyleGalleryClass = pStyleGaller.get_Class(i); if (pStyleGalleryClass.Name != sGalleryClassName) continue; //获取 EnumStyleGalleryItem 对象 pEnumSyleGalleryItem = pStyleGaller.get_Items(sGalleryClassName, sServerStylePath, ""); pEnumSyleGalleryItem.Reset(); //遍历 pEnumSyleGalleryItem pStyleGallerItem = pEnumSyleGalleryItem.Next(); while (pStyleGallerItem != null) { if (pStyleGallerItem.Name == symbolName) { //获取符号 ISymbol pSymbol = pStyleGallerItem.Item as ISymbol; System.Runtime.InteropServices.Marshal.ReleaseComObject(pEnumSyleGalleryItem ); System.Runtime.InteropServices.Marshal.ReleaseComObject(pStyleGalleryClass); return pSymbol; } pStyleGallerItem = pEnumSyleGalleryItem.Next(); } } System.Runtime.InteropServices.Marshal.ReleaseComObject(pEnumSyleGalleryItem ); System.Runtime.InteropServices.Marshal.ReleaseComObject(pStyleGalleryClass); return null; } catch (Exception Err) { MessageBox.Show(Err.Message, " 提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return null; } } /// ///设置要素图层唯一值符号化 /// /// private void UniqueValueRenderFlyr(IFeatureLayer pFeatureLayer) { try { //创建 UniqueValueRendererClass 对象 IUniqueValueRenderer pUVRender = new UniqueValueRendererClass(); List pFieldValues= new List(); pFieldValues.Add("Hospital 2"); pFieldValues.Add("School 1"); pFieldValues.Add("Airport"); for(int i=0;i 0) { IFeatureLayerDefinition pFDefinition = pFeatureLayer as IFeatureLayerDefinition; //创建新图层 IFeatureLayer pNewFeatureLayer = pFDefinition.CreateSelectionLayer("newlayerName", true, null, null); pNewFeatureLayer.Name = "查询结果城市"; axMapControl1.AddLayer(pNewFeatureLayer as ILayer); } } code] 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; ////// 在程序运行时的内存中创建矢量要素层,并加到地图控件最顶端 /// /// 地图控件 ///IFeatureLayer 新加的要素层 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 oField = new FieldClass(); IFields oFields = new FieldsClass(); IFieldsEdit oFieldsEdit = null; IFieldEdit oFieldEdit = null; IFeatureClass oFeatureClass = null; IFeatureLayer oFeatureLayer = 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;} } /// 在地图控件上添加透明临时图元/// /// 地图控件 /// Envelope 或 Polygon 几何实体 /// 是否清除原有内容 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); } } /// /// 获取查询要素 /// /// 要素图层 /// 图形范围参数 /// 符号条件要素集合 private List GetSeartchFeatures( IFeatureLayer pFeatureLayer,IGeometry pGeometry) { try { List pList = new List(); //创建 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; } } bool bSearch = false; //定义 bool 变量用于启动多边形查询功能 private void button1_Click(object sender, EventArgs e) { try { //向地图控件添加内存图层 IFeatureLayer pFeatureLayer = this.AddFeatureLayerByMemoryWS(this.axMapControl1,this.axMapControl1.Spatial Reference); this.axMapControl1.AddLayer(pFeatureLayer); //设置鼠标样式为十字丝 this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair; //启动范围查询功能 bSearch = true; } 添加一个新的 Form 在 Form 上添加一个 DataGridView 控件用于显示查询结果信 息。如图 4 所示: private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e) { if (bSearch) { //设置鼠标样式为十字丝 this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair; //获取画定范围的 Geometry IGeometry pGeometry = this.axMapControl1.TrackPolygon(); //添加半透名临时图形 this.AddTransTempEle(this.axMapControl1, pGeometry, false); IFeatureLayer pFeatureLayer=this.axMapControl1.get_Layer(1) as IFeatureLayer; //执行查询获取符号条件的要素 List pFList = this.GetSeartchFeatures(pFeatureLayer, pGeometry); attribute pAttribute = new attribute(); //设置信息显示窗体中 DataGridView 的属性 //设置行数 pFList.Count+1 包括字段名哪一行即表头 pAttribute.dataGridView1.RowCount = pFList.Count+1; //设置边界风格 pAttribute.dataGridView1.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Sunken; //设置列数 pAttribute.dataGridView1.ColumnCount = pFList[0].Fields.FieldCount; //遍历第一个要素的字段用于给列头赋值(字段的名称) for(int m=0;m pFeatures = new List(); IFeature pFeature = pFeatureCursor.NextFeature(); while (pFeature != null) { pFeatures.Add(pFeature); pFeature = pFeatureCursor.NextFeature(); } for (int i = 0; i < pFeatures.Count; i++) { MessageBox.Show(((pFeatures.Shape as IPolygon) as IArea).Area.ToString()); } 分析:pFeatures 集合存储了指向 FeatureClass 上所有 Feature 的引用,但是 由于 Recycling 参数设置为 TRUE 也就是说每执行一个 NextFeautre 方法上一条记 录的 Feature 值在内存中被回收,所以到最后遍历 pFeatures 集合的时候所有的 IFeature 引用指向的 Feature 对象都为 Null。所以会引发一下错误(如下图 7 所示): 图 7 参数 Recycling 设置为 False IFeatureClass pFeatureClass = (this.axMapControl1.get_Layer(0) as IFeatureLayer).FeatureClass; //IFeatureCursor pFeatureCursor = pFeatureClass.Search(null, true); IFeatureCursor pFeatureCursor = pFeatureClass.Search(null, false); List pFeatures = new List(); IFeature pFeature = pFeatureCursor.NextFeature(); while (pFeature != null) { pFeatures.Add(pFeature); pFeature = pFeatureCursor.NextFeature(); } for (int i = 0; i < pFeatures.Count; i++) { MessageBox.Show(((pFeatures.Shape as IPolygon) as IArea).Area.ToString()); } 分析:pFeatures 集合存储了指向 FeatureClass 上所有 Feature 的引用,但是由 于 Recycling 参数设置为 False 也就是说每执行一个 NextFeautre 方法上一条记录 的 Feature 值在内存中依然存在,所以到最后遍历 pFeatures 集合的时候所有的 IFeature 引用指向的 Feature 对象都依然存在。所以会执行的很 Happy(如下图 8 所示): 图 8 6.学习空间分析 空间分析功能是 GIS 的主要功能之一,本章将为读者介绍一些 GIS 开发常 用的功能涉及到的空间拓扑运算,空间关系运算,空间临近运算所使用到的接口。 例如开发一个缓冲区分析功能,获取两个几何要素的最短距离,判断两个几何要 素的拓扑关系等都需要使用到这些接口,使用这些接口可以极大提高开发者的开 发效率。 1.1 目标 1.熟悉 ITopologicalOperator 接口(用于空间拓扑运算)的使用 2.熟悉 IRelationalOperator 接口(用于空间关联运算)的使用 3.熟悉 IProximityOperator 接口(用于空间距离运算)的使用 1.2 准备工作 1.IDE:Visual Studio 2005/2008 2.ArcGIS Engine Developer kit 9.3 1.1 ITopologicalOperator 接口 1.1.1 ITopologicalOperator 接口简介 ITopologicalOperator 接口用来通过对已存在的几何对象做空间拓扑运算以 产生新的结合对象。实现该接口的类有 Point,Multipoint,Polyline,Polygon,MultiPatch 这些都是高级几何对象,另外 GeometryBag 也实现了该接口,低级的构建几何对象如 Segments(Line,Circular Arc,Elliptic Arc,Bezier Curve),Paths 或者 Rings 如果想使用该接口需包装成高级几 何对象。 ITopologicalOperator 接口在 GIS 开发中使用非常广泛,通常 GIS 系统中缓 冲区分析,裁剪几何图形,几何图形差分操作,几何图形合并操作等都需要使用 此接口。下表是 ITopologicalOperator 接口主要的方法说明: 方法名称 说明 Boundary 几何图形对象的边界 Buffer 对几何图形对象进行缓冲区空间拓扑操作 Clip 对几何图形对象进行裁剪空间拓扑操作 ConstructUnion 高效的合并多个枚举几何对象与单个几何对象合并 为单个几何对象,这对于大量几何对象的合并非常高 效 ConvexHull 构建几何对象的凸边形 Cut 切割几何对象 Difference 一个几何图形减去它与另一个几何图形相交的部分 Intersect 两个同维度几何对象的交集部分 Simplify 使几何对象拓扑一致 SymmetricDifference 对称差分将两个几何图形的并集部分减去两个几何 图形交集的部分 Union 合并两个同维度的几何对象为单个几何对象 1. Boundary 属性 如图所示 Polygon 几何对象的 Boundary 是组成它的 Polyline 几何对象 Polyline 几何对象的[Boundary 是组成它的顶点 Point 几何对象 而 Point 几何对象的 Boundary 是空对象,示意图如下图所示: 2.Buffer 方法: Buffer 方法可以给一个高级几何对象产生一个缓冲区,无论是 Polygon,Polyline,Point 它们的缓冲区都是具有面积的几何对象,如下图所示: 3.Clip 方法 Clip 方法可以将用一个 Envelope 对象对一个几何对象进行裁剪,参见结果 是几何对象被 Envelope 对象所包围的部分如图所示: 4.ConvexHull 方法 ConvexHull 方法可以产生一个几何图形的最小的边框凸多边形(没有凹面包 含几何图形的最小多边形) 5.Cut 方法 Cut 方法不支持 GeometryBags 几何对象,它可以指定一条切割曲线和一个几 何图形,经过切割运算后把几何图形分为左右两部分,做,右两部分是相对曲线 的方向而言。点与多点不能被切割,Polyline 和 Polygon 只有与切割曲线相交时 才能执行 Cut 方法,如下图: 6.Difference 方法 Difference 方法用于产生两个几何对象的差集。如图所示: 7.Union 方法和 ConstructUnion 都用于合并几何对象,所不同的是前者合并两个 同维度的几何对象为单个几何对象,而后者是高效的合并多个枚举几何对象与单 个几何对象合并为单个几何对象,这对于大量几何对象的合并非常高效的。 8.Intersect 方法 Intersect 方法用于返回两个同维度几何对象的交集,即两个几何对象的重合 部分。如下图所示: 9.SymetricDifference 方法 SymetricDifference 方法用于产生两个几何图形的对称差分,即两个几何的 并集部分减去两个几何的交集部分,如下图所示: 10.IsSimple 属性和 Simplify 方法 IsSimple 属性用于检测几何对象是否是拓扑正确即为简化几何对象,而 Simplify 方法用于简化几何对象使几何对象的拓扑正确。如下图所示: 6.3.2 简化几何对象功能开发 在开发对几何对象空间分析时,所操作的几何对象必须是简化的几何对象, 以下代码片段演示了如何使一个几何对象在拓扑上一致,例如在一个 PointCollection 对象中移除所有的重合点;对于 segmentCollection 移除所有重合 线段,而相交的线段会变成非相交线段(即在相交处产生一个顶点);对于 Polygon 所有相交的环将被移除,未封闭的环将被封闭。 /// /// 简化几何对象 /// /// 几何对象 private void SimplifyGeometry(IGeometry pGeometry) { try { ITopologicalOperator pTopOperator = pGeometry as ITopologicalOperator; if (pTopOperator != null) { if (!(pTopOperator.IsKnownSimple)) { if (!(pTopOperator.IsSimple)) { pTopOperator.Simplify(); } } } } catch (Exception Err) { MessageBox.Show(Err.Message, " 提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } 6.4 IRelationalOperator 接口 6.4.1 IRelationalOperator 接口简介 几何对象之间都存在某种关联关系,如包含,相等,在内部,相交,叠加等。 这些关联关系的获得都可以通过 IRelationalOperator 接口来获得,关系运算是在 两个几何对象间进行的,通过 IRelationalOperator 的某一个方法返回一个布尔值 来说明这两个几何对象是否有这种关系。所有支持 ITopologicaloperator 的几何对 象的类也实现了 IRelationalOperator 接口,其中包括 Envelope 对象,这意味着还 可以对两个几何对象的 Envelope 进行关联关系检查。 方法名称 描述 Contains 检查两个几何图形几何图形 1 是否包 含几何图形2 Crosses 用于检测两个几何图形是否相交 Equal 用于检测两个几何图形是否相等 Touches 用于检测两个几何图形是否相连 Disjoint 用于检测两个几何图形是否不相交 Overlaps 用于检测两个几何图形是否有重叠 Relation 用于检测是否存在定义 relationship Within 检查两个几何图形几何图形 1 是否被 包含于几何图形2 6.4.2 判断几何对象包含关系功能开发 以下代码片段演示如何判断几何图形 A 是否包含几何图形 B: /// /// 检测几何图形 A 是否包含几何图形 B /// /// 几何图形 A /// 几何图形 B /// True 为包含,False 为不包含 private bool CheckGeometryContain(IGeometry pGeometryA, IGeometry pGeometryB) { IRelationalOperator pRelOperator = pGeometryA as IRelationalOperator; if (pRelOperator.Contains(pGeometryB)) { return true; } else { return false; } } 6.5 IProximityOperator 接口 6.5.1 IProximityOperator 接口简介 IProximityOperator 接口用于获取两个几何图形的距离,以及给定一个 Point, 求另一个几何图形上离离给定点最近的点。IProximityOperator 接口的主要方法 有:QueryNearesPoint,ReturnDistance, ReturnNearestPoint ReturnDistance 方法用于返回两个几何对象间的最短距离,QueryNearesPoint 方法 用于查询获取几何对象上离给定输入点的最近距离的点的引用, ReturnNearestPoint 方法用于创建并返回几何对象上离给定输入点的最近距离的 点。 6.5.2 最近点查询功能开发 以下代码片段演示如何使用 IProximityOperator 接口获取给定点与要查询的 几何图形的最近点: /// 在 pGeometry 上返回一个离 pInputPoint 最近的 point /// /// 给定的点对象 /// 要查询的几何图形 /// the nearest Point private IPoint NearestPoint(IPoint pInputPoint, IGeometry pGeometry) { try { IProximityOperator pProximity = (IProximityOperator)pGeometry; IPoint pNearestPoint = pProximity.ReturnNearestPoint(pInputPoint, esriSegmentExtension.esriNoExtension); return pNearestPoint; } catch(Exception Err) { MessageBox.Show(Err.Message, " 提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return null; } } 以下代码片段演示如何使用 IProximityOperator 接口查询给定的两个几何对 象的距离: /// /// 获取两个几何图形的距离 /// /// 几何图形 A /// 几何图形 B /// 两个几何图形的距离 private double GetTwoGeometryDistance(IGeometry pGeometryA, IGeometry pGeometryB) { IProximityOperator pProOperator = pGeometryA as IProximityOperator; if (pGeometryA!=null|| pGeometryB !=null) { double distance= pProOperator.ReturnDistance(pGeometryB); return distance; } else { return 0; } } 7. 学习地图输出 地图输出是一个 GIS 系统应有的功能,它分为两种类型:一种是地图的打 印输出,即把地图的某一范围通过打印机或者绘图仪打印在纸质媒介上,如图1 所示;另一种是地图的转换输出,即把地图的某一范围输出转换为不同的文件格 式,如 JPEG,PDF,SVG,TIFF 以及 Adobe AI 等栅格或矢量图形文件,如图2 所示。 7.1 目标 1.能够使用 PageLayout 对象通过打印机或绘图仪出图。 2.能够在地图上画取一定范围直接将该范围的地图数据导出为矢量或栅格图形 文件(AI,JPEG 等)。 图 1 图 2 7.2Printer 类 ArcGIS Engine 中对于地图打印使用的是 Printer 类是个抽象类,它有三个子 类:EmfPrinter,ArcPressPrinter 和 PsPrinter 这三种类对象都支持各自类型的硬拷 贝设备,开发者选择需要的打印对象不是随意决定的,二取决于程序使用的打印 设备类型和驱动程序的类型。 它们都实现了 IPrinter 接口,IPrinter 接口定义了所有打印对象的一般方法和 属性。如 IPrinter 的 Pager 属性用于初始化与系统关联的打印机。IPrinter 的 StartPrint 方法用于返回一个打印设备的 hDC,Irinter 的 FinishPrinting 用于清除打 印后的缓存对象。 Paper 对象是 Printer 对象的一个关键属性对象,它主要的作用是维持 Printer 对象使用的打印机和打印纸张的联系。应用程序启动的时候,一个 Paper 对象就 自动产生,创建的是基于系统缺省打印机。如果要使用另一台打印机就需产生一 个新的 Paper 对象,并将它的 PrinterName 设置为打印机名。 Paper 类主要实现了 IPaper 接口,它主要用了对打印纸张的设置。例如 IPaper 的 Orientation 属性用于获取打印的方向属性值 1 为纵向,2 为横向。 7.3 打印输出 7.3.1PageLayoutControl 控件打印出图 我们通常开发一个 GIS 系统打印模块时一般用到 PageLayoutControl 控件,使 用 IPageLayoutControl 接口的 PrintPageLayout 方法可以打印 PageLayoutControl 控件中视图。它与控件的 Page 对象相关,在使用 IPageLayeoutControl 的 PrintPageLayout 方法前对 Page 对象进行设置。通过 IPage 接口的 PageToPrinterMapping 可以设置页面和打印纸张的匹配,例如如果打印的页面的 宽度大于纸张的宽度,可以选定是伸缩地图还是切割地图。 使用 PageLayoutControl 控件打印地图的代码片段如下: /// /// 打印 PageLayout /// /// PageLayout 对象 public void PrintPageLayout(AxPageLayoutControl pPageLayout) { try { if (pPageLayout.Printer != null) { IPrinter pPrinter = pPageLayout.Printer; if (pPrinter.Paper.Orientation != pPageLayout.Page.Orientation) { pPrinter.Paper.Orientation = pPageLayout.Page.Orientation; } pPageLayout.PrintPageLayout( 1, 0,0); } } catch (Exception Err) { MessageBox.Show(Err.Message, "打印", MessageBoxButtons.OK, MessageBoxIcon.Information); } } 7.3.2 地图转换输出 地图输出分为两大类,一类是基于栅格格式的文件输出如:JPG,BMP,PGN 等一类是基于矢量格式的输出,如 SVG,AI 等。 Windows 平台一般的屏幕分辨率是 96dpi,这个值也是 ArcGIS 影像文件格式输出 的缺省分辨率。而矢量格式的地图输出如PDF,AI等,他们的缺省分辨率为300dip. 分辨率 图 3 Exporter 类使所有转换输出类的父类如图 3 所示,它是一个抽象类实现了 IExport 接口。IExport 接口用于定义地图输出的一般方法和属性。部分主要方法 和属性如下表 方法属性名称 描述 Name Exporter 的名称 ExportFileName 输出文件名称 PixelBounds 确定输出范围 Resolution 分辨率 Priority 优先次序 Cleanup 清楚临时文件释放内存等 StartExporting 初始化 Exporter FinishExporting 关闭 Exporter 7.3.2.1 栅格格式文件输出: ExportImage 类用于将地图输出为栅格格式文件的对象。ExportImage 是 Export 的一个子类,它也是一个抽象类,实现了 IExportImage 接口它定义了所有操作栅 格格式文件的一般方法和属性。部分主要方法和属性如下表: 方法属性名称 描述 BackgroundColor 输出栅格文件的背景色 Height 影像的高度 Width 影像的宽度 ImageType 输出图片类型 1 位单色掩膜图 1 位黑白图 8 位灰度图 24 位真彩色 如图 1ExportImage 的子类有五种分别是 ExportBMP,ExportJPEG,ExportPNG,ExportTIFF 和 ExportGIF,通过这几个对象可 以分别将地图数据生成 BMP,JPEG,PNG,TIFF 和 GIF 等图形文件。 7.3.2.2 基于矢量格式文件输出: ExportVector 类用于地图数据转换输出为矢量格式的文件。ExportVector 是一 个抽象类,它实现了多个设置输出矢量的格式文件设置的接口。它有五个子类: ExportEMF,ExportAI,ExportPDF,ExportPS 和 ExportSVG 它们分别用于生成五种 不同格式的矢量数据文件。 以下代码片段演示如何把地图数据输出为栅格或矢量文件: /// /// pageLayout 输出图片 /// /// ture 为成功,false 为失败 private bool ExportMapToImage() { try { SaveFileDialog pSaveDialog = new SaveFileDialog(); pSaveDialog.FileName = ""; pSaveDialog.Filter = "JPG 图片(*.JPG)|*.jpg|tif 图片(*.tif)|*.tif|PDF 文档 (*.PDF)|*.pdf"; if (pSaveDialog.ShowDialog() == DialogResult.OK) { double iScreenDispalyResolution = PageLayoutCtrl.ActiveView.ScreenDisplay.DisplayTransformation.Resolution; IExporter pExporter=null; if (pSaveDialog.FilterIndex == 0) { pExporter = new JpegExporterClass(); } else if (pSaveDialog.FilterIndex == 1) { pExporter = new TiffExporterClass(); } else if (pSaveDialog.FilterIndex == 2) { pExporter = new PDFExporterClass(); } pExporter.ExportFileName = pSaveDialog.FileName; pExporter.Resolution = (short)iScreenDispalyResolution; tagRECT deviceRect = PageLayoutCtrl.ActiveView.ScreenDisplay.DisplayTransformation.get_DeviceFrame( ); IEnvelope pDeviceEnvelope = new EnvelopeClass(); pDeviceEnvelope.PutCoords(deviceRect.left, deviceRect.bottom, deviceRect.right, deviceRect.top); pExporter.PixelBounds = pDeviceEnvelope; ITrackCancel pCancle=new CancelTrackerClass(); PageLayoutCtrl.ActiveView.Output(pExporter.StartExporting(), pExporter.Resolution, ref deviceRect, PageLayoutCtrl.ActiveView.Extent, pCancle); Application.DoEvents(); pExporter.FinishExporting(); return true; } else { return false; } } catch (Exception Err) { MessageBox.Show(Err.Message, "输出图片", MessageBoxButtons.OK, MessageBoxIcon.Information); return false; } }
还剩134页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

nufront

贡献于2018-04-18

下载需要 10 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf