夜雨聆风学习资料网

ARTICLE · 1296545

ArcHIGH水文水动力模型软件—接口与渲染

ArcHIGH水文水动力模型软件—接口与渲染

上一篇说到"要在 GIS 之上扩展通用的模型数据结构",这听起来很美。但落到实处,有两个绕不过去的硬问题:数据结构用什么形式定义?定义了之后 GIS 凭什么认它、显示它? 这一篇把这两个问题拆开讲。本篇也是ArcHIGH架构理论的最后一篇。


一、ArcHIGH 的编码核心思想

高内聚、低耦合是软件工程中的模块设计准则,通过这种设计思想可以使得软件的单元测试、修改、复用变得简单,并减少软件改一处大面积崩塌的弊端。COM组件思想就是这一理念的核心成果,它从模块编制方法上就强制了必须是高内聚、低耦合的。虽然这个思想是微软上世纪90年代左右提出的,但至今仍生命力旺盛。其有一条铁律:组件模块之间只通过接口(编码里以 interface为关键词)打交道。ArcGIS 是COM组件编程思想的集大成者,它将大量的GIS功能写成了可复用的 COM组件,然后像搭积木一样通过组件接口将模块连接起来,形成了功能强大的软件。这种程序设计的思想有一个严格的规范:不能直接访问一个 COM 组件的内部实现,只能按接口上声明的方法调用。这既保证了封装性,也带来一个后果——

想让模型和 ArcGIS 框架打交道,第一件事不是写实现,而是设计接口。

而且接口一旦发布就很难改,还得能应付各种没料到的场景。三条规则是答题纲要:

规则
要点
反例
一、符合 COM 规范
GUID 标识接口、IUnknown 基接口
不守规矩,组件注册不上去,平台根本扫不到
二、含各模型共性
放水文模型普遍都有的东西
把新安江的"蓄水容量曲线形状参数 B"塞进去——SWAT 没这东西
三、不能为特定模型设计
要能应付现在还想不到的需求
为某个模型定死接口,第二个模型来了就废

ArcHIGH 完全遵循COM组件设计思想,一切皆接口,接口后面是怎么设计的完全是内聚的部分,但对外看起来就只有接口。这就跟插座和插头的关系类似,插座规定了三孔和两孔,这个类似于组件的接口规范,至于插头后面连的是什么电器(组件),插座管不着,只要双方是按照规定的口对上的,连上就可以用。


二、设计模型要素

ArcGIS软件打开一个点图层、面图层或者线图层(在 ArcGIS 组件里面,它们都叫 FeatureLayer),属性表中的一行或者地图上显示的一个图形在 ArcGIS 组件中对应一个 Feature,这里翻译为"要素",它们都是简单的点、线、面要素。

按照前一篇的说明,它们不足以表达复杂的水文模型,就必须建立更复杂的通用的模型要素:首先要通过定义接口,然后实现接口来完成。比如一个水文站,它在地图上就是一个点,但还有大量的水文站相关的一些操作,所以针对这种简单要素定义一个ISimpleFeature;针对新安江模型,它则包含子流域、水系、雨量分配泰森多边形等,就不再是一个简单的要素,而是要定义一个组合要素的接口IFeatureCollection,里面包含大量的ISimpleFeature。

这里的这些组合与 ArcGIS 中通过属性表关联有本质的区别,组合起来后实现了“高内聚”,对外则只能通过接口实现“低耦合”。另外为了实现在磁盘上存储,以及坐标的定义,还得实现IPersistStream和IGeometry等接口。

按这写设计,设计了四个核心接口(interface)以及它们的实现,在软件工程的 UML类图中表达是这样的:

上面两个蓝色是实现类,下面绿色是它们实现的接口。简单要素SimpleFeature 实现 ISimpleFeature + IPersistStream;组合要素CombinedFeature 除此之外还实现了 IFeatureCollection,一个组合要素由若干个简单要素组成

简单要素是不可再分的基本实体 —— 一个子流域可以当作一个多边形,一条河道可以当作一条折线。组合要素代表模型的全部数据,比如整个流域,由多个简单要素组成。

ISimpleFeature 的组成很简单:一个几何IGeometry,加几项基本属性。

组成
说明
唯一 ID
区分同一图层里的不同要素
名称
给要素打标签
几何IGeometry,复用 ArcGIS的设计,是自定义要素与平台的桥
GetParameter / SetParameter
读写模型参数

上表中最后一行要特别说明,它是用来获取/设置模型参数的,水文模型的参数是附着在要素上的 —— 某个子流域的产流参数、某条河道的糙率,都属于它自己,所以参数管理必须放进要素接口。

而参数的存取方式,这里做了一个和 ArcGIS 软件内置要素不一样的选择:

ArcGIS 内置要素
自定义要素
参数载体
属性表
键值对
对模型开发者
需要熟悉属性表机制
直观,不用学

差异看着小,但站在水文专家角度,模型的参数本来就是"名字 → 数值",用属性表是自找麻烦。

在面向对象的组件编程思想中,CombinedFeature 继承 ISimpleFeature 的全部特性,再实现集合类型的 IFeatureCollection —— 管理内部的简单要素:添加、删除、获取数量。

这里有个关键细节,看 IFeatureCollection 这几个方法:

  • Add(strCate : string, pFeature : ISimpleFeature) 

  • GetFeature(strCate : string, nIndex : long) : ISimpleFeature 

  • FeatureCount(strCate : string) : long 

每个方法都带一个 strCate 字符串参数 —— 因为组合要素内部的简单要素是分类存放的。子流域归为 "sub-basin",河道归为 "channel"。有了类别标识才能有效组织管理。


三、设计模型图层(GIS基本能力)

接口设计好了,接下来是麻烦的部分。

虽然自定义要素是按 COM 规范设计的,但 ArcGIS 依然不能接纳它们。

现代GIS以图层作为要素承载体,GIS内置的FeatureLayer(对应点、线、面图层)、TinLayer(对应三角网图层)、RasterLayer(对应DEM图层) 的共同点是都只认内置要素。

塞自定义要素进去,平台直接不认识。既然GIS内置的图层不认模型要素,那就只能自己做一个模型图层,把这些自定义要素装起来,再加进GIS。

点图层、线图层、面图层都只认内置要素,塞不进自定义要素;模型图层是专门为模型要素设计的容器,一个图层容纳 N 个模型要素,由平台统一管理、显示、渲染

这个自定义的模型图层设计有个原则 —— 它要能容纳任何符合规范的模型要素,不只针对特定水文模型要素。这就是上一篇说的"通用模型图层"。实现门槛比写要素高得多:ArcGIS 规范里有大量强制要求,自定义图层必须继承指定的若干接口才能被平台接受,此外模型图层应该还有与模型相关的一些特性操作,为此我们可以自定义一个额外的图层接口ICustomLayer。


四、画模型图层(渲染器)

模型图层能接进平台了,数据能存了,但看不见。

ArcGIS平台现有的渲染技术是为内置要素设计的,渲染不了自定义模型要素。

还有个结构性障碍更麻烦:

ArcGIS 现有的渲染器架构,一个要素图层里只能渲染一种简单几何类型。 点、线、面各管各的,一个图层挑一种。

但模型要素是复合的。一个新安江模型的要素里同时有流域边界(面)、子流域(面)、河道(线)—— 三样东西,两种几何类型。现成的渲染器难以胜任。

解法:自定义渲染器 + LegendGroup

按照 ArcGIS 的组件规范,我们自己写一个渲染器,唯一目标就是在同一个图层里同时渲染多种类型的几何。看下面的 UML类:

CustomLayer 实现了 ILayer、IGeoDatabase、ILayerDrawingProperties 等 ArcGIS 规定的必须实现的接口 ;CustomRenderer 实现 ILegendInfo(也是 ArcGIS 规定的接口)。一个图层配一个渲染器,底层还有 IPersistStream 负责存盘

ArcGIS 中实现渲染的关键技术叫 LegendGroup(图例组):

一个 LegendGroup,代表一种自定义要素类型的渲染方式。

以新安江模型为例,它由流域边界(面)、子流域(面)、河道(线)组成,渲染器里就该有三个 LegendGroup。数量就按第二节那个 strCate 类别数来确定 —— 接口里分成几类,渲染器里就有几个LegendGroup。

另外,渲染器是图层的一个附属品,图层创建的同时就创建这个渲染器;等待第一个要素加进图层,上面UML类图中的ICustomRenderer 的 Create 函数就按这个模型要素的类别,确定 LegendGroup 的数量。到此,图层管数据,渲染器管显示,一一对应。

完整的接入流程

四个对象的分工:CustomLayer 是容器,直接连到 GIS 地图;CustomRenderer 管显示;CombinedFeature 是真正的模型要素。下面是接入与渲染的六步流程——注意图层必须先建,它是唯一能直接连接 ArcGIS 平台的对象
  1. GUI 创建模型图层
  2. 与图层同时创建渲染器
  3. 图层加入平台,接受管理
  4. 导入水文数据,创建模型要素
  5. 模型要素加入自定义图层
  6. 渲染器绘制模型要素,以便在平台中显示

顺序有讲究 —— 图层必须先建。因为图层是唯一能直接连接 ArcGIS 平台的载体,只有它先就位,其他东西才有着落。


五、这一套设计,换来了什么

模型侧几乎不用改代码。 模型本来就是按自己的数据结构开发的,而这些结构与自定义模型要素是一致的,可以直接拿到 ArcGIS 里用。

能跨语言。 COM 规范与具体编程语言无关,C++、C#、VB、Java、Python 都直接兼容。水文专家用自己最熟悉的语言写模型,不被平台绑住。

能移植。 其他水文模型、水动力模型、环境模型,都可以沿用同一套方法接进平台,不需要大幅改源码。

代价也有:每个模型仍然需要定义自己的专用接口,这不算简单的工作。


六、下一篇

下一篇写实际怎么跑起来:以新安江模型为例,从导入 Arc Hydro 划好的子流域和河道,到添加雨量站、泰森多边形、水文数据,再到一键运行、对比模拟与实测过程线。


ArcHIGH 是河海大学水文水资源学院水文预报所团队的水循环模拟软件,自主可控。这里记录它的设计思路、应用案例和一点使用心得。联系人:向小华,邮箱:<xxhxiang@hhu.edu.cn>   QQ群:1129879018

回首页,搜索你想要的文档

在首页搜索框输入关键词,快速定位资料

文库首页搜索指引 立即搜索

相关学习资料