Godot 城市模拟 – 005 OpenStreetMap 介绍:数据结构与详细示例
本文最后更新于17 天前

file

什么是 OpenStreetMap?

OpenStreetMap(简称 OSM)是一个开源、协作的全球地图项目,旨在创建一个由志愿者共同编辑和维护的免费地理数据库。与商业地图服务(如 Google Maps)不同,OSM 的数据开放给所有人使用、修改和分发,遵循开放数据许可证(如 ODbL)。OSM 的核心在于其社区驱动的方式:用户通过 GPS 设备、航空影像或本地知识收集数据,并上传到中央数据库。这些数据可用于制作地图、导航应用、地理分析等。

OSM 的数据以简单的、基于 XML 的格式存储,主要围绕三种基本对象:节点(Node)路径(Way)关系(Relation),并通过标签(Tag) 添加属性。这种结构使得 OSM 数据轻量、灵活且易于扩展。下面,我们将逐步深入探讨 OSM 的数据结构,并通过一个详细示例来理解其工作原理。

OSM 数据结构概述

OSM 数据模型基于以下核心元素:

  • 节点(Node):代表地图上的一个点,用经纬度坐标定义。例如,一个路灯或建筑物角落。
  • 路径(Way):由有序的节点序列组成的线或面。例如,一条道路(线)或一个公园边界(面)。
  • 关系(Relation):用于分组或关联多个对象(节点、路径或其他关系)。例如,一个公交路线(包含多个路径)或一个行政边界。
  • 标签(Tag):键值对(key-value pairs),附加到节点、路径或关系上,用于描述属性(如名称、类型等)。

所有元素都有通用属性,如 id(唯一标识符)、version(编辑版本)、timestamp(最后修改时间)和 changeset(关联的修改集)。数据通常以 XML 或 PBF(Protocolbuffer Binary Format)格式存储。接下来,我们通过一个示例来一步步解析 OSM 数据结构。

一步一步了解 OpenStreetMap 示例

以下是一个典型的 OSM XML 数据片段,包含了一个边界定义、一个节点、一个路径和一个关系。我们将逐部分拆解,并解释每个元素的作用。示例基于用户提供的真实数据,但已简化以确保清晰性。

<?xml version='1.0' encoding='UTF-8'?>
<osm version="0.6" generator="osmium/1.14.0">
  <!-- 示例数据将在这里展开 -->
</osm>

步骤 1: 理解整体结构

  • 根元素 表示 OSM 数据文档,属性 version="0.6" 指定 OSM API 版本,generator 说明生成工具(如 Osmium)。
  • 数据包含在 内,包括 子元素。

步骤 2: 边界定义(Bounds)

边界元素定义了数据的经纬度范围,用于优化地图渲染或查询。

<bounds minlat="38.45043" minlon="-75.78974" maxlat="40.03221" maxlon="-74.96121"/>
  • 解释:这个边界框覆盖了美国特拉华州附近区域,最小纬度 38.45043、最小经度 -75.78974,最大纬度 40.03221、最大经度 -74.96121。它帮助应用程序快速定位数据,但不是必须的。

步骤 3: 节点(Node)

节点是 OSM 的基本点元素。以下示例表示一个测量点(survey point)。

<node id="75390099" version="11" timestamp="2023-01-22T00:03:05Z" lat="39.7221284" lon="-75.7886029">
  <tag k="description" v="Lat-Long (NAD27) N39°43'26.3" W75°47'19.9" UTM (NAD27) 18S 432415 4397212 UTM (WGS84) 18S 432391 4397420"/>
  <tag k="man_made" v="survey_point"/>
  <tag k="name" v="Tri-State Marker"/>
</node>
  • 属性解释
    • id="75390099":节点的唯一 ID。
    • version="11":该节点已被编辑 11 次,版本号用于冲突解决。
    • timestamp="2023-01-22T00:03:05Z":最后修改时间(UTC)。
    • lat="39.7221284" lon="-75.7886029":经纬度坐标,定义点的位置。
  • 标签解释(使用 子元素):
    • k="description":键为 “description”,值提供详细的坐标描述。
    • k="man_made" v="survey_point":表示这是一个测量点。
    • k="name" v="Tri-State Marker":名称为“Tri-State Marker”,可能标记州界。
  • 作用:这个节点代表一个具体的地理点,标签添加了语义信息,使数据可查询(如查找所有测量点)。

步骤 4: 路径(Way)

路径由节点序列组成,可以表示线(如道路)或面(如建筑)。以下示例是一个轨迹路径(highway=track)。

<way id="11749873" version="4" timestamp="2012-09-21T05:23:27Z">
  <nd ref="105203702"/>
  <nd ref="105203705"/>
  <tag k="highway" v="track"/>
</way>
  • 属性解释:与节点类似,idversiontimestamp 表示元数据。
  • 节点引用( 子元素)
    • ref="105203702"ref="105203705":引用两个节点的 ID,定义路径的起点和终点。路径由这些节点按顺序连接而成。
  • 标签解释
    • k="highway" v="track":表示这是一条未铺装的道路或小径。
  • 作用:路径用于线性特征。如果节点序列形成闭合环(首尾节点相同),并可添加 area=yes 标签,则代表面(如多边形)。

步骤 5: 关系(Relation)

关系用于组合多个元素,表达复杂结构(如边界或路线)。以下示例是一个行政边界。

<relation id="117172" version="5" timestamp="2020-06-19T22:26:18Z">
  <member type="way" ref="33502448" role="outer"/>
  <member type="node" ref="157622606" role="admin_centre"/>
  <tag k="name" v="Townsend"/>
  <tag k="type" v="boundary"/>
  <tag k="boundary" v="administrative"/>
  <tag k="wikidata" v="Q755689"/>
  <tag k="wikipedia" v="en:Townsend, Delaware"/>
  <tag k="admin_level" v="8"/>
  <tag k="border_type" v="town"/>
</relation>
  • 属性解释idversiontimestamp 与其他元素一致。
  • 成员( 子元素)
    • type="way" ref="33502448" role="outer":引用一个路径(ID 33502448),角色为“outer”,表示边界的外环。
    • type="node" ref="157622606" role="admin_centre":引用一个节点(ID 157622606),角色为“admin_centre”,表示行政中心。
  • 标签解释
    • k="name" v="Townsend":关系名称为“Townsend”(一个城镇)。
    • k="type" v="boundary"k="boundary" v="administrative":定义这是一个行政边界。
    • k="admin_level" v="8":行政级别为 8(通常表示城镇级)。
    • 其他标签如 wikidatawikipedia 提供外部链接。
  • 作用:关系将分散的元素组织起来,完整描述一个地理实体(如城镇边界及其中心点)。

完善数据样例及详细介绍

以下是一个更完整的 OSM 数据示例,模拟一个小型公园区域,包含多个节点、一个闭合路径(面)和一个关系。数据基于真实模式,但为教学目的简化。

<?xml version='1.0' encoding='UTF-8'?>
<osm version="0.6" generator="example">
  <!-- 边界定义:覆盖一个小区域 -->
  <bounds minlat="39.720" minlon="-75.790" maxlat="39.730" maxlon="-75.780"/>

  <!-- 节点1:公园入口点 -->
  <node id="1001" version="1" timestamp="2023-01-01T10:00:00Z" lat="39.725" lon="-75.785">
    <tag k="entrance" v="yes"/>
    <tag k="name" v="Main Entrance"/>
  </node>

  <!-- 节点2-4:公园边界的角点 -->
  <node id="1002" version="1" timestamp="2023-01-01T10:00:00Z" lat="39.725" lon="-75.782"/>
  <node id="1003" version="1" timestamp="2023-01-01T10:00:00Z" lat="39.728" lon="-75.782"/>
  <node id="1004" version="1" timestamp="2023-01-01T10:00:00Z" lat="39.728" lon="-75.785"/>

  <!-- 路径:表示公园边界(闭合面) -->
  <way id="2001" version="1" timestamp="2023-01-01T10:00:00Z">
    <nd ref="1001"/> <!-- 起点/入口 -->
    <nd ref="1002"/>
    <nd ref="1003"/>
    <nd ref="1004"/>
    <nd ref="1001"/> <!-- 闭合回起点 -->
    <tag k="leisure" v="park"/>
    <tag k="name" v="Central Park"/>
    <tag k="area" v="yes"/> <!-- 标记为面 -->
  </way>

  <!-- 关系:将公园及其入口分组 -->
  <relation id="3001" version="1" timestamp="2023-01-01T10:00:00Z">
    <member type="way" ref="2001" role="outer"/>
    <member type="node" ref="1001" role="entrance"/>
    <tag k="type" v="multipolygon"/>
    <tag k="name" v="Central Park Area"/>
  </relation>
</osm>

样例详细解释:

  • 整体结构:这个示例描述了一个名为“Central Park”的公园。数据包括边界、4个节点、1个路径和1个关系。
  • 节点
    • 节点 1001:公园入口,标签 entrance=yesname="Main Entrance" 指定其作用。
    • 节点 1002-1004:匿名节点(无标签),仅用于定义边界坐标。
  • 路径
    • 路径 2001 由节点 1001→1002→1003→1004→1001 顺序连接,形成闭合环。
    • 标签 leisure=park 表示休闲公园,name="Central Park" 给出名称,area=yes 明确这是一个面(否则路径默认为线)。
  • 关系
    • 关系 3001 将路径(角色 “outer”)和入口节点(角色 “entrance”)组合。
    • 标签 type=multipolygon 表示这是一个复杂多边形关系,常用于处理有孔的区域。
  • 用途:这种结构允许应用程序将公园视为一个整体对象(例如,点击公园时显示入口信息),展示了 OSM 数据的灵活性和丰富性。


扫码关注,及时关注技术动态


暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇