基于OGR库的S-57标准电子海图到Shapefile格式的转换 | ![]() |
电子海图是为适应航海需要而绘制的包含海域地理信息和航海信息的一种数字化的专题地图, 符合国际标准的电子海图数据统称为S-57电子海图(electronic navigational chart, ENC), S-57标准成为国际共识[1]。电子海图不仅可以清晰地显示海图的各种信息, 而且能在短时间内实现海图的定位和更新, 为开发和利用海洋资源提供保障。因为通常S-57海图文件是以扩展名为.000的文件格式存储在磁盘中的, 这就使得大量丰富的S-57电子海图数据不能与地理信息系统(GIS)实现资源共享, 限制了S-57的广泛应用。Shapefile是目前最通用的GIS地图数据格式之一, 具有广泛的用户群, 因而将S-57电子海图格式转换成Shapefile文件格式十分重要。本文主要研究如何基于开源C++库OGR和ISO 8211Lib库将S-57数据格式的电子海图转换成ArcGIS地理信息平台支持的Shapefile格式, 从而使S-57标准电子海图可以广泛应用于GIS领域。
1 基于OGR库海图数据读取与存储ISO 8211Lib库是一款开源库, 库内封装了读取S-57电子海图格式文件所需的几乎全部的底层函数和类, 为准确解析S-57标准提供了一系列的方法和属性。利用该开源库可以读取S-57标准中规定的各种记录的字段及其关系。ISO 8211Lib库主要封装了DDFModule、DDFRecord、DDFField、DDFFieldDefn和DDFSubFieldDefn 5个类[2, 3]。OGR库类很好地将ISO 8211Lib库封装到S-57的驱动中, 主要提供对矢量数据格式的读写, OGR支持Shape格式、Oracle空间数据库、S-57电子海图格式、SDTS、PostGIS、mid/mif等文件格式, 提供了对S-57海图格式方便的读写方法。在OGR中, 每一种数据格式都有一个驱动类与之对应, 提供对矢量数据的读取与保存操作, OGR统一管理所有支持的驱动, 为各种矢量数据的读取与保存提供了方便的操作。S57reader类是对ISO 8211Lib库的封装, 该类包含了读取S-57电子海图数据文件所用到的基本函数, 主要有Open(打开S-57电子海图文件)、Close(关闭S-57电子海图文件)等。
1.1 S-57文件读取S-57文件到Shapefile文件的转换需要用到OGR对文件的读取与保存操作。OGR对所支持的矢量文件的读写是通过OGRSFDriver类来实现的, 所以首先要注册所支持的文件格式的OGRFDriver类的子类, 通过OGRSFDriverRegistrar类的静态函数RegisterDriver来注册对Shapefile文件提供读写操作的OGRShapeDriver类和对S-57文件提供读写操作的OGRS57Driver类。通过OGRS57Driver类的实例OGRS57Driver:Open()函数打开S-57文件, 调用S57reader类中的函数逐层深入读取海图数据。海图数据是分层存储的, 海图数据的多个子字段构成字段, 多个字段构成记录, 多个记录构成文件, 相互间是层叠关系, 在对海图数据进行分层读取时, 必须按顺序调用ISO 8211Lib库中的类[4]。
1.2 S-57文件转存为了将读取的海图数据更好地存储起来, 定义了转换过程中所需的数据参数描述、特征记录和空间记录类[5]。根据空间记录元素之间的拓扑关系, 定义了CPointFeature、CLineFeature和CAreaFeature 3个类, 分别用于存储描述点、线和面3个特征物标记录, 定义了CDescrip类用于存储海图数据的描述信息。采用标准模板库(standard template library, STL)的map-vector结构对读取的S-57电子海图数据进行存储。现以点特征记录为例说明数据的存储方式, 首先定义存储点的容器: vector < CPointFeature > PointFeature; 类CPointFeature的实例话对象是PointFeature, 然后建立一个相对应的map容器:Map < CPointFeature, int > Point_Feature_map, 后面的int类型为记录的ID, 这样就建立起一一对应关系。最后通过OGRShapeDriver类的实例OGRShapeDriver:CreateDataSource()函数创建支持Shape的OGR数据源, 通过循环依次将map-vector结构中数据转存到Shape数据集中。通过调用OGRShapeDriver的CreateLayer为Shape数据集创建相应的图层, 然后分别将属性和图形要素复制到Shape数据集中新建的图层。图 1为数据读取、转换和存储的过程。
![]() |
图 1 数据转换流程图 Fig.1 Flow Chart of Data Conversion |
2 S-57格式到Shape格式的特征转换 2.1 S-57文件与Shape文件关系
S-57标准对数据的描述是按照层次结构进行的。交换集是交换和传输的基本单元, 由文件构成, 它们之间是包含与被包含的关系。交换集按其描述信息内容的不同可以分为目录文件、自述文件、文本文件、图形文件和数据集文件5类。数据集文件是交换集中最重要的文件, 它用于存放海图的真实数据信息, 在一个交换集中至少有一个数据集文件, 一般采用ASCII方式和二进制方式进行编码。数据集文件由记录组成, 在S-57标准中, 根据记录中所描述的内容不同, 可将记录分为特征记录、空间记录、目录记录、数据集描述(元)记录和数据字典记录5种类型。其中最重要的是特征记录、空间记录和数据集描述(元)记录。特征记录用于描述交换集中实体的属性信息, 包括物标之间的关系以及更新方法; 空间记录用于描述交换集中实体的空间信息, 目前只有矢量型记录。一个完整的ESRI的Shape文件包括主文件(*.shp)、索引文件(*.shx)和dBASE表文件(*.dbf)3个文件。*.shp用于记录空间坐标信息, 即Shape位置信息, *.dbf用于记录具体位置和属性信息, *.shx是对主文件的索引, 指出主文件中记录在文件中的位置信息。S-57文件与Shape文件间的映射关系如图 2所示。
![]() |
图 2 S-57文件与Shape文件关系 Fig.2 Relationship Between S-57 File and Shape File |
2.2 空间参考系的转换
空间参考(spatial reference)包含一个坐标系统和精度, 它定义了数据集的地理坐标系统或投影坐标系统, 可以对要素进行精确定位[6]。S-57海图采用的坐标系统为WGS84[7, 8], 可以通过OGRLayer:GetSpatitalRef()函数获得S-57源文件的空间参考系, 并通过OGRDataSource:CreaterLayer的第二个参数传入生成的Shape图层, 使得S-57海图文件与转换后的Shapefile文件具有相同的空间参考系, 不改变原数据的属性。
2.3 属性要素特征转换OGRDataSource类包含了一个要素集或者要素层的架构信息, 通过OGRDataSource打开的S-57文件中有S-57各个图层的属性信息, 这些属性需要与Shapefile文件体系中的.dbf属性表相对应。OGRFeatureDefn类中封装了图层要素的属性信息, 包括类型、名称及其默认参考系等。一个OGRLayer有一个OGRFeatureDefn与之相对应。OGRFeatureDefn中的单个字段的描述信息可以通过OGRFieldDefn类来读取。在转换S-57属性字段时, 可以通过S-57属性表中的字段个数循环转换, 通过对应每一个S-57图层的OGRFeatureDefn类的函数GetFieldDefn()获取相应的字段, 然后通过目标Shape的OGRLayer:CreateField()函数创建相应的字段。
2.4 图形要素特征转换图形要素转换处理的信息为点、线、面的坐标信息。OGRFeature类是封装的一个完整的图形要素类, 用来存储OGRLayer中的单个图形要素的属性。可用OGRLayer:ResetReading()函数重置读取图层, 从第一个图形要素读取, 然后通过循环依次调用OGRLayer:GetNextFeature()函数获得每一个图形要素的信息, 并保存在一个OGRFeature对象中。然后通过OGRFeature:CreateFeature()函数创建一个新的图形要素, 通过OGRFeature:SetFrom()将图形要素和属性表关联, OGRGeometry: assignSpatialReference()将相应的空间参考系与新生成的要素关联。最后调用OGRLayer:CreateFeature()函数将新生成的图形要素保存在Shape图层中。为了安全起见, 在执行完操作后要删除要素, 同时销毁数据源。
3 符号库XML配置文件及海图显示 3.1 构建符号库XML配置文件按照XML语法规则, 建立海图S-57格式与Shape格式间符号库转换的XML配置文件(ShpLayer.xml)。该文件以 < ShpfileLayers > < /ShpfileLayers>为根元素, 以 < shpfileLayer > < /shpfileLayer > 为子元素, 然后依次对每一个子元素的内容进行编写。szLayerName代表Shape文件的文件名, 如szLayerName=“SOU NDG_point”代表Shape文件名字为水深的图层。nIndex表示图层的索引, 每一个图层对应一个索引, 不可重复, 相当于用于唯一标识图层的关键字。nType用于表示图层存储的是哪种类型的数据, nType=“0”表示存储的是点数据, 即点图层; nType=“1”表示存储的是线数据, 即线图层; nType=“2”表示存储的是面数据, 也就是面图层。dShowScale用于设置图层的显示比例尺, 由于S-57标准规范将SENC信息的显示标准分成显示基础(始终存在于显示中)、标准显示(缺省显示)、其余信息(按需显示)3个类别, 所以在特定比例尺下并不是所有物标都需要显示。本文将1:900 000作为分界线, 即dShowScale=“900 000”, 表示当比例尺小于1:900 000时该图层不显示。bLabel、szFieldName和nFontSize是相对应的, 用于设置该图层某个字段的属性值是否显示, 显示哪个字段的属性值, 以及显示的大小。如在SOUNDG_point图层中的bLabel=“1”表示显示属性值, szFieldName=“Depth”表示显示深度字段的属性值, nFontSize=“5”表示显示大小为5。nFontName、nSymStyle、nCharacterIndex和nSymSize是相对应的, nFontName用于设置调用哪个符号文件库, 调用MO本身自带的符号则省略, 如nFontName=“”, 调用自己绘制的符号库“S57”则需要标明, 如nFontName=“S57”; nSymStyle用于设置符号的类型, 调用MO自带的符号, nSymStyle=“1”表示调用点状符号, nSymStyle=“2”表示调用线状符号, nSymStyle=“3”表示调用面状符号, nSymStyle=“4”表示统一调用S57符号库里的符号; nCharacterIndex用于设置被调用符号的索引值, nCharacterIndex=“65”表示调用符号库里的第65个符号; nSymSize用于设置被调用符号的大小。nSymColor用于设置符号的颜色, 为了使符号颜色符合S-57显示标准, 就要建立物标颜色分配表, 建立分配表应参照S-57传输标准中的《电子海图物标代码表》, 使其顺序完全对应。由于在不同的背景环境下, CRT显示器对电子海图所发射光的折射率和透射率不同, 因此相对应的颜色分配表的设置也因白昼、黄昏和黑夜3个背景的不同而不同, 电子海图物标编码表包含的物标有很多, 本文仅以白昼背景为例对部分物标进行颜色配置, 如表 1。在XML编写时采用RGB颜色表示法, 如nSymColor=“0, 0, 0”表示该符号颜色为黑色。
表 1 某个物标的颜色分配表 Tab.1 Object Color Assignment Table |
![]() |
3.2 电子海图的加载与显示
由于文中符号库XML配置文件中只包含了一些简单的数据, 因此使用TinyXML读取XML。TinyXML是一个基于DOM模型的用C++编写的XML开源解析库, 它由两个头文件和四个CPP文件构成, 在使用前应将它的两个头文件(tinystr.h和tinyxml.h)以及四个CPP文件(tinyxml.cpp、tinyxmlparser.cpp、tinystr.cpp和tinyxmlerror.cpp)导入工程中, 然后就可以通过接口调用它内部封装的函数来实现对XML中信息的读取。首先定义一个包括图层名称、图层索引、类型、显示比例尺、字段名称、符号类型、图层注记的字体索引、符号的颜色等属性信息的结构体LayerInfo; 通过GetFilePath()和GetModulePath()来获取XML文件的路径, 然后LoadFile()函数加载XML文件, 读取XML文件中的内容并存储于结构体中, 创建一个ShpLayerXmlStru类型的容器LayerXmlStruVec来存储从XML中读取的数据。其次创建XML的文档对象, 然后依次读取该XML文档中每个元素的属性值, 并复制给结构体对象的属性值, 读取XML文档中的每个元素的属性值之后, 把它放入前面定义的容器中, 直到读取结束; 把读取的图层信息加载到结构体数组LayerInfo中。本文用中国东海和南海交界海域数据做验证, 根据海图原始数据模型存储海图矢量数据, 层层读取并存储各字段数据, 既不影响海图数据的原有结构, 又不丢失海图的原有信息, 转换结果空间数据和属性数据基本准确, 达到精度要求。
4 结束语本文研究了S-57海图格式转换为Shapefile格式的方法, 很好地实现了GIS软件对S-57海图的直接读取, 方便利用ArcEngine进行海洋地理信息系统开发时对S-57电子海图的支撑, 提高S-57海图的通用性, 这对加快我国电子海图地理信息系统建设具有重要的实用价值和现实意义。
[1] |
黄忠刚, 吴俊彦, 和钟声, 等. CDC到S-57物标属性对照研究[J]. 海洋测绘, 2007, 27(5): 52-54. DOI:10.3969/j.issn.1671-3044.2007.05.015 |
[2] |
刘锋, 张严, 陈彦勇, 等. S-57电子海图的快速读取及可视化存储[J]. 舰船科学技术, 2014, 36(7): 108-112. DOI:10.3404/j.issn.1672-7649.2014.07.023 |
[3] |
万晓霞, 洛佳男, 邬念, 等. S-101电子海图可视化关键技术[J]. 测绘地理信息, 2018, 43(4): 1-7. |
[4] |
唐葆祥, 刘东峰. S-57电子海图数据读取和自动多模式分层显示[J]. 微计算机信息, 2012, 28(2): 105-106. |
[5] |
孔德宁, 黄伟, 曹万华. 基于S-57自定义海图数据转换及优化[J]. 舰船电子工程, 2007, 27(1): 74-76. DOI:10.3969/j.issn.1627-9730.2007.01.023 |
[6] |
宋艳敏, 陈东银. 基于ArcEngine与OGR库的Shapefiles文件到KML格式转换方法研究[J]. 国土资源遥感, 2009(2): 110-113. |
[7] |
艾健, 林荣. dwg非标准海图数据向S-57标准格式转换的关键技术研究[J]. 船海工程, 2013, 42(1): 171-173. DOI:10.3963/j.issn.1671-7953.2013.01.046 |
[8] |
田少华, 丛亮亮. MapInfo矢量数据到S57标准数据的映射研究与实现[J]. 大连海事大学学报, 2015, 41(3): 51-58. |