电子海图开发入门:S-57、S-52、S-100 到底是什么
把手机地图一路放大,你会看到更细的路网、更多的店铺——画什么、怎么画,是产品设计师说了算的。但把一张电子海图放大,规则完全不同:某片水域是深蓝还是浅蓝、某条线用实线还是虚线、危险沉船亮不亮,都不是渲染引擎"觉得好看"就行,而是国际标准一个字一个字写死的。
原因很朴素:海图不是给人逛的,是给船员做决策用的。 颜色错一档、深浅差一档,代价可能就是搁浅。所以 IMO(国际海事组织)认可的 ECDIS(电子海图显示与信息系统)必须严格按 IHO 标准来渲染,没有自由发挥的空间。
这决定了海图开发的知识结构和普通地图开发不太一样。除了渲染引擎本身,你必须懂两套标准,外加一场正在发生的换代:
- S-57 —— 数据:一张海图以什么结构存储和交换
- S-52 —— 显示:每个要素在屏幕上长什么样
- S-100 —— 框架:下一代标准体系,新产品都挂在它下面
图 1:S-57 管数据,S-52 管显示,S-100 是承载新产品族的下一代框架
这篇文章把三者的关系讲清楚,文末给一条可执行的学习路线。
S-57:海图的"数据库表结构"
一句话概括:S-57 规定了海图数据的组织方式和交换格式。
心智模型很简单——整张海图就是一堆"要素"(Feature),每个要素由三部分组成:
- 对象类(OBJL):这是一个字典化的枚举,比如 DEPARE(深度区)、SOUNDG(水深点组)、COALNE(海岸线)、WRECKS(沉船)。每个对象类有唯一编码,全世界的 ECDIS 都按同一本字典解析。
- 属性(ATTF):挂在对对象上的键值对。比如 DEPARE 带 DRVAL1/DRVAL2(这个深度区的最小/最大水深),SOUNDG 带 VALSOU(水深值)。
- 几何:只有点、线、面三种。而且要素之间存在拓扑——相邻两个深度区共享同一条边界。这也解释了为什么 S-57 数据里"边"要单独存,不是每个面各存一份。
它带来的直接推论是:渲染海图不是"画点线面",而是"解释属性"。一块水域是什么颜色,取决于 DEPARE 的深度区间落在哪个档;一个沉船要不要加危险标记,取决于它的属性组合。数据里没有任何颜色信息。
图 2:一块 0–10 米的水域如何变成屏幕上的浅蓝色——颜色是查表查出来的
交换层面,一个 ENC 交换集通常长这样:一个目录文件(CATALOG.031)+ 基础单元(.000)+ 若干增量更新文件(.001、.002……)。注意更新不是重发一张新图,而是"增/删/改"记录的序列,接收端必须按序正确应用——实际工程里相当一部分坑都出在更新机制上。
另外还有一类 M_ 开头的元要素(如 M_COVR 图幅覆盖范围、M_QUAL 数据质量),它们不参与常规渲染,但 ECDIS 必须特殊处理,忽略它们是新手最常见的第一个 bug。
给开发者的捷径:先别啃标准的 ISO 8211 封装层。用 GDAL 的 S-57 驱动把 ENC 转成 GeoJSON 或者塞进数据库,对着真实数据翻对象目录,比干读 PDF 快十倍。
S-52:把数据库"翻译"成屏幕
一句话概括:S-52 规定了每个要素画成什么样,而且细到色值和像素。
它的核心是三件套:
1. Look-up 表:决定"对象类 → 显示模板"的映射。比如 DEPARE 按 DRVAL1/DRVAL2 落进哪个深度档,用哪个填充模板;浮标类按其类别挂哪个符号模板。这张表是标准的一部分,不能自己发明。
2. 符号库 + 命名色 + 色盘:颜色不是 RGB 随手定的。IHO 定义了一套命名色 token,再给出昼(DAY)、昏(DUSK)、夜(NIGHT)三套色值表,外加单色模式。渲染时引用色 token,切色盘就是换一套色值重渲——这就是海图"昼夜模式"的实现方式,也是为什么符号必须按色盘动态着色而不是贴死图片。
3. 船员可调参数(Mariner Parameters):这是最容易被普通地图开发者忽略的一点。安全等深线、安全水深、浅水/深水阈值,是船员的设置,不是图的属性。同一张 ENC,安全等深线设 10 米和 20 米,屏幕上"安全水域"的范围完全不同。
第三点意味着一个架构级约束:颜色不能烘死在瓦片里。阈值一改,相关图层要能重新着色、即时生效。习惯了"瓦片=不可变缓存"的 Web 地图思路,在这里会撞墙。这个约束怎么在矢量瓦片架构下优雅地解决,我后面会单独写一篇。
顺带一提,S-52 还定义了三级显示模式(Base / Standard / Full),控制哪些要素默认显示——这属于"标准给的免费功能",实现成本很低,别漏。
图 3:切色盘 = 同一批命名色换一套 RGB;注意"黑"这个 token 夜间会翻白
S-100:正在发生的换代
一句话概括:S-100 是下一代数据框架,S-57/S-52 是它要逐步接替的上一代。
S-57 的老问题:对象模型是封闭枚举,想加新要素类型就得改标准本身;只能表达矢量点线面;目录版本升级牵一发动全身。
S-100 的思路完全不同:注册制 + 要素概念字典。各产品规范自定义要素类型,注册进框架即可互相组合,还支持栅格、影像乃至三维。在这套框架下冒出来一整个产品家族:
| 产品 | 内容 |
|---|---|
| S-101 | 下一代电子海图(ENC) |
| S-102 | 高精度水深表面 |
| S-104 | 动态水位 |
| S-111 | 表层流 |
| S-124 | 航行警告 |
| S-125 | 航标(AtoN) |
| S-127 | 船舶交通管理 |
| S-131 | 港口设施 |
现实判断给两条:其一,监管层面允许双标准长期并存,所以 S-57 与 S-101 的同屏渲染、数据转换、目录映射,会是未来很多年这个行业的真实工作量;其二,S-100 系列的中文资料少到可以视为空白——如果你在做技术选型或者转型规划,这是个值得注意的信号,也是本博客选择持续写它的原因。
学习路线(也是本系列的地图)
第一步:跑通现成的。 装 OpenCPN,加载 IHO S-64 官方测试数据,对着屏幕理解"数据 → 显示"的完整链路;再用 GDAL 命令行把同一个 ENC 导出成 GeoJSON,看看对象、属性、几何是怎么落地的。
第二步:按需读标准。 不要从头到尾通读。S-57 的 Appendix A(对象目录)当字典查;S-52 先只读显示流程那几张图;S-64 留着——等你写了渲染代码,它是检验对错的考卷。
第三步:造一个最小渲染器。 ENC → GeoJSON/矢量瓦片 → MapLibre 样式化。别小看这个玩具,look-up 表怎么实现、色盘怎么切换、船员参数怎么做到运行时生效——这些真正没资料的环节都会在路上遇到。本系列接下来的文章就是沿这条路走读。
资源清单
- IHO 官网(iho.int):S-52、S-57、S-64、S-100 系列标准 PDF 全部免费下载
- IHO S-64 测试数据集:做开发和验证最合规的示例数据来源
- OpenCPN:开源 ECDIS,最快的"所见即所懂"工具
- GDAL:S-57 驱动,数据解析瑞士军刀
- MapLibre:开源地图渲染引擎,本系列实战部分的主力
(本站不卖课不带货,不会出现"xxx 训练营"链接。)
小结
三句话带走:
- S-57 管数据:要素 = 对象类 + 属性 + 几何,颜色不在数据里
- S-52 管显示:look-up 表 + 命名色色盘 + 船员参数,一切皆规则
- S-100 管未来:注册制框架,S-101/124/125 等产品族的底座
下一篇预告:《S-57 数据解剖:把一个 ENC 文件拆给你看》——拿真实测试数据,从目录文件拆到单个要素。
我是夜航海图,做海图与地图渲染开发的工程师。博客「航图笔记」同步更新全部文章,欢迎 RSS 订阅。你卡在哪一步,评论区聊聊。
评论
评论基于 GitHub Discussions,需要 GitHub 账号;没有也欢迎通过 RSS 阅读器或各平台评论区交流。