网速太慢怎么办-音乐制作软件中文版

itool
2023年4月5日发(作者:网管软件绿色)一ArcGIS介绍 1

1、1ArcGIS Engine 中的类库 5

1、2 和ArcGIS Engine开发相关的C#知识

1、2、1接口 编程

1、3C#接 口的 例子

1、3、1快速 掌握 OMD

1、4快速 理解 Q I



二. 使用控件创建第一个桌面应用程序

2、1代 码加 载 Mxd 文档

2、2添加 Shape 文 件

2、3庖丁 解牛 识控 件

2、4第一 个控 件 MapControl

2、5变主动为被动-出接口(OutBound interface)

2、6鹰眼图的实现

2、7 TOCContro 控 件

2、8显示属性表的信息

2、9命令 和工 具的 宿主控 件 ToolBarControl 控 件

2、10命令和工具

2、11脱离 ToolBarControl 控件 的命 令和 工具

2、12另一 个视 图控 件 PageLayoutControl

2、13 MapControl 控件与 PageLayout 控件的联动

2、14第一个对象 Map

2、15使用Feature方法对地图中的要素进行查询



四. 空间 数据 库

4.1 Geodatabase 介绍

4.2 Geodatabase 统一的存储框架

4、3 IWorkSpace 接 口 介绍

4、3、1 如何 打开 一个 数据库

4、3、2打开个人数据库

4、3、3打开文件数据库

4、3、4打开 SDE 数据库

4、4如何 获取 数据 库中的 所有要素类

4、4、1深入理解数据集

4、4、2获取数据库中的要素类

4、5峰回 路转 打开 数据库 的另一种方式

4、5、1 IName(名称对象)介绍

4、6如何 删除 要素 类

4、6、1 IFeatureWorkspace接 口介 绍

4、7如何 创建 一个 要素数 据类

4、8 IField,IFieldEdit,I Fields,IFieldsEditI,GeometryDef,IGeometryDefEdit 接口

4、9如何 改变 字段 的别名

4、10栅格 数据 管理

4、10、1打开 栅格 数据

4、10、2打开 栅格 目录 中的一 个数据

4、10、3创建 栅格 数据 集

4、11打开 镶嵌 数据 集

4、12创建 一个 镶嵌 数据集

4、13和查 询相 关的 对象和 接口

4、14 false 和 true 参数的差别

4、15 Search 和 Select 方法的比较

4、16 Cursor 和 FeatureCursor 对象



4、17 QueryFilter 与 SpatialFilter 对象

4、18 IFeatureSelection 接 口

4、19使用 I FeatureSelection 接口高亮显示

4、20空间 查询

4、21附件 功能

4、22和附 件相 关的 接口

4、23综合 例子 空间 查询和 创建 Table

4、24 数据 转换

4、25 Querylayer

4、26使用 查询 图层 快速浏 览



五. 几何对象和空间参考

5、1点和 多点

5、2 Segment,path,ring和Polyline的区别

5、3Envelope 几何 对象

5、4 Curve 对 象几 何 对象

5、5 Multi patch 几何 对象

5、6 Geometry 集 合 接口

5、7空间 参考



六. 矢量 数据 空间分析

6、1叠加 分析

6、2关系 操作

6、3临近 操作

6、4拓扑 关系 操作

6、5空间 插值

6、6开发 利器 GP



七. 符号 化

7、1和符 号化 相关 的对象

7、2符号 对象

7、3专题 图制 作

7、4唯一 值

7、5分类 图

7、6比例 图

7、7简单



7、8饼图

7、9点状 图

7、10柱状 图



八. 栅格 数据 分析

8、1两个 扩展 模块

8、2栅格 分析 的通 常步骤

8、3空间 分析

8、4和栅 格空 间分 析的相 关接口

8、5重要 名词 (表 面、栅格 表面、TIN表面)

8、6表面 分析

8、7专属于空间 分析的 表面分析(邻域 分析 ,单元分析 ,栅格提取, 代数 计算 等)

8、7、1邻域 分析

8、7、2密度 分析

8、7、3 3D 分 析(获取高程、通视分析)

8、7、4Tin 表面分析

8、7、5 Tin 生成 等高 线

8、8AE 创建 泰森 多边 形

8、9波段 计算 和影 像金字 塔

8、10分级 渲染

8、11拉伸



九. 编辑(IWorkspaceEdit 、IMultiuserWorkspaceEdi t)

9、1 Network dataset 分析

9、2如何创建一个无向网络

9、3线性 参考

9、3、1为什么使用线性参考

9、4什么是动态分段



十二 .安装 部署

12、2. 将 NetFramwork35sp1 ,ArcGIS Engine Runtime 一起打包









一、ArcGIS介绍

ArcGIS 软件 架构





ArcGIS 是 ESRI 在全面整合了 GIS 与数据库、软件工程、人工智能、网络技术及其它多方面的计算机主流

技术之后,成功地推出了代表 GIS 最高技术水平的全系列 GIS 产品。ArcGIS 是一个全面的,可伸缩的 GIS

平台,为用户构建一个完善的 GIS 系统提供完整的解决方案。ArcGIS 的基本体系能够让用户在任何需要的

地方部署 GIS 功能和业务逻辑,无论是在桌面、服务器、还是在野外:





桌面 GIS(ArcGIS Desktop)—ArcGIS 桌面 GIS 软件产品是用来编辑、设计、共享、管理和发布地理信息

和概念。ArcGIS 桌面可伸缩的产品结构,从 ArcReader,向上扩展到 ArcView、ArcEditor 和 ArcInfo。目

前 ArcInfo 被公认为是功能最强大的 GIS 产品。通过一系列的可选的软件扩展模块,ArcGIS Desktop 产品

的能力还可以进一步得到扩展。





嵌入式 GIS(Embedded GIS)—ArcGIS Engine 是一个完整的嵌入式 GIS 组件库和工具包,开发者能用它创

建一个新的、或扩展原有的可定制的桌面应用程序。使用 ArcGIS Engine,开发者能将 GIS 功能嵌入到已

有的应用程序中,如基于工业标准的产品以及一些商业应用,也可以创建自定义的应用程序,为组织机构

中的众多用户提供 GIS 功能。





服务器 GIS(Server GIS)—ArcGIS Server、ArcIMS 和 ArcSDE 用于创建和管理基于服务的 GIS 应用程序,

在大型机构和互联网上众多用户之间共享地理信息。ArcGIS Server 是一个中心应用服务器,它包含一个

可共享的 GIS 软件对象库,能在企业和 Web 计算框架中建立服务器端的 GIS 应用。ArcIMS 是通过开放的 I



nternet 协议发布地图、数据和元数据的可伸缩的网络地图服务器。 ArcSDE 是在各种关系型数据库管理系

统中管理

地理信息的高级空间数据服务器。





移动 GIS(Mobile GIS)— ArcPad,支持 GPS 的无线移动设备,越来越多地应用在野外数据采集和信息访

问中。ArcGIS 桌面和 ArcGIS Engine 可以运行在便携式电脑或平板电脑上,用户可以在野外进行数据采集、

分析和乃至制定决策。





ArcGIS Engine 介 绍





ArcGIS Engine 是一组完备的并且打包的嵌入式 GIS 组件库和工具库,开发人员可用来创建新的或扩展已

有的桌面应用程序。使用 ArcGIS Engine,开发人员可以将 GIS 功能嵌入到已有的应用软件中,如自定义

行业专用产品;或嵌入到商业生产应用软件中,如 Mirosoftf Word 和 Excel;还可以创建集中式自定义

应用软件,并将其发送给机构内的多个用户。





ArcGIS Engine 由两个产品组成:构建软件所用的开发工具包以及使已完成的应用程序能够运行的可再发

布的 Runtime(运行时环境)。 ArcGIS Engine 开发工具包是一个基于组件的软件开发产品,可用于构建

自定义 GIS 和制图应用软件。它并不是一个终端用户产品,而是软件开发人员的工 具包,适于为 Windows、

UNIX 或 Linux 用户构建基础制图和综合动态 GIS 应用软件。ArcGIS Engine Runtime 是一个使终端用户

软件能够运行的核心 ArcObjects 组件产品,并且将被安装在每一台运行 ArcGISEngine 应用程序的计算机

上。







?

?



ArcGIS Engine 是基于 COM 技术的可嵌入的组件库和工具包,ArcGIS Engine 可以帮助我们很轻松的构

建自定义应用程序.

使用 ArcGIS Engine,开发人员可以将 GIS 功能嵌入到已有的应用软件中,如自定义行业专用产品;

或嵌入到商业生产应用软件中,如 Mirosoftf Word 和 Excel;还可以创建集中式自定义应用软件,并

将其发送给机构内的多个用户。





ArcGIS Engine 由两个产品组成:

? 面向开发人员的软件开发包(ArcGIS Engin e Develop er kit)

? 面向最终用户的运行时(ArcGIS Engin e Run time)

ArcGIS Engine 开发工具包是一个基于组件的软件开发产品,可用于构建自定义 GIS 和制图应用软件。它

并不是一个终端用户产品,而是软件开发人员的工具包,支持四种开发环境(C++, COM, .NET,以及

Java),适于为 Windows、 UNIX 或 Linux 用户构建基础制图和综合动态 GIS 应用软件。

ArcGIS Engine Runtime 是一个使终端用户软件能够运行的核心 ArcObjects 组件产品,并且将被安装在

每一台运行 ArcGIS Engine 应用程序的计算机上。



ArcGIS Engine 的逻辑体系结构 :

◆ Ba se Se rvices

包含了 ArcEngine 中最核心的 ArcObjects 组件,几乎所有的 GIS 组件需要调用它们,如 Ge

ometry 和 Display 等。

◆ Data Acce ss

包含了访问矢量或栅格数据的 GeoDatabase 所有的

接口和类组件。

◆ Map Pre sentation

包含了 GIS 应用程序用于数据显示、数据符号化、要素标注和专题图制作等需要的接口和类

组件。





◆ Develper Components

包含了进行快速开发所需要的全部可视化控件,如 MapControl、PageLayoutControl、SceneControl、Glo

beControl、TOCControl、ToolbarControl、SymbologyControl 和 LicensenControl 控件等,除了这些,

该库还包括大量可以有 ToolbarControl 调用的内置 commands、tools、Menus,它们可以极大地简化二次

开发工作。

◆ Extensions





在图中我们可看出,ArcEngine 的开发体系是一条纵线,功能丰富,层次清晰。最上层的 Extensions 包含

了许多高级开发功能,如 GeoDatabase Update、空间分析、三维分析、网络分析、Schematics 逻辑示意图

以及数据互操作等。ArcEngine 标准版并不包含这些 ArcObjects 许可,他们只能作为扩展存在,需要特定

的 License 才能运行。





1、1ArcGIS Engine 中 的类 库





ArcGIS Engine 开发中,为了更好的管理这些 COM 对象,ESRI 将这些 COM 对象放在不同的组件库中,而他

们被物理的防盗 bin 目录下的 dll 中,而逻辑上被分散到不同的命名空间中





System

System 库是ArcGIS 架构中最底层的库。该库包含了暴露组成ArcGIS 的其它库所使用的服务的组件。

System 库中定义了许多接口,它们可以由开发者来实现。AoInitializer 对象在 System 中定义;所有开

发者必须使用该对象在使用Engine 功能的应用程序中初始化和uninitialize ArcGIS Engine。开发者不扩

展该库,但可以通过实现其中的接口来扩展ArcGIS系统。

SystemUI





SystemUI 库中包含了可在ArcGIS Engine 中扩展的用户界面组件的接口定义,包括 ICommand、ITool 和

IToolControl 接口。开发者使用这些接口来扩展UI 组件。该库所包含的对象是utility 对象,开发者可

用于简化某些用户界面的开发。开发者不扩展该库,但可以通过实现其中的接口来扩展ArcGIS 系统。

Geometry

Geometry 库处理存储在特征类(feature classes)或其它图形要素(graphical elements)中的特征的

geometry 或shape。大多数用户交互的基本几何对象有Point 、MultiPoint 、Polyline和Polygon 。除了

这些顶层的实体,还有作为Polylines 和Polygons 构建模块的几何体(geometries)。这些是组成几何体的

基元(primitives)。它们是Segments、Paths 和Rings。Polylines和Polygons 由形成一条Path 的依次相

连的Segments 组成。一个Segment 包含两个不同的点,

起点和终点,和一个定义从起点到终点的曲线的要素类型。这种segments 有 CircularArc、Line、

EllipticArc 和BezierCurve。所有的几何对象都可以有与它们顶点相关的Z、M 和IDs。基本的几何对象都

支持几何操作,如Buffer 和Clip。开

发者不可以扩展几何基元。GIS 中的实体是指现实世界中的特征;这

些现实世界中的特征的位置由具有空间参考的几何体来定义。投影和地理坐标系统的空间参考对象都包含

在Geometry 库中。开发者可以通过在空间参考间添加新的空间参考和投影来扩展空间参考系统。





Display

Display 库包含了用于GIS 数据显示的对象。除了负责实际图像输出的主要显示对象,该库中还包含了表

示颜色和符号的对象,这些颜色和符号用于控制显示上所绘制实体的属性。库中也包含了为用户在与显示

交互时提供可视化反馈的对象。开发者大都通过类似于Map 或PageLayout 对象提供的视图与显示交互。该

库的所有部分都可以被扩展,常被扩展的有符号、颜色和显示反馈(display feedbacks)。

Output

Output 库被用于创建图形输出到设备,如打印机、绘图仪和硬拷贝格式,如增强型图元文件 (enhanced

metafiles)和栅格影像格式(JPG、BMP 等)。开发者使用该库和ArcGIS 系统其它部分中的对象来创建图形

输出。通常这些是Display 和Carto 库中的对象。开发者可以扩展output 库用于定制的设备和输出格式 。

GeoDatabase

GeoDatabase 库提供了用于geodatabase 的编程API。Geodatabase 是一个构建在标准工业关系和对象数据



库技术基础上的地理数据储存库。库中的对象为ArcGIS 支持的所有数据源提供了统一的编程模型。

GeoDatabase 库定义了许多由架构中较高层次数据源提供者实现的接口。开发者可以扩展geodatabase 来

支持特殊的数据对象(Features、Classes 等)类型。此外,还可以使用PlugInDataSource 对象添加自定义

的矢量数据源。geodatabase 支持的native

数据类型不可以被扩展。





DataSourcesFile

DataSourcesFile 库包含用于基于文件数据源的GeoDatabase API 的实现。这些基于文件的数据源包括

shapefile、coverage、TIN、CAD、SDC、ArcGIS StreetMap?和VPF。开发者不能扩展DataSourcesFile 库。

DataSourcesGDB

DataSourcesGDB 库包含了用于数据库数据源的GeoDatabase API 的实现。这些数据源包括 Microsoft

Access 和SDE?软件支持的RDBMSs。开发者不能扩展DataSourcesGDB库。

DataSourceOleDB

DataSourcesOleDB 库包含用于Microsoft OLE DB 数据源的GeoDatabase API 的实现。该库只有在

Microsoft Windows 操作系统上才可以使用。这些数据源包括任何OLE DB 支持的数据提供者和文本文件工

作空间。开发者不能扩展DataSourcesOleDB库。

DataSourceRaster

DataSourcesRaster 库包含了用于Raster 数据源的GeoDatabase API 的实现。这些数据源包括 SDE 软件支

持的RDBMSs,和所有支持的RDO栅格文件格式。当需要支持新的栅格

格式时,开发者不扩展该库,而是扩展RDO。开发者不扩展DataSourcesRaste 库



GeoDatabaseDistributed

GeoDatabaseDistributed 库通过提供数据导入、导出geodatabase 的工具来支持到企业 geodatabase 的分

布式访问。开发者不扩展GeoDatabaseDistributed 库。





Carto

Carto 库支持地图的创建和显示;这些地图可以包含一幅地图或具有多幅地图和相关旁注的页中的数据。

PageLayout 对象是宿主一幅或多幅地图和相关旁注(指北针、图例、比例尺条等 )的容器。Map 对象是图层

的容器。Map 对象有操作地图中所有图层的属性:空间参考、地图比例尺等,还有操作地图图层的方法。

有多种不同类型的图层可以被加载到地图中。不同数据源通常有一个相关图层负责在地图上显示数据;矢

量特征由FeatureLayer 对象处理,栅格数据由 RasterLayer 对象处理,TIN 数据由TinLayer 对象处理等。

若需要,图层可以为它们的相关数据处理所有的绘制操作。但更常见的是图层拥有一个相关的Renderer 对

象。Renderer 对象的属性控制数据在地图中怎样显示。Renderers 一般使用 Display 库中的symbols 进行

实际绘图;renderer 只是匹配指定的符号与要绘制的实体的属性。一个Map 和一个PageLayout 可以包含

要素(elements)。要素利用几何体来定义它在地图或页面上的位置,以及控制要素显示的行为。有用于基

本形状、文本标注、复杂旁注等的要素。Carto 库也包含对地图注记和动态标注的支持。

Location

Location 库包含支持地理编码和与route 事件一起工作的对象。可通过full 控件的finegrained对象访问

地理编码功能,或GeocodeServer 对象提供了一个简化的API。开发者可以创建他们自己的地理编码对象 。

线性参考功能提供了添加事件到线性特征的对象,并使用多种绘制方法渲染这些事件。开发者可以扩展线

性参考功能。

NetworkAnalysis

NetworkAnalysis 库提供的对象在网络加载到geodatabase 中时,使用网络数据和对象populating a

geodatabase 来分析网络。开发者可以扩展该库来支持定制的网络跟踪。该库是用于utility 网络的——

gas lines、electricity supply lines 等。



Controls





开发者使用Controls 库来构建或扩展具有ArcGIS 功能的应用程序。ArcGIS Controls 通过封装

ArcObjects 和提供一个coarser-grained API,简化了开发过程。尽管控件封装了fine grained ArcObjects,

但它们并不限制访问这些ArcObjects。MapControl 和PageLayoutControl分别封装了Carto 库中的Map 和

PageLayout 对象。ReaderControl 封装了Map 和PageLayout对象,并在使用该控件时提供了简化的 API。

如果地图出版商拥有授权许可,那么开发者可

以访问Map 和PageLayout 控件的类似方式访问内部对象。该库也包含实现内容列表的 TOCControl 和宿主

与一个合适控件一起工作的命

令和工具的ToolbarControl





GeoAnalyst

GeoAnalyst 库包含支持核心空间分析功能的对象。这些功能在ArcGIS Spatial Analyst和ArcGIS 3D

Analyst?库中使用。开发者可以通过创建一个新的栅格操作类型来扩展该库。要求有ArcGIS Spatial

Analyst 或3D Analyst 许可才能使用该库中的对象。

3DAnalyst

3DAnalyst 库包含在三维场景中使用的对象,它们的工作方式类似于Carto 库中包含的对象在二维地图中

工作。Scene 对象是库中的主要对象之一,因为它与Map 对象类似,是数据的容器。Camera 和Target 对

象根据特征相对于观察者的位置,指定场景的视图。一个场景(scene)包含一个或多个图层;这些图层指定

了场景中的数据和数据怎样绘制。

3DAnalyst 库拥有一个开发控件和一组和该控件协同工作的命令和工具。该控件可以与Controls 库中的对

象联合使用。除了创建命令和工具,开发者对该库的扩展较少。使用该库中的对象需要3D Analyst 许可。

GlobeCore

GlobeCore 库包含与globe 数据一起工作的对象,工作方式类似于Carto 库中包含的对象在二维地图中工

作。Globe 对象是库中的主要对象之一,因为它与Map 对象类似,是数据的容器。GlobeCamera 对象根据

globe 相对于观察者的位置,指定了 Globe 视图。Globe 可以有一个或多个图层;这些图层指定了Globe 上

的数据和数据怎样绘制。





介绍完这些,让我们有个感性上的认识,在以后找某个对象的时候,知道去哪个 dll 中找。







1、2 和ArcGIS



Engine开发相关的C#知识









1.2.1接口 编程





使用 ArcGIS Engine,也就意味着使用里面的接口,那么什么是接口呢?在面向对象的编程中,我们都会

接触到这个玩意儿,我们知道面向对象有三大特性 封装,继承,多态,相信很多人在学习多态的时候,

会接触接口。



接口可以用这样一句话来描述“接口就是包含一系列不被实现的方法.而把这些方法的实现交给继承它的

类.”,这句话看起来很晦涩,没关系,我们通过下面一个例子说明 我定义了一个接口 IPeople





using System;

using c;

using ;





namespace InterfaceTest

{

interface IPeople

{

void gender();

}

}





这个接口里面有一个性别的方法,这个只对方法进行了定义,而方法内却没有内容,也就是说,通过这个

接口的这个 gender 方法,我们不能知道它到底干什么,但是要知道这个 gender 到底是干什么用的,那么

就要看实现了这个方法的类。同理我定义两个类,分别实现这个接口。

using System;

using c;

using ;

using ;

namespace InterfaceTest

{

class Boy:IPeople

{

public void gender()

{


ine("I’m a boy.");

}



}



}





using System;

using c;

using ;

using ;

namespace InterfaceTest

{

class Girl:IPeople

{

public void gender()

{

ine("I’m a girl.");







}



}

}





通过上面的两个类,我们就很清楚的看到这个方法的作用了,我们也可以看到一个接口可以被多个类实现。

我们运行一下这个,看一下效果

using System;

using c;

using ;

using ;

namespace InterfaceTest

{

class Program

{

static void Main(string[] args)

{

IPeople Person; // 声明接口变量



Person = new Boy(); // 实例化,接口变量中存放对象的引用

(); // 这个调用的是 Boy 中的 gender 方法

Person = new Girl(); // 实例化,接口变量中存放对象的引用

(); // 这个调用的是 Gril 中的 gender 方法

ne();







}



}

}





运行结果如下:





1、3C#接 口的 例子





1、3、1快速 掌握 OMD





我们已经知道使用 ArcGIS Engine 开发,也就意味着我们要和接口打交道,ArcGIS Engine 中提供的接口

和类加起来估计上万,但是用过 ArcGIS Engine 的人,知道这个数字不为过。ArcGIS Engine 为了帮助我

们方便的使用这些,将这些分散在不同的类库中,为了便于我们阅读,ArcGIS Engine 提供了一系列的对

象模型图,也就是 OMD (Object model diagrams) 对象模型图表。

下面图示中,便是贯穿本节的对象模型图的钥匙。





这些符号是基于 UML 画图工具创建的,UML 符号是面向对象分析和设计的工业图样标准。

对象模型图中提供的信息非常多,是对象浏览器中信息的重要补充。Visual Basic,或者其它的开发环境,

都会列出所有的类和成员,但不会指明这些类之间的关系。所以,对象模型图是非常有利于读者对 ArcInfo

组件的理解的!

本书使用 UML 来描述 ArcInfo 组件,即 ArcObjects,并描述你能够创建的数据模型。

以下详细说明。





1. 类和 对 象

在 UML 图中有三种类型的类:抽象类(abstract class)、组件类(CO class)与普通类(instantiable

class)。

抽象类:不能创建或实例化,从来没有一个抽象类的实例用于定义子类的公共接口,创建实例的任务由其

子类完成。子类继承其定义的接口。 OMD 符号为:二维的内部有阴影的矩形。

普通类:不能创建,从别的对象获得实例。 OMD 符号为:3D 矩形内部没有阴影。

组件类:可以直接创建实例的类,在 C#中,用 New 关键字。 OMD 符号为:带阴影的 3D 矩形符号。

2. 关联



在抽象类、可创建类和可实例化类之间,有几种存在的关联(或称关系)。





联系(associa

tion)便描述了类之间的关联。在两端的类中可以定义多重性( Multipli city)关联。





在这张图上,一个业主能有拥有一块或多块宗地;同样地,一块宗地可以被一个

或多个业主所共有。

多重性关联就是限制对象类与其它对象关联的数目关系。以下是用于多重性关联

的符号:

1 —— 一个并 且只有一个,这种多样性是可选的;如果不标明,则默认为“1”

0..1 —— 零个 或一个

M..N —— 从 M 到 N(正整数)

*或者 0… * —— 从零到任意正整数

1… * —— 从一到任意正整数

多个联系





在这张图上,我们可以得知有不

类继承(type inheritance)定义了专门的类,它们拥有超类的属性和方法,并且同时也有自身的属性和方

法。





上图说明 primary line 和 secondary line 是 line 的一种类型。

实例化(Instanti ation)指定一个类的对象有这样的方法,它能够创建另外一个类的对象。





pole 对象有一个方法能够创建 transformer 对象。

聚合(Aggregati on)是一种不对称的关联方式,在这种方式下一个类的对象被认为是一个 “整体”,而另一

个类的对象被认为是“部件”。





一个 transformer bank 正好有 3 个 transformer 。在这个图中 transformer 能和一个 transformer bank

相关联,但当 transformer bank 移除以后,transformer 依然能够存在。





组成(Com positi on)是一种更为强壮的聚合方式,此种方式下,“整体”对象控制着“部分”对象的生存时间。





一个 Pole 包含一个或多个 Crossarm。在这个图中当 pole 被移除后,Crossarm 就不能再使用了。因为 Pole

控制着 Crossarm 的生存时间。

在 OMD 图中,我们不仅仅能看到类之间的相互关系,还可以得到属性的一些信息,如下图:





属性和方法:

属性:哑铃状的图标,Read(左侧的实心哑铃)和 write(右侧的实心哑铃)

属性除了我们常说的类型,还有一种属性,这个属性本身就是一个对象,符号,空心的哑铃

方法:指向左侧的箭头。



ArcEngline 组件库的每一个组件中定义有不同的类,类下面定义了不同接口,接口中包含不同的属性和方

法。类之间有类型继承(Typelnheritance)关系,接口之间有互相调用(Query lnterface) 及相互继承

(Interfacelnheritance)关系。





1.1 类与对象在面向对象编程中,类和对象是两个非常重要的概念,可以这么说类就是创建对象的蓝本 ,而

对象是指具有属性和动作的实体,它封装了一个客观实体的属性与行为。ArcObjc ets 中有三类 class,分别是

抽象类(AbstractClass)、组件类(CoClass)和普通类(Class)。抽象类的主要目的是为它的子类定义公共

接口,一个抽象类将把它的部分或全

部实现延迟到子类中,因此,一个抽象类不能被实例化。一个组件类

对象可以被直接创建,普通类对象虽然不能直接创建,但它可以可以作为其它类的一个属性或者从其它类

的实例化来创建。





1.2 接口和类接口定义了一组方法和属性,在 ArcObjects 中接口名称都以”I”开始,如 IMap, Ilayer 等。类

实现了接口中的方法。一个类可以有多个接口,如 FeatureLayerClass 类有 IFeatureLayer,IFeatureSelection

等不同接口,而一个接口也可被多个类所拥有,如 CadFeatureLayer 类和 FeatureLayer 类都有 IFeatureLayer

接口。接口定义了能做什么,而定义了该怎么做(The interfacedefines what an object can do, and the class

defines how it is done.79 页 Explroing ArcObjects V9.0),在 AO 开发的时候,和对象间的通信是通过接口完

成的,而不是我们在一些其他面向对象语言如(Java)中和对象的通信是通过对象完成的.





1.3 接口查询(Query Interface) 一个类可以有多个接口,声明了接口变量并且指向一个对象的时候,这个变

量只能使用该接口内的方法和属性,而不能 访问其他接口中的方法和属性,如: Dim pMap as IMap Set pMap

= New Map p ‘这里会产生错误此时的 pMap 只能使用 IMap 接口中定义的方法和属性,比如获取

图层的个数,添加图层等,但是不能清空视图上的内容(因为这个方法是在 IActiveView 中定义的)

QueryInterface(QI)很方便的让我们在一个类的不同接口间进行切换:





Dim pView as IActiveView set pView= pMap ‘QI 现在 mView 就可以使用 IActiveView 中定义的方法了.





1.4 类类型继承类型继承是指类之间的接口类型的继承,而不是继承其实现。继承过来的接口只是名称相

同,具体的实现则不同。比如 ShpfileWorkspaceFactry 和 AccessWorkspaceFactry 都继承 WorkspaceFactry ,

而他们的打开(Op enFromFile)方法却不一样,ShpfileWorkspaceFactry 的(Op enFromFile)方法需要一个

文件目录位置作为参数,而 AccessWorkspaceFactry 的(Op enFromFile)方法需要一个数据库(mdb)位置

作为参数。1.5 接口继承如 ImapFrame 接口和 IMapSurroundFrame 接口继承于 IFrameElement 接口,则父类

接口 IFrameElement 所具有的方法和属性对派生接口 ImapFrame 和 IMapSurroundFrame 都有效。



1、4快速 理解 Q I





C#+QI 的例 子





COM 中,和我们打交道的是接口,也就是说类对我们是隐形的,那么我们要做开发,要使用这些功能,我

们只能通过接口,通过接口暴露出来的方法,COM 是一种服务器端/客户端架构,服务器端定义了操作的方

法,客户端通过接口调用这些方法。下面的这幅图很能说明 COM 的结构:





言归正传,说这篇博文的主题 QI,还记得上

一篇我强调的,一个接口可以被多个类实现,而 QI 要解决的

就是一个类实现多个接口的问题。在 COM 中,接口定义了方法,类实现了接口中定义的方法,而一个接口

只能使用自己内部定义的方法,而不能越界,就好比一个班级一样,这个班级内有班长,有学习委员,有

体育委员,每位干部各司其职,每一位干部负责自己职权范围之内的事情,各位干部相互协作,解决班级

内的事情,这班级内的每一位干部就相当于一个接口,而这个班级就相当于实现了这些接口的类。当这个

班级的一些事情需要班长处理的时候,我们就执行班长这个接口中定义的方法,当需要学习委员处理的话,

我们再将执行权交给学习委员这个接口,这也就是接口之间的互相访问(Query Interface),通过这个我

们大体上对 QI 有了感性上的认识,下面我们通过实例演示一下。

我定义了两个接口

using System;

using c;

using ;

using ;

namespace QITest

{

interface IFavoriteFood

{

void Food();

}

}

using System;

using c;

using ;

using ;

namespace QITest

{



}



interface IVoice

{

void Voice();

}



然后定义了一个Cat的类实现这里面的方法

using System;

using c;

using ;

using ;

namespace QITest

{

class Cat:IFavoriteFood ,IVoice

{

public void Food()

{

ine("我喜欢的食物是老鼠.");

}

public void Voice()

{

ine("喵,喵,喵...");







}



}



}



这个Cat类的功能就是实现两个接口的方法,猫最喜欢的事物是老鼠,而他的声音是“喵,喵,

喵”。

运行下

using System;

using c;

using ;

using ;

namespace QITest

{

class Prog ram

{

static void Main(string[] args)

{

IVoice pVoice = new Cat();

();//只能调用IVoice中定义的方法

// ();这个就会报错,因为 IVoice 接口中没有这个方法的定义

IFavoriteFood pFavoriteFood = pVoice as IFavoriteFood;

();//只能调用IFavoriteFood定义的方法

ne();







}



}



}



效果如下:





三. 使用 控件 创建 第一个桌面应用 程序







1)



建 一 个 Windows 窗 体应 用 程 序(文件--新 建--项目--Windos 窗体应用程序)





2)在 点 了确定之后 ,在 VS 的工具箱中 找到到和 ArcEngine 相 关 的 控件





其中,AxMapControl 就是 Map 地图控件,AxPageLayouControl 是布局地图控件,

AxTOCControl 是目录控件,AxToolbarControl 是 GIS 工具栏控件,

AxSceneControl 是 Scene 三维场景控件,axGlobeControl 是 Globe 控件,

AxLicenseControl

是许可控件,AxSymbologyControl 是符号选择器控件,

AxArcReaderControl 是 ArcReader 控件,AxArcReaderGlobeControl 是

ArcReaderGlobe 控件。AxLicenseControl 是许可控件,一般 GIS 系统中都必须

添加,否则无法使用。将刚才的窗体的名称改为 Engine

3)然 后 添 加 Toc, Map, Toolbar 控 件 。许可控件是首 选的,否则无法使用





添加 完 这几个控件 后,VS 会自动为我们添加一些 引用





4)添 加 地 图文档(Map 控 件-右键-属 性)





5)Toolbar 控 件 和 Toc 控件 与 Map 控 件的关联(设置 Bu ddy 属性)





6)在 Toolbar 中 进 行 设置 ( Toolbar 控 件-右键-属性-Itmes 选 项)





7)添 加 工 具命令



在 Toolbar control 上右键—属性在 items 选项卡中添 加几个工具命令





8)运 行 我们的应用 程序,发现下面的错误





出现这个问题的原因是因为 ArcGIS 10 发生了变化,将下面的语句添加到使用

AO 对象的前面:





();





如我放在 Main 函数中





利用刚才添加的打开文档的命令打开一个新的文档





也可利用上面的放大,缩小工具进行简单的操作了。





在上面,当我们将这些空间拖到窗体中的时候,会自动加载一些 dll,我们知道

ArcGIS Engine 编程,也就意味着和 COM 对象接触。





2、1代 码加 载 Mxd 文档





用代码添加 Mxd 文档,用到 File(sFilePath),我们只要将 Mxd 文档的路

径传给这个方法即可。我们添加一个按钮:





在这个按钮的单击事件中填写如下代码:





OpenFileDialog OpenMXD = new OpenFileDialog();





= "打开地图";





lDirectory = "E:";





="Map Documents (*.mxd)|*.mxd";





if (alog() == )

{





string MxdPath = me;







}



File(MxdPath);





控件的 LoadMxFile 是用来加载地图文档的





我们将刚才写的代码封装成一个函数





public string OpenMxd()

{

string MxdPath = "";



OpenFileDialog OpenMXD = new OpenFileDialog();





= "打开地图";





lDirectory = "E:";





= "Map Documents (*.mxd)|*.mxd";





if (alog() == )

{





MxdPath = me;





}







}



return MxdPath;





2、2添加 Shape 文 件





AxMapControl 还包含下面三个方法用来添加不同类型的数据





这些方法的使用和上面的相似,方法中的参数可能不同,对于 AddShapeFile 来说,它需要两个参数,第一

个参数是 shp 文件名所在的目录,第二个是文件名,因为打开 shp 文件要两个参数,所以构造一个数组,

用来返回相应的参数





代码如下:





public string[

] OpenShapeFile()

{





string[] ShpFile = new string[2];





OpenFileDialog OpenShpFile = new OpenFileDialog();



= "打开Shape文件";





lDirectory = "E:";





= "Shape文件(*.shp)|*.shp";





if (alog() == )

{





string ShapPath = me;

//利用""将文件路径分成两部分





int Position = dexOf("");





string FilePath = ing(0,Position);





string ShpName = ing(Position+1);





ShpFile[0] = FilePath;





ShpFile[1] = ShpName;





}







}



return ShpFile;





2、3庖丁 解牛 识控 件





ArcGIS Engine 中提供了很多的控件,这些控件和 ArcMap 中的一些东西有对应关系的:







ArcGIS Engine 中的 MapControl 控件和 Pag eLayoutControl 控件分别对应于 ArcMap 中的数据

视图和布局视图,MapControl 控件主要用于空间数据的显示和分析,它封装了地图对象,

而 PageLayoutControl 控件是用于地图的修饰和整理,可以用来生成专题图等,它封装了

PageLayout 对象。





TOCControl 控件 和 ToolbarControl 控件分别对应 ArcMap 中的 Table of Contents 控件和工具条

控件,这两个控件都有一个 buddy 属性,这两个控件需要和一个伙伴空间协同工作,伙伴

控件可以是 MapControl,Pag eLayoutContro,SceneControl 或者 globeControl 控件。





IMap Documen t p MapD ocum ent = ne w MapDo cum entC lass();





if ( pMapDoc ume _I sMa pDocume nt( path))

{

pMa pDocume nt. Open(path, null) ;

IMa p pMap;

for (int i = 0; i < = p MapDocum ent .MapCou nt - 1; i ++)

{

pM ap = pMapD ocu _Ma p(i);

Co nso eLi ne(pMap. Nam e);

IE num Layer p Enu mLayer = pM _ Lay ers(n ull, tr ue);

pE num Layer.R ese t();

IL aye r pLaye r = pEnumLa yer .Next() ;

wh ile (pLaye r ! = n ull )

{

C ons teL ine(pLay er. Name);







}



p Lay er = pE num xt( );



}



}





2、4第一 个控 件 MapControl





MapControl 对应于 ArcMap 中的数据视图,它封装了 Map 对象,并提供了额外的属性,方法,事件等。在

ArcGIS Engine 的帮助文件中,我们可以看到 MapControl 主要实现了如下接口:





在前面的例子中,我们已经看到如何使用 MapControl 加载 Mxd 文档和 Shp 文件等。下面

我们通过实现鹰眼图这个功能来进一步学习 MapControl 控件。在实现鹰眼图之前,我们需

要接口有更深入的了解。





2、5变主动为被动-出接口(OutBound interface)





COM 编程类似客户端和服务器端的两层结构,COM 所建立的是一个软件模块与另一个软

件模块之间的链接, 当这种链接建立之后, 模块之间就可以通过被称之为 Interface“接口 ”

的机制来进行通信。在绝大部分情况下, 客户

应用程序与组件的通信过程是单向的, 客户创

建组件对象, 然后客户通过接口调用对象所提供的功能, 在适当的时候再把对象释放掉。在



这种交互过程中, 客户总是主动的, 而组件总是处于被动状态, 通过自身暴露给客户的接

口监听客户的请求, 一旦接收到客户的请求便做出反应,这些反应的“幕后“,也就是代码

是被屏蔽掉的,我们是看不到这些接口内的方法是如何实现的。这样的接口称为入接口

InBound Interface,但是对于一个全面交互过程来说, 这样的单向通信往往是不能满足实

际的需要, 组件对象也要主动与客户进行通信, 因此, 与入接口相对应, 对象也可以提供出

接口 OutBound interface,对象通过这些出接口与客户进行通信。之所以把这些接口称为

出接口, 其原因在于这些接口并不由 COM 服务器端的对象实现, 而是由客户程序自己来

实现, 客户实现这些接口, 服务器端调用此接口的成员函数, 即调用了客户自定义的函数,

这时组件对象变成了客户端的客户。也就是说出接口的实现是由我们自己实现,而被服务器

调用,这样的接口,我们往往称之为事件接口,这些接口里面定义了一些如 OnMouseUp,

OnMouseMove 等函数,当相应事件发生的时候,由服务器去执行这个事件里面的内容。





2、6鹰眼图的实现





鹰眼图的实现用到控件如下::







控件名称
控件类型
备注
axMapControl1

主图
axMapControl2

鸟瞰图
axToolbarControl1


axTOCControl1






分析:鹰眼图的操作主要由以下几个动作,当在一个控件中移动一幅图的时候另一控件中的

图也发生变化,当在主控件中重新加载一幅图的时候,另外一个控件的图也发生相应的变化,

同时我们在鸟瞰的控件中加入一红色边框,注意这个其实是一个面,只是填充的颜色是透明

的而已。通过分析我们知道,我们要添加两个 MapControl 控件,名字分别是 axMapControl1

和 axMapControl2,其中 axMapControl1 为主图,而 axMapControl1 为鸟瞰图。





对于名称为 axMapControl1 的 MapControl 控件,只需要在 axMapControl1 的 OnExtentUpdated

和 OnMapReplaced 中分别添加以下代码:





private void axMapControl1_OnExtentUpdated(object sender,

IMapControlEvents2_OnExtentUpdatedEvent e)



{



// 得到新范围





IEnvelope pEnvelope = (IEnvelope)elope;





IGraphicsContainer pGraphicsContainer = as IGraphicsContainer;





IActiveView pActiveView = pGraphicsContainer as IActiveView;





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





AllElements();





IRectangleElement pRectangleEle = new RectangleElementClass();





IElement pElement = pRectangleEle as IElement;





ry =

pEnvelope;





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





IRgbColor pColor = new RgbColorClass();





= 255;





= 0;





= 0;





arency = 255;





//产生一个线符号对象





ILineSymbol pOutline = new SimpleLineSymbolClass();





= 3;





= pColor;





//设置颜色属性





pColor = new RgbColorClass();





= 255;





= 0;





= 0;





arency = 0;





//设置填充符号的属性





IFillSymbol pFillSymbol = new SimpleFillSymbolClass();





= pColor;





e = pOutline;





IFillShapeElement pFillShapeEle = pElement as IFillShapeElement;





= pFillSymbol;





ment((IElement)pFillShapeEle, 0);







}



lRefresh(ewGraphics, null, null);





private void axMapControl1_OnMapReplaced(object sender,

IMapControlEvents2_OnMapReplacedEvent e)

{





if (ount > 0)

{

= new MapClass();





for (int i = 0; i <= ount - 1; i++)

{

er(_Layer(i));



}

= ;





h();







}



}





对于名称为 axMapControl2 的 MapControl 控件,只需要在 axMapControl2 的 OnMouseMove 和 OnMouseDown

中分别添加以下代码:





private void axMapControl2_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent

e)

{

if ( == 1)

{

IPoint pPoint = new PointClass();





rds(, );





At(pPoint);







null, null);



lRefresh(ewGeography,







}



}







e)



private void axMapControl2_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent

{

if (ount > 0)

{

if ( == 1)

{

IPoint pPoint = new PointClass();





rds(, );



At(pPoint);





lRefresh(ewGeography, null, null);

}

else if ( == 2)

{

IEnvelope pEnv = ectangle();





= pEnv;





lRefresh(ewGeography, null, null);







}



}



}





运行后的效果如下:





2、7 TOCContro 控 件





TOCControl 控件使用的是用伙伴控件中的数据地图,它控制图层是否在伙伴控件空显示以及

和伙伴控件在符号上保持一致,TOCControl 为用户提供了一个交互式的环境,如果

TOCControl 控件的伙伴控件是 MapControl 控件,当我们将 TOCControl 控件中图层删掉是,

MapControl 控件中相应的图层也会被删掉。



2、8显示属性表的信息







我们知道 ArcMap 中的 Table of Contents 有很多功能,如下图:





而 ArcGIS Engine 提供的 TOCControl 控件几乎没有提供,那么这些都是需要自己开发的,在

这里我做一个显示属性表的功能。





分析:要显示某一个图层的属性表,首先要将这个图层选中,然后在另外一个 Form 中将选

中的这个图层的属性信息进行显示。





添加一个上下文菜单,添加一个新的 Form 窗体,在这个新的窗体上添加 GridView 控件,并

在 TOCControl 控件的 OnMouseDown 事件下添加如下代码(pGlobalFeatureLayer 是我定义的一个全局变量):





private void axTOCControl1_OnMouseDown(object sender,

ntrolEvents_OnMouseDownEvent e)

{





if (ount > 0)

{



esriTOCControlItem pItem = new esriTOCControlItem();





pGlobalFeatureLayer = new FeatureLayerClass();





IBasicMap pBasicMap = new MapClass();





object pOther = new object();





object pIndex = new object();





t(e.x, e.y, ref pItem, ref pBasicMap, ref

pGlobalFeatureLayer, ref pOther, ref pIndex);

}





if ( == 2)

{

(axTOCControl1, e.x, e.y);

}





}





在上下文菜单的打开属性表的 Click 事件中添加如下代码:





private void 打开属性表ToolStripMenuItem_Click(object sender, EventArgs e)

{

FormTable Ft = new FormTable(pGlobalFeatureLayer as IFeatureLayer);





();





}





在新的窗体中添加一个将属性表显示到 GridView 控件中的函数,如下:





public void Itable2Dtable()

{





IFields pFields;

pFields = ;





Count = ount;



for (int i = 0; i < ount;i++ )

{





string fldName = _Field(i).Name;

s[i].Name = fldName;





s[i].ValueType =

e(ParseFieldType(_Field(i).Type));

}





IFeatureCursor pFeatureCursor;

pFeatureCursor = (null, false);





IFeature pFeature;

pFeature = ature();

while (pFeature != null)

{

string[] fldValue = new string[ount];





for (int i = 0; i < ount; i++)

{

string fldName;

fldName = _Field(i).Name;

if (fldName==pFeatureLayer .FeatureClass .ShapeFieldName)

{

fldValue[i] = ng(ryType);

}

else

fldValue[i] = ng(_Value(i));

}

(fldValue);

pFeature = ature();





}





}





运行后,效果如下:





2、9命令 和工 具的 宿主控 件 ToolBarControl 控 件





在 ToolBarControl 控件中,我们通过 ToolBarControl 控件的属性页面添加了一些如打开文档,

平移,放大等功能,在 ArcGIS Eng ine 中我们将宿主在 ToolBar

Control 控件中的内容分为三类

“命令,工具,工具控件“





命令,就是当用户单击时所产生的操作,比如说,我们要打开一个地图文档,我们只需要在

ToolBarControl 控件上添加打开地图文档这个操作,然后用鼠标点击。





工具,存在着交互这个操作。当我们在 ToolBarControl 控件上使用一个工具的时候,我们需

要通过两步操作:(1)单击这个工具,(2)使用这个工具更相应的控件做交互操作。





如果我们点击了平移这个操作,那么这个时候我们还要用鼠标和地图进行平移等交互,那和

谁交互呢,我们知道 ToolBarControl 有一个 buddy 属,这个就体现了在 budy 属性上。

ToolbarControl 会将伙伴控件的 CurrentTool 属性设置为我们用鼠标点击的工具,然后伙伴控

件就等着和我们的工具交互。





工具控件,这通常是用户界面组件,如 ToolBarControl 控件上的列表框和组合框。





其实在 ToolBarControl 控件中还可以宿主工具条菜单(ToolbarMenu),工具条菜单表示单击

命令项的一个垂直列表。用户必须选择工具条菜单上的一个命令项,或单击工具条菜单之外

的地方使其消失。工具条菜单只能驻留命令项(不允许驻留工具或者工具控件)





2、10命令和工具





在 ArcGIS Eng ine 中,命令是实现了 ICommand 接口,在 ArcGIS Eng in 的开发帮助中,我们可

以看到 ICommand 接口以下成员:





当用户单击这个命令时会导致 k 方法 被调 用 ,并 执行 某种 操作。





要将 一个 命令宿主到 ToolBarControl 控 件上 ,有 以下 三 种方 法:







1.



使用 UID







2.



使用 progID







3.



使用 ICommand





UID pUID = new UIDClass();





= "lsUndoCommand";





m(pUID, -1, 0, false, -1,

mmandStyleIconOnly);





m("lsUndoCommand", 0, -1, true, 0,

mmandStyleIconOnly);





ICommand pUndo = new ControlsUndoCommandClass();





m(pUndo, 0, -1, false, 0, mmandStyleIconOnly);





ICommand 接口 是 可以 被扩 展的 ,也 就是说这个接口对我们 是开放 的, 只要我 们将

ICommand 接口 中 成员 实现 ,因 为这 个格式是固定的,Esri 提供 了相应的模板





我们知道宿主在 ToolBa rControl 上的 命令操作的对象是 ToolBa rControl 的伙 伴控件 ,但

是, 这个 命令怎么和 这个伙 伴控件 联系 起来了 ,注意到 ICommand 接 口中 有一个

te 方法 ,这 个方 法有 一个 参数 hook。





[C #]

p u b l i c vo id O n C r e a t e (

object ho ok

) ;





这个 hook 是 一个 object 对 象。也就是 说这儿命令和

那个控件协作 ,要看这个 hook 传入 的

是那 种控 件。



当命令对象宿主到 ToolBarControl 控件上后就会立即调用 te 方法,同时会

将 ToolBarControl 控件传递给 hook 这个参数,以便命令能和 ToolBarControl 控件的伙伴控件

协作。一般要在这个方法里面要测试这个 hook 是不是有效,也就是说这个命能不能和这个

hook 协作,要看这个命令支不支持这样的操作,比如说我们要打开一个地图文档,我们知

道打开地图文档这个命令是可以和 MapControl,Pag eLayoutControl 控件协作的,如果我们传

进去的是 TOCContro 控件,那么这个命令就会失效,这些话看起来很费解,我们通过一个代

码来好好体会这些话。





我们 自己 定义一个打 开地图 文档的 命令





利用 Esri 提 供的 命 令模 板





选择 和命 令对象协作 的控件





using System;

using g;

using pServices;

using asses;

using ;

using ls;

using ;

using ;





namespace EngineApplication

{

///

/// Summary description for OpenMxdCommand.

///


[Guid("c142fea5-2e8e-4f68-95e1-9cad4a6a290e")]

[ClassInterface()]

[ProgId("dCommand")]

public sealed class OpenMxdCommand : BaseCommand

{

#region COM Registration Function(s)

[ComRegisterFunction()]

[ComVisible(false)]

static void RegisterFunction(Type registerType)



{



// Required for ArcGIS Component Category Registrar support

ArcGISCategoryRegistration(registerType);







}



//

// TODO: Add any COM registration code here

//





[ComUnregisterFunction()]

[ComVisible(false)]

static void UnregisterFunction(Type registerType)

{

// Required for ArcGIS Component Category Registrar support

ArcGISCategoryUnregistration(registerType);







}



//

// TODO: Add any COM unregistration code here

//





#region ArcGIS Component Category Registrar generated code

///

/// Required method for ArcGIS Component Category registration -

/// Do not modify the contents of this method with the code editor.

///


private static void ArcGISCategoryRegistration(Type registerType)

{

string regKey = ("HKEY_CLASSES_ROOTCLSID{{{0}}}",

);

er(regKey);





}

///

/// Required method for ArcGIS Component Category unregistration -

/// Do not modify the contents of this method with the code editor.

///


private static void ArcGISCategoryUnregistration(Type registerType)

{

string regKey = ("HKEY_CLASSES_ROOTCLSID{{{0}}}",

);

ster(regKey);





}





#endregion

#endregion





IMapControl2 pMapControl

;





public OpenMxdCommand()

{

//

// TODO: Define values for the public properties

//

base.m_category = "打开地图文档"; //localizable text

base.m_caption = "打开地图文档"; //localizable text

base.m_message = "打开地图文档"; //localizable text

base.m_toolTip = "打开地图文档"; //localizable text

base.m_name = "打开地图文档"; //unique id, non-localizable (e.g.

"MyCategory_MyCommand")







try

{

}



//

// TODO: change bitmap name if necessary

//

string bitmapResourceName = GetType().Name + ".bmp";

base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);



}



catch (Exception ex)

{

ine(e, "Invalid Bitmap");

}





#region Overridden Class Methods





///

/// Occurs when this command is created

///


/// Instance of the application

public override void OnCreate(object hook)

{

if (hook == null)

return;

//在这里对hook进行判断





if (hook is IToolbarControl)







{

}



IToolbarControl pToolBar= hook as IToolbarControl ;

pMapControl = as IMapControl2;



else if(hook is IMapControl2 )

{

pMapControl = hook as IMapControl2;

}







}



// TODO: Add other initialization code





///

/// Occurs when this command is clicked

///


public override void OnClick()

{

// TODO: Add k implementation





//launch a new OpenFile dialog

OpenFileDialog pOpenFileDialog = new OpenFileDialog();

= "Map Documents (*.mxd)|*.mxd";

elect = false;

= "Open Map Document";

if (alog() == )

{

string docName = me;





IMapDocument pMapDoc = new MapDocumentClass();

if (_IsPresent(docName)

&& !_IsPasswordProtected(docName))

{





File(me, null, null);





// set the first map as the active view



h();





();







}



}



}







}



}



#endregion





通过 下面 两句将我们 自定义 的打开 地图 文档的 命令宿主到 ToolBarControl 上





OpenMxdCommand pMxdCommand = new OpenMxdCommand();

m(pMxdCommand, -1, 0, false, -1,

mmandStyleIconOnly);





效果如下:



我们可以对上述代 码添加 断点 ,发 现当程 序执行到 m(pMxdCommand, -1, 0,

false, -1, mmandStyleIconOnly);的时候,OnCreate 函数被执行,进而对 hook

参数判断,通过进一步跟踪,发现程序执行到





if (hook is IToolbarControl)







{

}



IToolbarControl pToolBar= hook as IToolbarControl ;

pMapControl = as IMapControl2;





说明程序将 ToolbarControl 控件传入进去。






而工 具是 实现了 Itool 和 ICommand 这两 个接 口, 从 ITool 的接 口成 员中 我们 就不难看出

工具 和命 令的区别:





ITool 接口的成员几乎都是和交互相关的一些事件.





上述我们都是将命令或者工具宿主到了 ToolBarControl 控件上,能不能脱离 ToolBarControl 控件呢?答

案是可以的。



2、11脱离 ToolBarControl 控件 的命 令和 工具





我们在 Form 中添加 MenueStrip 控件,并添加以下几个功能,然后分别写入相应的代码





private void 文件ToolStripMenuItem_Click(object sender, EventArgs e)

{

ICommand pMxd = new ControlsOpenDocCommandClass();





te();







}



k();





private void 查询ToolStripMenuItem_Click(object sender, EventArgs e)

{

ICommand pAddData = new ControlsAddDataCommandClass();





te();







}



k();





private void 空间分析ToolStripMenuItem_Click(object sender, EventArgs e)

{

ICommand pZoomIn = new ControlsMapZoomInToolClass();





te();





tTool = pZoomIn as ITool;





}





private void 缩小ToolStripMenuItem_Click(object sender, EventArgs e)

{

ICommand pZoomOut = new ControlsMapZoomOutToolClass();





te();







}



tTool = pZoomOut as ITool;





通过运行程序,发现和 toolbarcontrol 的效果一样





2、12另一 个视 图控 件 PageLayoutControl





在 ArcMap 中除了在介绍 MapControl 控件的时候提到的数据视图,还有另外一种视图,就

是布局视图(Layout),PageLlayoutControl 控件则对应了 ArcMap 中的布局视图。

PageLayoutControl 控件主要用于制图,它可以方便的操作各种元素对象,以产生一副精美的

地图对象出来。该控件中封装了一个 Pag eLayout 对象,这个对象用于控制布局视图中的对

象的属性。





2、13 MapControl 控件与 PageLayout 控件的联动





分析:要实现这两个控件的联动,我们首先回顾下 ArcMap 中的情景,两个控件的联动不仅

仅是简单的切换,在切换的时候还因该保留各自控件上的一些状态,比如说当我们在

MapControl 上有一个放大操作时,当我们没有将这个放大操作取消而切换到 PageLayout 控

件,在 PageLayout 控件上做了一些操作后,又切换到 MapControl 控件,我们应该还应该能

进行放大操作而不用重新使用放大这个工具。





通过分析我们可以得到下面几点:





当切换两个控件的时候,地图的同步





各自控件上激活的工具或者命令的保留





当存在 TOC 控件和 ToolBar 控件的时候,切换了地图控件和布局控件,那么这两个控件的伙

伴控件也应发生变化。



在 Form 中添加 TabControl 控

件,分别将地图控件和布局控件放置到里面,如下图所示:





我们在 NET 中定义一个类,这个类用来实现这两个功能,类的名称是 ControlsSynchronizer





///

/// 在构造函数中传入地图控件和布局控件

///


///

///

public ControlsSynchronizer(IMapControl3 _MapControl, IPageLayoutControl2

_PageLayoutControl)

: this()

{

//assign the class members

pMapControl = _MapControl;



}



pPageLayoutControl = _PageLayoutControl;





///

/// 激活地图控件并销毁布局控件

///


public void ActivateMap()

{

try

{

if (pPageLayoutControl == null || pMapControl == null)

throw new Exception("ControlsSynchronizer::ActivateMap:

Either MapControl or

PageLayoutControl are not initialized!");





//cache the current tool of the PageLayoutControl

if (tTool != null) pPageLayoutActiveTool =

tTool;





//deactivate the PagleLayout

vate();





//activate the MapControl

te();







tool



//assign the last active tool that has been used on the MapControl back as the active

if (pMapActiveTool != null) tTool = pMapActiveTool;





pIsMapControlactive = true;







}



//on each of the framework controls, set the Buddy control to the MapControl

dies();



catch (Exception ex)

{

throw new Exception(("ControlsSynchronizer::ActivateMap:

{0}",

e));

}

}





///

/// 激活布局控件并销毁地图控件

///


public void ActivatePageLayout()

{

try

{

if (pPageLayoutControl == null || pMapControl == null)

throw new Exception("ControlsSynchronizer::ActivatePageLayout:

Either MapControl

or PageLayoutControl are not initialized!");





//cache the current tool of the MapControl

if (tTool != null) pMapActiveTool = tTool;





//deactivate the MapControl

vate();





//activate the PageLayoutControl

te();





//assign the last active tool that has been used on the PageLayoutControl back as the

active tool

if (pPageLayoutActiveTool != null) tTool =

pPageLayoutActiveTool;





pIsMapControlactive = false;







}



//on each of the framework controls, set the Buddy control to the PageLayoutControl

dies();



catch (Exception ex)

{

throw new Exception(("ControlsSynchronizer::ActivatePageLayout:

{0}",

e));

}

}





///

/// 当激活的控件发生变化时,IToolbarControl控件和ITOCControl控件的伙伴控件也应发生变化



///


/// the active control

private void SetBuddies(object _buddy)

{

try

{

if (_buddy == null)

throw new Exception("ControlsSynchronizer::SetBuddies:

Target Buddy Control is not

initialized!");







}



foreach (object obj in pFrameworkControls)

{

if (obj is IToolbarControl)

{

((IToolbarControl)obj).SetBuddyControl(_buddy);

}

else if (obj is ITOCControl)

{

((ITOCControl)obj).SetBuddyControl(_buddy);

}

}



catch (Exception ex)

{

throw new Exception(("ControlsSynchronizer::SetBuddies:

{0}",

e));

}

}





///

/// 如果地图发生了变化,那么地图控件和布局控件的地图也应发生变化

///


///

public void ReplaceMap(IMap _NewMap)

{



if (_NewMap == null)

throw new Exception("ControlsSynchronizer::ReplaceMap:

New map for replacement is

not initialized!");





if (pPageLayoutControl == null || pMapControl == null)

throw new Exception("ControlsSynchronizer::ReplaceMap:

Either MapControl or

PageLayoutControl are not initialized!");





//create a new instance of IMaps collection which is needed by the PageLayout

IMaps pMaps = new Maps();

//add the new map to the Maps collection

(_NewMap);





bool bIsMapActive = pIsMapControlactive;





//call replace map on the PageLayout in order to replace the focus map

//we must call ActivatePageLayout, since it is the control we call 'ReplaceMaps'

tePageLayout();

eMaps(pMaps);





//assign the new map to the MapControl

= _NewMap;





//reset the active tools

pPageLayoutActiveTool = null;

pMapActiveTool = null;







}



//make sure that the last active control is activated

if (bIsMapActive)

{

teMap();

h();

}

else

{

tePageLayout();

h();

}





///

/// 当运行应用程序的时候,即便没有加载地图,则创建一个空的地图,让这两个控件和这个地图绑



定在一起,这样就能保持一致

///


/// true if the MapControl supposed to be activated

first

public void BindControls(bool _ActivateMapFirst)

{

if (pPageLayoutControl == null || pMapControl == null)

throw new Exception("ControlsSynchronizer::BindControls:

Either MapControl or

PageLayoutControl are not initialized!");





//创建一个地图实例

IMap pNewMap = new MapClass();





= "Map";





//其中Maps为我们创建的一个类,表示的是地图的集合

IMaps pMaps = new Maps();

//add the new Map instance to the Maps collection

(pNewMap);





//call replace map on the PageLayout in order to replace the focus map

eMaps(pMaps);

//assign the new map

to the MapControl

= pNewMap;





//reset the active tools

pPageLayoutActiveTool = null;





pMapActiveTool = null;







}



//make sure that the last active control is activated

if (_ActivateMapFirst)

teMap();

else

tePageLayout();





还记得我们上次创建的那个打开地图文档的命令?





在打开地图的时候,我们只不过是将这个地图付给了 Map 控件,这样的话布局控件是

得不到图的,因此应该对 OnClick 改动下,在这个里面将 map 控件和布局控件同步起来



public override void OnClick()







{



//launch a new OpenFile dialog

OpenFileDialog dlg = new OpenFileDialog();

= "Map Documents (*.mxd)|*.mxd";

elect = false;

= "Open Map Document";

if (alog() == )

{

string docName = me;





IMapDocument pMapDoc = new MapDocumentClass();





if (_IsPresent(docName) && !_IsPasswordProtected(docName))

{

(docName, );





// set the first map as the active view

IMap map = _Map(0);

iveView((IActiveView)map);





yout = yout;





eMap(map);





();







}



}



m_sDocumentPath = docName;



}





在ControlsSynchronizer类中使用的Maps类的代码如下:





namespace EngineApplication

{

///

/// Implementation of interface IMaps which is eventually a collection of Maps

///


public class Maps : IMaps, IDisposable



{



//class member - using internally an ArrayList to manage the Maps collection

private ArrayList pArray = null;





#region class constructor

public Maps()

{

pArray = new ArrayList();

}

#endregion





#region IDisposable Members





///

/// Dispose the collection

///


public void Dispose()

{

if (pArray != null)

{

();

pArray = null;

}

}





#endregion





#region IMaps Members





///

/// Remove the Map at the given index

///


///

public void RemoveAt(int Index)

{

if (Index > || Index < 0)

throw new Exception("Maps::RemoveAt:

Index is out of range!");







}



At(Index);





///

/// Reset the Maps array

///




public void Reset()

{

();

}





///

/// Get the number of Maps in the collection

///


public int Count

{

get

{

return ;

}

}





public IMap get_Item(int Index)

{

if (Index > || Index < 0)

throw new Exception("Maps::get_Item:

Index is out of range!");







}



return pArray[Index] as IMap;





///

/// Remove the instance of the given Map

///


///



public void Remove(IMap Map)

{

(Map);

}





///

/// Create a new Map, add it to the collection and return it to the caller

///


///

public IMap Create()

{

IMap newMap = new MapClass();

(newMap);





return newMap;



}





///

/// Add the given Map to the collection

///


///

public void Add(IMap Map)

{

if (Map == null)

throw new Exception("Maps::Add:

New Map is mot initialized!");







}



(Map);







}



}



#endregion





2、14第一个对象 Map





地图是 GIS 中的重要概念,也是 GIS 的应用中的成果,GIS 的很多成果都是用地图来说话的,

当我们打开 ArcMap 程序后,首先看到的是数据视图(ArcMap 有两种视图,数据视图和布

局视图)骂我们看到的这个数据视图其实就是一个 Map 对象。





在 ArcMap 中,可以显示在 Map 中的数据有两大类,也就是地理数据和图形元素,空间数

据是 GIS 分析制图的数据源,保存在地理数据库库或者 Shp 文件中,图形元素也是一种可以

在 Map 上显示的对象。他们两个的共同特征是拥有一个 g eomtry 属性。

地图对象是地图数据的容器,它由图层和图形数据组成。Map 对象实现了众多的接

口,如下:





IMap 接口





该接口主要用于管理 Map 对象中的图层对象,要素选择集和空间参考等对象,IMap 接口也

往往是我们一个任务的起点。使用 IMap 接口,我们可以获取这个Map 对象中的图层的个数,

可以添加图层,删除图层,还可以利用 IMap 实现查询的高亮显示。IMap 接口提供了两个和

查询相关的方法 ByShape 方法和 Feature 方法。





Feature 方法可以将在 Map 中获得的一个要素放到这个要素的图层选择集中,这

个方法有一个很重要的用途就是这个方法能使获取的要素高亮显示





使用 ByShape 方法对地图中的要素进行查询





[C #]



p u b l i c vo id S e l e c t B y S h a p e (

IGeome try Shape,

ISelec tio nEnvir onment env ,

bool j ust One

) ;





ByShape 方法将会在 Map 中的所有图层中进行查询,这个方法需要三个参数,

第一个参数是一个 Geomtry 对象,ByShape 在查询的时候凡是和我们输入进去

的这个几何对象相交的要素都会查询出来,但是这有一个前提就是每一个要素图层的

Selectable 属性是 true。





第二个参数 ISelectionEnvironment,ISelectionEnvironment 参数控制着 构造选择集的结果和显示的

方法等。





第三个参数是一个 bool 值。

我们在 Ma pC ontrol’控件中画一个多边形的面,查找出和我们这个多边形面相交的所有图层中的要素





IGeometry pGeo =axMapC

olygon();





ByShape(pGeo, null, false);







效果如下:



h();







2、15使用Featur方法对地图中的要素进行查询



2、15使用Feature方法对地图中的要素进行查询

[C #]

p u b l i c vo id S e l e c t F e a t u r e (

ILayer La yer,

IFeatu re Feature

) ;



void SearchHightlight(IMap _pMap,IFeatureLayer _pFeatureLayer, IQueryFilter _pQuery, bool

_Bool)

{

IFeatureCursor pFtCursor = _(_pQuery, _Bool);





IFeature pFt = ature();





while (pFt != null)

{

_Feature(_pFeatureLayer as ILayer, pFt);





pFt = ature();







}



}





效果 如下 :





IGraphicsContainer 接口





在介绍 Map 对象的时候,我们说过 Map 不仅仅可以显示空间数据,还可以对一些元素进行

显示,Map 对象通过 IGraphicsContainer 接口来管理这些元素对象。



IActiveView 接口





IActiveView 接口定义了 Map 对象的数据显示功能,这个接口管理着绘制图形的显示范围。

在 ArcMap 中,我们已经知道有两种视图数据视图和布局视图,而在 ArcGIS Eng ine 中有两

个对象实现了这个接口 Map 和 Pag eLayout。





IActiveView 接口有一个很重要的方法 PartialRefresh,该方法可以让视图对象使用不同的方

式来局部刷新以便重新绘制。





ILayer





ILayer 接口是被图层(Layer)对象实现的,图层对象是用来在地图中显示空间信息,注意,

图层不含有空间数据,它只是获取数据的一个引用层而已。图层对象是一个抽象对象,它定

义了所有图层的公共方法和属性,它拥有很多子类,如 IFeatureLayer,IGeoFeatureLayer,

ICadFeatureLayer,IRasterLayer。图层相当于要素的载体,当用 ArcMap 将要素类打开后就成

为了图层。





IFeatureLayer





IFeatureLayer 接口用于管理要素类(Featureclass)图层的信息 。IFeatureLayer 有一个非

常重要的方法 ,这个方法用于对要素图层中符合要求的数据进行查询。



IGeoFeaturelayer





该接口主要用于控制要素图层中宇地理相关的内容,如要素类着色和渲染,以及空间范围等。

IGeoFeatureLayer 有一个很重要的属性 er,使用这个属性,我们就可

以对空间数据符号化。





四. 空间 数据 库





空间 数据 库介 绍





4.1 Geodatabase 介绍





Geodatabase 是 ESRI 在 ArcInfo8 中引入的一种全新的面向对象的空间数据模型,在物理级别上空间数据





库分为三种不同的存储形式,即个人数据库,文件数据库,以及面向企业的 SDE 数据库,个人数据库依赖





于微软的 ACCESS 数据库,也只能在 windows 平台上运行,除此之外个人数据

库有容量的限制,最大存储量





不能超过 2GB,文件数据库以二进制方式管理空间数据,单张表可以存储 1TB,可以通过关键字进行配置,是





容量可以扩充到 256TB,从这个数据存储层面来说,文件数据库的容量是无限的,而且可以在多个平台上运





行,如 linux,unix,但是它和个人数据库有一个相同点,就是不能多人同时编辑,而 Sde 数据库除了多





人同时编辑数据之外,还提供了一些其他高级功能,如同步复制,历史归档等,同时 SDE 数据库也可以运





行在多个平台上,通过 SDE 将空间数据存储在目前流行的关系型数据库中,目前 SDE 支 持 5 中数据库(oracle,





sql server,db2, infomix,postgresql);在逻辑上,空间数据库采用统一的框架,为管理空间数据提





供了统一的模式。





Geodatabase 是一种面向对象的数据模型,在此模型中, 它不仅管理和存储了空间数据,还定义了空间实





体之间的相互关系,如空间中的实体可以表示为具有性质、行为等。



Geodatabase 还支持表达具有不同类型特征的对象,包括简单的物体、地理要素(具有空间信息的对





象)、网络要素(与其他要素有几何关系的对象)、拓扑相关要素、注记要素以及其他更专业的特征类型。该





模型还允许定义对象之间的关系和规则,从而保持地物对象间相关性和拓扑性的完整。





4.2 Geodatabase 统一的存储框架





Geodatabase 以层次结构的数据对象来组织地理数据。这些数据对象存储在要素类 (Feature Classes)、





对象类(0bject classes)和数据集 (Feature datasets)中。Object Class 可以理解为是一个在 Geodatabase





中储存非空间数据的表。而 Feature class 是具有相同几何类型和属性结构的要素(Feature)的集合。





要素数据集(Feature datasets)是共用同一空间参考要素类的集合。要素类 (Feature Class)储存可以在要





素数据集(Feature datasets)内部组织简单要素,也可以独立于要素数据集(Feature datasets)。独立于





要素数据集(Feature datasets)的简单的要素类(Feature Class)称为独立要素类 (Feature class)。存储





拓扑要素( Feature )的要素类必须在要素数据集(Feature dataset)内,以确保一个共同的空间参考。





注意表的地位和要素数据集是等同的,也就是说,表是不能存储在要素数据集中。





Geodatabase 的基本体系结构包括要素数据集、栅格数据集、 TIN 数据集、独立的对象类、独立的要素类 、





独立的关系类和属性域等,如下图:







在上图中我们可以看到最顶级的工作空间。



数据库在 ArcGIS Engine 中被抽象为一个工作空间





(Worksapce),下面的 OMD 图描述了空间数据库的结构:





4、3 IWork

Space 接 口 介绍





IWorkspace 接口提供访问工作空间的通用属性和方法,如它的连接属性,以及包含的数据集的方法。



4、3、1 如何 打开 一个 数据库





要打开一个数据库,也就意味着我们要得到那个工作空间,而工作空间是一个普通类,也就意味着我们只





能从其他类来得到这个工作空间,这个类就是工作空间工厂(WorkspaceFactory),而这个类又是一个抽





象类,也就意味着我们只能使用它的子类来实例化一个对象,WorkspaceFactory 有众多的子类,我们可以





从 OMD 图中获得



在这里说明下,shapefile 是 Esri 早期的空间数据格式,以文件管理,shapefile 文件所在的文

件夹也被抽象为一个 workspace,相应的要的到 shapefile,就要用到啥喷

shapefileworkspacefactory





IWorkSpaceFactory 是 Geodatabase 的入口,它定义了数据库的通用属性,比如打开,创建等,我们在 ArcGIS





Engine 的帮助中可以详细的得到它的信息,如下图:





打开数据库有两种方式,从上面的图表中也可以看出 OpenFromFile 方法和 Open 方法,这两者的区别在于





方法中的参数不同,其中 Open 方法需要一个 IPropertySet 对象,这个方法我们经常在打开 SDE 数据库中





使用,注意(这个方法同样可以用来打开个人数据库,文件数据库)。





4、3、2打开个人数据库





public IWorkspace GetMDBWorkspace(String _pGDBName)

{

IWorkspaceFactory pWsFac = new AccessWorkspaceFactoryClass();





IWorkspace pWs = omFile(_pGDBName,0);



}



return pWs;





4、3、3打开文件数据库





public IWorkspace GetFGDBWorkspace(String _pGDBName)

{

IWorkspaceFactory pWsFac = new FileGDBWorkspaceFactoryClass();





IWorkspace pWs = omFile(_pGDBName, 0);







}



return pWs;





4、3、4打开 SDE 数据库





打开 SDE 数据库我们使用的是 Open 方法,要用这个方法,我们就要对 IPropertySet 对象设置,要打开 SDE





数据库,我们要获取 SDE 数据库的服务器地址,数据库实例,数据库,用户,密码等参数。而 IPropertySet





就好比一个 Key-Value 的对象,用来帮组我们设置这些,然后传到 Open 方法中。





public IWorkspace GetSDEWorkspace(String _pServerIP, String _pInstance, String _pUser, String

_pPassword, String _pDatabase, String _pVersion)

{





rtySet pPropertySet = new

tySetClass();

perty("SERVER", _pServerIP);

perty("INSTANCE", _pInstance);

perty("DATABASE", _pDatabase);

perty("USER", _pUser);

perty("PASSWORD", _pPassword);

perty("VERSION", _pVersion);

paceFactory2 workspaceF

actory;

workspaceFactory = (paceFactory2)new

kspaceFactoryClass();

return (pPropertySet, 0);

}



4、4如何 获取 数据 库中的 所有要素类





4、4、1深入理解数据集





在 Geodatabase 中,要素类可以直接存储在数据库中,也可以存储在数据集中。数据集(Dataset)是一个





代表了 Workspace 中所谓数据集合的抽象类,它是一个集合,但是在理解数据集对象的时候,要用广义的





概念来看待,不要从我们在数据库里存储的那个物理结构去理解,否则会走入误区,因为在设计数据库的





时候,我们可以在数据集里面存储相关的要素类。那么我们在编程的时候就可以这么想,要获取数据库中





的某一个要素类,要先获取数据集,然后获取要素类,其实通过工作空间





atureClass 就可以,可以把数据库比作文件夹,数据集比作子文件夹,但是在





数据库中的表,要素类,是没有重复的,不像 Windows 上的文件夹 ,子文件夹里面可以有名称重复的文件,





刚才说到用广义的意义,应该知道所有放在工作空间的对象都是一种数据集对象,也就是说 Table,





FeatureClass 等都是数据集,也就是说数据集中的数据可以是一个字段,一行记录,一张表等。Workspace





其实也是一种数据集,它也继承了 IDataset 这个接口。在数据库中一切对象都可以看做是数据集,不管是





要素类,还是表,或者栅格数据,那么怎么区分我们得到的到底是表,还是要素类?IDataset 有一个很重





要的属性 ,通过这个属性我们就可以判断, 的这个属性是一个枚举类型的常





量,如下图:





4、4、2获取数据库中的要素类





在 ArcGIS Engine 中,要得到某一个类,首要要获取工作空间,然后进入工作空间再得到相应的东西,我





们定义一个函数用来获取个人数据库的路径





public string WsPath()

{





string WsFileName="";





OpenFileDialog OpenFile = new OpenFileDialog();





= "个人数据库(MDB)|*.mdb";





DialogResult DialogR = alog();





if (DialogR == )

{





}

else

{







}



WsFileName = me;





return WsFileName;





}





要获取要素类,首先要进入





private void button2_Click(object sender, EventArgs e)

{

string WsName = WsPath();





if (WsName != "")

{





IWorkspaceFactory pWsFt = new AccessWorkspaceFactoryClass();





IWorkspace pWs = omFile(WsName, 0);





IEnumDataset pEDataset = _Datasets(Any);





IDataset pDataset = ();





while (pDataset != null)

{

if (pDatase

==FeatureClass)

{

();

}

//如果是数据集

else if ( == FeatureDataset)

{

IEnumDataset pESubDataset = s;





IDataset pSubDataset = ();





while (pSubDataset != null)

{

();







}



}



pSubDataset = ();



}



pDataset = ();





}







}

效果如下:



= [0].ToString();





判断要素是否被编辑





gEd ited





4、5峰回 路转 打开 数据库 的另一种方式





4、5、1 IName(名称对象)介绍





数据集对象可以分为两大类,一种是 Table,我们无法将 Table 存储在要素数据集中(可以尝试下),一





种是 Geodataset,这个是要素类的容器。数据集对象有一个很重要的 属性,就是这个 Fullname,用这个可





以返回和数据集相关的名称对象,而这个名称对象有一个很重要的方法 Open(),这个可以获取和这个名





称对象相关的对象(内存中的),Open()方法的返回值是 object,所以用 Open 方法的时候,我们必须





心里清楚,自己到底是要得到那个对象,然后 QI 到我们要的对象上。



IName 对象是一个代表性对象。通过使用 IName 对象,可以访问它所代表的对象的一些基本属性,而不用





将整个对象调入内存。我们用 IWorkspace 获得一个 Workspace,那可是会调入内存的,而 IWorkspaceName





则不会,除非你用了 .在我看来,那些继承 IName 的接口,在数据转换和叠加分析的





时候经常要用到这个。





IName 是一个抽象类,拥有很多子类,借助它的子类 IWorkspaceName 也可以打开数据库。打开一个数据库,





我们要指定它的类型,是个人数据库,还是文件数据库。IWorkspaceName 的





aceFactoryProgID 属性用于完成这一操作,这个属性是一个枚举的常量类型







*?

*?

*?

*?

*?

*?

*?

*?

*?

*?

*?

*?



esriData Source ssWorkspaceFactory

esriData Source oWorkspaceFa ctory

esriData Source sFile.C adWorkspaceFa ctory

esriData Source BWork spa ceFactory

esriData Source ork spa ceFactory

esriData Source sFile.P CC overageWorkspaceFa ctory

esriData Source rWorkspace Factory

esriData Source kspaceFactory

esriData Source ileWorkspaceFactory

esriData Source tFileWorkspaceFactory

esriData Source kspaceFactory

esriData Source kspace Factory





public IWorkspace Get_Workspace(string _pWorkspacePath)

{





IWorkspaceName pWorkspaceName = new WorkspaceNameClass();





aceFactoryProgID = "esriDataS

WorkspaceFactory";





me = _pWorkspacePath;





IName pName = pWorkspaceName as IName;





IWorkspace pWorkspace = () as IWorkspace;





return pWorkspace;





}





工作空间(WorkSpace)在逻辑上是一个包含空间数据集和非空间数据集的容器,我们往日所说的要素类 ,





栅格数据集,表等都存储在这个工作空间中。工作空间提供了访问内部空间和非空间数据的方法啊。工作





空间实现了众多的接口,比如 IWorkSpace,IFeatureWorkspace 等。我们在这里对这几个接口坐下介绍。





4、6如何 删除 要素 类





要想删除一个要素类,那么必须先得到这个,在得到这个要素类的时候,我们要学习一个新的接口





IFeatureWorkspace。









4、6、1 IFeatureWorkspace接 口介 绍

这个接口主要是用于管理基于矢量数据的,如表,,要素类,要素数据集等。他的主要方法和属性如下





上图方法中的 OpenDataset,OpenTable,OpenFeatureClass 都是要传入一个相应的名称,如要打开一个名





称为 PointTest 的要素类,只需要在 OpenFeatureClass 中传入这个要素类的名称,代码如下:





IWorkspaceFactory pWsFt = new AccessWorkspaceFactoryClass();



IWorkspace pWs = omFile(WsName, 0);





IFeatureWorkspace pFWs = pWs as IFeatureWorkspace;





IFeatureClass pFClass = atureClass("PointTest");





如果是在 ArcMap 中,我们会切换到 Catalog 中然后进入相应的数据库,然后删除相应的要素类,这种操作





会让我们想到 FeatureClas 这个对象会提供删除的方法,其实不然,这个删除的方法是定义在 Dataset 这





个对象中。





private void button1_Click(object sender, EventArgs e)

{

string WsName = WsPath();





if( WsName !="")

{





IWorkspaceFactory pWsFt = new AccessWorkspaceFactoryClass();





IWorkspace pWs = omFile(WsName, 0);





IFeatureWorkspace pFWs = pWs as IFeatureWorkspace;





IFeatureClass pFClass = atureClass("PointTest");





IDataset pDatset = pFClass as IDataset;





();





}





}





删除前





删除后





4、7如何 创建 一个 要素数 据类





创建要素类用到了 FeatureClass 方法,在这个方法中有众多的参数,为了满足





这些参数,我们要学习和了解下面的接口.





4、8 IField,IFieldEdit,I Fields,IFieldsEditI,GeometryDef,

IGeometryDefEdit 接口





字段对应表中的一列,一个要素类必须有至少 2 个字段,而多个字段的集合就构成了字段集,在要素类中,





有一个特殊的字段,描述了空间对象,我们称之为几何字段,其中 GeometryDef 是用来设计几何字段的。



这个几何字段定义了要素类的类型,比如说我们要在 Cat

alog 创建一个点要素类,那么我们必须 指定他的类





型为 Point,如下图:





而上面这 6 个接口,其实是三类,以 Edit 结尾的接口是可写的,也就是说对字段,字段集合,以及几何字





段的编辑都是通过后者完成的。空间数据的一个重要属性就是参考系,参考系也是在 GeometryDef 中定义





的。





注意 在 NET 中,会遇到以“_2”结尾的属性,这些属性是可写的。





//定义一个几何字段,类型为点类型

ISpatialReference pSpatialReference =

lReference;





IGeometryDefEdit pGeoDef = new GeometryDefClass();

IGeometryDefEdit pGeoDefEdit = pGeoDef as IGeometryDefEdit;

ryType_2 = ometryPoint;

lReference_2 = pSpatialReference;





//定义一个字段集合对象

IFields pFields = new FieldsClass();

IFieldsEdit pFieldsEdit = (IFieldsEdit)pFields;





//定义单个的字段

IField pField = new FieldClass();

IFieldEdit pFieldEdit = (IFieldEdit)pField;



_2 = "SHAPE";

_2 = eldTypeGeometry;

ld(pField);

ryDef_2 = pGeoDef;





//定义单个的字段,并添加到字段集合中

pField = new FieldClass();

pFieldEdit = (IFieldEdit)pField;

_2 = "STCD";

_2 = eldTypeString;

ld(pField);





//定义单个的字段,并添加到字段集合中

pField = new FieldClass();

pFieldEdit = (IFieldEdit)pField;

_2 = "SLM10";

_2 = eldTypeString;

ld(pField);

//定义单个的字段,并添加到字段集合中

pField = new FieldClass();

pFieldEdit = (IFieldEdit)pField;

_2 = "SLM20";

_2 = eldTypeString;

ld(pField);

//定义单个的字段,并添加到字段集合中

pField = new FieldClass();

pFieldEdit = (IFieldEdit)pField;

_2 = "SLM40";

_2 = eldTypeString;

ld(pField);





IWorkspaceFactory pFtWsFct = new AccessWorkspaceFactory();





IFeatureWorkspace pWs = omFile(@"E:", 0) as

IFeatureWorkspace;





IFeatureClass pFtClass = FeatureClass("Test", pFields, null, null,

Simple, "SHAPE", null)





结果如下:





4、9如何 改变 字段 的别名





public void ChangeFieldAliasName(ITable pTable, string pOriFieldName, string

pDesFieldName)

{





IClassSchemaEdit pClassSchemaEdit = (IClassSchemaEdit)pTable;





//给对象加上锁

ISchemaLock pSchemaLock = (ISchemaLock)pTable;





SchemaLock(clusiveSchemaLock);





if (eld(pOriFieldName) != -1)

{





pClas

ieldAliasName(pOriFieldName, pDesFieldName);







}



SchemaLock(aredSchemaLock);



}



else

{

return;

}



域 子类





void CreateDomain(IWorkspace pWorkspace)

{





IWorkspaceDomains pWorkspaceDomains = (IWorkspaceDomains)pWorkspace;





ICodedValueDomain pCodedValueDomain = new CodedValueDomainClass();





e("RES", "Residential");

e("COM", "Commercial");

e("IND", "Industrial");





IDomain pDomain = (IDomain)pCodedValueDomain;

= "Building Types";

ype = eldTypeString;

olicy = TDuplicate;

olicy = TDefaultValue;







}



ain(pDomain);





public void AssignDomainToFieldWithSubtypes(IFeatureClass pFeatureClass)

{





IDataset pDataset = (IDataset)pFeatureClass;





IWorkspace pWorkspace = ace;

IWorkspaceDomains pWorkspaceDomains = (IWorkspaceDomains)pWorkspace;





IDomain pDistributionDiamDomain =

_DomainByName("DistDiam");





ISubtypes pSubtypes = (ISubtypes)pFeatureClass;





_Domain(1, "SIZE_ONE", pDistributionDiamDomain);





}





public void AddPipeSubtypes(IFeatureClass pFeatureClass)

{





ISubtypes pSubtypes = (ISubtypes)pFeatureClass;





eFieldName = "PipeType";





type(1, "Primary");

type(2, "Secondary");







}



tSubtypeCode = 1;





4、10栅格 数据 管理





栅格 数据 介绍





在空间数据库中,Esri 对栅格数据提供了三种模型,栅格数据集,栅格目录,以及 ArcGIS 10 中新推出的

镶嵌数据集。





栅格数据集也就是我们经常所得 jpg,tif 文件等,ArcGIS 将这些栅格数据抽象为 RasterDataset,栅格数

据集就代表了磁盘中的一个文件,它由一个或多个波段组成。在使用栅格数据集的时候,栅格数据会被转

换成 IMG 文件存储在数据库中。





我们可以对栅格数据集进行一些操作,如改变空间参考,建立影像金字塔等。



栅格目录,正如其名字一样是一个目录,跟书的目录相似,它记录了一个或者多个栅格数据集,每一个栅

格数据集都作为一条记录存储在栅格目录中。栅格目录对栅格数据集的管理有两种方式,托管和非托管;





托管方式的时候,栅格数据是存储在数据库中





非托管的时候,栅格目录记录了栅格数据集的路径,也就是栅格数据并没有存储在数据库中。当我们删除

一条记录的时候,对我们的栅格数据没有任何影响。





镶嵌数据集可以说是栅格数据集和栅格目录的混合技术,它的存储方式和栅格目录类似,但是在使用的时



候和普通的栅格数据集是一样的,镶嵌数据集用于管理和发布海量多分辨率,多传感器影像,对栅格数据

提供了动态镶嵌和实时处理的功能。





对文件地理数据库、个人地理数据库和 ArcSDE 地理数据库中的栅格存储加以比较







栅格存

储特征

大小限





文件地理数据库

每个栅格数据集或栅格

目录的大小限制为 1

TB



个人地理数据库

每个地理数据库限制为 2 千兆字节

(GB)(此值为表的大小限制,而不是

栅格数据集的大小限制。)



ArcSDE 地理数

据库

无限制;取决

于 DBMS 限制







栅格数

据集文

件格式

存储



文件地理数据库栅格数

据集

*????栅格数据集:托管

*????Mosaic 数据集:非

托管

*????栅格目录:托管或

非托管

*????作为属性的栅格:

托管或非托管

存储在文件系统中



ERDAS IMAGINE、JPEG 或 JPEG 2000

*????栅格数据集:托管

*????Mosaic 数据集:非托管

*????栅格目录:托管或非托管

*????作为属性的栅格:托管或非托管

存储在 Microsoft Access 中



ArcSDE 栅格

数据集

*???托管

*???镶嵌数据

集:非托



存储在 RDBMS









压缩



LZ77、JPEG、JPEG 2000



LZ77、JPEG、JPEG 2000 或无



LZ77、JPEG、





或无

JPEG 2000 或


金字塔
支持部分构建金字塔
重新构建整个金字塔
支持部分构建

金字塔
镶嵌
可以在镶嵌时追加栅格

数据集
每次镶嵌至栅格数据集时都将重写

一个新的数据集
可以在镶嵌时

追加栅格数据


更新
允许增量更新

允许增量更新
用户数
单个用户和较小的工作

组;多位读取者和一位

写入者
单个用户和较小的工作组;多位读取

者和一位写入者
多用户;许多

用户和许多写

入者






4、10、1打开 栅格 数据





要打开一个栅格数据,这个有点类似我们打开 FeatureClass 一样,先要获取工作空间 ,只不过我们过于要素

类的时候需要 IFeatureWorkspace,而栅格数据则需要 IRasterWorkspace,示例如下:





IRasterWorkspace GetRasterWorkspace(string pWsName)



{







try

{

}



IWorkspaceFactory pWorkFact = new RasterWorkspaceFactoryClass();

return omFile(pWsName, 0) as IRasterWorkspace;



}



catch (Exception ex)

{

return null;

}





IRasterDataset OpenFileRasterDataset(string pFolderName, string pFileName)

{





IRasterWorkspace pRasterWorkspace = GetRasterWorkspace(pFolderName);







}



IRasterDataset pRasterDataset = sterDataset(pFileName);

return pRasterDataset;



注意当访问的栅格数据是存在 SDE 中,文件数据库中或者个人数据库中,应该使用 IRasterWorkspaceEx 接口





IRasterWorkspace 与 IRasterWorkspaceEx 的区别





1) IRasterWorkspace 主要是用来读取以文件格式存

储在本地的栅格数据





2) IRasteWorkspaceEx 接口主要是用来读取 GeoDatabase 中的栅格数据集和栅格目录,如下示例:





IRasterDataset OpenGDBRasterDataset(IRasterWorkspaceEx pRasterWorkspaceEx, string

pDatasetName)

{

//打开存放在数据库中的栅格数据

return sterDataset(pDatasetName);

}





4、10、2打开 栅格 目录 中的一 个数据







{



IRasterDataset GetRasterCatalogItem(IRasterCatalog pCatalog, int pObjectID)

//栅格目录继承了IFeatureClass

IFeatureClass pFeatureClass = (IFeatureClass)pCatalog;

IRasterCatalogItem pRasterCatalogItem =



(IRasterCatalogItem)ture(pObjectID);

return Dataset;

}





4、10、3创建 栅格 数据 集





public IRasterDataset CreateRasterDataset(string pRasterFolderPath, string

pFileName,string pRasterType,ISpatialReference pSpr )

{







IRasterWorkspace2;



IRasterWorkspace2 pRasterWs = GetRasterWorkspace(pRasterFolderPath) as





IPoint pPoint = new PointClass();

rds(15.0, 15.0);





int pWidth = 300;

int pHeight = 300;

double xCell = 30;

double yCell = 30;

int NumBand = 1;







pRasterType,

pSpr,



IRasterDataset pRasterDataset = RasterDataset(pFileName,

pPoint, pWidth, pHeight, xCell, yCell, NumBand, _UCHAR,

true);





IRasterBandCollection pRasterBands =

(IRasterBandCollection)pRasterDataset;





IRasterBand pRasterBand = (0);

IRasterProps pRasterProps = (IRasterProps)pRasterBand;





Value = 255;





IRaster pRaster = DefaultRaster();





IPnt pPnt = new PntClass();

rds(30, 30);





IRaster2 pRaster2 = pRaster as IRaster2;

IRasterEdit pRasterEdit = (IRasterEdit)pRaster2;





IRasterCursor pRasterCursor = CursorEx(pPnt);







do

{



IPixelBlock3 pPixelblock = lock as IPixelBlock3;





pixels = ()_PixelData(0);

for (int i = 0; i < ; i++)

for (int j = 0; j < ; j++)

if (i == j)

ue((255), i, j);

else

ue(((i * j + 30) / 255), i, j);





_PixelData(0, ()pixels);





IPnt pUpperLeft = t;





(pUpperLeft, (IPixelBlock)pPixelblock);





} while (());

eComObject(pRasterEdit);







}



return pRasterDataset;





4、11打开 镶嵌 数据 集





IMosaicDataset GetMosaicDataset(string pFGDBPath,string pMDame)

{

IWorkspaceFactory pWorkspaceFactory = new FileGDBWorkspaceFactoryClass();

IWorkspace pFgdbWorkspace = omFile(pFGDBPath, 0);





IMosaicWorkspaceExtensionHelper pMosaicExentionHelper = new

MosaicWorkspaceExtensionHelperClass();





IMosaicWorkspaceExtension pMosaicExtention =

tension(pFgdbWorkspace);





return saicDataset(pMDame);





}



4、12创建 一个 镶嵌 数据集





///

/// 创建镶嵌数据集

///


///

///

///

///

IMosaicDataset CreateMosaicDataset(string pFGDBPath, string pMDame,

ISpatialReference pSrs )

{





IWorkspaceFactory pWorkspaceFactory = new FileGDBWorkspaceFactory();





IWorkspace pFgdbWorkspace = omFile(pFGDBPath, 0);





ICreateMosaicDatasetParameters pCreationPars = new

CreateMosaicDatasetParametersClass();





unt = 3;





ype = _UCHAR;





IMosaicWorkspaceExtensionHelper pMosaicExentionHelper = new

MosaicWorkspaceExtensionHelperClass();





IMosaicWorkspaceExtension pMosaicExtention =

tension(pFgdbWorkspace);







"");



return MosaicDataset(pMDame, pSrs, pCreationPars,





}





4、13和查 询相 关的 对象和 接口





查询在 GIS 领域应该是一个很频繁的操作,在 GIS 中除了具有属性查询(和其他关系型数据库的查询类似),

还提供了空间查询。在介绍查询的时候,让我们先了解下面的对象。



Table 对象





Table 是不含有空间信息的一张二维表,它主要实现了 ITable 接口。在这张二维表中,每一行称之为 Row

(IRow),ITable 接口 定义了对这张二维表行的插入,更新,查询,以及删除等操作。





独立表(standalone table):就是一个单独的不含空间信息的表也就是只能在 ArcMap 中 Table of Contents

的 Source 选项卡中看到的。





对象类





对象类是在 Table 的基础上扩展起来的,因此在外观上来看,它也是一个二维表,也是用来存储非空间数

据,它与 Table 的区别在于它的一行是一个 Object(对象),尽管在形式上也是一条记录,但它是具有属

性和行为的一个对象,而非简单的记录了。





FeatureClass 对象





要素类是存储在工作空间中的一种数据组织方式,要素类是在对象类的基础上的进一步扩展,包含了现实

世界中的空间实体。要素类由要素组成(Feature),要素对应要素类中的一行 ,要素相当于空间对象

(Geometry )+相应的属性信息。IFeatureClass 定义了对要素的查询,更新,删除等操作。关于 ROW,Table,

对象类,Feature,要素类,我们可以从下面的图上得到启示:



FeatureClass 对象实现了 IFeatureClass 接口,IFeatureClass 对查询定义了两个方法

和 。





Search 方法需要传入两个参数,一个是过滤器;另外一个是布尔

值,用于说明放回的要素游标是否被回收,

一般的,如果仅仅是为了读取数据,那么这个参数应该是 true,如果要对选择出来的要素更新,那么这个

参数应该设置为 false。那么这两个参数到底有什么意义,我们从下面的代码中看一下。





4、14 false 和 true 参数的差别





我们定义一个 Search 函数,通过传 false 和 true 来对这两个参数进行说明,代码如下:





void Search(IFeatureClass _pFeatureClass,bool _Bool)

{





IFeature pFt1, pFt2;





IFeatureCursor pFtCursor;

if (_Bool == false)

{

pFtCursor = _(null, _Bool);





pFt1 = ature();





while (pFt1 != null)

{

pFt2 = ature();





if (pFt1 == pFt2)

{

("Recycling 参数是 false");

}

pFt1 = ature();







}



}



else

{

pFtCursor = _(null, _Bool);





pFt1 = ature();



while (pFt1 != null)

{

pFt2 = ature();





if (pFt1 == pFt2)

{

("Recycling 参数是true");

}

pFt1 = ature();







}



}





}





当 recycling 为 true 的时候 ,我们会看到程序执行到 ("Recycling 参数是 true"),如

下图:





等号成立,说明了当为 true,程序返回的是同一个 Feature 的引用,查询后的要素共享同一内存,说名 Next

之后前一个游标所占的内存被回收了,当为 false 的时候,等号不成立。说明系统给每一个要素分配了一个

游标。





4、15 Search 和 Select 方法的比较





Search 返回游标,Select 返回选择集



游标:必须遍历游标才能得到所有的结果,不必太关注内存





选择集: 查询后既可得到,但是通常只保留 OID 字段,数据量打的时候要考虑内存压力





4、16 Cursor 和 FeatureCursor 对象





Cursor 中文‘游标“,它本质上是一个指向数据的指针,自身并不包含数据。游标有三类,查询游标,插

入游标和更新游标,每一中游标都是又其相应的方法得到,如查询游标是由 方法得到。游

标是 GIS 中使用频率很高的,凡是和数据的查询,更新,删除等都跟他有关。ICursor 定义了对游标的操

作。当我们通过 对数据进行查询,要获取具体 Row 的信息的时候,要通过 w

方法向前遍历,游标是不能后退的。游标是和 Table 相对应的。IFeatureCursor 继承了 ICursor,

IFeatureCursor 是和要素类相对应。





4、17 QueryFilter 与 SpatialFilter 对象





在 ArcGIS Engine 中进行查询或者选择,都需要传给一个查找条件,或者过滤条件,这个条件就相当于一

般的 SQL 语句中的 Where 语句,如 Select * from 用户 where 性别=’女’;我们知道 GIS 不仅仅有

属性

查询,还有一般关系型数据库不具有的空间查询。而 QueryFilter 对象和 SpatialFilter 对象分别对应了

ArcGIS Engine 中的属性查询和空间查询。





IQueryFilter 被两个类实现 QueryFilterClass 和 SpatialFilterClass,前者是针对属性查询的,后者是

针对空间查询的。





在介绍下这些对象后,我们现在来做一个高亮显示的查询操作。





4、18 IFeatureSelection 接 口





IFeatureSelection 接口负责管理一个图层中的要素选择集的方法和属性。 IFeatureSelection 接口的 Add

方法可以把本图层中的一个要素添加到图层的选择集中;SelectFeatures 方法则利用过滤器对象将符合条

件的要素放入到图层的选择集中。使用 IFeatureSelection 接口可以实现要素的高亮显示。在 ArcGIS Engine

中有很多类实现了这个接口,如下图:





4、19使用 I FeatureSelection 接口高亮显示





在介绍 IMap 接口那一节,我们用 IMap 的 Feature 方法实现了对查询的要素高亮显示,现在我

们用 IFeatureSelection 接口实现查询高亮显示





IMap pMap = ;





IFeatureLayer pFeaturelayer = GetLayer(pMap, "Roads") as IFeatureLayer;





IFeatureSelection pFeatureSelection = pFeaturelayer as IFeatureSelection;





IQueryFilter pQuery = new QueryFilterClass();





lause = "TYPE=" +"'paved'";





Features(pQuery,lectionResultNew,false

);





h();





其中 GetLayer 函数是我们写的一个根据图层的名称获取图层的方法,代码如下图:





private ILayer GetLayer(IMap pMap, string LayerName)

{

IEnumLayer pEnunLayer;

pEnunLayer = _Layers(null, false);

();

ILayer pRetureLayer;

pRetureLayer = ();





while (pRetureLayer != null)

{

if ( == LayerName)

{

break;

}







}



pRetureLayer = ();



return pRetureLayer;



}





4、20空间 查询





空间查询可以说是两步过滤,属性过滤和空间过滤,既然有空间过滤,空间查询体现在

ry 和 lRel 上,那么这个接口的 Geometry 和 spatialrel 属

性是必须的。众所周知 ArcMap 的空间查询是非常丰富的,而 ArcGIS Engine 可以毫无保留的实现 ArcMap

所能提供的全部空间查询,对于 ArcGIS Engine 来说这些空间查询只是 ISpatialFilter 的参数,而这些参

数都是常量,如下表所示:





示例:查询矩形范围内的点要素:





public reCursor

GetAllFeaturesFromPointSearchInGeoFeatureLayer(ope pEnvelope,

IPoint pPoint, IFeatureClass pFeatureClass)

{





if (pPoint == null || pFeatureClass == null)

{

return null;

}





//ITopologicalOper

ator pTopo = pPoint as ITopologicalOperator;





//IGeometry pGeo = (pSearchTolerance);





pShapeFieldName = ieldName;





alFilter pSpatialFilter = new

lFilterClass();



ry = pEnvelope;

lRel =

atialRelEnvelopeIntersects;

ryField = pShapeFieldName;





reCursor pFeatureCursor =

(pSpatialFilter, false);







}



return pFeatureCursor;





4、21附件 功能





附件功能是 ArcGIS 10 的一个新功能,ArcGIS 10 引入了要素类附件,这样就能够灵活地管理与要素相关

的附加信息。我们可以向单个要素添加文件作为附件,它们可以是图像、PDF、文本文档或任意其他文件类

型。例如,如果用某个要素表示建筑物,则可以使用附件来添加多张从不同角度拍摄的建筑物照片,以及

包含建筑物契约和税务信息的 PDF 文件。

附件与超链接类似,但允许多个文件与一个要素相关联、将关联的文件存储在地理数据库中并以更多方式

访问这些文件。可通过识别 窗口、属性 窗口(编辑时)、属性表窗口以及 HTML 弹出窗口来查看这些附

件。





4、22和附 件相 关的 接口





ITableAttachments

该接口用于控制一个要素类的附件,为一个要素类开启附件功能等,因此该接口被要素类(FeatureClass

实现)

IAttachmentManager

从该接口的字面意思就可以看出,该接口是用来管理附件的,相当于一个关系类,通过该接口将附件添加

到和要素相关联的那个关系类中

IAttachment

该接口表示一个附件,附件对象实现。

IMemoryBlobStream

ArcGIS 实际上是将附件以二进制存入到数据库中的,该接口用于控制附件的读取





实例:开启附件功能,并添加一个附件。





private void CreateAttachTable(IFeatureClass pFeatureClass,int pID,string pFilePath,string



pFileType)

{



//要素表是否有附件表,数据库只能是10版本的

ITableAttachments pTableAtt = pFeatureClass as ITableAttachments;





if (achments == false)

{

achments();

}





//获取附件管理器

IAttachmentManager pAttachmentManager = mentManager;





//用二进制流读取数据

IMemoryBlobStream pMemoryBlobStream = new MemoryBlobStreamClass();

omFile(pFilePath);





//创建一个附件

IAttachment pAttachment = new AttachmentClass();





tType=pFileType;





= eName(pFilePath);





= pMemoryBlobStream;





//添加到表中

achment(pID, pAttachment);





}





4、23综合 例

子 空间 查询和 创建 Table





创建符合要求的表





///



/// 输出结果为一个张表,这张表有3个字段,其中面ID为面要素数据的 FID

/// 个数用于记录这个面包含的点的个数

///


///

///

///





public ITable CreateTable(string _TablePath, string _TableName)

{

IWorkspaceFactory pWks = new ShapefileWorkspaceFactoryClass();





IFeatureWorkspace pFwk = omFile(_TablePath, 0) as IFeatureWorkspace;





//用于记录面中的ID;





IField pFieldID = new FieldClass();





IFieldEdit pFieldIID = pFieldID as IFieldEdit;





_2 = eldTypeInteger;





_2 = "面ID";





//用于记录个数的;

IField pFieldCount = new FieldClass();





IFieldEdit pFieldICount = pFieldCount as IFieldEdit;





_2 = eldTypeInteger;

_2 = "个数";





//用于添加表中的必要字段

tClassDescription objectClassDescription = new

ClassDescriptionClass();





IFields pTableFields = edFields;





IFieldsEdit pTableFieldsEdit = pTableFields as IFieldsEdit;





ld(pFieldID);





ld(pFieldCount);





ITable pTable = Table(_TableName, pTableFields, null, null, "");





return pTable;





}





///

/// 第一个参数为面数据,第二个参数为点数据,第三个为输出的表

///


///

///

///

public void StatisticPointCount(IFeatureClass _pPolygonFClass, IFeatureClass

_pPointFClass, ITable _pTable)

{

IFeatureCursor pPolyCursor = _(null, false);





IFeature pPolyFeature = ature();





while (pPolyFeature != null)

{

IGeometry pPolGeo = ;





int Count = 0;





ISpatialFilter spatialFilter = new SpatialFilterClass();





ry = pPolGeo;





lRel = atialRelContains;





IFeatureCursor pPointCur = _(spatialFilter, false);





if (pPointCur != null)

{

IFeature pPointFeature = ature();





while (pPointFeature != null)

{

pPointFeature = ature();

Count++;



}





}





if (Count != 0)

{







}



IRow pRow = _Row();

_Value(1, _Value(0));

_Value(2, Count);

();



pPolyFeature = ature();







}



}





效果如下:





上面这个例子只是用了空间过滤,没有用到属性过滤,我们将上面的代码稍微改动下,加上一句





结果对照







4、24 数据 转换







数据转换主要涉及复制和转换数据出入 Geodatabases 的对象。





两个主要的数据转换对象是 FeatureDataConverter 和 GeoDBDataTransfer。





ArcCatalog 用户应该熟悉 FeatureDataConverter;导入(import)功能广泛使用该 coclass。



ArcCatalog 用户也应该熟悉 GeoDBDataTransfer;在 Geodatabases 之间复制数据集的





copy/paste 功能使用该 class。





还有其它一些对象和接口支持 FeatureDataConverter 和 GeoDBDataTransfer,并执行以下





功能:





使用 IFieldChecker 检查字段名称中的潜在问题。





检查使用 IEnumInvalidObject 的转换过程中被拒绝的数据。





使终端用户了解 IFeatureProgress





///

/ //

/ //


/ //

/ // < /pa ram >

/ //

/ //

/ // < /pa ram >

/ //

public vo id ConvertFeatureClass(IW ork spa ceF act ory _pSWorkspaceFactory,String

_pSW s,st ring _pS Name , IW orks paceFactory _p TWor kspaceF act ory ,St ring _pTW s,st rin g

_pTN ame )

{

// Ope n the sour ce an d t arge t work space s.





IWo rksp ace pSWo rksp ace = _ pSWo rksp omFile(_pSWs, 0 );





IWo rksp ace pTWo rksp ace = _ pTWo rksp omFile(_pTWs, 0 );





IFe atur eWorkspace pFt Ws = pSWo rksp ace as IFe atur eWor ksp ace ;





IFe atur eClass pSou rceF eatureClass = pF tWs. OpenFea tur eCl ass (_p SNa me) ;





IDa tase t pSD atas et = pSo urce FeatureClass as IDa tase t;





IFe atur eClassName pS ourc eFeatureClassName = pSDa tase me a s

IFea ture ClassName;





IDa tase t pTD atas et = (I Data set)pTWorkspace;





INa me pTD atas etName = p TDat aset .FullName;





IWo rksp aceName pTa rget WorkspaceName = (IW orks pace Nam e)p TDa tas etN ame ;





IFe atur eClassName pT arge tFeatureClassName = new Fe atur eCla ssN ame Cla ss ();





IDa tase tName pT arge tDatasetName = ( IDa tase tName)p Tar get Fea tur eCl ass Nam e;

pTa rget = _pTN ame;

pTa rget aceName = pTar getW orkspaceName;





// 创建 字段 检查对象

IFi eldC hecker pFie ldCh ecker = ne w Fiel dChe ckerCla ss( );





IFi elds sour ceFi elds = pSou rceF ;

IFi elds pTar getF ields = nu ll;





IEn umFi eldError p Enum FieldError = null ;





pFi eldC orkspace = p SWor kspa ce;





pFi eldC teWorkspace = p TWor kspa ce;





// 验证 字段

pFi eldC te(sourceFields, o ut pEn umFi eldE rro r, out pT arge tFie lds );

if (pE numF ieldError != nul l)

{

/ / H andl e the erro rs in a way ap prop riate to your a ppli cati on.

C onso le.W riteLine("Errors wer e enco unte

red durin g fiel d vali dati on." );

}





Str ing p Shap eFie ldName = p Sour ceFe ieldName;

int p Fiel dInd ex = pSo urce eld(pShapeFieldName);



IFi eld p Shap eFie ld = sou rceF _Field(pFieldIndex);





IGeo metr yDef pTa rget GeometryDef = pSh apeF ryDef;





// 创建 要素 转换对象

IFe atur eDataConverter p FDCo nverter = new Fea ture Data Con ver ter Cla ss ();





IEn umIn validObject p Enum InvalidObject = p FDCo nver tFeatureClass





( pSou rceF eatureClassName, nu ll, nu ll, pT arge tFeatureClassName,

p Targ etGe ometryDef, pTa rget Fields, "" , 1000 , 0 );







}



// Che ck for e rrors .

IIn vali dObjectInfo p Inva lidInfo = null ;

pEn umIn ();

whi le ((p Inva lidInfo = pEnu mInv ()) ! = nul l)

{

/ / H andl e the erro rs in a way ap prop riate to the ap plic atio n.

C onso le.W riteLine("Errors occ urre d for t he follo wing feat ure: {0}" ,

pInv alid dObjectID);

}





I Work spac eFactory pSwf = ne w Acce ssWo rkspaceFactor yCl ass ();





IWor kspa ceFactory pD wf = new Acc essW orks pac eFa cto ryC las s( );





Conv ertF eatureClass(pSwf,"E:","s", pDw f," E: d .mdb ", "d" );





4、25 Querylayer







查询图层是通过 SQL 查询定义的图层或独立表。通过查询图层可将空间信息和非空间信息都存储在 DBMS

中,从而使这些信息可以轻松地整合到 ArcMap 中的各 GIS 项目。由于查询图层将通过 SQL 对数据库表

和视图进行直接查询,所以查询图层所使用的空间信息不需要位于地理数据库中。



在 ArcMap 中进行操作时,可以通过定义 SQL 查询来创建查询图层。然后针对数据库中的表和视图运行查

询,并将结果集以图层或独立表的形式(取决于查询本身)添加到 ArcMap 中。





每次在 ArcMap 中显示或使用该图层时都将执行该查询。这样,无需生成数据的副本或快照便可显示最新

信息,这尤其适用于处理频繁更改的动态信息。查询图层功能适用于 ArcGIS 支持的所有 DBMS。





查询图层允许 ArcMap 整合地理数据库和 DBMS 中的数据。因此,无论信息存储的位置和方式如何,查询

图层都可以快速地将空间信息和非空间信息整合到 GIS 项目。





4、26使用 查询 图层 快速浏 览







*?

*?

*?



通过对 DBMS 中的表和视图定义查询,ArcMap 用户可将“查询图层”添加到地图。

查询图层类似于任何其他要素图层或单独表,所以这些图层可用于作为地理处理工具的输入来

显示数据,或使用开发人员 API 通过编程方式进行访问。

创建“查询图层”后,它可另存为图层文件 (.lyr) 或用于创建图层包 (.lpk)。这样可以很容易

地与其他应用程序、地图文档和其他用户共享

“查询图层”。





ArcMap 中的所有图层都需要唯一标识符。因此,查询图层也必须含有唯一标识符。

通常,唯一标识符字段属于 Object ID 属性,地理数据库中所有对象均应具有该属性。但是,由于

查询图层也可以使用未存储在地理数据库中的数据创建,因此各查询图层的字段集中未必都具有

Object ID 字段。因此,有必要指定将哪个字段或哪组字段用于在 ArcGIS 中生成唯一标识符。





默认情况下,ArcGIS 会在验证时将在结果集中找到的第一个非空字段设置为唯一标识符字段。该值通常为

适宜用作唯一标识符字段的值,但您也可以通过在唯一标识符字段列表中选择其他字段来更改此属性。

仅某些字段类型可用作唯一标识符。这些字段类型包括整型、字符串、GUID 和日期。如果指定的是单个整

型字段,则 ArcGIS 将只会直接使用该字段中的值识别从查询图层返回的所有要素和行。但是,如果将单

个字符串字段或一组字段用作唯一标识符,则 ArcGIS 必须将这些唯一值映射为一个整数。在系统需要使

用 ObjectID 属性的任何时候(例如,创建地图选择内容或打开属性表时)均可在 ArcGIS 中完成此操作。

由于唯一标识符字段中的值是识别 ArcGIS 中行或要素对象的唯一值,因此,该字段中的值必须始终唯一

且不可为空。您必须确保此字段中的值满足此要求。ArcGIS 并不强制要求查询图层的唯一标识符字段中的

值必须唯一。但如果遇到不唯一的值,ArcGIS 中某些元素的行为将无法预测。

您可以在唯一标识符列表中选择和取消选择字段。如果选择了多个字段,则这些字段中的值将作为键用于

生成唯一整数值,生成字段的名称将始终为 ESRI_OID,除非已存在具有该名称的字段。





在 ArcGIS Engine 中要使用查询图层,我们要了解一个接口 ISqlWorkspace,从这个接口的名称也容易看

出,这个接口可以和 SQL 打交道,这正是 QueryLayer 的一个特点。在帮助文件中我们可以获得 ISqlWorkspace

的详细信息,如下图:









les()返回 IStringArray 类型的变量,用这个方法我们可以获取数

据库中所有的表的名称。





eryCursor()这个方法通过传入一个过滤语句,返回一个游标;





eryClass()返回通过过滤条件返回 ITable 类型的对象。





ISqlWorkspace 被 SqlWorkspaceClass 实现,而 SqlWorkspaceClass 同时实现了 IWorkspace

接口。那也就意味着 ISqlWorkspace 的使用和 IWorksapce 的使用是类似的,我们可以按照

以下步骤来执行一个 QueryLayer。



1) 获取 SqlWorkspaceFactory





2) 获取 SqlWorkspace





3) 构造查询语句





4) 执行查询





5) 获取结果





public IFeatureLayer OracleQueryLayer()

{

// 创建SqlWorkspaceFactory的对象

Type pFactoryType =

eFromProgID("kspaceFactory");





IWorkspaceFactory pWorkspaceFactory =

(IWorkspaceFactory)Instance(pFactoryType);





// 构造连接数据库的参数

IPropertySet pConnectionProps = new PropertySetClass();

perty("dbclient", "Oracle11g");

perty("serverinstance", "esri");

perty("authentication_mode", "DBMS");

perty("user", "scott");

perty("password", "arcgis");





// 打开工作空间

IWorkspace workspace = (pConnectionProps, 0);





ISqlWorkspace pSQLWorkspace = workspace as ISqlWorkspace;





//获取数据库中的所有表的名称





IStringArray pStringArray= les();





for (int i = 0; i < ; i++)

{



(_Element(i));





}





// 构造过滤条件 SELECT * FROM PointQueryLayer





IQueryDescription queryDescription = ryDescription("SELECT *

FROM PointQueryLayer");





ITable pTable = eryClass("QueryLayerTest", queryDescription);





IFeatureLayer pFeatureLayer = new FeatureLayerClass();





eClass = pTable as IFeatureClass;





return pFeatureLayer;





}



五. 几何 对象 和空 间参考





几何对象是 ArcGIS Engine 中最基本的也是最常用的对象,我们所说的空间对象(点,线,面)都是几何

对象,我们在删除,创建和进行地理分析的时候,就是处理一个包含几个对象的矢量图形。





Geometry 是 ArcGIS Engine 中使用最为广泛的对象集之一,用户在创建、删除、编辑和进行地理分析的时

候,就是处理一个包含几何形体的矢量对象;除了显示要素意外,控件对象选择,要素符号化,标注要素,

编辑要素都需要 Geometry 参与。





在这个模型中,我们看到某些几何对象可以组合产生新的几何形体,如 polyline 又 path 构成,path 又可

以由 segement 组成,但是这并不意味着用户必须按照这种层次去构造 polyline。世界上 point 可以构成

任何几何形体。

我们还可以看到 IGeometryCollection 接口,这个几口是具有相同类型的几何对象的集合。他可能是描述

一条 polyline 的路径的集合。或者是描述路径的片段的几何,甚至是直接描述组成 polyline 的点。

Point 对象是一个 0 维的几个图形,具有 X,Y 坐标,如下图:





同时,点对象还可以有 Z 和 M 两个可选属性,Z 用于描述这个点的高程,而 M 用于描述这个点的测量值,M

这个属性在线性参考和动态分段中经常用到。





MultiPoint:点集对象是一系列无序的

点的群集,这些点具有相同的属性信息。如油田场地上可以有多个

大大小小的油井。





Polyline 多义线是一个有序的路径(path)的集合,这些路径既可以是连续的,也可以是不连续的,如下

图:





Envolope 是一个矩形,他用于表示几何对象的空间范围,它覆盖了几何对象的最小坐标和最大坐标,如下

图所示:





5、1点和 多点





世界的本质是物质,对于 GIS 来说,点就应该是矢量数据的本质,点生线,线生面??,如此组合,构成

了 GIS 世界中的矢量空间。





Point 几何对象

Point 是一个 0 维的几何图形,具有 X,Y 坐标值,以及一些可选的属性:如高程值(Z 值),度量值(M 值) 和

ID 号,点对象用于描述精确定位的对象,例如一个电话亭在一个城市的精确位置。以下代码演示如何创建

一个 Point 对象:





///

/// 获取点

///


///

///

///

private IPoint ConstructPoint(double x, double y)

{

IPoint pPoint = new PointClass();



rds(x, y);

return pPoint;

}





MultiPoint 几何对象

MultiPoint 对象是一系列无序的点的群集,这些点具有相同的属性信息。例如可以用一个点集来表示整个

城市天然气调压站。如下图所示:一个 Multipoint 对象由6个 Point 对象组成。





以下代码片段演示如何构建 Multipoint 对象:





private object pMissing = g;





public IGeometry GetMultipointGeometry()

{

const double MultipointPointCount = 25;





IPointCollection pPointCollection = new MultipointClass();





for (int i = 0; i < MultipointPointCount; i++)

{

nt(GetPoint(), ref pMissing, ref pMissing);

}







}



return pPointCollection as IGeometry;



private IPoint GetPoint()

{

const double Min = -10;

const double Max = 10;





Random pRandom = new Random();





double x = Min + (Max - Min) * uble();

double y = Min + (Max - Min) * uble();







}



return ConstructPoint(x, y);







5、2 Segment,Path, Ri



ng 和Polyline 对 象





Segment 几何对象

Segment 对象是一个有起点和终点的“线“,也就是说 Segement 只有两个点,至于两点之间的线是直的,

还是曲的,需要其余的参数定义。所以 Segment 是由起点,终点和参数三个方面决定的。Segment 有 4 个

子类,它的 4 个子类如下图:





Path 几何对象

Path 是连续的 Segment 的集合,除了路径的第一个 Segment 和最后一个 Segment 外其余的 Segment 的起始

点都是前一个 Segment 的终止点,即 Pat h 对象的中的 Segment 不能出现分离,Path 可以是任 意数的 Segment

子类的组合。





Ring 几何对象

Ring 是一个封闭的 Path 即起始和终

止点有相同的坐标值。它有内部和外部属性。





Polyline 几何对象



Polyline 对象是由一个或多个相连或者不相连的 path 对象的有序集合,它可以是单个 Path 对象组成,也

可以是多个相连的 Path 对象组成,或者是多个分离的 Path 组成,如下图所示。Polyline 通常用来代表线

状地物如道路,河流,管线等等。





Polylines 是有序 path 组成的集合,可以拥有 M、Z 和 ID 属性值。Polyline 对象的 IPointCollection

接口包含了所有节点的复制,IGeometryCollection 接口可以获取 polyline 的 paths,ISegmentCollection

接口可以获取 polyline 的 segments。





一个 Polyline 对象必须满足以下准则:

1.组成 Polyline 对象的所有 Path 对象必须是有效的。

2.组成 Polyline 对象的所有 Path 对象不能重合,相交或自相交。

3.组成 Polyline 对象的多个 Path 对象可以连接与某一点,也可以分离。

对象的长度不能为 0.

IPolyline 是 Polyline 类的主要接口,IPolyline 的 Reshape 方法可以使用一个 Path 对象为一个

Polyline 对象整形,IPolyline 的 SimplifyNetwork 方法用于简化网络。

Polyline 对象可以使用 IGeometryCollection 接口添加 Path 对象的方法来创建,使用该接口需注意

以下情况:

1.每一个 Path 对象必须是有效的,或使用 IPath::Simplify 方法后有效。

2.由于 Polyline 是 Path 对象的有序集合,所以添加 Path 对象时必须注意顺序和方向。

3.为了保证 Polyline 是有效的,可以创建完 Polyline 对象后使用 ITopologicalOperator 接口的

Simplify 方法。

下面代码片段演示了一个 Polyline 的构成:





private object pMissing = g;





public IGeometry GetPolylineGeometry()

{

const double PathCount = 3;

const double PathVertexCount = 3;





IGeometryCollection pGeometryCollection = new PolylineClass();





for (int i = 0; i < PathCount; i++)

{

IPointCollection pPointCollection = new PathClass();





for (int j = 0; j < PathVertexCount; j++)

{

nt(GetPoint(), ref pMissing, ref pMissing);

}







ref pMissing);

}



metry(pPointCollection as IGeometry, ref pMissing,







}



return pGeometryCollection as IGeometry;



private IPoint GetPoint()

{

const double Min = -10;

const double Max = 10;





Random random = new Random();





double x = Min + (Max - Min) * uble();

double y = Min + (Max - Min) * uble();







}



return ConstructPoint(x, y);





Segment,Path,Ring 和 Polyline 的区别

在这四者当中 Segment 是最小的单位具体的构成路线可以分为两个条:





Segment-Path-Ring(封闭的 Path)





Segment-Path-Polyline



我们可以这样说 Segment 是 Path,只不过是这个 Path 由一个 Segment 组成,Ring 也是一种

Path,只

不过是一个起点和终点重合的 Path,至于 Polyline 那就很明显了,他们的区别可

以从下图看出:





Polygone 对象





Polylgon 对象是由一个或多个 Ring 对象的有序集合,它可以是由单个 Ring 对象构

成,也可以使用多个 Ring 组成。Polygon 通常用来代表有面积的多边形矢量对象,如行政

区,建筑物等。Polygone 的组成结构可以看下图:







组成 Polygone 的是 Ring 其中 Ring 可以分为 Outer Ring(外环)和 Inner



Ring(内环)



之分。外环和内环都是有方向的,它们的区别是外环的方向是顺时针的,内环的方向是逆时

针。如下图:



Igeometry





以下代码片段演示如何构建一个 Polygon:





private object pMissing = g;





public IGeometry GetPolygonGeometry()

{

const double RingVertexCount = 360;

const double RingDegrees = 360.0;

const double pOutRingRadius = 100;

const double pInRingRadius = 40;





IGeometryCollection pGeometryCollection = new PolygonClass();





IPointCollection pOuterPointCollection = new RingClass();

IPointCollection pInnerPointCollection = new RingClass();





double pRotationAngleInRadians =

GetRadians(RingDegrees / RingVertexCount);





for (int j = 0; j < RingVertexCount; j++)

{





nt(ConstructPoint(pOutRingRadius

*(j*pRotationAngleInRadians),pOutRingRadius *(j*pRotationAngleInRadians)),

ref pMissing, ref pMissing);





nt(ConstructPoint (pInRingRadius * (j

* pRotationAngleInRadians), pInRingRadius * (j * pRotationAngle InRadians)), ref pMissing,

ref pMissing);





}





ITopologicalOperator pTopologicalOperator =

pGeometryCollection as ITopologicalOperator;





fy();





return pGeometryCollection as IGeometry;



}





private double GetRadians(double pDecimalDegrees)

{

return pDecimalDegrees * ( / 180);

}





5、3Envelope 几何 对象





Envelope 是所有几何对象的外接矩形,用于表示几何对象的最小边框,所有的几何对象都有一

个 Envelope 对象,IEnvelope 是 Envelope 对象的主要接口,通过它可以获取几何对象的

XMax,XMin,YMax,YMin,Height,Width 属性。通过 IEnvelope 的 Expand 方法还可以按比例缩放 Envelope 对

象的范围,如下图所示:



5、4 Curve 对 象几 何 对象







除去 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 千米间的曲线对象 curve(2, 5, btrue, out pNewCurve);

此外 ICurve 的 QueryTangent 和 QueryNormal 方法分别用于获取 Curve 对象上某一点的曲线的切线

和法线。





5、5 Multi patch 几何 对象







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.





5、6 Geometry 集 合 接口





通过前边对于具体的 Geometry 对象的介绍可知,除了 Point 对象之外,其他几何对象都是通过其他

几何对象集合构建而成。如 MultiPoint 对象是点的集合,Path 对象是 Segment 对象的集合,Polyline 对

象是 Path 对象的集合,Polygon 对象是 Ring 对象的集合,Multipatch 对象是 Triangle Strip 和 Trangle

Fan, Trangle,Ring 对象的集合。

ArcGIS Engine 提供了三个主要的几何图形集合接口用于对几何对象的操作,分别是

IPointCollection,ISegmentCollection 和 IGeometryCollection,这些接口揭示出 ArcGIS Engine 的几何

模型的实质——它们是一种组合构成的模式,这种组合并不一定按照严格的层次结构组织。

在前面介绍一些几何对象的时候,也给大家

演示了部分使用功能,这三个接口在程序开发中经常使

用到,接下来简单阐述以下这三个接口的使用方法。

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 接口



通过 IGeometryCollection 创建一个 Polygon 对象的代码片段如下:

private IPolygon ConstructorPolygon(List pRingList)

{

try

{





IGeometryCollection pGCollection = new PolygonClass();

object o = g;







对象



}



for (int i = 0; i < ; i++)

{

//通过IGeometryCollection接口的AddGeometry方法向Polygon对象中添加Ring子

metry(pRingList[i], ref o, ref o);

}

//QI至ITopologicalOperator

ITopologicalOperator pTopological = pGCollection as ITopologicalOperator;

//执行Simplify操作

fy();

IPolygon pPolygon = pGCollection as IPolygon;

//返回Polygon对象

return pPolygon;



catch (Exception Err)

{







}



}



return null;





private IPolygon MergePolygons(IPolygon firstPolygon, IPolygon SecondPolygon)

{

try

{

//创建一个Polygon对象

IGeometryCollection pGCollection1 = new PolygonClass();

IGeometryCollection pGCollection2 = firstPolygon as IGeometryCollection;

IGeometryCollection pGCollection3 = SecondPolygon as IGeometryCollection;

//添加firstPolygon

metryCollection

(pGCollection2);

//添加SecondPolygon

metryCollection(pGCollection3);

//QI至ITopologicalOperator

ITopologicalOperator pTopological = pGCollection1 as ITopologicalOperator;



}



//执行Simplify操作

fy();

IPolygon pPolygon = pGCollection1 as IPolygon;

//返回Polygon对象

return pPolygon;



catch (Exception Err)

{







}



}



return null;





ISegmentCollection 接口

ISegmentCollection 接口被 Path,Ring,Polyline 和 Polygon 四个类所实现,它们被称作是 Segment

集合对象,使用这个接口可以处理组成 Segment 集合对象中的每一个子 Segment 对象。使用

ISegmentCollection 接口可以为一个 Segment 集合对象添加,插入,删除 Segment 子对象。

ISegmentCollection 接口 SetCircle 和 SetRectangle 方法提供了一种简单不需要添加 Segment 的情况下

构建一个完成的 Path,Ring,Polyline 和 Polygon 的方法。

IPointCollection 接口

IPointCollection 可以被多个几何对象类所实现,这些对象都是由多个点构成如:

Mullipoint,Path,Ring,Polyline,Polygon,TriangleFan,TrangleStrip,Trangle,Multipatch 等,它们都

可以称作 PointCollection 对象,通过 IPointCollection 接口定义的方法可以获取,添加,插入,查询 ,

移除几何对象中的某个顶点。同以上两个接口一样它也定义了操作一个点集合对象的方法,例如通过

AddPoint 方法可以向 PointCollection 对象中的特定索引位添加一个点对象,如果不指定位置,则添加到

最后。通过 IPointCollection 的 Point 属性通过顶点索引可以得到某一顶点。

在 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





示例 代码





//传入线段和打断的个数进行打断

priv ate IEnumGeomet ry Mak eMulti Points(IP olyline p

Geo metry , i nt in Poin ts)

{





IC onstructGeome tryCollectio n p ConGeo Collection = new GeometryBagC lass();





pC onGeoCollecti uct DivideEqual( pGeom etry, inP oints,

esri ConstructD ivideEnum .esriDivideInto Polylines);





IE numGeometry pEn umGeometry = pCon GeoCo llect ion as IEnu mGeometry;





re turn pEn umGeo metry;





}

uctDivide Length





private IPolygon FlatBuffer(IPolyline pLline1, double pBufferDis)

{

object o = g;

//分别对输入的线平移两次(正方向和负方向)



}



IConstructCurve pCurve1 = new PolylineClass();

uctOffset(pLline1, pBufferDis, ref o, ref o);

IPointCollection pCol = pCurve1 as IPointCollection;

IConstructCurve pCurve2 = new PolylineClass();

uctOffset(pLline1, -1 * pBufferDis, ref o, ref o);

//把第二次平移的线的所有节点翻转

IPolyline pline2 = pCurve2 as IPolyline;

eOrientation();

//把第二条的所有节点放到第一条线的IPointCollection里面

IPointCollection pCol2 = pline2 as IPointCollection;

ntCollection(pCol2);

//用面去初始化一个IPointCollection

IPointCollection pPointCol = new PolygonClass();

ntCollection(pCol);

//把IPointCollection转换为面

IPolygon pPolygon = pPointCol as IPolygon;

//简化节点次序

fyPreserveFromTo();

return pPolygon;





IGeometryBag vs. IGeometryCollection





GeometryBag 是支持 IGeometry 接口的几何对象引用的集合,任何几何对象都可以通过

IGeometryCollection 接口添加到 GeometryBag 中,但是在使用拓扑操作的时候,需要注意不同类型的几

何类型可能会有相互不兼容的情况。在向 GeometryBag 中添加几何对象的时候,GeometryBag 对象需要指

定空间参考,添加到其中的几何对象均拥有和 GeometryBag 对象一样的空间参考。在 GIS 中,矢量数据模

型是地理数据的重要表现形式,而 Esri 提供了多种方式对矢量数据进行管理, shpfile,coverage 以及

Geodatabase。在 Geodatabase 中,一个要素类的一条记录都有一个 Shape 字段,而这个 Shape 字段就存储

了我们的空间形体。这个空间形体用来精确的描述现实世界中的空间对象,我们知道 ArcGIS 中提供了众多

的空间分析工具,而这些分析就是对这个 Shape 进行操作的。





5、7空间 参考





空间参考(Spatial Reference)是 GIS 数据的骨骼框架,能够将我们的数据定位到相应的位置,为

地图中的每一点提供准确的坐标。 在同一个地图上显示的地图数据的空间参考必须是一致的,如果两个图

层的空间参考不一致,往往会导致两幅地图无法正确拼合,因此开发一个 GIS 系统时,为数据选择正确的

空间参考非常重要。



ArcGIS Engine 提供了一系列对象供

开发者管理 GIS 系统的坐标系统。对大部分开发者而言了解

ProjectedCoordinateSystem, GeographicCoordinateSystem, SpatialReference Environment 这三个

组件类是非常有必要的,对于高级开发者而言,可能需要自定义坐标系统可以使用这些对象

Projection,Datum,AngularUnit,Spheriod,PrimeMeridian 和 GeoTransformation 等。





ISpatialReferenceFactory pSpatialReferenceFactory = new SpatialReferenceEnvironmentClass();

IGeographicCoordinateSystem geographicCoordinateSystem =

GeographicCoordinateSystem((int)GeoCS_W

GS1984);





六. 矢量 数据 空间分析





6、1叠加 分析





叠加分析是将有关主题层组成的数据层面,进行叠加产生一个新数据层面的操作,其结果综合了原来两层

或多层要素所具有的属性,从已有的数据中提取空间隐含的信息。叠加分析不仅包含空间关系的比较,还

包含属性关系的比较。叠加分析可以分为矢量图层的叠加分析和栅格数据的叠加分析,其中矢量的叠加分

析包括交集(Intersect)、裁减(Clip)、合并叠加(Union)以及合并( Merge)等类型。矢量图层叠加

分析需要用到的主要接口是 IBasicGeoProcessor,它提供了以下方法和属性:





在 IBasicGeoProcessor 接口中,它所定义的几个方法的参数都很相似,现在我们以 Intersect 方法为例,

在帮助中,我们可以看到 Intersect 方法包含下面几个参数:





p u b l i c IF eatureC las s I n t e r s e c t (

IT able in putT able ,(第一个要素类)

bo ol useS elec tedI nput ,(是否使用第一个要素中选择的数据)



IT able ov erla yTab le, (第二个要素类)

bo ol useS elec tedO verl ay, (是否使用第二个要素中选择的数据)

do uble To lera nce, (容差)

IF eatu reCl assN ame outp utNa me(输出要素对象)





输出要素对象的类型是 IFeatureClassName,也就是名称对象,关于名称对象,在数据库那一章节有详细

说明,其它几个参数比较容易理解,我们要做Intersect也就是构造这几个参数而已,如果深入理解下,Esri

提供的这个方法,这些参数也正如叠加分析的定义那样,对相关数据的输入,通过叠加分析,构造一个新

的数据从而挖掘潜在信息,下面的一个例子演示了如何进行Intersect操作:





public IFeatureClass Intsect(IFeatureClass _pFtClass,IFeatureClass _pFtOverlay,string

_FilePath,string _pFileName)

{





IFeatureClassName pOutPut = new FeatureClassNameClass();





ype = _ype;





ieldName = _ieldName;





eType = Simple;





//set output location and feature class name





IWorkspaceName pWsN = new WorkspaceNameClass();





aceFactoryProgID

= "ileWorkspaceFactory";





me = _FilePath;





//也可以用这种方法,IName 和IDataset的用法





/* IWorkspaceFactory pWsFc = new ShapefileWorkspaceFactoryClass();





IWorkspace pWs = omFile(_FilePath, 0);





IDataset pDataset = pWs as IDataset;





IWorkspaceName pWsN = me as IWorkspaceName;

*/





IDatasetName pDatasetName = pOutPut as IDatasetName;





= _pFileName;





aceName =pWsN;





IBasicGeoprocessor pBasicGeo = new BasicGeoprocessorClass();





IFeatureClass pFeatureClass = ect(_pFtClass as ITable , false,

_pFtOverlay as ITable , false, 0.1, pOutPut);





return pFeatureClass;





}

其中,第一个要素类如下:





第二个要素类如下:





Insetsect 之后,结果如下 :





6、2关系 操作





GIS中的空间对象除了拥有属性数据之外,他们之间还拥有某种关系,比如说一个点在一个面的内部,两个

对象相交,相等,包含,相接等关系。关系运算符(Relational Operators)比较两个几何体,并返回一个

boolean 来说明所要的关



系是否存在,这些关系都是通过 IRelationalOperator 接口实现的。IRelationalOperatior 接口的方法如

下:





IRelationalOperator 接口被面,线等几何要素实现,IRelationalOperator 接口中的方法的参数也非常类

似,参数往往是一个几何对象,以 ns 方法为例说明:





[C #]

p u b l i c bo ol C o n t a i n s (

IG eome try ot her (另一个几个对象)

) ;





示例:利用 IRelationalOperator 实现空间包含统计:





IFeatureClass pPolygonFClass = GetFeatureClass(@"D:空间查询分析用的空间数据", "三级成矿区带

");







探矿权点");



IFeatureClass pPointFClass = GetFeatureClass(@"D:空间查询分析用的空间数据", "





ITable pTable = CreateTable(@"D:空间查询分析用的空间数据", "Res3");





IFeatureCursor pPolyCursor = (null, false);





IFeature pPolyFeature = ature();





while (pPolyFeature != null)

{



IGeometry pPolGeo = ;





IRelationalOperator pRel = pPolGeo as IRelationalOperator;





int Count = 0;





IFeatureCursor pPointCur = (null, false);





IFeature pPointFeature = ature();





while (pPointFeature != null)

{

IGeometry pPointGeo = ;





if (ns(pPointGeo))

{

Count++;

}

pPointFeature = ature();





}

if (Count != 0)

{

IRow pRow = Row();

_Value(1, _Value(0));

_Value(2, Count);

();





}







}



pPolyFeature = ature();





结果和前面的一样





6、3临近 操作





临近操作用于确定一个到

多个要素、或两个要素类间的要素邻近性。它经常用来识别和一个要素最近的其

他要素或者两个要素间的最短距离等,在 ArcGIS Engine 中,实现临近分析操作的接口是

IProximityOperator,IProximityOperator 接口只有三个方法,如下:





这三个方法主要用于得到两个几何对象之间的距离或得到一个给定点到某个几个对象的最近点之间的距离 ,

比如我们求一个点到一个多边形的最近的点,就可以用这个接口。下图展示了一个查找最近点的示例:





示例:通过临近分析操作实现 Moran'I 中的邻接矩阵





Moran'I 分为全局和局部两种。

通常情况,先做一个地区的全局 I 指数,全局指数只是告诉我们空间是否出现了集聚或异常值,但并

没有告诉我们在哪里出现。换句话说全局 Moran'I 只回答 Yes 还是 NO;如果全局有自相关出现,接着做局

部自相关;

局部 Moran'I 会告诉我们哪里出现了异常值或者哪里出现了集聚,是一个回答 Where 的工具。在计算

Moran 的时候有一个很关键的步骤就是计算邻接矩阵 ,借助 IProximityOperator 接口我们可以生成这样一

个矩阵表,代码如下:



///

/// 这个字段要是唯一的

///


///

///

///

///

///





private ITable CreateWeightTable(string _FilePath, string _TableName,IFeatureClass

_pFeatureClass,string _FieldName)

{

IWorkspaceFactory pWks = new ShapefileWorkspaceFactoryClass();





IFeatureWorkspace pFwk = omFile(_FilePath, 0) as IFeatureWorkspace;





//用于添加表中的必要字段

tClassDescription objectClassDescription = new

ClassDescriptionClass();





IFields pTableFields = edFields;





IFieldsEdit pTableFieldsEdit = pTableFields as IFieldsEdit;





int index = _eld(_FieldName);





IField pField = new FieldClass();





IFieldEdit pFieldEdit = pField as IFieldEdit;





_2 = _FieldName;

ld(pFieldEdit);





_2 = __Field(index).Type;





IFeatureCursor pFtCursor = _(null, false);





IFeature pFt = ature();





while (pFt!= null )

{

IField pFieldv = new FieldClass();





IFieldEdit pFieldEditv = pFieldv as IFieldEdit;







}



_2 = _Value(index).ToString();

_2 = eldTypeInteger;

ld(pFieldEditv);

pFt = ature();





ITable pTable = Table(_TableName, pTableFields, null, null, "");





IFeatureCursor pFtCursor1 = _

h(null, false);





IFeature pFt1 = ature();





while (pFt1 != null)

{





IRow pRow = Row();





pRow .set_Value(1,_Value(index));





();







}



pFt1 = ature();





return pTable;





}





IFeatureClass pPolygonFClass = GetFeatureClass(@"D:空间查询分析用的空间数据 ", "行政区");





ITable pTable = CreateWeightTable(@"D:空间查询分析用的空间数据",

"Weight",pPolygonFClass ,"NAME");





IFeature pFt1, pFt2;





IFeatureCursor pFtCur1, pFtCur2;





pFtCur1 = (null, false);





pFt1 = ature();





ICursor pCursor = (null, false);





IRow pRow = w();





int j = 0;

///这里是关键,在这里进行计算,这里可以通过计算上三角或者下三角进行优化

while (pFt1 != null)

{

IProximityOperator pProx = as IProximityOperator;





pFtCur2 = (null, false);





pFt2 = ature();





while (pFt2 != null)

{

double dis = Distance();





if(dis ==0)

{

_Value(j + 2, 1);







}



();



}

j = 0;



pFt2 = ature();

j++;



pRow = w();



}



pFt1 = ature();





6、4拓扑 关系 操作





空间拓扑关系是空间分析中的重要部分,各种空间分析的结果都可以通过几何图像之间的拓扑运算实现。

比如:查找距离超市 1000 米内有多少居民。这些居民中有多少潜在顾客。这也是一个典型的缓冲区分析 ,

实际上就是给超市做了个 1000 米得缓冲区,然后用这个缓冲区和居民数据叠加,进而挖掘潜在顾客。空间

拓扑关系都定义在了 ITopologicalOperator 接口中,从帮助文档中我们可以获得 ITopologicalOperator

的详细信息,如下:





ITopologicalOperator 接口提供了基于现有几何体(geometries)之间拓扑关系来构建新几

何体的方法和属性





示例:在地图上通过鼠标点击实现空间缓冲查询,代码如下:





IMap pMap = ;





IActiveView pActView = pMap as IActiveView;





IPoint pt = oint(e.x, e.y);





ITopologicalOperator pTopo = pt as ITopologicalOperator;





IGeometry pGeo = (500);





lor rgbColor = new orClass();

= 255;





color = rgbColor; // Implicit Cast

eFillSymbol simpleFillSymbol = new



FillSymbolClass();

= color;





l symbol = simpleFillSymbol as

l;





bol(symbol);





lygon(pGeo);





ByShape(pGeo, nul

l, false);

//闪动1000次

hape(pGeo, 1000, 2, symbol);





h();





6、5空间 插值





在 GIS 的地理空间信息采集过程中,我们对某种地理空间现象或特征进行地理空间测量,都是基于一种离

散的样本测量,利用这些有限的采样点数据,而对研究区域内其他未知区域的特征数据进行地理空间信息

的推理和估计,从而构建一个连续的地理特征表面分布,我们把这种地理空间推理计算和估计的方法称为

地理空间插值。



地理 空间 插值 方法:





GIS 中常用的地理空间插值方法主要包括如下几种:







*?

*?

*?

*?

*?



距离加权倒数空间插值法(IDW)

自然临近空间插值法

样条空间插值法

克里格空间插值法

趋势空间插值法





这些地理空间插值方法给我们一种技术手段以供对未知点的推理和估算,其测算结果具有地统计意义,测

算结果与样本空间大小及样本空间的分布直接相关,而且这些插值方法在预测估值的时候都有自己的前提

假设,这个假设也就是每一种插值算法的理论前提。ArcGIS Engine 中 空间插值的方法都定义在 IInter

polationOp 接口中,现在这个接口已经到了 IInterpolationOp3,下面就是 IInterpolationOp3 接口中定

义的方法:





和插 值相 关的 接口





IFeatureClassDescriptor 接口:





IFeatureClassDescriptor 接口被FeatureClassDescriptor 对象实现,FeatureClassDescriptor 对象通

过指定一个值字段用来来描述插值的时候所需要的一些信息。





IRasterAnalysisEnvironment 接口:





IRasterAnalysisEnvironment 接口定义了插值后生成栅格的大小,范围,Mask 等。



IRasterRadius 接口:





从这个的字面意思就可以看出这个接口是和距离有关的,没错,我们知道一些插值比如 IDW 就是和距离有

关的,而设置距离的一些信息就定义在这个接口中,这个接口被 RasterRadiusClass 类实现。





示例:利用 ArcGIS Engine 实现 IDW 差值,代码如下:





public IGeoDataset IDW(IFeatureClass _pFeatureClass, string _pFieldName, double _pDistance,

double _pCell, int _pPower)

{

IGeoDataset Geo = _pFeatureClass as IGeoDataset;





object pExtent = ;





object o = g;





IFeatureClassDescriptor pFeatureClassDes = new FeatureClassDescriptorClass();





(_pFeatureClass, null, _pFieldName);





IInterpolationOp pInterOp = new RasterInterpolationOpClass();





IRasterAnalysisEnvironment pRasterAEnv = pInterOp as IRasterAnalysisEnvironment;





// = Geo;







ref o);



ent(sterEnvValue, ref pExtent,





object pCellSize = _pCell;//可以根据不同的点图层进行设置





lSize(e

sterEnvValue, ref

pCellSize);





IRasterRadius pRasterrad = new RasterRadiusClass();





object obj = g;





ed(_pDistance, ref obj);





object pBar = g;





IGeoDataset pGeoIDW = (pFeatureClassDes as IGeoDataset, _pPower,

pRasterrad, ref pBar);





return pGeoIDW;





}





6、6开发 利器 GP





Geoprocessing 是 ArcGIS 的一个基础组成部分,它提供了数据分析、数据管理和数据转换等大多数 GIS

用户常用的工具。 GIS 程序通常需要操作和分析地理数据,如将数据集从一种投影转换为另一种投影,要

素添加缓冲区。ArcGIS 10 包括了超过七百个 Geoprocessing 工具来执行这些任务。





在开发一个 ArcGIS Engine 的应用程序的时候,这些 Geoprocessing 工具也经常被用到, 为了降低开

发难度和提高开发效率,Esri 在 ArcGIS Engine 9.2 中添加了 GeoProcessor 类,更为可贵的是我们知道

在 ArcMap 中我们可以自定义一些用来解决相关问题的工具,而 Engine 提供的这个类也可以调用我们自定

义的工具。





在使用 GeoProcessor 时,一般需先定义一个 GeoProcessor 对象,cessor 是

简化调用 Geoprocessing 工具任务的主要对象。这个对象是执行 ArcGIS 中任何 Geoprocessing 工具的唯

一访问点,它是一个粗粒度对象,包含了许多属性和方法,在设置完操作类的参数后,则通过 GeoProcessor

的 Excute 函数来执行,Excute 方法中需要一个操作对象作为参数,如:Intersect,Clip 等,具体包含哪

些操作类,可通过 ArcToolBox 和 ESRI 的帮助文档查找。Geoprocessor 对象可以使用任何语言,包括.NET

和 Java 等来进行访问。





示例:利用 GP 实现 Intersect 分析:





在 ArcMap 中要实现 Intersect,我们只需要找到 Intersect 工具,打开,然后设置相关的参数,如下:





在 ArcGIS Engine 中,我们也可以利用寥寥数句,完成和这个一样的功能,代码如下:





从这简短的代码可以看出,几乎是零代码就完成了一个 Intersect 操作,但是我还是要强调下,在 ArcGIS

Engine 中,由于许可的原因,并不是所有的工具都可以通过这样的操作实现,但是 ArcGIS Desktop Editor

级别的工具在 ArcGIS Engine 的 Geodatabaseupdate 许可中是可以完全实现的,如果要实现 ArcGIS Desktop

Info 中的所有功能,那么就要有 ArcGIS Desktop Info 的许可,这一点还请牢记。



七. 符号 化





符号化可以认为是给我们的空间数据披上多彩的衣服,让她更加婀娜多姿。在我们拿到地图的时候,映入

眼帘的是花花绿绿的符号。地图符号是表达空间数据的一种手段,是将现实世界可视化的有力工具,也是

我们沟通地图的语言。他不仅仅表示了空间

数据的位置,还表示了空间数据的特征,布局形状等。





地图符号话决定了我们的数据最终在我们面前的面目,也是第一印象,就好比一个打扮中女孩给人的第一

感觉如何。





GIS 制图是一门科学,在我国很多高校开设了地图制图学专业,涉及计算机图形学、地图学、电子地图设

计与原理等多门专业课程。随着地理信息系统技术的发展,地图制图与 GIS 的结合越来越紧密,制作一幅

内涵丰富的电子地图已经成为 3S 行业用户工作成果的重要展示方式。





7、1和符 号化 相关 的对象





颜色 对象





颜色是显示世界中事物最普遍的属性.对于不同的行业来说,他们眼中的颜色不尽相同.我们常见的红绿蓝

等,其实这是一种称之为 RGB 的颜色模型,除了这种模型之外,在印刷行业常用的是一种称之为 CMYK 的颜色

模型,而在遥感图像增强处理的时候我们还知道另外一种颜色模型 HSI





在 ArcGIS Engine 中样色对象实现了 IColor 接口,这个接口被一下对象实现:





从这个表中也可以看出 ArcGIS Enine 中存在五种颜色模型 RGB,HSV,HIS,GARY 和 CMYK.





RGB





RGB 色彩模式使用 RGB 模型 为图像中每一个像素的 RGB 分量分配一个 0~255 范围内的强度值。RGB 图像只使

用三种颜色,就可以使它们按照不同的比例混合,在屏幕上重现 16777216 种颜色。





在 RGB 模式下,每种 RGB 成分都可使用从 0(黑色)到 255(白色)的值。 例如,亮红色使用 R 值 255、

G 值 0 和 B 值 0。 当所有三种成分值相等时,产生灰色阴影。 当所有成分的值均为 255 时,结果是纯

白色;当该值为 0 时,结果是纯黑色。





HSV 颜 色 模 型

每一种颜色都是由色相(Hue,简 H),饱和度(Saturation,简 S)和色明度(Value,简 V)所表示

的。HSV 模型对应于





圆柱坐标系中的一个圆锥形子集,圆锥的顶面对应于 V=1。它包含 RGB 模型中的 R=1,G=1,B=1 三个面,

所代表的颜色较亮。色彩 H 由绕 V 轴的旋转角给定。红色对应于 角度 0° ,绿色对应于角度 120°,蓝色

对应于角度 240°。在 HSV 颜色模型中,每一种颜色和它的补色相差 180°。饱和度 S 取值从 0 到 1,所以

圆锥顶面的半径为 1。HSV 颜色模型所代表的颜色域是 CIE 色度图的一个子集,这个 模型中饱和度为百分

之百的颜色,其纯度一般小于百分之百。在圆锥的顶点(即原点)处,V=0,H 和 S 无定义,代表黑色。圆锥

的顶面中心处 S=0,V=1,H 无定义,代表白色。从该点到原点代表亮度渐暗的灰色,即具有不同 灰度的灰

色。对于这些点,S=0,H 的值无定义。可以说 ,HSV 模型中的 V 轴对应于 RGB 颜色空间中的主对角线。 在

圆锥顶面的圆周上的颜

色,V=1,S=1,这种颜色是纯色。HSV 模型对应于画家配色的方法。画家用改变色

浓和 色深的方法从某种纯色获得不同色调的颜色,在一种纯色中加入白色以改变色浓,加入黑色以改变色

深,同时加入不同比例的白色,黑色即可获得各种不同的色调。





HSI 颜 色 模 型

HSI 色彩空间是从人的视觉系统出发,用色调( Hue)、色饱





H SI





和度(Saturation 或 Chroma)和亮度 (Intensity 或 Brightness)来描述色彩。HSI 色彩空间可以用一

个圆锥空间模型来描述。用这种 描述 HIS 色彩空间的圆锥模型相当复杂,但确能把色调、亮度和色饱和度

的变化情形表现得很清楚。 通常把色调和饱和度通称为色度,用来表示颜色的类别与深浅程度。由于人的

视觉对亮度的敏感 程度远强于对颜色浓淡的敏感程度,为了便于色彩处理和识别,人的视觉系统经常采用

HSI 色彩空间, 它比 RGB 色彩空间更符合人的视觉特性。在图像处理和计算机视觉中大量算法都可在 HSI

色彩空间中 方便地使用,它们可以分开处理而且是相互独立的。因此,在 HSI 色彩空间可以大大简化图像

分析 和处理的工作量。HSI 色彩空间和 RGB 色彩空间只是同一物理量的不同表示法,因而它们之间存在着

转换关系。





CMYK 颜 色 模 型

CMYK(Cyan, Magenta, Yellow)颜色空间应用于印刷工业,





CM YK 与 RGB 的 关 系





印刷业通过青(C)、品(M)、黄(Y)三原色油墨的不同网点面积率的叠印来表现丰富多彩的颜色和阶调,这便

是三原色的 CMY 颜色空间。实际印刷中,一般采用青 (C)、品(M)、黄(Y)、黑(BK)四色印刷,在印刷的中

间调至暗调增加黑版。当红绿蓝三原色被混合时,会产生 白色,但是当混合蓝绿色、紫红色和黄色三原色

时会产生黑色。既然实际用的墨水并不会产生纯正的颜色, 黑色是包括在分开的颜色,而这模型称之为

CMYK。CMYK 颜色空间是和设备或者是印刷过程相关的,则工艺方法、 油墨的特性、纸张的特性等,不同

的条件有不同的印刷结果。所以 CMYK 颜色空间称为与设备有关的表色空间。 而且,CMYK 具有多值性,也

就是说对同一种具有相同绝对色度的颜色,在相同的印刷过程前提下,可以用分种 CMYK 数字组合来表示



和印刷出来。这种特性给颜色管理带来了很多麻烦,同样也给控制带来了很多的灵活性。 在印刷过程中,

必然要经过一个分色的过程,所谓分色就是将计算机中使 用的 RGB 颜色转换成印刷使用的 CMYK 颜色。在

转换过程中存在着两个复杂的问题,其一是这两个颜色模型在表现颜色的范围上不完全一样,RGB 的色域

较大而 CMYK 则较小,因此就要进行色域压缩;

其二是这两个颜色都是和具体的设备相关的,颜色本身没有

绝对性。因此就需要通过一个与设备无关的颜色模型来进行转换,即可以通过以上介绍的 XYZ 或 LAB 色空

间来进行转换。





色带





在制图的过程中,有的时候使用的颜色不止一种,比如说我这个专题图需要 200 种颜色。对于这种需求,

不可能让程序员或者制图人员设置 200 种颜色吧?为此 ArcGIS Engine 中提供了颜色带对象。颜色带对象

用来一次产生多种颜色,这给我们制图带来了很大的方便。





颜色带对象实现了 IColorRamp 接口,该接口被 4 个类实现,如下图:





iColorRamap 接口定义了这 4 个类的公共方法和属性





7、2符号 对象





符号可以用来表示地理对象的某些描述性信息,如我们看到一个房子的符号,就说明了此处

表达的是一个和房子相关的对象。这样符号就作为一种传递空间信息的载体。符号就是用于

显示在地图上的修饰要素的元素对象,作为元素对象的一个属性而存在,符号的形状可以让

我们将现实世界中的实体对象加以区分,比如铁路和公路的符号,这些符号的差异也能让我

们了解要素时间属性上的差别和联系。





在 GIS 中我们简单的空间实体抽象为点,线,面三种要素,在 ArcGIS Eng ine 中对符号也抽

象为和前者对应的 MarkerSymbol,LineSymbol 和 FillSymbol。此外还有两种特殊的符号,一种

是用于显示 3D 的 3D Chart,另一种是用来标注文字的 TextSymbol。



MarkerSymbol





MarkerSymbol 对象是用于修饰点对象的符号,在 AE 的帮助中,我们可以看到 Markersymbol

有好几种子类,其中不同的子类产生不同的符号, 但是所有的 MmarkerSymbol 类都实现了

IMarkerSymbol 接口,这个接口定义了符号的公共属性,如下图:





LineSymbol 对 象





从字面意思可以得知这个对象是用来修饰线状要素的,和 MarkerSymbol 对象一样,该对象

有好几种子类,其中每种 LineS ymbol 对象都实现 了 ILineSymbol 接口,这个接口有两个属性,

这也是 LineSymbol 对象的公共属性,如下图:





FillSymbol 对 象





填充符号是针对面状要素类型的,它实现了 IFillSymbol 接口,该接口有两个属性





e 属性是修饰面状要素的轮廓是一个 ILineSymbol 对象。IFillSymbol 接口是一

个抽象类,在 AE 的帮助中我们可以看到有以下类实现了 IFillSymbol 接口。





7、3专题 图制 作





上面对 ArcGIS 中的一些颜色,符号做了详细的介绍,这些都是为了专题图的制作而打基础 。 专题图是突

出表示一种或几种自然图或社会经济现象的地图,专题图按照空间分布的点状、线状和面状分布大致有以

下的一些表示方

法:定点符号法、线状符号法、质别底色法、等值线法、定位图表法、范围法、点值法、

分值比较法、分区图表法和动线法等。ArcMap 提供了很多制作不同类型的专题图,在 Layer Pproperties

的 Symbol 选项卡中可以看到下图:





ArcGIS 中将专题图分为 5 大类。



我在前面介绍图层的时候提到 IGeoFeatureLayer 接口,专题图的制作和这个接口息息相关,该接口有一个

er 属性,该属性返回 IFeatureRenderer,该接口被 FeatureRender 对象实现,

而 FeatureRender 类是一个抽象类,在 AE 的帮助中可以看到下图:





关于制作专题图的 OMD 图可以参看如下:





7、4唯一 值





ArcMap 中是如何做的:







1.



加载要分类渲染的数据







2.



在图层上右键/properties/Symbolygy







3.



在 Categories 中找到 Unique Values



4.



设置唯一值字段,然后 Add All Values,如如下图:





和唯 一值 渲染 图相关 的接口





IUniqueValueRenderer





该接口被 UniqueValueRenderer 对象实现,用来控制唯一值渲染的主要信息,如字段设置,符号等。





示例:唯一值渲染代码:





public UniqueValueRender(AxMapControl pMapcontrol, IFeatureLayer pFtLayer,int pCount, string

pFieldName)

{





IGeoFeatureLayer pGeoFeaturelayer = pFtLayer as IGeoFeatureLayer;





IUniqueValueRenderer pUnique = new UniqueValueRendererClass();





ount = 1;





_Field(0, pFieldName);





ISimpleFillSymbol pSimFill = new SimpleFillSymbolClass();





//给颜色





IFeatureCursor pFtCursor = (null, false);





IFeature pFt = ature();





IFillSymbol pFillSymbol1;





////添加第一个符号

//pFillSymbol1 = new SimpleFillSymbolClass();

// = GetRGBColor(103, 252, 179) as IColor;





////添加第二个符号

//IFillSymbol pFillSymbol2 = new SimpleFillSymbolClass();

// = GetRGBColor(125, 155, 251) as IColor;





//创建并设置随机色谱从上面的的图可以看出我们要给每一个值定义一种颜色,我们可以创

建色谱,但是色谱的这些参数





IRandomColorRamp pColorRamp = new RandomColorRampClass();





ue = 0;





ue = 20;





uration = 15;





= 360;





ue = 100;





uration = 30;





= pCount ;





// = ount;





bool ok = true;



Ramp(out ok);





IEnumColors pEnumRamp = ;





//IColor pColor = ();





int pIndex =eld(pFieldName);





//因为我只有24条记录,所以改变这些,这些都不会超过255或者为负数.求余





int i = 0;





while (pFt != null)



{

IColor pColor = ();

if(pColor ==null)

{

();

pColor = ();





}





//以下注释代码为自定义的两种颜色 ,如果不使用随机的颜色,可以采用这样的





//if (i % 2 == 0)

//{

// ue(ng(_Value(pIndex)), pFieldName,

pFillSymbol1 as ISymbol);





//}

//else

//{

// ue(ng(_Value(pIndex)), pFieldName,

pFillSymbol2 as ISymbol);

//}



//i++;





pFillSymbol1 = new SimpleFillSymbolClass();





= pColor;

ue(ng(_Value(pIndex)), pFieldName,

pFillSymbol1 as ISymbol);





pFt = ature();





// pColor = ();





}





er = pUnique as IFeatureRenderer;







null);



lRefresh(ewGeography, null,





}





private IRgbColor GetRGBColor(int R, int G, int B)//子类赋给父类

{

IRgbColor pRGB;





pRGB = new RgbColorClass();





= R;





= G;





= B;





return pRGB;







}



}



此图为注释掉的代码,自定义的两种颜色生成生成的专题图:





此图为随机颜色生成的专题图:





7、5分类 图





和分 类渲 染图 相关的 接口





IClassBreaksRenderer





该接口主要被 ClassBreaksRenderer 对象实现,该接口控制了分类渲染对象的主要信息,如分类的字段,

分类间隔值等。





IBasicHistogram





该接口被 BasicTableHistogram 对象实现,IBasicHistogram 接口的 GetHistogram(out datavalus,out

Frenquen)方法用于获取相应数值字段的数据和对应的频数。





IClassifyGEN

该接口用于控制对要素类中的数值字段类型的数据进行统计和分类,在 ArcGIS 分类有等间距,等比和标准

差分类等,而这些对应的对象都实现了 IClassifyGEN 接口,如下图:





IClassifyGEN 接口的 Classify 方法用于产生分割线,在分类的时候应该特别注意应该将分割线数据的第

一个值付给分类渲染对象的最小值,如:





mBreak = reaks(0)





将分割线数据的第二个数值付给分类渲染对象的第一个值,如:





(0) = reaks(1)





这个对应关系可以看下图:





示例:分类渲染代码:





public class ClassRender

{

public ClassRender(AxMapControl pMapControl, IFeatureLayer pFtLayer, int ClassCount,

string pFieldName)

{

IGeoFeatureLayer pGeolayer;





IActiveView pActiveView;





pGeolayer = pFtLayer as IGeoFeatureLayer;





pActiveView = View;





//以下是为了统计和分类所需要的对象





ITable pTable;





IClassifyGEN pClassify;//C#要作为分类对象。





ITableHistogram pTableHist;/

/相当于一个统计表





IBasicHistogram pBasicHist;//这个对象有一个很重要的方法





double[] ClassNum;





int ClassCountResult;//返回分类个数。





IHsvColor pFromColor;





IHsvColor pToColor;//用于构建另外一个颜色带对象。





IAlgorithmicColorRamp pAlgo;





pTable = pGeolayer as ITable;





IMap pMap;





pMap = ;





nceScale = 0;





pBasicHist = new BasicTableHistogramClass();//也可以实例化pTableHist

pTableHist = pBasicHist as ITableHistogram;





= pTable;





= pFieldName;





object datavalus;





object Frenquen;





togram(out datavalus,out Frenquen);//获得数据和相应的频数。





pClassify = new EqualIntervalClass();







try

{

}



fy(datavalus, Frenquen, ref ClassCount);



catch (Exception e)

{

(e);

}





// 分类完成





ClassNum = (double[])reaks;





ClassCountResult = erBound(0);//返回分级个数。





IClassBreaksRenderer pClassBreak;





pClassBreak = new ClassBreaksRendererClass();





= pFieldName;





ount = ClassCountResult;





assesAscending = true;





pAlgo = new AlgorithmicColorRampClass();





thm = VAlgorithm;





pFromColor = Hsv(60, 100, 96);





pToColor = Hsv(0, 100, 96);





lor = pFromColor;





r = pToColor;





= ClassCountResult;





bool ok;





Ramp(out ok);





IEnumColors pEnumColor;





pEnumColor = ;





();





IColor pColor;





ISimpleFillSymbol pSimFill;





for (int indexColor = 0; indexColor <= ClassCountResult - 1; indexColor++)

{

pColor = ();





pSimFill = new SimpleFillSymbolClass();





= pColor;





// = pRgbColor[indexColor ];





= SSolid;





//染色





_Symbol(indexColor, pSimFill as ISymbol);





_Break(indexColor, ClassNum[indexColor + 1]);





}





er = pClassBreak as IFeatureRenderer;





lRefresh(ewGeography, null, null);





}

public IHsvColor Hsv(int hue, int saturation, int val)

{

IHsvColor pHsvC;





pHsvC = new HsvColorClass();





= hue;





tion = saturation;





= val;





return pHsvC;



}

public IRgbColor ColorRgb(int r, int g, int b)

{

IRgbColor pRGB;





pRGB = new RgbColorClass();





= r;





= g;





= b;





return pRGB;







}



}



7、6比例 图





和比 例渲 染图 相关的 接口





IProportionalSymbolRenderer 该接口被 ProportionalSymbolRenderer 对象实现,用来控

制唯一值渲染的

主要信息,如字段设置,最小值和最大值等。





示例:比例渲染代码:





public class ProPortialRender

{

public ProPortialRender(AxMapControl pMapcontrol, IFeatureLayer pFtLayer, string

pFieldName)

{

IGeoFeatureLayer pGeo = pFtLayer as IGeoFeatureLayer;





IProportionalSymbolRenderer pProRender = new ProportionalSymbolRendererClass();





= pFieldName;





nit = knownUnits;





ISimpleMarkerSymbol pMarkerSymbol = new SimpleMarkerSymbolClass();





= SCircle;





= 2;





= GetRGBColor(255, 0, 0);





bol = pMarkerSymbol as ISymbol;





IDataStatistics pDataStat = new DataStatisticsClass();





IFeatureCursor pFtCursor = (null, false);



= pFtCursor as ICursor;





= pFieldName;





aValue = m;





aValue = m;





IFillSymbol pFillS = new SimpleFillSymbolClass();





= GetRGBColor(239, 228, 190);





ILineSymbol pLineS = new SimpleLineSymbolClass();





= 2;





e = pLineS;





ISimpleFillSymbol pSFillS = pFillS as ISimpleFillSymbol;





= GetRGBColor(100, 100, 253);





oundSymbol = pFillS;





er = pProRender as IFeatureRenderer;





h();



}





public IRgbColor GetRGBColor(int r, int g, int b)

{

IRgbColor pRGB;





pRGB = new RgbColorClass();





= r;





= g;





= b;





return pRGB;





}





}





7、7简单 图





public class SimpleRender

{



public SimpleRender(AxMapControl pMapcontrol, IFeatureLayer pFtLayer, String Field)

{





IGeoFeatureLayer pGeolayer;





IActiveView pActiveView;





pGeolayer = pFtLayer as IGeoFeatureLayer;





pActiveView = View;





IFillSymbol pFillSymbol;





ILineSymbol pLineSymbol;





pFillSymbol = new SimpleFillSymbolClass();





= GetRGBColor(220, 110, 200);





pLineSymbol = new SimpleLineSymbolClass();





= GetRGBColor(255, 120, 105);





= 2;





e = pLineSymbol;





ISimpleRenderer pSimpleRender;//用什么符号渲染





pSimpleRender = new SimpleRendererClass();





= pFillSymbol as ISymbol ;





ption = "China";





= "SimpleRender";





ITransparencyRenderer pTrans;





pTrans = pSimpleRender as ITransparencyRenderer;





arencyField = Field;



er = pTrans as IFeatureRenderer;





lRefresh(ewGeography, null, null);





//地理图层的渲染对象是一

个要素渲染对象,而这个对象是由一些相关对象组成的。

//属性也是一个对象,说明大对象是由小对象组成的。





}





private IRgbColor GetRGBColor(int R, int G, int B)//子类赋给父类

{

IRgbColor pRGB;





pRGB = new RgbColorClass();





= R;





= G;





= B;





return pRGB;





}





}





7、8饼图





public PieRender(AxMapControl pMapcontrol, IFeatureLayer pFtLayer, string pFieldName1, string

pFieldName2)

{





IGeoFeatureLayer pGeoFeaLayer = (IGeoFeatureLayer)pFtLayer;

IChartRenderer pChartRenderer = new ChartRendererClass();

// Set up the field to draw charts

IRendererFields pRenderFields = (IRendererFields)pChartRenderer;

ld(pFieldName1, pFieldName1);

ld(pFieldName2, pFieldName2);

IPieChartRenderer pPieChartRender = (IPieChartRenderer)pChartRenderer;





//计算最大值部分有待补充////////////////////////////////////

//Calculate the max value of the data field to scale the chart





//ICursor pCursor = new CursorClass();

IQueryFilter pQueryFilter = new QueryFilterClass();

//IRowBuffer pRow = new RowBufferClass();

ITable pTable = (ITable)pGeoFeaLayer;

ld(pFieldName1);

ICursor pCursor = (pQueryFilter, true);





IDataStatistics pDataStat = new DataStatisticsClass();





IFeatureCursor pFtCursor = (null, false);





= pFtCursor as ICursor;





= pFieldName1;





double pMax = m;





IPieChartSymbol pPiechartSymbol = new PieChartSymbolClass();

IFillSymbol pFillSymbol = new SimpleFillSymbolClass();

IChartSymbol pChartSymbol = (IChartSymbol)pPiechartSymbol;

ise = true;

line = true;

ILineSymbol pOutLine = new SimpleLineSymbolClass();

= GetRGBColor(255, 0, 255);

= 1;

e = pOutLine;





IMarkerSymbol pMarkerSymbol = (IMarkerSymbol)pPiechartSymbol;

//finally

ue = pMax;

= 16;

//像符号数组中添加 添加符号

ISymbolArray pSymbolArray = (ISymbolArray)pPiechartSymbol;

= GetRGBColor(213, 212, 252);

e = pOutLine;

bol((ISymbol)pFillSymbol);

//////////////////////////

= GetRGBColor(183, 242, 122);

e = pOutLine;

bol((ISymbol)pFillSymbol);

//set up the background

= GetRGBColor(239, 228, 190);

mbol = (ISymbol)pFillSymbol;

rposter = false;

e = 1;

ue = m;

ryCompensation = false;

tionalBySum = true;



}



ymbol = (IChartSymbol)pPiechartSymbol;


Legend();

er = (IFeatureRenderer)pChartRenderer;

h();





public IRgbColor GetRGBColor(int r, int g, int b)

{

IRgbColor pRGB;





pRGB = new RgbColorClass();





= r;





= g;





= b;





return pRGB;







}



}





7、9点状 图





和点状图相关的接口





IGeoFeatureLayer pGeoLayer;





IDotDensityRenderer pDotDensityRenderer;//渲染对象





IDotDensityFillSymbol pDotDensityFill;//渲染填充符号对象,大对象分解小对象,独立的可

看作对象。





IRendererFields pRendField;//用那个字段渲染。





ISymbolArray pSymbolArry;





public DotRender(AxMapControl pMapControl, IFeatureLayer pFtLayer, double pValue,string

pFieldName)

{





IActiveView pActiveView;





yer = pFtLayer as IGeoFeatureLayer;





pActiveView = View;





pDotDensityRenderer = new DotDensityRendererClass();





pRendField = pDotDensityRenderer as IRendererFields;





ld(pFieldName, pFieldName); //同一个对象的接口的切换,很方便的 。





nsityFill = new DotDensityFillSymbolClass();





e = 1;





= GetRGBColor(0, 0, 0);





oundColor = GetRGBColor(239, 228, 190);





pSymbolArry = pDotDensityFill as ISymbolArray;//难道是密度。





ISimpleMarkerSymbol pSimpleMark;





pSimpleMark = new SimpleMarkerSymbolClass();





= SCircle;





= 1;





= GetRGBColor(128, 128, 255);





bol(pSimpleMark as ISymbol);





sitySymbol = pDotDensityFill;





ue = pValue;





Legend();





er = (IFeatureRenderer)pDotDensityRenderer;



h();





}

public IRgbColor GetRGBColor(int r, int g, int b)

{

IRgbColor pRGB;





pRGB = new RgbColorClass();





= r;





= g;





= b;





return pRGB;





}





7、10柱状 图





public BarRender(AxMapControl pMapcontrol, IFeatureLayer pFtLayer, String pFieldName1,

string pFieldName2)

{





IGeoFeatureLayer pGeoFeatureLayer = pFtLayer as IGeoFeatureLayer;





IFeatureClass pFeatureClass = eClass;





//定义柱状图渲染组建对象

IChartRenderer pChartRenderer = new ChartRendererClass();



//定义渲染字段对象并给字段对象实例化为pChartRenderer

IRendererFields pRendererFields;

pRendererFields = (IRendererFields)pChartRenderer;

//向渲染字段对象中添加字段--- 待补充自定义添加

ld(pFieldName1, pFieldName1);

ld(pFieldName2, pFieldName2);





ITable pTable;

pTable = pGeoFeatureLayer as ITable;





int[] pFieldIn

decies = new int[2];





pFieldIndecies[0] = eld(pFieldName1);

pFieldIndecies[1] = eld(pFieldName2);





IDataStatistics pDataStat = new DataStatisticsClass();





IFeatureCursor pFtCursor = (null, false);





= pFtCursor as ICursor;





= pFieldName2;





double pMax = m;





// 定义并设置渲染时用的chart marker symbol

IBarChartSymbol pBarChartSymbol = new BarChartSymbolClass();

= 6;





IChartSymbol pChartSymbol;

pChartSymbol = pBarChartSymbol as IChartSymbol;





IMarkerSymbol pMarkerSymbol;

pMarkerSymbol = (IMarkerSymbol)pBarChartSymbol;





IFillSymbol pFillSymbol;

//设置pChartSymbol的最大值



ue = pMax;

// 设置bars的最大高度

= 80;

//下面给每一个bar设置符号





//定义符号数组

ISymbolArray pSymbolArray = (ISymbolArray)pBarChartSymbol;





//添加第一个符号

pFillSymbol = new SimpleFillSymbolClass();

= GetRGBColor(193, 252, 179) as IColor;

bol(pFillSymbol as ISymbol);

//添加第二个符号

pFillSymbol = new SimpleFillSymbolClass();

= GetRGBColor(145, 55, 251) as IColor;

bol(pFillSymbol as ISymbol);





ymbol = pChartSymbol as IChartSymbol;

// = "AREA";

Legend();





rposter = false;

//将柱状图渲染对象与渲染图层挂钩

er = (IFeatureRenderer)pChartRenderer;







}



//刷新地图和TOOCotrol

IActiveView pActiveView = pMapcontrol .ActiveView as IActiveView;

lRefresh(ewGeography, null, null);





public IRgbColor GetRGBColor(int r, int g, int b)

{

IRgbColor pRGB;





pRGB = new RgbColorClass();





= r;



= g;





= b;





return pRGB;







}



}





八. 栅格 数据 分析





栅格 数据 分析 介绍





GIS 数据一般可分为两种主要的类型:栅格数据和矢量数据。矢量数据由弧、结点、线以及它们之间用以

组成地理空间数据的关联关系来定义。真实要素和真实表面可以表示为存储在 GIS 中的矢量数据。栅格数

据则是栅格单元的矩形矩阵,以行和列的形式表示。每个栅格单元均表示地球表面上一块经过定义的方形

区域,其值在整个栅格单元范围内始终保持不变。表面可以通过栅格数据呈现,数据中的每个栅格单元均

表示实际信息的某个值。该值可以为高程数据、污染程度、地下水位高度等。栅格数据从数学的角度来看

就是一个二维矩阵,那么我们对栅格数据的分析也就可以看成是对这个二维矩阵的数学计算.

栅格数据一般可以存储为 ESRI GRID(

由一系列文件组成),TIFF 格式(包括一个 TIF 文件和一个 AUX

文件),IMAGINE Image 格式 在 ArcGIS Engine 中一般调用 ISaveAs 接口来保存栅格数据

一个栅格数据集由一个或者多个波段(RasterBand)的数据组成,一个波段就是一个数据矩阵。对于格

网数据(DEM 数据)和单波段的影像数据,表现为仅仅只有一个波段数据的栅格数据集,而对于多光谱

影像数据则表现为具有多个波段的栅格数据集

栅格目录(RasterCatalog)用于显示某个研究区域内各种相邻的栅格数据,这些相邻的栅格数据没有

经过拼接处理合成一副大的影像图.





ArcGIS 10 中新出来了一种栅格数据管理模型,镶嵌数据集,镶嵌数据集可以看做是栅格数据集和栅格目

录的混合技术.镶嵌数据集有众多的优点而被众多的人接受,镶嵌数据集用于存储、管理、查看和查询各种

大小的栅格和影像数据集。镶嵌数据集是地理数据库中的数据模型,用于管理一组以目录形式存储并以镶

嵌影像方式查看的栅格数据集(影像)。镶嵌数据集具有高级栅格查询功能和处理函数,还可用作提供影

像服务的源。



8、1两个 扩展 模块





ArcGIS Desktop 中提供了许多用来处理栅格数据的工具,以便您进行数据管理、转换和变换;但要在分析

操作中使用栅格数据,还需要使用其中一个扩展模块。

ArcGIS 提供了两个扩展模块,用来增强栅格数据的分析功能。它们是

? ArcGIS Spatial Analyst - 此扩展模块提供了一整套高级空间建模和分析工具,可用来执行集成的

栅格和矢量分析。

? ArcGIS 3D Analyst - 此扩展模块可用于高效地显示、分析和生成表面数据,并且提供了用于进行三

维建模和分析的工具。

利用这两个扩展模块可以创建基于栅格的数据,并对其查询,分析,绘图。在空间分析模块中我们可以采

用的数据包括影像,Grid 以及其他的栅格数据集。

空间分析适用于生成 GRID 表面,还包含强大的表面分析工具,包括能够写复杂的地图代数命令。用户可从

现存数据中得到新的数据,分析空间关系和空间特征,比如距离制图,统计分析等.

ArcGIS 3D Analyst 模块适用于 3 维可视化分析,能够对表面数据进行高效率的可视化和分析,ArcGIS 3D

Analyst 提供了三维建模的高级 GIS 工具,比如挖填分析,通视分析等。

两种扩展模块都都能够计算坡度、坡向、山体阴影等等.





不得 不提 的一 个类库





GeoAnalyst 类库是一个被拥有 3D 扩展和空间分析扩展所共享的类库,包含的核心的空间分析操作 . 该类

库基于对栅格类相关的对象和接口的 Datasourcesraster 类库上.以下为 GeoAnalyst Object 的 OMD 图:







辅助 (帮助



helpe

r) 对象





栅格分析是一个很复杂的操作,在 ArcGIS Engine 中要使用一个分析,往往是由好多对象相互协作才能完成,

上图的上半部分是由一组对象进行栅格分析的集合。在上面的 OMD 中的下部分存在着一些孤立的对象(通常

称为辅助对象)用于指定分析时候的参数,例如,IDW 插值的时候设置距离阈值等。如下面的 kriging 插

值中就用到了两个辅助对象:

public void Kkriging(IFeatureClass pFeatureClass)

{





// FeatureClassDescriptor 对象用于控制和描述插值的参数





IFeatureClassDescriptor pFDescr = new FeatureClassDescriptorClass();

(pFeatureClass, null, "Ozone");





// 栅格半径辅助对象用于控制插值的参数

IRasterRadius pRasRadius = new RasterRadiusClass();

object object_Missing = g;





iable(12, ref object_Missing);





IInterpolationOp pInterpOp = new RasterInterpolationOpClass();







}



IRaster pRasterOut = (IRaster)((IGeoDataset)pFDescr,

oAnalysisExponentialSemiVariogram,

pRasRadius, false, ref object_Missing);





8、2栅格 分析 的通 常步骤





1,分析环境设置

2,设置输入参数(输入数据等)

3,执行分析操作

4,使用分析结果

分析环境设置

因为 ArcGIS 10 将 Sptial Analyst 和 3D Analyst 工具条的功能移植到了 Toolbox 中,所以在对分析环境

设置的时候是在打开工具后在下面的 Enviroment Settings 中设置, Enviroment Settings 的界面如下:





坐标系统

和矢量数据类似,没有坐标系统的栅格数据是没有太大使用价值的。很多基本的空间分析操作都要求

你的数据指定坐标系统。同时可以指定输出结果的坐标系统。

输出栅格形式

缺省情况下,大多数的空间分析操作生成的栅格是 ArcInfo 的 Grid 格式,生成的 Grid 有临时和永久

两种形式.

设置分析范围

在 Processings Extent 中,可以设置空间分析的范围,可以用户指定坐标范围,一般情况是选择等同

于某个图层的空间范围或者当前显示范围





设置 Cell 大小

在空间分析中,分析结果缺省的 cell 大小为输入数据的最大 cell 的大小,用户可以指定 cell 大小或

者指定输出 cell 等同于输入的某个数据的 cell 大小 .





除了上述设置外,还要对工作目录进行设置和分析 Mask,分析掩码是用来标识分析中操作的部分,所以分

析掩码中的空值单元将被屏蔽掉。



ArcGIS Engine 中提供的和分析环境对应的接口是 IRasterAnalysisEnvironment,该接口的属性和方法如

下:





而 ArcGIS Engine 中提供的空间分析的类也几乎全部继承了这个接口,在帮助手册中我们可以看到以下类继

承了 IRasterAnalysisEnvironment 接口:





帮助中的这个图可以和 ArcGIS

Desktop 中的以下功能对应:





这个对应关系也说明了,用 ArcGIS Engine 我们可以实现和 ArcGIS Desktop 相同的功能。





在 ArcGIS Engine 中和空间分析相关的对象被分到 3 个不同的类库当中,每一个类库包含和空间分析相关的

一些对象和接口,之所以这样划分,是因为许可的模式,一些和空间分析相关的对象在 ArcGIS 的核心产品中,

一些类库(GeoAnalyst library )可用于 3D 分析和空间分析当中,还有一些只能被拥有空间分析的模块使用

(IExtractionOp).





8、3空间 分析





8、4和栅 格空 间分 析的相 关接口





栅格数据结构简单、直观,非常利于计算机操作和处理,是 GIS 常用的空间基础数据格式。 基于栅格数据

的空间分析是 GIS 空间分析的基础,也是 ArcGIS 的空间分析的重要组成部分 .在 ArcGIS Engine 中对栅格

数据的空间分析提供了众多的接口,现在我们对常用的进行简单介绍。



IRasterProps





该接口用来描述通用的栅格数据的属性,如行数,列数等.如下面的代码用来获取栅格数据的高和宽

void GetRasterProps(IRaster pRaster)

{

IRasterProps pRasterPros = pRaster as IRasterProps;





int pH = ;//3973





int pW = ;//5629





}





IRasterCursor





IRasterCursor 接口控制着一个 Raster 的像素块(Pixblock), IRasterCurosr 接口跟前面介绍的

IFeatureCursor 一样具有一个 NEXT 方法,用于获取下一个 Pixblock,在默认情况下 IRasterCurosr 将整个

Raster 划分为高为 128 的像素块,宽为整个 raster 的宽, IRasterCurosr 每次读取比前一次低于 128 行的







像素块



接口的属性和方法如下:





为了获取 IRasterCursor,我们要用 IRaster::CreateCursor 或者 IRaster2::CreateCursorEx 方法,而这

两个的区别是前者不需要参数,而是系统默认的,而后者是需要我们制定一个大小(IPnt,看清是 IPnt,不是

IPoint)

void GetRasterCursorDefault(IRaster pRaster)

{





IRasterCursor pRasterCursor = Cursor();



while (())

{

IPixelBlock pPixBlock = lock;





int W = ;

//这个W也就是整个栅格数据记得宽度





int H = ;







}



}





void GetRasterCursorCustom(IRaster pRaster)

{





IRaster2 pRaster2 = pRaster as IRaster2;





IPnt pPnt = new PntClass();





pPnt.X = 256;





pPnt.Y = 256;





//IRasterCursor pRasterCursor2 = CursorEx(null);

//参数null的时候,获取PixBlock大小为1*1





while (())

{

IPixelBlock pPixBlock = lock;





int W = ;





int H = ;





}





}



IPixelBlock





我们知道栅格数据的容量一般很大,怎么样调高效率呢,如果按照数组的方式一个一个像素的读取

,将整

个栅格数据集都塞进二维数组也不是不可以,但是这样占的内存很多。ArcGIS 用数据库管理栅格数据的时

候是按照 block(默认是 128*128)将数据存在数据库中.而在 ArcGIS Engine 中,IPixelBlock 接口就提

供了类似的功能





IRasterLayerExport





IRasterLayerExport 接口提供的栅格数据提取功能有限,只能以矩形范围作为提取范围,如果需要更强大

的栅格数据提供功能,请考虑 IExtractionOp 接口,IExtractionOp 接口提供了多边形,圆,属性,矩形

等几种形式作为提取栅格数据.





IRasterDataset





该接口用来描述栅格数据集,栅格数据集可以认为是对栅格数据的抽象,用于代表磁盘上的栅格数据,比

如 jpg,img 等。下例为获取一个栅格数据:





IRasterWorkspace pRasterWs = GetRasterWorkspace(@".dataIDW数据");





IRasterDataset pRasterDataset =

sterDataset(" - 副本.tif");





IRasterBandCollection





栅格数据集代表磁盘上的栅格数据文件,我们知道栅格数据是由一个或多个波段组成,这些波段的集合就

是被 IRasterBandCollection 接口控制,这也说明如果要获取某一个具体的波段,应该考虑该接口。





IRaster





IRaster 接口被 Raster 对象实现,Raster 对象是一个内存对象,IRaster 接口用于控制对栅格数据像素的

读取,此接口还有一个 ResampleMethod 方法用于控制栅格数据的重采样,该接口所包含的方法如下:





IRasterLayer





该接口和 Featurelayer 接口类似,是用来承载 Raster 对象的重要接口,该接口也可以用来控制栅格数

据的渲染。以下代码为打开一个栅格数据:

private void 打开栅格数据ToolStripMenuItem_Click(object sender, EventArgs e)

{





IRasterWorkspace pRasterWs = GetRasterWorkspace(@".dataIDW数据");





IRasterDataset pRasterDataset =

sterDataset(" - 副本.tif");





IRasterLayer pRasterLayer = new RasterLayerClass();





FromDataset(pRasterDataset);





er(pRasterLayer as ILayer); ;

}





IRasterGeometryProc





IRasterGeometryProc 接口被 RasterGeometryProc 对象实现,而 RasterGeometryProc 对象只能操作我们

前面提到的 Raster 对象,因为 Raster 对象是内存对象,那么也就意味着 对 Raster 的对象的操作是临时的。

该接口是用来对 Raster 进行处理的,该接口包含众多的对 Raster 进行处理的方法,如可以用一个矩形对

栅格数据进行裁剪,或者对 Raster 进行重采样等,更多方法如下图:





关于栅格数据重采样:





栅格数据的重采样主要基于三种方法:最邻近采样(NEAREST),双线性 ILINEAR)和三次卷积采样(CUBIC)。



(1).最邻近采样:它用输入栅格数据中最临近栅格值作为输出值。因此,在重采样后的输出栅格中的

每个栅格值, 都是输入栅格数据中真实存在而未加任何改变的值。这种方法简单易用,计算量小,重采

样的速度最快。

(2).双线性采样:此重采样法取待采样点(x,y)点周围四个邻点,在 y 方向(或 X 方向)内插两次,

再在 x 方向(或 y 方向)内插一次,得到(x,y)点的栅格值。

(3).三次卷积采样:这是进一步提高内插精度的一种方法。它的基本思想是增加邻点来获得最佳插值

函数。取待计算点周围相邻的 16 个点,与双线性采样类似,可先在某一方向上内插,如先在 x 方 向 上,

每四个值依次内插四次,再根据四次的计算结果在 y 方上内插,最终得到内插结果 。

代码示例:采用双线性采样:

IRasterGeometryProc rasterGeometryProc = new RasterGeometryProcClass();

le(_CubicConvolution, newCellSize,

clipRaster);

示例,改变栅格数据像素的值





public void ChangeRasterValue(IRasterDataset2 pRasterDatset)

{





IRaster2 pRaster2 = FullRaster() as IRaster2;





IPnt pPntBlock = new PntClass();



pPntBlock.X = 128;





pPntBlock.Y = 128;

IRasterCursor pRasterCursor = CursorEx(pPntBlock);





IRasterEdit pRasterEdit = pRaster2 as IRasterEdit;





if (t())

{

IRasterBandCollection pBands = pRasterDatset as IRasterBandCollection;

IPixelBlock3 pPixelblock3 = null;

int pBlockwidth = 0;

int pBlockheight = 0;

pixels;

IPnt pPnt = null;

object pValue;

long pBandCount = ;





//获取Nodata

//IRasterProps pRasterPro = pRaster2 as IRasterProps;





//object pNodata = Value;







do

{



pPixelblock3 = lock as IPixelBlock3;

pBlockwidth = ;

pBlockheight = ;





for (int k = 0; k < pBandCount; k++)

{





pixels = ()_PixelData(k);

for (int i = 0; i < pBlockwidth; i++)

{

for (int j = 0; j < pBlockheight; j++)

{





pValue = ue(i, j);





if (32(pValue) == 0)

{

ue((50), i, j);







}



}



}



}



_PixelData(k, pixels);





pPnt = t;

(pPnt, (IPixelBlock)pPixelblock3);







}



}

while (());

eComObject(pRasterEdit);





}





原始影像图:





处理后的影像图:





///

/// 分割栅格数据

///


///

///

///

///

public void CreateT

ilesFromRasterDataset(IRasterDataset pRasterDataset, IWorkspace

pOutputWorkspace, int pWidth, int pHeight)

{





IRasterProps pRasterProps = (IRasterProps)DefaultRaster();

double xTileSize = llSize().X * pWidth;

double yTileSize = llSize().Y * pHeight;





int xTileCount = (int)g((double) / pWidth);

int yTileCount = (int)g((double) / pHeight);





IEnvelope pExtent = ;

IEnvelope pTileExtent = new EnvelopeClass();

ISaveAs pSaveAs = null;



for (int i = 0; i < xTileCount; i++)

{

for (int j = 0; j < yTileCount; j++)

{

pRasterProps = (IRasterProps)DefaultRaster();





= + i * xTileSize;

= + xTileSize;

= + j * yTileSize;

= + yTileSize;





= pHeight;

= pWidth;

= pTileExtent;







}



}



}



pSaveAs = (ISaveAs)pRasterProps;

("tile_" + i + "_" + j + ".tif", pOutputWorkspace, "TIFF");





8、5重要 名词 (表 面、栅格 表面、TIN表面)





什么 是表 面





3D 表面模型是三维空间中要素(真实或假想)的一种数字表达形式。比如地下天然气矿床以及用于测定地

下水位深度的深井组成的网络,但表面也可以是派生的或假想的。某种特定细菌在每个井中的污染程度就

是派生表面的一个示例。这些污染程度级别也可以绘制成 3D 表面地图。而假想 3D 表面通常在视频游戏

或计算机模拟环境中可以见到。





通常可以使用专门设计的算法来获取或计算 3D 表面,这些算法对点、线或面数据进行采样然后将其转换

为数字 3D 表面。ArcGIS 可以创建和存储三种类型的表面模型:栅格、TIN 和 terrain 数据集(没见过)。





栅格 表面





GIS 数据一般可分为两种主要的类型:栅格数据和矢量数据。矢量数据由弧、结点、线以及它们之间用以

组成地理空间数据的关联关系来定义。真实要素和真实表面可以表示为存储在 GIS 中的矢量数据。栅格数

据则是栅格单元的矩形矩阵,以行和列的形式表示。每个栅格单元均表示地球表面上一块经过定义的方形

区域,其值在整个栅格单元范围内始终保持不变。表面可以通过栅格数据呈现,数据中的每个栅格单元均

表示实际信息的某个值。该值可以为高程数据、污染程度、地下水位高度等。



TIN



表 面





不规则三角网 (TIN) 以数字方式来表示表面形态。TIN 是基于矢量的数字地理数据的一种形式,通过将一

系列折点(点)组成三角形来构建。通过由一系列边连接各个折点,形成三角网。可

通过多种不同的插值

方法形成这些三角形,例如 Delaunay 三角测量法或距离排序法。ArcGIS 支持 Delaunay 三角测量方法。





8、6表面 分析





在栅格表面分析的时候经常会遇到 ISurfaceop 和 Isurface 接口,为此我们对这两个接口做一下介绍 ,虽然

这两个接口只相差两个字母,但是功能和用法却大不一样.







ISurfaceOp 和



ISurface 的区 别





ISurfaceOp 接口被 RasterSurfaceOpClass 类实现,而 RasterSurfaceOpClass 类是在

lyst 类库中,通过前面的介绍我们知道 lyst 类库中的接口和类是

被拥有 3D 扩展模块和空间扩展模块的用户所拥有.在帮助文档中我们可以看到 ISurfaceOp 接口所拥有的属

性和方法如下:





在空间分析模块中我们可以看到下图



这样的比较使得我们知道 ISurfaceOp 接口完全可以实现空间分析下的 Surface 工具集中的功

能而 ISurface 接口被 RasterSurfaceClass 类实现,而 RasterSurfaceClass 类是在

t3D 类库中,也就是这个接口只能在 3D 分析中使用,Isurface 接口拥有更多的

方法和属性,以下为部分截图:





8、7专属于空间 分析的 表面分析(邻域 分析 ,单元分析 ,栅格提取, 代数 计算 等)





8、7、1邻域 分析





public IGeoDataset CreateNeighborhoodOpBlockStatisticsRaster(IGeoDataset GeoDataset)

{





INeighborhoodOp pNeighborhoodOP = new RasterNeighborhoodOpClass();





IRasterNeighborhood pRasterNeighborhood = new RasterNeighborhoodClass();



tangle(3, 3,

itsCells);





IGeoDataset pGeoOutput =

tatistics(GeoDataset,oAnalysisStat

sMean, pRasterNeighborhood, true);





return pGeoOutput;





}





裁剪





public IGeoDataset CreateExtractOp(IGeoDataset pGeoDataset, on

pPolygone)

{





ctionOp pExtractionOp = new

ExtractionOpClass();





taset pGeoOutput =

n(pGeoDataset, pPolygone, true);





return pGeoOutput;





}





8、7、2密度 分析





密度分析的对象为 RasterDensityOp,而该对象实现了 IDensityOp 接口,该接口里面定义了密

度分析的几种方法,比如点密度,核密度等,如下图:





public IRaster DensityAnalyst(IFeatureClass pFeatureClass,string pFieldName, double

pCellSize, double pRadius)

{

//辅助对象,设置密度分析时候的参数





IFeatureClassDescriptor pFDescr = new FeatureClassDescriptorClass();

(pFeatureClass, null, pFieldName);





IDensityOp pDensityOp = new RasterDensityOpClass();





//设置环境

IRasterAnalysisEnvironment pEnv = pDensityOp as IRasterAnalysisEnvironment;





object objec

t_cellSize = ()pCellSize;





lSize(sterEnvValue, ref

object_cellSize);





double_radio_dis = pRadius;

object object_radio_dis = ()double_radio_dis;

object Missing = g;

//核函数密度制图方法生成栅格数据

IRaster pRaster = Density(pFDescr as IGeoDataset, ref

object_radio_dis, ref Missing) as IRaster;





return pRaster;





}





IDistanceOp 接 口





public IGeoDataset CreateDistanceOpCostPathRaster(IGeoDataset pGeoDataset1, IGeoDataset

pGeoDataset2, IGeoDataset pGeoDataset3)

{





IDistanceOp pDistanceOp = new RasterDistanceOpClass();





IGeoDataset pGeoDatasetOutput = th(pGeoDataset1, pGeoDataset2,

pGeoDataset3, oAnalysisPathForEachZone);





return pGeoDatasetOutput;





}





RasterConvertHelperClass 接 口





public void ConvertRaterToLineFeature(string pRasterWs,string

pRasterDatasetName,string pShapeFileName)

{





IRasterDataset pRasterDataset =

GetRasterWorkspace(pRasterWs).OpenRasterDataset(pRasterDatasetName);



IConversionOp pConversionOp = new RasterConversionOpClass();





IRasterAnalysisEnvironment pEnv = (IRasterAnalysisEnvironment)pConversionOp;

IWorkspaceFactory pWorkspaceFactory = new RasterWorkspaceFactoryClass();

IWorkspace pWorkspace = omFile(pRasterWs, 0);

kspace = pWorkspace;

IWorkspaceFactory pShapeFactory = new ShapefileWorkspaceFactoryClass();

IWorkspace pShapeWS = omFile(pRasterWs, 0);





pDangle = ()1.0;

IGeoDataset pFeatClassOutput =

DataToLineFeatureData((IGeoDataset)pRasterDataset,

pShapeWS, pShapeFileName, false, false, ref pDangle);

}





///

/// 要素转成Grid

///


///

///

///

///

///

public IGeoDataset CreateGridFromFeatureClass(IFeatureClass pFeaureClass, String

pRasterWorkspaceFolder, double pCellsize ,string pGridName)

{





IGeoDataset pGeoDataset = (taset)pFeaureClass; //

Explicit Cast





ISpatialReference pSpatialReference = lReference;





IConversionOp pConversionOp = new

ConversionOpClass();





IWorkspaceFactory pWorkspaceFactory = new

WorkspaceFactoryClass();





IWorkspace pWorkspace = omFile(pRasterWorkspaceFolder,



0);





IRasterAnalysisEnvironment pAnalysisEnvironment =

(rAnalysisEnvironment)pConversionOp; // Explicit Cast

kspace = pWorkspace;





ope pEnvelope = new



lopeClass();

pEnvelope = ;





object pObjectCellSize = ()pCellsize;





lSize(sterE

nvValue, ref pObjectCellSize);





object object_Envelope = ()pEnvelope;

object object_Missing = g;





ent(sterEnv

Value, ref object_Envelope, ref object_Missing);





tialReference = pSpatialReference;





IRasterDataset pRasterDataset = new

DatasetClass();







pGridName);



pRasterDataset = erDataset(pGeoDataset, "GRID", pWorkspace,





IGeoDataset pGeoOutput = (taset)pRasterDataset;





return pGeoOutput;





}



8、7、3 3D 分 析





获取高程的代码





double GetElevation(IRaster pRaster, IPoint point)

{

IRasterSurface pRasterSurface = new RasterSurfaceClass();

ter(pRaster, 0);

ISurface pSurface = pRasterSurface as ISurface;

return vation(point);





}





通视分析代码





if(_Layer(0)!=null)

{

IRasterLayer pRasterLayer = _Layer(0) as IRasterLayer;





IRasterSurface pRasterSurface = new RasterSurfaceClass();





ter(, 0);





ISurface pSurface = pRasterSurface as ISurface;





IPolyline pPolyline = ine() as IPolyline;





IPoint pPoint =null ;





IPolyline pVPolyline =null;





IPolyline pInPolyline= null;





object pRef=0.13;





bool pBool =true;

//获取Dem的高程

double pZ1 = vation(int);

double pZ2= vation(t);





IPoint pPoint1 = new PointClass();





pPoint1.Z = pZ1;





pPoint1.X = int.X;





pPoint1.Y = int.Y;





IPoint pPoint2 = new PointClass();





pPoint2.Z = pZ2;





pPoint2.X = t.X;





pPoint2.Y = t.Y;





eOfSight(pPoint1, pPoint2, out pPoint, out pVPolyline,

out pInPolyline, out pBool, false, false, ref pRef);

if (pVPolyline != null)

{





IElement pLineElementV = new LineElementClass();





ry = pVPolyline;





ILineSymbol pLinesymbolV = new SimpleLineSymbolClass();





= 2;





IRgbColor pColorV = new RgbColorClass();





=255;





= pColorV;





ILineElement pLineV = pLineElementV as ILineElement;





= pLinesymbolV;



0);



}



ment(pLineElementV,





if (pInPolyline != null)

{





IElement pLineElementIn = new LineElementClass();





ry = pInPolyline;





ILineSymbol pLinesymbolIn = new SimpleLineSymbolClass();





pLinesy

= 2;





IRgbColor pColorIn = new RgbColorClass();

= 255;





= pColorIn;

ILineElement pLineIn = pLineElementIn as ILineElement;





= pLinesymbolIn;







1);



ment(pLineElementIn,





}





lRefresh(ewGraphics, null, null);





8、7、4Tin 表面分析





ITinSurface Interface





Tin 的表面分析得益于 ITinSurface 接口,而 ITinSurface 继承了 ISurface 接口,我们知道空间分析和 3D

分析在栅格表面分析有部分重合,但是 Tin 的表面分析只能在 3D 分析下进行 .Tin 是一个用来模拟地表的

组件类以便进行相应的分析.





打开 Tin





public ITinLayer GetTINLayer(string pPath)//打开TIN文件

{

ITinWorkspace pTinWorkspace;

IWorkspace pWS;

IWorkspaceFactory pWSFact = new TinWorkspaceFactoryClass();





ITinLayer pTinLayer = new TinLayerClass();





string pathToWorkspace = ectoryName(pPath);

string tinName = eName(pPath);

ITin pTin;





pWS = omFile(pathToWorkspace, 0);

pTinWorkspace = pWS as ITinWorkspace;





if (_IsTin(tinName))

{

pTin = n(tinName);





t = pTin;





enderers();





return pTinLayer;





}

else

{

("该目录不包含Tin文件");

return null;





}





}





或者下面的代码



ITinAdvanced2 pTin = new TinClass();

(@"E:arcgisEngineIDW数据dvtin");





ITinLayer pTinLayer = new TinLayerClass();





t = pTin;

er(pTinLayer as ILayer);





创建 Tin





private void 创建TinToolStripMenuItem_Click(object sender, EventArgs e)

{

IFeatureClass pFeatureClass = GetFeatureClass(@"E:arcgisEngineIDW数据", "山东

20100321");







TinTest");

}



IField pField = _Field(eld("H"));

ITin pTin = CreateTin(pFeatureClass, pField, @"E:arcgisEngineIDW数据

ITinLayer pTinLayer = new TinLayerClass();

t = pTin;

er(pTinLayer as ILayer);





///

/// 创建Tin

///


///

///

///

///

public ITin CreateTin(IFeatureClass pFeatureClass, IField pField, string pPath)

{

IGeoDataset pGeoDataset = pFeatureClass as IGeoDataset;





ITinEdit pTinEdit = new TinClass();

w();

object pObj = g;

mFeatureClass(pFeatureClass, null, pField, null,

nMassPoint, ref pObj);



(pPath, ref pObj);

h();

return pTinEdit as ITin;





}





8、7、5 Tin 生成 等高 线





priv

ate void Tin2Contour(ITin pTin,IFeatureClass pFeatureClass)

{

ITinSurface pTinSurface = pTin as ITinSurface;







}



//不要启动编辑,因为这个接口会在要素类中添加字段

r(0, 2, pFeatureClass, "Height", 0);





private void 等高线ToolStripMenuItem_Click(object sender, EventArgs e)

{

ITinLayer pTinLayer = GetTINLayer(@"E:arcgisEngineIDW数据dvtin");





IFeatureClass pFeatureClass = GetFeatureClass(@"E:arcgisEngineIDW数据",

"TinContour");





Tin2Contour(t as ITin, pFeatureClass);





IFeatureLayer pFeatLayer = new FeatureLayerClass();



= "等高线";





eClass = pFeatureClass;





er(pFeatLayer as ILayer);





}





8、8AE 创建 泰森 多边 形





private void 泰森多边形ToolStripMenuItem_Click(object sender, EventArgs e)

{

ITinLayer pTinLayer = GetTINLayer(@"E:arcgisEngineIDW数据dvtin");





IFeatureClass pFeatureClass = GetFeatureClass(@"E:arcgisEngineIDW数据", "Vr");





CreateVr(pFeatureClass, t as ITin);





IFeatureLayer pFeatLayer = new FeatureLayerClass();





= "泰森多边形";





eClass = pFeatureClass;







}



er(pFeatLayer as ILayer);





///

/// 创建泰森多边形

///


///

///

void CreateVr(IFeatureClass pFeatureClass ,ITin pTin)

{

ITinNodeCollection pTinColl = pTin as ITinNodeCollection;





tToVoronoiRegions(pFeatureClass, null, null, "", "");





}





分析 助手





栅格数据分析异常复杂和庞大,但是 Esri 提供给了我们连个利器 lAnalystTools 和

t3Dtools,只要拥有相关的许可,那么这些分析都会变得容易。





8、9波段 计算 和影 像金字 塔





///

/// 波段统计和创建影像金字塔

///


///

public static void CalculateStatsAndPyramids(IRasterDataset pRasterDataset)

{





IRasterBandCollection pBandColl = (IRasterBandCollection)pRasterDataset;





// 波段统计

for (int i = 0; i < ; i++)

{

IRasterBand pRasterBand = (i);





eStatsAndHist();



}





//创建金字塔







}



IRasterPyramid pRasterPyramids = (IRasterPyramid)pRasterDataset;

if (t == false)

{

();

}





8、10分级 渲染





public IRasterRenderer ClassifyRenderer(rDataset

pRasterDataset)

{

try

{

//Create the classify renderer.

IRasterClassifyColorRampRenderer pClassifyRenderer = new

RasterClassifyColorRampRendererClass();

IRasterRenderer pRasterRenderer = (IRasterRenderer)pClassifyRenderer;





//Set up the renderer properties

.

IRaster pRaster = DefaultRaster();

= pRaster;

ount = 9;

();





IRgbColor pFromColor = new RgbColorClass();

= 255;

= 0;

= 0;

IRgbColor pToColor = new RgbColorClass();

= 0;

= 255;

= 255;





//Set the color ramp for the symbology.

IAlgorithmicColorRamp pRamp = new AlgorithmicColorRampClass();

= 9;

lor = pFromColor;



r = pToColor;

bool pBoolColorRamp;

Ramp(out pBoolColorRamp);







}



//Create the symbol for the classes.

IFillSymbol pFillSymbol = new SimpleFillSymbolClass();

for (int i = 0; i < ount; i++)

{

= _Color(i);

_Symbol(i, (ISymbol)pFillSymbol);

_Label(i, ng(i));

}

return pRasterRenderer;



}



catch (Exception ex)

{

ine(e);

return null;

}





渲染





public IRasterRenderer ColormapRenderer(rDataset

pRasterDataset)

{

try

{

IRasterRenderer pColormapRender = new RasterColormapRendererClass();

IRaster pRaster = DefaultRaster();

= pRaster;





return pColormapRender;







}



}

catch (Exception ex)

{

ine(e);

return null;

}



8、11拉伸





public IRasterRenderer StretchRenderer(rDataset pRasterDataset)

{

try

{

//Define the from and to colors for the color ramp.

IRgbColor pFromColor = new RgbColorClass();

= 255;

= 0;

= 0;

IRgbColor pToColor = new RgbColorClass();

= 0;

= 255;

= 0;

//Create the color ramp.

IAlgorithmicColorRamp pRamp = new AlgorithmicColorRampClass();

= 255;

lor = pFromColor;

r = pToColor;

bool createColorRamp;

Ramp(out createColorRamp);

//Create a stretch renderer.

IRasterStretchColorRampRenderer pStretchRenderer = new

RasterStretchColorRampRendererClass();

IRasterRenderer pRasterRenderer = (IRasterRenderer)pStretchRenderer;

//Set the renderer properties.

IRaster pRaster = DefaultRaster();

= pRaster;

();

dex = 0;

amp = pRamp;

//Set the stretch type.

IRasterStretch pStretchType = (IRasterStretch)pRasterRenderer;

hType =

sterStretch_StandardDeviations;

rdDeviationsParam = 2;

return pRasterRenderer;

}

catch (Exception ex)

{

ine(e);

return null;



}



}





九. 编







编辑对于 GIS 来说无处不在,对空间数据的更改,增加和删除都是随数据的编辑,而这个最常用的操作幕

后又是怎么运作的呢?我们从下面进行详细介绍。





编辑 是如 何进 行的?





在 ArcGIS Engine 中编辑操作必须位于一个编辑会话中,且编辑编辑操作不能在其他编辑操作嵌套。下图

显示了使用 IWorkspaceEdit 进行操作的流程。该图不包括使用撤消和重做操作:





Geodatabase 编辑是长事务操作,一个编辑会话对应于一个长事务,应用程序在编辑会话中看到的仅是该

应用程序对数据更改所做的变化数据变化,其它同时执行的的更改(若允许)在编辑会话被保存或丢弃之前

是看不到的(SDE 数据库可以多人同时编辑)。



编辑 会话





应用程序可以使用地理数据库编辑会话和编辑操作管理数据库事务。编辑会话和编辑操作操作提供了几个

好处:

1,将编辑组合成事务。如果在编辑完成之前发生错误,这个事物就会回滚。





2,可选的由数据库维护“重做”和“撤销“数据库操作堆栈。





编辑操作后停止,它被放置在撤消堆栈。应用程序开发人员可以遍历撤消/重做堆栈 ,以便调用

UndoEditOperation 和 RedoEditOperation。,





3,编辑会话和编辑操作允许出现批量更新,在编辑 SDE 数据库的时候以便提供显着的性能优势。

4,在地理数据库允许多个用户同时并发编辑数据,在编辑会话期间用户不会看到其他用户所做的变化,直

到会话结束的时候才可以。

5,地理数据库保证在一个编辑会话中存在一个唯一的从数据库中检索行对象实例。如果已经在编辑会话中

实例化了该实例,任何访问非回收的对象将返回该对象在内存中的对象实例。





编辑 操作





ArcGIS Engine 的编辑相当于数据库中一个事物的操作,我们可以清楚的知道在 ArcMap 中,如果我们要做

一个编辑,第一步就是启动编辑,然后操作,最后保存,在我们启动编辑的时候实际上相当于开启了一个

和关系型数据库中对应的一个事物,在我们开启编辑,保存操作,停止编辑都对应了 ArcGIS Engine 中提

供的如下三个方法:







ArcGIS Engine
关系型数据库
StartEditOpe ra tion
Start a transaction
StopEditOperation
Commit the transaction
AbortEditOperation
Abort the transaction






下面给出了一个启动编辑会话和编辑操作的简单示例代码,该例子的作用是给数据库中的一个表创建一个

新的行。





public void StartEdit(IWorkspace pWorkspace, ITable pTable)

{





IWorkspaceEdit pWorkspaceEdit = (IWorkspaceEdit)pWorkspace;

//启动编辑会话

diting(false);

//启动编辑操作

ditOperation();





IRow pRow =

teRow();







}



_Value(2, "练习");

();

//结束编辑操作

itOperation();

//结束编辑会话

iting(true);





IWorkspaceEdit





IWorkspaceEdit 接口是 ArcGIS Engine 实现空间数据编辑的重要接口,它让程序启动或者停止一个编辑流

程,在这个编辑流程内,可以对数据库中的数据进行删除,添加,更改。我们所有的对要素或者属性的修

改都可以放到一个会话中,这个会话就相当于 ArcMap 中的 Start Edting,当会话启动后,我们就可以在

图层中对数据进行修改,删除等操作。如果我们已经在使用 IEngineEdito 接口编辑 Geodatabase,那就不

应该使用该接口控制编辑。





IWorkspaceEdit 接口的方法和属性如下:





这个例子中,我创建了 1000 条要素,并结合缓冲将数据写到文件中,并且添加了时间统计,当然数据是我

捏造的,还请原谅,这个花费的时间为 0.978 秒,速度还行。





///

/// 编辑的全局变量

///


///

///

private void button6_Click_1(object sender, EventArgs e)

{

IWorkspaceFactory pWsF = new ShapefileWorkspaceFactory();





IFeatureWorkspace pFtWs = omFile(@"E:arcgisEngine数据", 0) as

IFeatureWorkspace;





IFeatureClass pFtClass = atureClass("edit");





IFeatureLayer pFt = new FeatureLayerClass();





eClass = pFtClass;

= "画线";





er(pFt as ILayer);





h();





//为了进一步说明Idataset,我特意从下面的代码



IDataset pDataset = pFtClass as IDataset;





IWorkspace pWs = ace;





pWsEdit = pWs as IWorkspaceEdit;





diting(true);





ditOperation();





pBoolStart = gEdited();





IFeatureBuffer pFeatureBuffer = FeatureBuffer();





IFeatureCursor pFtCusor = (true);





ine polyline = new

neClass();

pPoint = new lass();





pPoint2 = new lass();

for (int i = 0; i < 1000; i++)

{





pPoint.X = 48 + i * 102;





pPoint.Y = 65 + i * 10;





int = pPoint;





pPoint2.X = 480 + i * 10;





pPoint2.Y = 615 + i * 102;





t = pPoint2;





= polyline;





_Value(2, i);







}



object pFeatureOID = Feature(pFeatureBuffer);





();





iting(true);





h();





}



IMultiuserWorkspaceEdi t





通过这个接口的字面意思就可以看出这个接口是为多用户编辑设计的,也就是针对 SDE 数据库的

。该接口

只有三个方法,如下图:





ultiuserEditing 是 SDE 数据库编辑的入口。相当于

().而该方法可开启 SDE 数据库的版本会话和非版本会话,这个区别是因为

ultiuserEditing 这个方法需要一个参数,这个





该方法需要一个参数是枚举类型的如下图所示





编辑 SDE 版本的代码示例

public void StartSDEVersion(IWorkspace pWorkspace)

{





IMultiuserWorkspaceEdit pMWorkspaceEdit = (IMultiuserWorkspaceEdit)pWorkspace;





IWorkspaceEdit pWorkspaceEdit = (IWorkspaceEdit)pWorkspace;





//启动版本编辑会话





ultiuserEditing(SMVersioned);

//启动编辑操作

ditOperation();





//编辑过程...





//结束编辑操作

itOperation();



//结束编辑会话

iting(true);





}





IEngineEditor





IEngineEditor 接口被 EngineEditor 对象继承并实现,EngineEditor 接口就相当于 ArcMap 中的编辑工具

条中的 Editor 一样,控制着整个编辑的生命周期(注意,我们可以在 ToolbarConrol 上 将 Editor 模拟出来,

然后按照 ArcGIS 桌面中的 Start Editing,同时也可以采用代码的方式,但是这两种方式在一个应用程序

中只能选取一个)





ArcGIS 桌面提供的编辑工具条





ArcGIS Engine 控件模拟的编辑工具条,





IEngineEditor 接口的方法和属性如下:





IEngineEditor 里面有好多 Task,Task 可以认为是为了执行一个操作而封装的一个流程,可能

有点抽象,我们可以回想一下 ArcMap 中的情况,当我们在 ArcMAP 中要创建一个新的要素

的时候,我们要将 Task 中选择为 Create new feature,然后在 Editor 工具条上结合草图工具

实现对数据的编辑。而且这个 Task 对我们是开放的,我们可以自定义操作





IEngineEditTask 接口 的方 法和 属性 如下 :





IEngineEditor 接口和 IWorkspaceEdit 的比较







IEngineEditor



IWorkspac eEdit







Start an edit session



Sta rtEditing



StartEditing







Stop an edit session



StopEditing



StopEditing







Start an edit operation



Sta rtOpe ra tion



StartEditOperation







Stop an edit opera tion



StopOperation



StopEditOpe ra tion







Abort an e dit opera tion



AbortOperation



AbortEditOperation







Rollback an e dit ope ra tion



UndoOperation



UndoEditOperation







Reapply a n edit operation



Re doOperation



RedoEditOperation







Commit edits



StopEditing(True)



StopEditing(True)





在上一个例子中,我们对 IWorkspaceEdit 接口做了介绍,通过 IWorkspaceEdit 接口,我们

实现了对要素的添加,而在编辑的时候,我还提到了另外一个接口 IEngineEditor。

IEngineEditor

接口被 EngineEditorClass 实现,而 EngineEditor 对象相当于我们在

ArcMap 中编辑的时候用到的 Editor 工具条,回想下我们要在一个线图层中添加一条新的要

素,我们往往是按照下面的步骤

1)Start Editing

2)将 Targetlayer 设置为我们要编辑的图层

3)设置 Task 为 Create new Feature



4)然后使用草图工具开始编辑。

其实这 4 个步骤分别对应了四个接口,而这 4 个接口中有 3 个接口都 EngineEditorClass

直接实现,这三个个接口分别是:

IEngineEditor

IEngineEditLayer

IEngineEditSketch

在这里还有一个 ITask 接口,ITask 接口为 IEngineEditor 接口的一个属性

Task 是一个任务流,ArcGIS 中的这个 Task 就是对一系列操作的封装,也就是用草图工具

所做的一系列动(Mousedown,Mousemove 等)。





这个示例中我定义了一个给等高线批量赋值的 Task。

以前在网上看过一个用 写的等高线批量赋值(AO),我参考其中的代码,用 C#重新

写了(Engine),迁移到 ArcGIS 10 中,现在跟大家分享,我参考的那个好像是 ”等高线自

动标注组件开发“,主要代码如下:





IWorkspaceFactory pWsF = new ShapefileWorkspaceFactory();





IFeatureWorkspace pFtWs = omFile(@"E:arcgisEngine数据", 0) as

IFeatureWorkspace;





IFeatureClass pFClass = atureClass("ctour9_Clip");





IFeatureLayer pFtLayer = new FeatureLayerClass();





= "等高线";





eClass = pFClass;





er(pFtLayer as ILayer);





h();

pEngineEditor = new EngineEditorClass();



//启动编辑





diting(pFtWs as IWorkspace, );





peration();

//设置目标图层

IEngineEditLayers pEditLayer = pEngineEditor as IEngineEditLayers;





getLayer(pFtLayer, 0);

//设置任务流

tTask = new CalculatContourTask() as IEngineEditTask;





//启用草图工具





ICommand pSketch = new ControlsEditingSketchToolClass();





te();





tTool = pSketch as ITool;





//结束编辑

if (ate == gineStateEditing)

{

iting(true);

}





using System;

using c;

using ;

using pServices;





using ;

using ls;

using abase;

using ry;

using ;

using stem;



using ;

using ;





namespace EngineApplication

{

[Guid("5b0c0692-eaf7-4d64-9cee-c8c1afaf06f4")]

[ClassInterface()]

[ProgId("rTask")]





public class CalculateContour :

Task

{

#region

IEditor pEngineEditor;

IEditSketch pEditSketch;

IEditLayers pEditLayer;





#endregion





#region "IEditTask Implementations"

public void Activate(IEditor pEditor, ask pEditTask)

{

if (pEditor == null)

return;





pEngineEditor = pEditor;

pEditSketch = pEngineEditor as IEditSketch;

ryType = ometryPolyline;

pEditLayer = pEditSketch as IEditLayers;





//Listen to engine editor events

((IEngineEditEvents_Event)pEditSketch).OnTargetLayerChanged += new

IEngineEditEvents_OnTargetLayerChangedEventHandler(OnTargetLayerChanged);





((IEngineEditEvents_Event)pEditSketch).OnCurrentTaskChanged += new

IEngineEditEvents_OnCurrentTaskChangedEventHandler(OnCurrentTaskChanged);

}





public void Deactivate()

{

// TODO: Add vate implementation





hSketch();





//Stop listening to engine editor events.

((IEngineEditEvents_Event)pEditSketch).OnTargetLayerChanged -=

OnTargetLayerChanged;





((IEngineEditEvents_Event)pEditSketch).OnCurrentTaskChanged -=

OnCurrentTaskChanged;







}



//Release object references.

pEngineEditor = null;

pEditSketch = null;

pEditLayer = null;





public string Name

{

get

{

// TODO: Add getter implementation

return "ContourTask";

}

}

public string UniqueName

{

get

{

return "ContourTask";

}

}





public string GroupName

{

get

{

//This property allows groups to be created/used in the

EngineEditTaskToolControl treeview.

//If an empty string is supplied the task will be appear in an "Other Tasks" group.

//In this example the Reshape Polyline_CSharp task will appear in the existing

Modify Tasks group.

return "Other Tasks";

}

}





public void OnDeleteSketch()

{

// TODO: Add teSketch implementation

}





public void OnFinishSketch()

{

// TODO: Add shSketch implementation





//get reference to featurelayer being edited

IFeatureLayer pFeatureLayer = tLayer as IFeatureLayer;

//get reference to the sketch geometry

IGeometry pPolyline = ry;





if (y == false)

{

ParaSetting pFormSetting = new ParaSetting(eClass);





alog();





if (Result == )

{

pHeightName = ;





pHeight = le();





pInterval = le();





e();





pFormSetting = null;





IFeatureCursor pFeatureCursor = GetFeatureCursor(pPolyline,

eClass);





CalculateIntersect(pFeatureCursor, pPolyline);







}



("OK");





}





//refresh the display

IActiveView pActiveView = as IActiveView;

lRefresh(esriViewDrawPhase

.esriViewGeography,

(object)pFeatureLayer, );





}





private IFeatureCursor GetFeatureCursor(IGeometry pGeometry, IFeatureClass

pFeatureClass)

{





//空间过虑器的创建

ISpatialFilter pSpatialFilter = new SpatialFilter();

ry = pGeometry;

//空间过虑器几何体实体

//空间过虑器参照系





//空间过虑器空间数据字段名

ryField = ieldName;

//空间过虑器空间关系类型

lRel = atialRelIntersects;

//相交

IFeatureCursor pFeatureCursor = (pSpatialFilter, false);





return pFeatureCursor;





}





//起始等高线值

private double pHeight;

//等高线间距

private double pInterval;

//高程字段名

private string pHeightName;





private void CalculateIntersect(IFeatureCursor pFeatureCursor, IGeometry Geometry)

{





//要素游标



IMultipoint pIntersectionPoints = null;

//多点

IPointCollection pPointColl = null;





List pFeatureList = new List();

//和直线相交的要素集合,未排序

double[,] pIndex = null;

//距离和初始索引





if (pFeatureCursor == null)

{

return;

}

ITopologicalOperator pTopoOperator = Geometry as ITopologicalOperator;





IPointCollection pSketchPointColl = Geometry as IPointCollection;

//所画直线的起点

IPoint P0 = _Point(0);

IFeature pFeature = ature();

double HValue = 0;

int FldIndex = 0;

();

while ((pFeature != null))

{

//和直线相交的要素集合

(pFeature);

//

pFeature = ature();

}

//此时pFeatureL中的等值线并不是按顺序(空间)排列,需要排序

//求出各交点到直线起点距离

int pCount = ;

pIndex = new double[2, pCount];

for (int i = 0; i <= pCount - 1; i++)

{

try

{

pFeature = pFeatureList[i];

//求交点:

pIntersectionPoints = ect(,

ometry0Dimension) as IMultipoint;





pPointColl = pIntersectionPoints as IPointCollection;



}



//QI

//原来序号

pIndex[0, i] = i;

//距离

pIndex[1, i] = GetDistace(P0, _Point(0));

//下个要素

pFeature = ature();



}



catch (Exception e)

{

(ng());

}



//排序:将和直线相交的等直线按与起点的距离排序,冒泡法

for (int i = 0; i <= pCount - 1; i++)

{

for (int j = i + 1; j <= pCount - 1; j++)

{

if (pIndex[1, j] < pIndex[1, i])

{

double pTempindex = pIndex[0, i];

pIndex[0, i] = pIndex[0, j];

pIndex[0, j] = pTempindex;

//交换索引

double pTemp = pIndex[1, i];





pIndex[1, i] = pIndex[1, j];







}



}



}



pIndex[1, j] = pTemp;

//交换距离



//开始高程赋值

HValue = pHei

ght;

try

{

for (int i = 0; i <= pCount - 1; i++)

{

pFeature = pFeatureList[i];

//获取高程字段的索引

FldIndex = eld(pHeightName);

//高程赋值

_Value(FldIndex, HValue as object);



}



//要素更新

();

//Get the next feature and next H

HValue = HValue + pInterval;





}

catch (Exception e)

{







}



}



(ng());





///

/// 获取我们画的线和等高线之间的距离

///


///

///

///

private double GetDistace(IPoint pPoint1, IPoint pPoint2)

{

return (pPoint1.X - pPoint2.X) * (pPoint1.X - pPoint2.X) + (pPoint1.Y - pPoint2.Y)

* (pPoint1.Y - pPoint2.Y);

}





#endregion





public void OnTargetLayerChanged()

{

PerformSketchToolEnabledChecks();

}





void OnCurrentTaskChanged()

{

if ( == "CalculateContourTask")

{

PerformSketchToolEnabledChecks();

}

}



private void PerformSketchToolEnabledChecks()

{

if (pEditLayer == null)

return;





//Only enable the sketch tool if there is a polyline target layer.

if (ype !=

ometryPolyline)

{

ryType = ometryNull;

return;

}





ryType = ometryPolyline;





}







}



}





public partial class ParaSetting : Form

{

public ParaSetting(IFeatureClass pFtClass)

{

InitializeComponent();







}



reClass = pFtClass;





IFeatureClass pFeatureClass;





private void ParaSetting_Load(object sender, EventArgs e)

{

AddFdName(reClass);

}





private void AddFdName(IFeatureClass pFeatureClass)

{





();

for (int i = 0; i <= ount - 1; i++)



{



if (_Field(i).Type ==



eldTypeDouble || _Field(i).Type ==

eldTypeInteger)

{

(_Field(i).Name);

}

}





}





}





十. 地图 输出





很多的时候在地图制作完成以后,我们需要将它用不同的格式输出,如 PDF,bmp 等格式,这样的格式方便

我们用户在没有安装 ArcMap 的计算机平台上对地图进行浏览,查看。地图输出可以分为两大类,即栅格数

据和适量数据格式,前者的如 BMP,JPG,而后者的如 PDF,,SVG.





IExport 接口作为地图输出的主要接口,被不同的类实现,如下图所示:





这 10 个类都是组件类,可以直接用来实例化,同样,这 10 个类对应了 ArcGIS 所支持的地图输出格式,

同时这 10 个类也可以划分为两大类,即矢量格式和栅格格式。Window 平台的分辨率一般为 96dpi,

而这个

也是 ArcGIS 栅格 数据输出的默认分辨率,而对于像 PDF 这样的分辨率,默认为 300dpi。IExport 接口定

义了地图输出的通用方法和属性,如下图:





矢量 格式 地图 输出





矢量格式文件的输出主要是依靠 IExportVector 接口 ,该 接口 被以 下 5 个类 实现:





示例:输出EMF格式:

private void ExportEMF()

{

IActiveView pActiveView;

pActiveView = View;

IExport pExport;

pExport = new ExportEMFClass();

FileName = @"E:";

tion = 300;

tagRECT exportRECT;

exportRECT = Frame;

IEnvelope pPixelBoundsEnv;

pPixelBoundsEnv = new EnvelopeClass();

rds(, ,

, );

ounds = pPixelBoundsEnv;

int hDC;

hDC = xporting();

(hDC, (int)tion, ref exportRECT, null, null);

Exporting();

p();

}





示例:输出PDF格式:



private void ExportPDF()

{





IActiveView pActiveView;

pActiveView = View;

IEnvelope pEnv;

pEnv = ;

IExport pExport;

pExport = new ExportPDFClass();

FileName = @"E:";

tion = 30;

tagRECT exportRECT;

= 0;

= 0;

= (int);







}



= (int);

IEnvelope pPixelBoundsEnv;

pPixelBoundsEnv = new EnvelopeClass();

rds(, ,

, );

ounds = pPixelBoundsEnv;

int hDC ;

hDC = xporting();

(hDC, (int)tion, ref exportRECT, null, null);

Exporting();

p();





栅格 格式 地图 输出





栅格格式文件的输出主要是依靠 IExportImage 接口 ,该 接 口被 以下 5 个类 实现 :





示例:根据传入的分辨率输出JPG格式:

public void CreateJPEGHiResolutionFromActiveView(IActiveView pActiveView,String

pFileName, Int32 pScreenResolution,

Int32 pOutputResolution)



{



t pExport = new JPEGClass();

FileName = pFileName;

tion = pOutputResolution;

T pExportRECT;

= 0;

= 0;

= * (pOutputResolution / pScreenResolution);

= * (pOutputResolution /



pScreenResolution);





ope pEnvelope = new peClass();

rds(, , ,

);

ounds = pEnvelope;







32 hDC = xporting();





(hDC, (16)tion, ref pExportRECT, null, null);

Exporting();

p();





}







十一 .ArcGIS Engine



实 战





坐标 生成 点(AddXY 功能)





野外采集的数据或一些客户提交的数据经常不是 shp 也不是以数据库存储的 FeatureClass,而是含有 X,Y

字段的 Excel 或者 Txt,利用 ArcMap 的 Addxydata 功能我们可以实现 Excel 数据到空间数据的转换,具体

操作是利用 Addxy 功能,设置好相关的参数,这个时候 ArcMap 会生成一个内存图层,借助于 ArcMap 的导

出功能,导成 shp 或者 FeatureClass,在这里我们用 ArcGIS Engine 实现这个功能,要实现这个 功能,我

们需要了解下面的几个接口:





IXYEvent2FieldsProperties:该接口用来控制生成空间数据的 X,Y 字段信息





IXYEventSourceName:该接口用来生成空间数据





///



/// 模拟Addxy

///


///

///

///





public IFeatureClass CreateXYEventSource(ITable pTable, ISpatialReference

pSpatialReference)

{

IXYEvent2FieldsProperties pEvent2FieldsProperties = new

XYEvent2FieldsPropertiesClass();

Name = "X";

Name = "Y";





IDataset pSourceDataset = (IDataset)pTable;

IName sourceName = me;





IXYEventSourceName pEventSourceName = new XYEventSourceNameClass();

roperties = pEvent2FieldsProperties;

ableName = sourceName; lReference =

pSpatialReference;





IName pName = (IName)pEventSourceName;

IXYEventSource pEventSource = (IXYEventSource)();







}



IFeatureClass pFeatureClass = (IFeatureClass)pEventSource; return pFeatureClass;





排序





在处理数据时,有时候需要对数据进行升序和降序排序,我们一贯的做法是在 ArcMap 中,在排序的字段上

右键,然后点击排序操作,可是当我们关闭这个数据后,重新打开属性表,发现顺序又变回去了,更甚者,

我们将数据排序之后,然后利用 ArcMap 倒出去,但是结果不是我们想要的,对于这样的问题 ArcGIS Engine

提供了一个 ITableSort 的接口,该接口可以实现我们想要的功能。ITableSort 接口包含以下属性和方法:





示例:利用 ITableSort 对要素类排序:





///

/// true 表示升序,false 表示降序

///


///

///

///

void Sort(ITable _pTable, string _FieldName, bool _Bool)

{

ITableSort pTableSort = new TableSortClass();





= _pTable;





= _FieldName;







_Ascending(_FieldName, _Bool);





(null);





ICursor pSortCursor = ;





IRow pSortRow = w();





IDataset plSortDataset =_pTable as IDataset;





IFeatureWorkspace pFWs = ace as IFeatureWorkspace;





ITable plStable = Table("NewSort", _, null, null, null);





while (pSortRow != null)



{



IRow pRow = Row();

for (int i = 0; i < ount; i++)

{

if (_Field(i).Type != eldTypeOID)

{

_Value(i, _Value(i));

}

}

();

pSortRow = w();





}





}





网络 分析





什么是网络(地理网络)





网络是由一系列相互连通的点和线组成,用来描述地理要素(资源)的流动情况,用来模拟城市交通网络,

如连接各个城市的高速公路、连接各家各户的排给水网络等。



网络分析需要解决的问题





1. 路径 分 析:

最佳路径分析:寻找最佳路径功能主要包括确定两点间的最佳路径和多点间的最佳路径。





2. 服务 区 域的判定 :

目的为在一个网络路径上确定任何位置的服务区域和服务网络,并显示在视图中。在创建服务区的基础上,

可评估该地点的可达性。





3. 查找 最 邻近设施 :

目的为在网络路径上找出距某一位置最近的设施,并设计到达这些设施的最近路线。例如:对一场火

灾来说,最近设施是指最近的消防栓;对一起交通事故来说,它是指离事故现场最近的能够提供急救服务

的医院;而对于一个家庭的日常生活来说,最近设施又是指距住宅最近的零售店或超市。

4. 导航 : 导航图生成

5. 物流 配 送

6. 爆管 分 析, 上 下游 追 踪分析

ArcGIS 对于网络分析的支持是非常丰富的我们上面提到的,ArcGIS 全都支持,而在 ArcGIS 10 中又增加

了基于霍夫模型的选址分析。rcGIS 提供了两种网络分析,即基于 Geometric Network 的有向网络和基于

Network Dataset 的无向网络。有向网络分析 意味着网络中流动的物质必须按照在 Network 中定义好的规

则前进,运行路径都是事先定义好的,可以被修改,但是不能被物质本身修改,而是被网络的工程师来修

改网络的规则,使通过设置结点的开启状态来改变网络的流动方向;而无向网络分析则意味著用户可以自

由定义在网络中前进的方向,速度以及终点,例如一个卡车司机可以决定在哪条道路上开始行进,在什么

地方停止,采用什么方向。并且还可以给网络设置限定性规则,例如是单行线还是禁行。





它们的区别可以参考下面的表格:





Geometric network
Network dataset
Network features:Edges and junctions
Network e

lements: Edges, junctions, and turns
数据源:GDB feature classes only
数据源:GDB feature classes, shapefiles, or

StreetMap data
System manages connectivity
User controls when connectivity is built








Weights based on feature attribute fields

存在于:Feature dataset only

单模型

Network tracing functionality

utilities/natural resources modeling

不支持转弯

uses custom features: simple/complex edge

features and junctions



More robust attribute (weight) model

存在于:Feature dataset or workspace

单模型或者多模型

Network solver functionality

transportation modeling

支持转弯

uses simple features: points and lines





Geometric Network 分析





Geometry Network 分析属于有向网络或者定向网络,网络中的流向由源(Source),汇(Sink)以及通达

性决定、网络中流动的资源自身不能决定流向。如水流的路径是预先设定好的,它只能按照预先设定好的

路径进行流通。当然我们可以通过开关阀门来达到改变水流的流向目的,但这属于流通规则的内容。在效

用网络中,水、电、气通过管道和线路输送给消费者,水、电、气被动地由高压向低压输送,不能主观选

择方向。Geometric Network 主要用于模拟现实世界中的水网,电网,煤气网,电话服务等资源网络。

几何网络(有向)网络解决的问题有:

A.寻找 连通的/不连通的管线

B.上/下游追踪

C.寻找环路

D.寻找通路

E.爆管分析

Geometric Network 由一组相互连接的 Edge 和 Junctions 组成,并且包含 Connectivity Rules。Geometric

Network 必须构建于 Geodatabase 的 Feature Dataset 中,其中的 Feature Class 是作为 Junctions 和

Edge 的数据源。Geometric Network 中包含两种主要的要素:Edges 和 Junctions 在几何网络中,Edge

和 Junctions 是 Topologically Connected to each other:Edge 和 Edge 在 Junctions 处连接,某个

Edge 中流动的要素是通过 Junctions 流动到其它的 Edge。

Geometric 中有两种类型的 Edges:



Simple Edges-连着两个 Junctions,Edge 的每一头连接一个 Junction;

Complex Edges-通常在端点处至少连接两个 Junctions,而且在 Edge 的中间部分,也可以连接很多

Junctions,例如:主管道上可以连接多个支管道。

Geometric 中有两种类型的 Junctions:

User defined Junctions:在构建 Geometric Network 时,根据用户定义的 Point Source 生成的

Junctions;

Orphan Junctions:当第一个 Edge Feature Class 添加到 Geometric Network 时,创建了 Simple

Junction Feature Class ,被称为 Orphan Junction Feature Class,主要是用于维护网络的 完 整性 。

当用户添加其它的 Junctions Feature 时,该点处的 Orphan Junctions 将被删除;此外当用户删除

Geometric Network 时,则 Orphan Junctions 也被删除。

当创建一个 Geometric Network 时,也

创建了一个相应的 Logic Network,用于表现和模型化要素之间

的连通关系,实现 Tracing 和 Flow 计算。Logic Network 是由一系列的 Table 组成,并且由 ArcGIS 维

护。当 Geometric Network 被更新或者删除时,Logic Network 会自动更新。





几何网络中的的相关元素





1, Sources 和 Sinks

网络要素的流动方向是从 Sources 和 Sinks 来计算的,从 Sources 流出,汇于 Sinks。可以在创

建 Geometric Network 时,将 Junctions 设置为 Sources 或者 Sinks 或者都不是,一旦设定为

Source 或者 Sink,则在属性表中添加字段 AncillaryRole 用于记录其类型。 ,





2, Network Weight

网络可以被设置权重,用于表示网络要素在其中流动的环境,使利用参与网络的 Feature 的属性

来设置网络的 Weight.





3, Enable and Disable Feature

Geometric Network 中的 Edge和 Junctions 可以在 Logic Network 中设置为 Enabled 或者 Disabled。

网络的 Enabled 或者 Disabled 状态是由要素属性字段 Enabled 设置的,可以选择的属性 为 True,

False,当通过简单要素类创建 Geometric Network 时,该字段自动添加为输入 要素中,并且缺

省状态下属性值为 True。



4, Connectivity

在现实生活中,Geometric Network 中并不是所有的要素都是可以相互连接的,系统所创建的网

络连通性可能不适合,则用户可以根据自己的需要修改 Connectivity,方法是:在 ArcCatalog

中点击创建的 Geometric Network,在 Properties 中选择 Connectivity 面板,实现 Connectivity

的设置。可以创建的 Connectivity Rule 包括两种:Edge-Junction Connectivity,Edge-Edge

Connectivity。





如何创建一个几何网络





在做几何网络分析的时候,首先要有这个几何网络,那么如何创建一个创建 Geometric Network?前面说

过要熟练的掌握 ArcGIS Engine,如果对于 ArcMap 掌握的很熟悉的话,那对我们学习 ArcGIS Engine 是很

有帮助的,ArcMap 对很多操作提供了界面,而 ArcGIS Engine 提供给我们的是 API,界面上的设置也是响应

的 API 的参数,希望从这个例子能加深这种体会。我们看以下 ArcMap 是如何生成一个几何网络的?





我们按照下面的步骤创建一个几何网络:





1,在 Catalog 中打开创建几个网络的工具





2,网络名称





3,参与网络的要素类





4,是否采用 enable 字段





5,指定 source 和 sink





6,创建权重





7,建立几何网络





打开创建几何网络的向导:





网络名称





参与网络的要素类





设置 enable 字段





设置 sink 和 source





设置权重





建立网络:





结果:





示例:用代码来创建几何网络:





/ //

/ // 打开 个人 数据库

/ //

/ //





/ //

pub lic I Work spac e Ge tWor kspace(String _pG DBNa me)

{

I Work spac eFactory p WsFac = new Acc essW orks pac eFa cto ryC las s( );



I Work spac e pWs = pWs Fac. OpenFromFile( _pG DBName,0);







}



r etur n pWs;





publ ic voi d Crea teGe ometricNetwork(IWorkspace _p Work spac e, IFea ture Data set Nam e

_pFe atur eDatasetName,String _p Geom etricName)

{





I Netw orkL oader2 pNe twor kLoader = new Net work Load erC las s( );





/ / 网 络 的名 称

p Netw orkL kName = _pG eome tricName;





/ / 网 络 的类 型

p Netw orkL kType = es riNe tworkTy pe. esr iNT Uti lit yNe two rk;





/ / S et the con tain ing feat ure da tase t.

p Netw orkL eDatasetName = ( IDa tase tNam e)_ pFe atu reD ata set Nam e;





/ / 检 查要 建立 几何网络的数据,每一个要素只能参 与一个 网络

i f ( pNet work FeatureClass("Pri mar yLi ne" ) ==

esri Netw iNL FCC Val id)

{

pNet work tureClass("Primar yLi ne" ,

esr iFea ComplexEdge, null , fa lse) ;

}





i f ( pNet work FeatureClass("Fee der ") = =

esri Netw iNL FCC Val id)

{

pNet work tureClass("Feeder ",

esri Feat SimpleJunction,

nul l, fa lse) ;

}







的设 置



// 我的 数据 中没有enable字段,所以,用了false ,如果 用true 的话,就要进行相关





INe twor kLoaderProps pNe twor kLoaderProps =

(INe twor kLoaderProps)pNetworkLoader;





p Netw orkL veEnabledValues = fals e;





/ / S et the anc illar y rol e fiel d for th e Fee der cl ass.

S trin g defa ultA ncillaryRoleFieldName =

pNet work tAncillaryRoleField;

e sriN etwo rkLoaderFieldCheck anc illa ryRoleF iel dCh eck =

pNet work ncillaryRoleField("F eed er" ,

defa ultA ncillaryRoleFieldName);

s witc h (anc illa ryRoleFieldCheck)

{

case esri Netw LFC Val id:

case esri Netw LFC Not Fou nd:

pNe twor illaryRole("F eed er" ,

esri Netw orkClassAncillaryRole. esr iNC ARS our ceS ink ,

defa ultA ncillaryRoleFieldName);

bre ak;

defa ult :

Con sole .WriteLine(

"The fi eld { 0} co uld n ot be used as an anc ill ary r ole fi eld ." ,

defa ultA ncillaryRoleFieldName);

bre ak;

}





p Netw orkL lerance = 0.02 ;





/ / 给 几何 网络 添加权重

p Netw orkL ght("Weight", es riWe ight Typ e.e sri WTD oub le, 0);





/ / 将 权 重和 PrimaryLine数据中的SHAPE_Length 字段关 联

p Netw orkL ghtAssociation("Weigh t", "Pri mary Lin e" ,

"SHA PE_L ength");





/ / 构 建 网络

p Netw orkL twork();





}





IWor kspa ce pW s = G etWo rksp ace( @"E:arcgisEngineGeom etr ic. mdb ") ;





I Feat

ureW orkspace p FtWs = pWs as IFea ture Work spa ce ;





I Feat ureD ataset pFt Data set = pF tWs. OpenFea tur eDa tas et( "w ork" );





I Data set pDat aset = pFt Data set as IDa tase t;





I Feat ureD atasetName pF tDat asetName = pDa tase llN ame as

IFea ture DatasetName;





C reat eGeo metricNetwork(pWs, pFt Datas etName, "T estG eome tri c" );

效果 如下 :





有了 几何 网络,接下来就是在这个几何网络上做分析,几何网络 能执行 的操作 都在

ITra ceFl owSolverGEN 接口中,该接口的方法如下图:





示例:用代码实现几何网络的最短路径分析:





publ ic voi d Solv ePat h(IMap _pM ap, IG eome tricNetwork _p Geom etri cNe two rk, str ing

_pWeightName, IPointCollection _pPoints, double _ pDi st, r ef IP oly lin e _p Polyline, ref

doub le _pP athC ost)

{

try

{ / / 这 4个 参数 其实就是一个定位Element的指 标

int intE dgeU serClassID;





int intE dgeU serID;





int intE dgeU serSubID;





int intE dgeI D;





IPo int pFou ndEd gePoint;





dou ble dblE dgeP ercent;





ITraceFlowSolverGEN pT rac eFl owS olve r = ne w TraceFlowSolverClass() as

ITra ceFl owSolverGEN;





INe tSol ver pNe tSol ver = pT race FlowSol ver as IN etSo lver ;





//操 作 是针对逻辑网络的,INetwork是逻辑 网络





INe twor k pN etwo rk = _pG eome tricNetwor k.N etw ork ;





pNe tSol Network = pNe twor k;





INe tEle ments p NetE lements = pNet work a s I NetE leme nts ;





int pCoun t = _ pPoi nts. PointCo unt ;

//定 义 一个边线旗数组

IEd geFl ag[] pEd geFl agList = new Edg eFla gCla ss [pCo unt ];





IPo intT oEID pP oint ToEID = new Po intT oEID Cla ss ();





pPo intT Map = _pM ap;





pPo intT ricNetwork = _ pGeo metr icNetwork;





pPo intT lerance = _ pDis t;





for (int i = 0; i < pCou nt; i ++)

{

INet Flag pNet Flag = ne w Edge Flag Clas s() as IN etFl ag;





IPoi nt pEd gePo int = _p Poin _ Poi nt( i);

//查 找输 入点的最近的边线

pPoi ntTo restEdge(pEdgePoint, out in tEdg eID, out

pFou ndEd gePoint, ou t dbl Edge Percent);





Ds(intEdgeID, esriElementType. esr iETEdge, out

intE dgeU serClassID, o ut int Edge UserID, out in tEdg eUse rSu bID );





pNet Flag .UserClassID = int Edge UserClassID;





pNet Flag .UserID = i ntEd geUs erID;





pNet Flag .UserSubID = i ntEd geUs erSubID;







}



IEdg eFla g pTe mp = ( IEd geFl ag)(pNe tFl ag as IEdg eFla g);

pEdg eFla gList[i] = pTem p;



pTr aceF eOrigins(ref pE dgeF lagL ist );





INe tSch ema pNe tSch ema = pN etwo rk as IN etSc hema ;





INe tWei ght pNe tWei ght = pN etSc t_W eig htB yNa me( _pW eig htN ame );





INe tSol verWeightsGEN pN etSo lverWeight s = pTr aceF lowS olv er as

INet Solv erWeightsGEN;





pNe tSol

oEdgeWeight = pN etWe ight; //开 始边线 的权重





pNe tSol EdgeWeight = pN etWe ight; //终 止边线 的权重



obj ect [] pRe s = new obj ect[ pCount - 1] ;





//通 过 FindPath得到边线和交汇点的集合

IEn umNe tEID p Enum NetEID_Junctions;





IEn umNe tEID pE numN etEID_Edges;







pRes );



pTr aceF th(esriFlowMet hod .es riF MCo nne cte d,

e sriS hort ObjFnMinSum,

o ut pEn umNe tEID_Junctions, o ut pEn umNe tEID _Ed ges , pC ount - 1 , r ef

//计 算 元素成本

_pP athC ost = 0 ;

for (int i = 0; i < pRes .Len gth; i++)

{

doub le m_Va = (d oubl e)pRes[i];







}



_pPa thCo st = _pPa thCo st + m_V a;





IGe omet ryCollection pNe wGeo metryColl = _p Poly line as

IGeo metr yCollection;//QI





ISp atia lReference pS pati alReference = _pMa atialReference;





IEI DHel per pEI DHel per = ne w EIDH elpe rCla ss( );





pEI DHel ricNetwork = _pG eome tricNetwork;





pEI DHel SpatialReference = pSp atia lReference;





pEI DHel Geometries = tr ue;





IEn umEI DInfo p Enum EIDInfo =

pEID Help EnumEIDInfo(pEnumNetEID_Edges);





int Count = pEn umEI t;





pEn umEI ();





for (int i = 0; i < Coun t; i++ )

{

IEID Info pEID Info = pE numE IDInfo. Nex t() ;



IGeo metr y pGe omet ry = pEI DInf ome try ;





pNew Geom metryCollection(pGeometry as

IGeo metr yCollection);

}

}

catc h (Exc epti on e x)

{

Con sole .WriteLine(e);

}

}





红色的表示计算结果





9、1 Network dataset 分析





Nework dataset 分析属于无向网络分析,无向网络分析的的网络是存储在 Network Dataset 中。Network

Dataset 由 Feature 要素创建而来,能够用来表现复杂场景,包括 Multimodal 交通网络,同样也可以包含

多个网络属性以模拟网络限制条件和层次结构。流向不确定、流动的资源可以决定流向。如交通系统中流

通介质可以自行决定方向、速度和目的地。

无向解决的问题有:

A.最短路径

B.物流输送



C.临近设施分析

D.服务区分析

E.选址分析

Network Dataset 包含以下三种类型:

(1)Network Dtaset:创建网络的数据源存储于 Personal 或者 Enterprise Geodatabase 中,因为其中

可以存储很多数据源,因此可以构建 Multimodal Network

(2)Shapefile-based Network Dataset:是基于 Polyline Shapefile 文件创建的,也可以添加 Shapefile

Turn Feature Class,这种 Network Dataset 不能够支持多种 Edge 类型,也不能用于创建 Multimodal

Networks

(3)ArcGIS Network Analyst 也可以读取 SDC Network Dataset,可以实现网络分析功能,而不能创建

Network Dataset

Network Elements 包括三类:Edges,Junctions,Turns。

Connectivity Group

要想定义 ArcGIS Ne

twork Analyst 的 Connectivity,首先要定义 Connectivity Group。每一个 Edge Source

只能够被赋予一个 Connectivity Group,而 Junction Source 可以被赋予多种 Connectivity Group。只有

将 Junction 设为两种或者多种 Connectivity Group,才可以去连接不同 Connectivity Group 的 Edge。

Connectivity Group 用于创建 Multimodal Transportation Network。

以下为 Network Dataset 所支持的三种 Connectivity Model:

(1)Connecting Edges within a Connectivity Group

可以设置“Endpoint Connectivity”,也可以设置“Any Vertex Connectivity”。第一种方式中,边和

边只能在终点处相交,第二种方式则可以在边的任意位置相交

(2)Connecting Edges through Junctions across Connectivity Group

能够将不同 Connectivity Group 中的 Edge 通过被不同 Connectivity Group 共享的 Junctions 连接。

(3)Elevation Fields

主要用于 Network Dataset 中检查 Line Endpoints 的 Connectivity。每一个 Edge Feature 具备两个字段

用来描述每一个端点的高程。

Network Attribute

Network Attribute 主要用于设定网络的流通属性,包括:

Name:

Usage Type:



Unit:Centimeter,Meter 等等

Data Types:Boolean,Integer,Float,Double

Use by Default:

Cost:例如走过某段路需要花费的时间

Descriptors:对某条道路的描述信息,例如道路速度的限制,有多少个红绿灯等。

Restrictions:例如某条线是禁行,或者是单向的

Hierarchy:例如道路的分级





Types of Evaluators used by a network

Network 的 Attribute 都需要设定 Value,通常是利用 Evaluators 从 Network Source 中获取属性值。具备

四种 Evaluators:

Field Evaluator:利用属性字段的值;

Field Expression Evaluator:利用属性字段构建计算表达式;

Constant Evaluators:赋予常数;

VBscript Evaluators:通过执行 VBScript 代码,主要用于赋予复杂的属性值

每个 Junction Source 和 Turn Source 需要一个 Evaluator,而每个 Edge Source 需要两个-Edge 的每个方

向都需要一个 Evaluator

Turns in the Network Dataset

Turn 的类型有多种,可以是 Multi Edge Turn,也可以是 U-Turn。在 ArcGIS 中,Turn 是通过 Turn Feature

Class 转变而来的,这些 Turn Feature Class 都是 Polyline Feature Class。Turn Feature Class 必须

是与其他 Network 要素位于同一个 Feature Dataset 中,具备相同的空间参考,不参与 Connectivity Groups,

也不具备 Elevation 信息。Turn 至少具备两条 Edge,至多 20 条 Edge。

Setting Directions

支持 Directions 的 Network Dataset 必须至少满足以下要求:

具备 Length 属性,包括 Length 单位;

至少有一个 Edge Source;

在 Edge Source 上至少有一个 Text 字段。



9、2如何创建一个无向网络





同几何网络一样,要做无向网络的分析,首先要有无向网络

,那么无向网络是怎么建立的呢?无向网络的

建立相比有向网络稍微复杂点,我们可以按照下面的步骤:

1,打开网络数据集的向导,定义几何网络的名称





2,参与网络数据集的要素类:





3,是否使用转向数据集





4,连通性设置





5,是否使用搞成字段来模拟连通性







6,权重设置



,







7,是否建立行驶方向



,







8,结果如下:



,





示例:代码创建 Networkdataset:

///

/ // 个人 数据 库的路径,要素数据集的路径,建立网络的 名称, 参与网 络的要 素类

/ //


/ // < /pa ram >

/ //

/ //



/ // < /pa ram >





v oid Cre ateN etworkDataset(string _ pWsN ame, str ing _p Data setN ame ,s tri ng

_pNe tNam e, st ring _pFt Name )

{

IDEN etwo rkDataset pDE Netw orkDataset = new DEN etwo rkDa tas etC las s( );





pDEN etwo ble = tru e;



IWor kspa ce pW s = G etWo rksp ace(_pWsName) ;





IFea ture Workspace pFt Ws = p Ws as IFe atur eWor ksp ace ;





IFea ture Dataset pF tDat aset = pFtW enFe atu reD ata set (_p Dat ase tNa me) ;





// 定义 空间 参考,负责会出错

IDE GeoD ataset pDE GeoD ataset = (I DEGe oDat ase t)p DEN etw ork Dat ase t;





IGe oDat aset pG eoDa taset = pFt Data set a s I GeoD atas et ;

p DEGe oDat = pGe oDat ;

p DEGe oDat lReference = p GeoD atas lReference;





// 网络 数据 集的名称

IDat aEle ment pD ataE lement = (I Data Element )pD ENe two rkD ata set ;





pDat aEle = _ pNet Name ;





// 参加 建立 网络数据集的要素类

INet work Source pEd geNe tworkSource = new Ed geFe atur eSo urc eCl ass () ;

pEdg eNet = _ pFtN ame;





pEdg eNet tType = esr iNet work Ele men tTy pe .es riN ETEd ge;





// 要素 类的 连通性

IEdg eFea tureSource pE dgeF eatureSource =

(IEd geFe atureSource)pEdgeNetworkSource;

pEdg eFea btypes = fa lse;





pEdg eFea onnectivityGroup = 1;





pEdg eFea onnectivityPolicy

=esr iNet CPEndVertex;





//不 用转 弯数据



pDEN etwo tsTurns = fa lse;





IArr ay pSo urce Array = ne w Arra yCla ss();

pSou rceA (pEdgeNetworkSource);





pDEN etwo s = pSo urce Array;





//网 络数 据集的属性设置





IArr ay pAt trib uteArray = ne w Arra yCla ss() ;





// Init iali ze va riabl es r euse d when c reati ng at trib utes :

IEva luat edNetworkAttribute pEv alNe tAttr;

INet work Attribute2 pN etAt tr2;

INet work FieldEvaluator p NetF ieldEval;

INet work ConstantEvaluator p NetC onstEval;





pEva lNet Att

r = new Ev alua tedNetworkAttrib ute Cla ss ();

pNet Attr 2 = (IN etwo rkAttribute2)pEvalNetA ttr ;

pNet Attr ="M eter s";

pNet Attr ype = es riNe tworkAttribut eUs age Typ e. esri NAU TCo st;

pNet Attr pe = esr iNet workAttribute Dat aTy pe .esr iNA DTD oub le;

pNet Attr = esr iNet workAttributeUni ts. esr iNA UMe ter s;

pNet Attr efault = fa lse;





pNet Fiel dEval = ne w Netw orkF ieldEvaluator Cla ss( );

pNet Fiel ression("[METERS]", "" );

//方 向设 置

pEva lNet _Evaluator(pEdgeNetworkSource,

esr iNet DAlong Digitized,

(INe twor kEvaluator)pNetFieldEval);

pEva lNet _Evaluator(pEdgeNetworkSource,

esr iNet DAgain stDigitized,

(INe twor kEvaluator)

pNe tFie ldEval);





pNet Cons tEval = ne w Netw orkC onstantEvalua tor Cla ss ();

pNet Cons ntValue = 0;

pEva lNet _DefaultEvaluator(esriNet wor kEl eme ntType .e sri NETE dge ,



(IN etwo rkEvaluator)pNetConstEval);





pEva lNet _DefaultEvaluator(esriNetworkElementType .es riN ETJ unc tio n,

(IN etwo rkEvaluator)pNetConstEval);

pEva lNet _DefaultEvaluator(esriNet wor kEl eme ntType .e sri NETT urn ,

(IN etwo rkEvaluator)pNetConstEval);





// 一个 网络 数据集可以有多个属性,我只添加 了一个

pAtt ribu (pEvalNetAttr);





pDEN etwo utes = pAt trib uteArray;





// 创建 网络 数据集,注意在创建几何网络的时 候会锁 定相应 的要素类,因此不要

用Ar cMap 或者catalog等打开参相应的数据





INetworkDataset p Net workDataset = Cr eat e(p FtD ata set, pDE Netw ork Dat ase t);





//建 立网 络





INet work Build p Netw orkBuild = (IN etwo rkBu ild )pN etw ork Dat ase t;





pNet work etwork();





}





/ //

/ // 创建 无向 网络

/ //

/ //

/ // < /pa ram >

/ //





p ubli c INet work Dataset Cr eate (IFeatureDataset _pFe atur eDa tas et,

IDEN etwo rkDataset2 _ pDEN etDataset)

{

IFea ture DatasetExtensionContainer pF eatu reDa tas etE xte nsi onC ont ain er =

(IFe atur eDatasetExtensionContainer) _pF eatur eDataset;





IFea ture DatasetExtension pF eatu reDatasetE xte nsi on =

pFea ture tension

(es riDa NetworkDataset);





IDat aset Container2 pD atas etContainer2 =

(IDa tase tContainer2)pFeatureDatasetExtension;





IDED atas et p DENe tDataset = (ID EDat aset)_p DEN etD ata set ;





INet work Dataset pN etwo rkDataset =

(INe twor kDataset)Datase t

(pD ENet Dataset);







}



retu rn pNe two rkDataset;





///

/// _ pFt Cla ss参数 为Stop s的 要素类,_pPointC是用

鼠标点 的点生 成的点 的集合,最后

一个 参数 是捕捉距离

/ //


/ // < /pa ram >

/ //



/ // < /pa ram >

/ //

void NAS olv e(INAContext _p NaC ont ext, IF eat ure Cla ss _pFt Cla ss, IPointCollection

_pPo intC , dou ble _ pDis t)

{

INAL ocat or p NAlo cator = _pNa Cont r;

for (in t i = 0; i < _pPo intC .PointCount; i ++)

{

IFe atur e pFt = _pF tCla Feature();





IRo wSub types p RowS ubtypes = pFt as IRo wSub type s;





pRo wSub faultValues();





pFt .Sha pe = _pP oint _Point(i) a s I Geom etry ;





IPo int pPoin t = null ;





I NALo cati on p Nalo cation = nu ll;





pNA loca ocationByPoint(_pPointC . get_ Point(i), re f

pNal ocat ion,ref pPo int, ref _pD ist) ;





INA Loca tionObject pN Aobj ect = pF t as I NALo cati onO bje ct ;





pNA obje tion = pNal ocat ion;





int pNam eFie ldIndex = _ pFtC lass .FindField(" Nam e" );





pFt .set _Value(pNameFieldIndex, pP oint .ng() + ", " +

pPoi nt.Y .ToString());





int pSta tusF ieldIndex = _pF tCla eld("S tat us" );





pFt .set _Value(pStatusFieldIndex,

esri NAOb ObjectStatusOK);





int pSeq uenc eFieldIndex = _pFt Clas eld( "Se que nce ") ;





pFt .set _Value(_eld("Se que nce ") ,

((IT able )_pFtClass).RowCount(null));





pFt .Sto re();







}



}





///

/ // 获取 网络 数据集

/ //


/ // < /pa ram >

/ //

/ //

/ //

I Netw orkD ataset Get NetD ataset(IFeatureWorkspace _ pFea ture Ws, str ing

_pDa tase tName,string _p NetD atasetName)

{





ESRI .Arc etContainer3 pD atas etCo nta ine r = nu ll;





ESRI .Arc reDataset pF eatu reDa tas et =

_pFe atur atureDataset(_pDatasetName);

ESRI .Arc reDatasetExtensionContainer



pFea ture DatasetExtensionContainer = pFea ture Dataset as

ESRI .Arc reDatasetExtensionContainer; // D ynam ic Ca st

ESRI .Arc reDatasetExtension

pFea ture DatasetExtension =

pFea ture tension(abase.e sri Dat aset

Type .esr iDTNetworkDat ase t);

pDat aset Container = p Feat ureD atasetExtension as

ESRI .Arc etContainer3; / / Dyna mic Ca st





ESRI .Arc et pNe tWor kDat ase t =

pDat aset _DatasetByName( riD ata set Typ e. esr iDTN

etwo rkDa taset, _pNe tDat asetName);







}



retu rn pNe tWor kDataset a s ESRI .Arc dat aba se. IN

e two rkD ata set ; / /





/ //

/ // 加载 Netw orkDataset到Map中

/ //

/ // < /pa ram >

/ //

v oid loa dNet (IMap _ pMap ,INetworkDataset _pN etwo rkDa tas et)

{

I Netw orkL ayer pN etLa yer = ne w Netw orkL ayer Cla ss( );





p NetL ayer .NetworkDataset = _ pNet work Dataset;







}



_ pMap .Add Layer(pNetLayer as ILa yer) ;



/ //

/ // 获取 网络 分析上下文,这个接口是网络分析中很重 要的一 个

/ //

/ //

/ //

/ //

p ubli c INAC onte xt G etSo lverContext(INASolver _ pNaS olve r, INet work Dat ase t

_pNe twor kDataset)

{

//Ge t the Dat a Eleme nt





IDatasetComponent p Dat aCom pon ent = _p Net wor kDa tas et as IDatasetComponent;





IDED atas et p DeDa taset = pDat aCom ement;



INAC onte xtEdit pCo ntex tEdit = _pN aSol ver. Cre ate Con tex t(p DeD ata set as

IDEN etwo rkDataset, _pN aSol ) as INA Cont extEdit ;







sche ma.

}



//Prepare the con tex t for a nal ysi s based upon the c urr ent n etw ork d ata set

pCon text (_pNetworkDataset, new GP Mess ages Cla ss ()) ;

retu rn pCo ntex tEdit a s INAC onte xt;



/ //

/ // 获取 NALa yer

/ //

/ //



/ // < /param>

/ //





I NALa yer G etNa Laye r(INASolver _ pNaS over,INACo nte xt _pNa Cont ext)

{

retu rn _pN aSov Layer(_pNaContext);

}





分析





IFea ture Class pf tcla ss =p NaCo _ItemByName("S top s" ) as

IFea ture Class;





NASo lve( pNaContext, pf tcla ss, pPoi ntC, 5000 );





IGPM essa ges gpM essa ges = ne w GPMe ssag esCl ass ();





bool p Bool = pNA Solv eClass. Sol ve( pNa Con text, gp Messa ges , nul l);





9、3线性 参考





什么是线性参考





线性参考是使用沿测量的线状要素的相对位置存储地理位置的方法。距离测量值用于定位沿线的事件:







要素上的测量值用于使用各种约定来定位点事件和线事件。以下是一些常见示例: 如下图所示,可以沿线定位点:







*?

*?



沿线测量值为 12 的位置

沿线的测量标记 10 以东 4 个单位





可通过几种方式参照线要素。在上例中







*?

*?



线从测量值 18 处开始,到测量值 26 处结束。

线从测量值 28 处开始并延伸 12 个单位。





9、3、1为什么使用线性参考





使用线性参照的原因很多,以下是两个主要原因:







*?

*?



许多位置以沿线性要素事件的方式记录,例如,使用“沿国道 287 参照英里标记 35 以东 27

米”这样的约定记录交

通事故的位置。许多传感器使用沿线(沿管线、道路、河流等)的距离

测量值或时间测量值来记录沿线状要素的条件。

线性参照还用于将多个属性集与线状要素的部分关联,不需要在每次更改属性值时分割(分段)

基本线。例如,大多数道路中心线要素类会在三个或更多路段相交以及路段的名称发生改变时

分段。

用户通常想要记录有关道路的许多其他属性。如果不使用线性参照,可能需要在属性值更改

的每个位置将道路分割成很多小段。这时,可供选择的方法是将这些情况处理为沿道路的线

性参照事件,如下图所示:





示例:在一个道路网络中利用线性参考找到 I D 为 200 0001 3, 并且长 度是 0-25 的区间 :



I Poly line Find Rout ByMeasure(IFeatureClass _ pRou teFC , st ring _pPK Name ,ob jec t _pID,

doub le _pF rom, doub le _p To)

{

IDat aset pDa tase t = ( IDa tase t)_pRouteFC;

INam e pNam e = p Data set. FullNam e;

IRouteLocatorName pRouteLocatorName = new RouteMeasureLocatorNameClas s();

pRou teLo eatureClassName = pNam e;

pRou teLo DFieldName = _p PKNa me;

pRou teLo easureUnit = es riUn its. esr iFe et;

pNam e = ( INa me)pR outeLocatorName;

IRou teLo cator2 pRo uteL ocator = (I Rout eLoc ato r2) pNa me. Ope n() ;





IRou teLo cation pRo uteL oc = new Ro uteM easu reL ine Loc ati onC las s( );





pRou teLo eUnit = esr iUni e t;

pRou teLo D = _ pID;

IRou teMe asureLineLocation r MLin eLoc =

(IRo uteM easureLineLocation)pRouteLoc;

rMLi neLo asure = _pFr om;

rMLi neLo ure = _pT o;





IGeo metr y pGe o = null ;





esri Loca tingError loc Erro r;

pRou teLo (pRouteLoc , out pG eo, ou t locE rror );







}



retu rn pGe o as IPo lyli ne;



IMap p Map = axMa pCont rol 1.M ap;





IFeatureWorkspace pFtWs = GetFGD BWo rks pac e(@"E:")

as IFea ture Workspace ;





IFea ture Layer p Feat ureLayer = new Fe atur eLay erC las s( );





pFea ture eClass = p FtWs .Ope nFe atu reC las s( "rou tes ") ;





pFea ture = "路 径";





axMa pCon er(pFeatureLayer a s I Laye r);





axMa pCon h();



IPol ylin e pP olyl ine = Fin dRou tByMeasure(eClass,

"ROU TE1" ,20000013, 0, 25) ;





IRgb Colo r pCo lor = ne w RgbC olor Class();





pCol or.R ed = 255 ;





IEle ment pEl emen t = new Lin eEle mentClass( );





ILin eSym bol pLi nesy mbol = new Sim pleL ineS ymb olC las s( );





pLin esym = p Colo r as ICo lor;





pLin esym = 1 00;





pEle ment .Geometry = p Poly line as IGe omet ry;





IGra phic sContainer pG rahi csC = pM ap as IGr aphi csCo nta ine r;





pGra hics ment(pElement, 0) ;





axMa pCon

rtialRefresh(esriViewDrawP hase.e sri Vie wGr aph ics , n ull,

null );





9、4什么是动态分段





动态分段是使用线性参照测量系统计算事件表中存储和管理事件的地图位置以及在地图上显示它们

的过程。术语“动态分段”源于每次更改属性值时无需分割(也就是“分段”)线要素的理念,即可以“动

态”定位线段。利用动态分段,可将多组属性与现有线状要素的任意部分相关联,无论其开始或结束

位置为何。可以显示、查询、编辑和分析这些属性,而不会影响基础线状要素的几何。

示例:用代码实现动态分段:

I Feat ureC lass Ev entT able2FeatureClass(IFeatur eCl ass _pR oute FC, stri ng

_pPK Name , ITa ble _ pEve ntTa ble, st ring _pFK Name , str ing _p From , st ring _ pTo)

{

IDat aset pDa tase t = ( IDa tase t)_pRouteFC;





INam e pNam e = p Data set. FullNam e;





IRouteLocatorName pRouteLocatorName = new RouteMeasureLocatorNameClas s();





pRou teLo eatureClassName = pNam e;





pRou teLo DFieldName = _pP KNam e;





pRou teLo easureUnit = es riUn its. esr iFe et;

pNam e = ( INa me)pR outeLocatorName;





IRou teEv entProperties2 p Rout eProp = new

Rout eMea sureLinePropertiesClass();





pRou tePr orField = tru e;

pRou tePr easureUnit = esr iUni ts.e sri Fee t;

pRou tePr outeIDFieldName = _ pFKN ame;





IRou teMe asureLineProperties rM Line Prop =

(IRo uteM easureLineProperties)pRouteProp;





rMLi nePr asureFieldName = _pF rom;

rMLi nePr ureFieldName = _ pTo;





IDat aset pDs = (ID atas et)_pEventTable;

INam e pNTa bleN ame = p Ds.F ullN ame;

IRou teEv entSourceName pR oute EventSourceNa me = ne w

Rout eEve ntSourceNameClass();

pRou teEv ableName = pNTa bleN ame;

pRou teEv roperties =

(IRo uteE ventProperties)pRouteProp;

pRou teEv ocatorName = pR oute LocatorName;





pNam e = ( INa me)pR outeEventSourceName;





IFea ture Class p Feat ureClass = (IF eatu reCl ass )pN ame .Op en( );





retu rn pFe atur eClass;





}





十二 .安装 部署





1. NetFramwork35sp1, ArcGIS Engine Runtime 单独安装





ArcGIS Engine 应用程序打包的打包,我们可以采取这样的方案(Runtime 和应用程序分开安装,

Runtime 和应用程序一起安装),这里我先介绍分开安装。为了能正确的使用我们开发的应用程序,确保

自己的电脑上装了以下组件:

1)NetFramework35sp1;

2)ArcGIS Engine 10 Runtime(ArcGIS Engine Runtime 已经正确授权)。





采用 Visual Stuido 2008 自带的打包程序打包

步骤如下:

1,在解决资源方案中添加新的项目(我的 Engine 应用程序也存在这个解决发方案中),如下图:





2,找到安装和部署的节点

,选择安装项目这个模板,并命名为 Setup,如下图:





3,选择 Setup 的文件系统编辑按钮中,然后在应用程序文件夹中右键 选择添加项目-输出,如下图:





4,选择主输出,项目为我们的 Engine 应用程序的名称,如下图:





5,我们会看到中间的一个窗口中多了很多 Esri 的 dll,还有我们的 exe,在我们应用程序上右键,创

建快捷方式,如下图:





6,在 Setup 的引用中,排除 Esri 的 dll,为什么?因为 Runtime 中有这些 dll,所以我们不需要打包

这些,如下图:





7,将我们刚才创建的快捷方式,重命名,拖到用户桌面的那个目录中或者程序菜单中,当然可以创建

两个快捷方式,分别拖过去.

8,执行 Setup,我们就可以看到打包后的 msi 和 exe,如下图:





安装就会看到如下界面,如下图:





12、2. 将 NetFramwork35sp1 ,ArcGIS Engine Runtime 一起打包





1,新建立一个工程,填写这个工程的位置以及工程的名字,如下图所示:





2, 新建工程完成后,Installshield 会进入 Project Assistant 界面,这是 Installshield 的安装助

手,它将一些最常用的操作按照“上一步”、“下一步”的方式组织成为一个向导,我们可以利用此向导

快速的完成安装程序制作的全过程。不过此方式过于简单,如果我们想进行复杂一些的操作就做不到了。

所以需要制作专业的安装程序的朋友们还是使用 Installation Designer 方式来制作安装程序,但是偶是

一个菜鸟,就两种方式结合了下。建立工程完成后,会在 Project Assistant 看到 InstallShield 的打包

流程,如下图:





3,下一步,填写应用程序的信息,如下图:





4,下一步,设置安装架构(我直接默认),如下图:





5,下一步之后就到了,应用程序的文件,如下图:





我们可以添加文件,我没这么做,而是切换到了 Installation Designer 这个中,在左边的 Files and

Folders 双击,如下图:





双击了 Files and Folders,会出来几个窗口,其中 Source computer’s folders 就是我们的计算机

上的目录,而下面的那个 Destination computer’s folders 就是安装的目录,将我们的源程序文件夹从

Source computer’s folders 拖到 Destination computer’s folders 的 Application Target Folder 中,

并建立在 Application Target Folder 右键 建立一个 temp 目录,将我们的 ArcEngine 10(这个目录中含

有 ArcGIS Engine Runtime 以及相应的授权文件)拖放到这个 temp 目录中,如下图:





建立 temp 目录如下图:





两步操作完成后,我们可以看到下面的结构图:





我们有切换的 Project Assistant 面板中,如下:





6,下一步,创建开始菜单和快捷方式,如下图:





单击 New

按钮,选择我们的 EXE 文件





将系统给的名字 launch WRE_ 重新命名下,如下图:





切换到 Installation Designer 中,找到 Shortcuts,进行进一步的设计,如下图:



将上图的 esri 删除掉,重新建立目录和快捷方式,并对右边的 Internal Name 进行改写,如下图:





7,切换到 Project Assistant,然后下一步,如下图:





8,下一步,这一步就让选择一些许可声明之类的(安装过软件的朋友都知道,安装的时候会出现一些

声明条款的,就是这个),我没有这个需要,所以没选这个,如下图:





9,下一步,选择语言,我当然选择中文了(说明下,不同的版本不同,2011 的默认语言是英文,2008

的是繁体中文,2010 是中文,想不到,我为了打包这个,用了 3 个版本的软件),如下图:





10,下一步,选择打包的类型,选择第一个(这个流程已经完成,别急着建立,我们的 Net Framework

3.5 SP1 还没打包进去呢),如下图:





11,切换到 Installation Designer 面板中,找到 InstallScript,如下图:



将这个函数粘贴在这个脚本文件中,函数如下:

function OnMoved()





string szCommand,szCmdLine,szPath,svResult,LicPath;





STRING svLine,svReturnLine,InsertTxt; //////操作文件的变量





NUMBER nvFileHandle; //////////文件句柄





NUMBER nvLineNumber ,nvResult; //////////操作文件的变量





begin





szPath=TARGETDIR^"temp";





szCommand = WINSYSDIR^"";





Long PathToShortPath(szCommand);







////////////////////////安装 AE



运行时





if (FindFile (szPath^"ArcEngine10", "", svResult) = 0) then





szCmdLine =TARGETDIR^"temp"^"ArcEngine10"^"" /qn";





LongPathToShortPath(szCmdLine);





Delay(1);





if (LaunchAppAndWait(szCommand ,"/i ""+szCmdLine,WAIT) < 0) then





abort;



endif;





endif;







/////////////////////////AE



授权





LicPath=" -Lif "" +TARGETDIR^"temp"^"ArcEngine10"^"ArcGIS Engine Runtime

" -s";





if (FindFile (TARGETDIR^"temp"^"ArcEngine10", "ArcGIS Engine Runtime ",

svResult) = 0) then





if(64) then





szCmdLine="C:Program FilesCommon Files

(x86)";





else





szCmdLine="C:Program FilesCommon

";





endif;





if (LaunchAppAndWait(szCmdLine ,LicPath,WAIT) < 0) then





abort;





endif;





endif;





if (ExistsDir(TARGETDIR^"temp")=0 ) then





if (DeleteProgramFolder (TARGETDIR^"temp") < 0) then





endif ;





endif ;





end;





12,打包 Net Framework 3.5 sp1,在 Prerequisites 中找到 Net Framework 3.5 sp1,如下图:





在 Net Framework 3.5 sp1 前打钩,出现是否下载的对话框,选择否(因为我已经有了这个)



如下图:





在 Net Framework 3.5 sp1 上右键,选择编辑,移除原来的那个文件,添加上自己机器上的

Net Framework 3.5 sp1,如如下图:





在 Application to Run 的界面中将 Specify the command line for the application 和 Specify the

command line for the application when the setup is running in silent mode 中的参数改为:/q 、

norestart,如下图:





14,在 User Interface 中找到 Dialogue,然后找到 Skin,设置皮肤的颜色,如下图:





设置完之后,建立我们的程序,运行成功后,如下图:





这样我们只需要将这个在客户机上安装即可。





3. 打包中的两个问题





问题(1):当执行 的时候,由于我们打包了 NetFramwork3.5 sp1,当 NetFramwork3.5 sp1

装完后,会问我们是否要重新启动电脑,如果点了否,安装程序就中断了 ,当再次安装 的时候,

就可以完成。





问题(2):当 Runtime 完成后,发现应用程序不能用,没有授权成功?授权是成功的,因为 ArcGIS Engine

10 的许可机制发生了点变化,所以我们可以通过手动配置:开始-程序-ArcGIS-Administrator(但是不需

要授权文件,只需要点了,授权,然后取消即可)。



因为有以上两个问题,我们可以变通下,比如说手动操作下 Administrator。





先说授权的问题,将 ArcGIS Engine 10 的许可的注册文件打包进去,操作如下:

将已经可用 ArcGIS Engine 10 的注册表导出去,然后利用 installshield,操作如下:

在 Installation Designer 面板中,在 System Configuratin 中找 到 Registy,然后右键,在 Destination

中找到 Local-Machine,如下图:





右键,找到 Import REG File





点了 Import REG File 之后,就看到注册表导入向导,进行设置如下:





想一下操作有问题吗?有一个前提条件,就是这个打包程序要开启使用注册表,在 Project Assistant

如下:





4,至于 NetFramwork3.5 sp1,在 Installation Designer 中找 Prerequistes 中将 NetFramwork3.5 sp1

前面的勾去掉,如下图:





5,在 Installation Designer 中,将 NetFramwork3.5 sp1 添加到 Language Independent 中,如下

图:





然后写入以下脚本:





/////安装





GetEnvVar("TEMP", tempdir);//得到临时目录





FindAllFiles(tempdir, "" , tempdir, CONTINUE );//在临时目录下搜索

文件





if(LaunchAppAndWait(tempdir, "/q /norestart",WAIT)<0) then





abort;





endif;





整个完整的脚本如下:





,function OnMoved()





string szCommand,szCmdLine,szPath,svResult,LicPath,tempdir;



STRING svLine,svReturnLine,InsertTxt; //////操作文件的变量





NUMBER nvFileHandle; //////////文件句柄





NUMBER nvLineNumber ,nvResult; //////////操作文件的变量





begin





sz

Path=TARGETDIR^"temp";





szCommand = WINSYSDIR^"";





Long PathToShortPath(szCommand);





/////安装





GetEnvVar("TEMP", tempdir);//得到临时目录





FindAllFiles(tempdir, "" , tempdir, CONTINUE );//在临时目录下搜索

文件





if(LaunchAppAndWait(tempdir, "/q /norestart",WAIT)<0) then



abort;



endif;



////////////////////////安装 AE



运行时



if (FindFile (szPath^"ArcEngine10", "", svResult) = 0) then



szCmdLine =TARGETDIR^"temp"^"ArcEngine10"^"" /qn";



LongPathToShortPath(szCmdLine);



Delay(1);



if (LaunchAppAndWait(szCommand ,"/i ""+szCmdLine,WAIT) < 0) then



abort;



endif;



endif;







/////////////////////////AE



授权



LicPath="/Lif ""+TARGETDIR^"temp"^"ArcEngine10"^"ArcGIS Engine Runtime

" /S";





if (FindFile (TARGETDIR^"temp"^"ArcEngine10", "ArcGIS Engine Runtime ",

svResult) = 0) then



szCmdLine="C:Program FilesCommon

";



if (LaunchAppAndWait(szCmdLine,LicPath,WAIT) < 0) then



abort;



endif;



endif;



LicPath="/Lif "" +TARGETDIR^"temp"^"ArcEngine10"^"" /S";





then



if (FindFile (TARGETDIR^"temp"^"ArcEngine10", "", svResult) = 0)



szCmdLine="C:Program FilesCommon

";



if (LaunchAppAndWait(szCmdLine ,LicPath,WAIT) < 0) then





abort;





endif;



endif;



if (ExistsDir(TARGETDIR^"temp")=0 ) then

if (DeleteProgramFolder (TARGETDIR^"temp") < 0) then



endif ;



endif ;

end;



经过测试,大功告成。

第 330 页 共 330 页





更多推荐

itool