在 osmchina 数据库中检索中国河流与流域水系的实用指南

在进行自然地理、生态红线、流域保护或沿江沿河经济带规划分析时,从 OpenStreetMap 数据库中准确提取主要江河水系是一项高频且基础的工作。

本文总结了在本地 osmchina(约 33GB)数据库中,结合中国水利行业河流代码标准(SL 249)、OSM 关系(Relation)拓扑及 Wikidata 实体检索江河干流的方法,并提供沿岸市县空间提取的实战技巧。


一、河流标识体系与代码标准

在对中国河流进行跨数据源比对和数字化建库时,通常涉及以下几套标识编码:

  1. 水利行业标准代码(SL 249)
    • 中国水利部行业标准《全国水资源综合规划水力代码标准》(如 SL 249-1999 / SL 249-2012)。
    • 规则:采用多位字母与数字编码表示流域与水系层级。例如:
      • 黄河:ADA00000
      • 岷江:AFC00006
      • 嘉陵江:AFD00006
      • 汉江:AFG00006
      • 金沙江:AFA01006
    • 在 OSM 中,热心制图者常将该编码收录在 tags->'code' 属性中。
  2. Wikidata 唯一实体代码(Q 标识符)
    • 国际通用的全球实体知识库编号(如长江为 Q5413,黄河为 Q7355,珠江为 Q201463)。
    • 不受名称简繁体、拼音、别名(如金沙江/川江/扬子江)变动的影响,是目前最可靠的全局检索锚点。
  3. OSM Relation ID
    • OSM 社区通过水系关系(type=waterway,waterway=river)将一条大河在物理上被切碎的数百段 Way 编组在一起。
    • 例如:长江干流关系 ID 为 9392345(全长约 3,824 km,从四川宜宾合江门三江口至崇明岛入海口)。

二、OSM 中河流要素的两种存储形态

在 planet_osm 架构下,河流主要有两种空间形态:

graph TD
    subgraph LineLayer["中心线与水流走向 (planet_osm_line)"]
        L1["waterway = 'river'<br/>(用于水系长度计算、流向分析与线网展示)"]
    end
    
    subgraph PolyLayer["水体水面多边形 (planet_osm_polygon)"]
        P1["natural = 'water' & water = 'river'<br/>(大江大河宽阔水面多边形,用于面积与白模计算)"]
    end
    
    subgraph RelLayer["完整水系关系 (planet_osm_rels)"]
        R1["type = 'waterway' & waterway = 'river'<br/>(汇集干流全线各段 way 的主关系,记录 code 与 wikidata)"]
    end
    
    RelLayer -->|成员引用 members| LineLayer
  • 做主干水系走向与沿岸相交分析时:推荐提取 planet_osm_rels 中的水系关系,再映射回 planet_osm_line 中的 way 几何线。
  • 做水域覆盖与湖泊面积统计时:使用 planet_osm_polygon(natural='water')。

三、查询河流的四大实用 SQL 技巧

技巧 1:从 planet_osm_rels 中快速定位河流关系

在关系表中,河流关系的 tags 包含丰富的语义信息(中文名、外文名、Wikidata、水利代码):

-- 方式 A:通过名称(支持中文、英文、拼音)
SELECT id, tags->>'name' AS name, tags->>'wikidata' AS wikidata, jsonb_array_length(members) AS way_count
FROM planet_osm_rels
WHERE (tags->>'type' = 'waterway' OR tags->>'waterway' = 'river')
  AND (tags->>'name' = '长江' OR tags->>'name:zh' = '长江' OR tags->>'name:en' = 'Yangtze');

-- 方式 B:通过 Wikidata ID(最精准,避免重名河流干扰)
SELECT id, tags->>'name' AS name, tags->>'wikidata' AS wikidata
FROM planet_osm_rels
WHERE tags->>'wikidata' = 'Q5413';

技巧 2:两步法快速提取水系主线 Way 并计算真实里程

找到 Relation ID(例如长江 9392345)后,直接提取其关联的全部物理 Way 并使用 PostGIS 聚合并计算总里程:

WITH river_ways AS (
    SELECT (m->>'ref')::bigint AS way_id
    FROM planet_osm_rels, jsonb_array_elements(members) m
    WHERE id = 9392345 AND (m->>'type') = 'W'
)
SELECT 
    COUNT(l.osm_id) AS way_count,
    ROUND((SUM(ST_Length(l.way)) / 1000)::numeric, 1) AS total_km,
    -- 抽稀输出适合前端渲染的轻量 GeoJSON (误差控制在 100米内)
    ST_AsGeoJSON(ST_Simplify(ST_Transform(ST_Union(l.way), 4326), 0.001)) AS geojson
FROM river_ways w
JOIN planet_osm_line l ON l.osm_id = w.way_id;

技巧 3:利用空间拓扑分析沿岸经过的地级城市与区县

通过水系主干线与中国行政区划底图(map_province、map_county)进行 ST_Intersects 空间求交,并使用 ST_Buffer(ST_MakeValid(geom), 0) 保障复杂多边形拓扑安全:

WITH river_ways AS (
    SELECT (m->>'ref')::bigint AS way_id
    FROM planet_osm_rels, jsonb_array_elements(members) m
    WHERE id = 9392345 AND (m->>'type') = 'W'
),
river_line AS (
    SELECT ST_Transform(ST_Union(l.way), 4326) AS geom
    FROM river_ways w
    JOIN planet_osm_line l ON l.osm_id = w.way_id
)
SELECT 
    CASE 
        WHEN c.parent_adcode IN (110000, 120000, 310000, 500000) THEN c.parent_adcode
        ELSE c.adcode
    END AS city_adcode,
    CASE 
        WHEN c.parent_adcode = 310000 THEN '上海市'
        WHEN c.parent_adcode = 500000 THEN '重庆市'
        ELSE c.name
    END AS city_name,
    COUNT(*) AS poly_count
FROM map_province c, river_line r
WHERE c.geom && r.geom AND ST_Intersects(c.geom, r.geom)
GROUP BY city_adcode, city_name
ORDER BY city_adcode;

实测统计:长江干流自宜宾起,沿途流经四川省、重庆市、湖北省、湖南省、江西省、安徽省、江苏省、上海市共 26 个地级行政区以及 105 个区县。


四、主要江河 OSM 关系速查表

在 osmchina 数据库中收录的部分重要河流关系对照:

河流名称 水利代码 (SL249) Wikidata ID OSM Relation ID 沿岸重点区域
长江 (干流) - Q5413 9392345 宜宾、泸州、重庆、宜昌、武汉、九江、芜湖、南京、上海
黄河 ADA00000 Q7355 171843 青海、甘肃、宁夏、内蒙古、陕西、山西、河南、山东
金沙江 AFA01006 Q1038418 9075912 青海、西藏、四川、云南
岷江 AFC00006 Q729269 9392349 茂县、都江堰、成都、乐山、宜宾
嘉陵江 AFD00006 Q1045185 288614 陕西、甘肃、广元、南充、合川、重庆
汉江 AFG00006 Q875573 403702 汉中、安康、十堰、襄阳、荆门、武汉
湘江 AFF10006 Q831884 193044 永州、衡阳、株洲、湘潭、长沙、岳阳
赣江 AFH10006 Q1046685 396599 赣州、吉安、南昌、九江

五、自动化工具支持

本项目已提供自动化河流提取工具脚本 scripts/export_river_geojson.py,支持传入河流名称(如 长江、黄河)或 Wikidata 编号,即可全自动提取河流几何与沿途市、县底图,并无缝发布至前端地图集。