空间数据编辑是指产生新的矢量数据或对已有的矢量空间数据进行的再加工,包括矢量数据的生产、加工、维护、错误修正等,这是空间数据维护与加工的基本环节,也是基于ArcGISEngine开发的GIS系统的基本功能。为保证数据的现势性,对空间数据的更新也是测绘地理信息相关部门的日常工作。空间数据的编辑包括矢量图形编辑和属性数据编辑两部分。本章以一个完整的实例讲述空间数据编辑各种工具的实现方法及对应的接口使用。全章按照空间数据编辑的基本流程给出详细的介绍,包括开始编辑、设置编辑图层、设置编辑任务、编辑操作、节点编辑、属性编辑、保存编辑和结束编辑等。
6.1简介
空间数据的编辑操作是针对工作空间下的数据进行的,如 ShapefileWorkspaces 工作空间、AccessWorkspace 工作空间、FileGDBWorkspace 工作空间等。本章以编辑 FileGDBWorkspace为例介绍空间数据的编辑(当然,也支持对 ShapefileWorkspaces 工作空 间、AccessWorkspace工作空间等数据的编辑操作)。实例代码位于本书随书光盘“...\chp06\空间数据编辑\code”中,实例数据位于本书随书光盘“...\chp06\空间数据编辑\data”中。
本章实例运行界面如图6.1所示。
6.1.1操作步骤
(1)单击【编辑】下拉菜单,选中【开始编辑】,此时菜单栏上显示为灰色部分的菜单将变为可用。
(2)设置【图层选择】下拉列表,选中要编辑的图层。
(3)进行编辑操作,菜单包括【选择要素】、【移动要素】、【撤销】、【恢复】、【添加要素】、【删除要素】、【属性编辑】、【移动节点】、【添加节点】和【删除节点】等,可根据需要进行操作。
(4)当完成一个编辑任务时,可在【编辑】下拉菜单中单击【保存编辑】,保存当前的编辑任务。若要继续执行其他编辑任务,可重复步骤(2)或(3)继续编辑。
(5)当编辑完成后,点击【编辑】下拉菜单,选中【结束编辑】,此时菜单栏上除【编辑】菜单外,其他菜单重新显示为灰色不可用状态。
本实例仿照 ArcGIS 10 Desktop的编辑工具条的操作,希望读者先熟练掌握ArcGIS的编辑操作,再进行相关编程的学习。软件的具体操作步骤可参见本书姊妹篇《ArcGIS 10地理信息系统教程:从初学到精通》对应章节。
6.1.2 实现思路
(1)调用 IEngineEditor接口的StartEditing方法打开一个编辑对象,并设定相关参数。 (2)将设定好参数的 IEngineEditor 接口跳转到 IEngineEditLayers 接口,利用该接口的 SetTargetLayer方法来设置一个目标图层。
(3)通过 IEngineEditTask 接口生成的对象设定编辑任务,并将其传递给当前EngineEditor 对象的 CurrentTask属性。
(4)实现所要执行的编辑操作。
(5)在编辑对象过程中,使用IEngineEditor接口的StopEditing方法,并输人参数“true” 结束编辑任务并保存(或者直接调用 ControlsEditingSaveCommand 方法进行保存,本章使用 前者)。
(6)停止编辑。
6.1.3代码说明
在ArcGIS Engine的编程过程中,数据编辑部分的代码较为复杂。一般地,ArcGISEngine 实现空间数据编辑的方法有两种:一种是直接调用ArcGIS Engine封装的工具,另一种是根据操作过程逐步编写代码。如要移动一个要素的节点,第一种方法是调用ControlsEditingVertexMoveToCommandClass 工具(具体调用方法,参见3.9节要素选择操 作相关部分);第二种方法需要一个个响应鼠标的MouseDown,MouseMove、MouseUp事件, 并编写各个步骤的详细代码。第一种方法简单直观,易于掌握,它相当于直接调用ArcGIS的移动节点的工具。ArcGIS平台中的很多工具都有对应的常量值,理论上第一种方法可以实现绝大多数的GIS操作,如放大、缩小、选择、编辑,甚至是各种空间分析等。当前已出版的ArcGIS Engine 教材中,多数采用了这种方式。但是这种方式对于读者掌握ArcGIS Engine编程和熟悉各种编程接口的作用则微乎其微了。第二种方法尽管读者掌握起来要下一定的功夫,但是对于读者深入掌握编辑的操作原理、提高编写代码的能力和分析代码逻辑的能力是大有裨益的。相信阅读完本章的读者,在代码分析、组织和编写上会有一个很大的提高。
本章实例的程序架构为一个解决方案下有两个项目,分别是GISEditor(作为启动项目)和GISEditor.EditTool。其中,GISEditor项目主要用来设计程序的主界面,包含实现各编辑 功能的按钮。GISEditor.EditTool项目主要用来实现各编辑操作,这个项目所包含的类从功能上可分为三种:命令类(CommandClass)、工具类(ToolClass)、公共基础类(BasicClass),在 解决方案管理器中分别对应于Command、Tool和BasicClass文件夹。
Command文件夹中包含的类是以命令方式来实现编辑操作的,运行时单击对应按钮即可,如撤销操作类(UndoCommandClass)、恢复操作类(RedoCommandClass)、删除要素操作 类(DelFeatureCommandClass)等。这些类所实现的编辑功能仅需要实现鼠标单击事件(OnClick)即可。它们继承自ICommand接口,可以通过实现ICommand接口的方法自动生成鼠标事件。具体操作是:右键单击ICommand接口,选择【实现接口(I)】,在出现的菜单中点击【实现接口(M)】,会自动生成ICommand 接口的方法声明,然后在这些方法中编写方法体即可。下面的ITool接口实现方法类似,不再赘述。
Tool 文件夹中所包含的类是以工具的方式(即鼠标与视图交互的方式)来实现编辑操作的,如添加节点工具类(AddVertexToolClass)、移动节点工具类(MoveVertexToolClass)、删除节点工 具类(DelVertexToolClass)、移动要素工具类(MoveFeatureToolClass)等。这些类所实现的编辑功 能需要鼠标的多个事件协调完成,如移动要素的实现需要在MoveFeatureToolClass 类中实现鼠标的 OnClick、OnMouseDown、OnMouseMove,OnMouseUp等事件。
BasicClass 文件夹中包含的类有编辑节点类(EditVertexClass)、视图控制类(MapManager)、 修改 Z、M值类(SupportZMFeatureClass)等。这些类封装了各种编辑操作的公共方法,如MapManager 中封装了GetRgbColor方法用于获取颜色、CalDistance 方法用于计算两点之间X 方向与Y方向上的距离、ConvertPixelsToMapUnits 方法用于单位之间的转换、 GetSelectedFeatures 方法用于获取选择要素等。这样做的好处在于极大地提高了代码的重用性和可读性。
实例代码中还用到了钩子接口(IHookHelper),它主要有如下功能:
(1)获取地图控件和主窗体。m_hookHelper.Hook=m_Hook,m_Hook 为 mainMapControl.Object,即主视图对象。
(2)获取IActiveView 和 IMap对象。m_Map=m_hookHelper.FocusMap。
(3)操作地图。HookActions hookActions = m_hookHelper as IHookHelper;获取 IHookActions,再通过 IHookActions 进行动画、漫游等操作(本章未用到IHookActions,此处 仅做参考)。
6.2编辑对象
ArdGIS Engine的编辑过程就是用户通过鼠标与控件进行点、线、面等几何对象的添加、修改、删除等可视化的交互过程。为更好地理解这个交互过程,需要了解编辑过程中的几何对象及DisplayFeedback对象。
6.2.1 几何对象
矢量数据模型是地理数据的主要表现形式, GeoDatabase的每一条要素的记录中都有一个“Shape”字段,用于保存一个或者多个几何对象,这些几何对象可以精确地描述具有离散特征的地理要素在地球上的具体位置和形状,也正是由于存在着这种精确的特征,才使得ArcGIS可以对地理要素进行空间分析和运算,得出用户需要的结果。几何对象(Geometry)类是所有几何对象的父类,它是一个抽象类。IGeometry接口定义了所有的几何对象都拥有的属性或方法,如Dimension用于查询几何形体对象的维度, Envelope用于返回几何对象的包络线,GeometryType则可以返回几何对象的类型等。
在几何对象模型中,很多对象都是组件类,这意味着开发人员可以直接创建一个几何对象。当使用new关键字创建一个几何对象后,这个Geometry其实是空的,需要给它添加具体的信息。如新建一个Point对象后,如果不设置它的X、Y坐标,这个点是无法显示的。
几何对象是ArcGIS Engine中使用最广泛的对象集之一。新建、删除、编辑几何对象和进行地理分析时,实际就是在处理一个几何形体对象。当然,显示要素、空间选择、制作专题图、标注编辑等很多过程中也需要几何对象的参与。几何对象分为两种层次,一种是构成要素形状的几何图形,如Point,Polyline,Envelope等;另一种是构成要素形状的组成部分,如Path,Segment等,前者被称为“高级几何对象,几何对象的关系可以用图6.2表示”.
1.高级几何对象
(1)点(Point)对象是一个零维的几何图形,具有X、Y坐标值及可选的属性,如高程(Z值)、测量值(M)和ID号,它用于描述需要精确定位的对象,如一个城市在全国的位置等。
(2)点集(MultiPoint)对象是无序点的集群,它用于表示具有相同属性设置的同一组点,是由多个点组成的一个点状地理对象。
(3)包络线(Envelope)对象是一个矩形,它用于表示要素的空间范围。它覆盖了几何对象的最小坐标和最大坐标,同时也记录了几何对象的2值和M值的变化范围。所有的几何形体对象都拥有一个包络线。
(4)多义线(Polyline)对象是一个有序路径(Path)的集合,这些路径既可以是连续的,也可以是离散的。这个对象可以用于表示具有线状特征的对象,如河流、公路和等高线等。用户可以使用单路径构成的多义线来表示简单线类型,如简单公路等;使用具有多个路径构成的多义线来表示复杂线类型,如具有多个支流的河流等。
(5)多边形(Polygon)对象是环(Ring)的集合,环是一个封闭的路径。Polygon可以由一个或多个环组成,设置环内套环,形成岛环的情况,但是内外环之间不能重叠,对于一个给定的点而言,它总是在多边形“内部”“外部”或者“边界上”,通常用于描述具有面状特性的要素。
2.高级几何对象的组成构件
高级几何对象是由一些部件组成的,如Polyline是由Path组成的,Polygon是由 Ring组成的。Path是连续的Segment的集合,除了路径的第一个Segment 和最后一个Segment外, 其余的Segment的起始点都是前一个Segment的终止点,即Path对象中的Segment不能出 现分离,Path 可以是任意数的 Line、CircularArc、EllipticArc 和 BezierCurve的组合,而 Segment是连接起点和终点的一段直线或曲线,图6.3所示为Path与Segment的示意图。Ring是一种封闭的路径,它的起止点是同一点。Ring 对象具有“内部”和“外部”属性。由于Ring 是封闭的Path,因此其组成可以看作是一系列首尾相连的同方向的Segment对象,并且不能自相交,如图6.4所示。
尽管 Polyline 由 Path 组成,Polygon 由 Ring 组成,且 Ring 和Path 都可看作是由 Segment组成,但这并不意味着用户必须有“层次”地建立一个高级几何对象。以新建一个Polyline为例,并不需要先生成一个Segment,然后由多个Segment生成 Path,再由多个Path 生成Polyline。实际上,Point 对象可以构成所有的几何形体。ArcGIS Engine 提供了 IGeometryCollection接口,让用户可以直接产生 PolyCurve类型(PolyCurve是一个抽象类, 泛化为Polyline和Polygon)的几何对象,一个IGeometryCollection是具有相同类型的几何对 象的集合。它可能是描述一条Polyline的Path集合,或者是描述路径的Segment集合,也可以直接是组成Polyline的点集合(同样也适用于Polygon的描述情况)。
几何对象的组合关系及接口如表6.1所示。