Skip to content

Latest commit

 

History

History
221 lines (155 loc) · 6.61 KB

数据格式说明.md

File metadata and controls

221 lines (155 loc) · 6.61 KB

数据格式说明

面向初次接触本项目的同学。本文解释每种文件是什么、为什么这样存、以及怎么用。


一、项目产出哪些文件?

渲染完成后,map/ 目录结构如下:

map/
├── gallery/                  ← 城市地图图像(给人看的)
│   ├── Chicago.jpg
│   ├── Tokyo.jpg
│   └── ...(60 张)
│
├── graphs/                   ← 城市路网原始数据(给算法用的)
│   ├── Chicago_nodes.parquet
│   ├── Chicago_edges.parquet
│   ├── Tokyo_nodes.parquet
│   ├── Tokyo_edges.parquet
│   └── ...(每座城市 2 个文件,共 120 个)
│
├── cache/                    ← OSMnx 的临时 HTTP 缓存(跑完可删)
│   └── ...
│
├── render.log                ← 渲染进度日志
└── errors.log                ← 失败城市记录

二、gallery/ — 城市地图图像

文件格式:JPG

JPG(也写作 JPEG)是最常见的图片格式。相比 PNG,JPG 用有损压缩, 文件体积小很多——对于地图这种"大面积纯色背景"的图像, 肉眼几乎看不出质量差距,但体积能小 5–10 倍。

属性 值
分辨率 3840 × 2160 像素(4K)
压缩质量 92(满分 100,接近无损)
背景色 #0A0400(近黑深红)
文件大小 约 3–10 MB / 张

用途

  • 直接打开欣赏城市路网形态
  • 作为算法动画的背景底图
  • 导入 PPT / 海报等设计场景

怎么打开

双击即可,任何图片查看器都支持。


三、graphs/ — 路网原始数据

这是本项目最重要的数据,算法模块(A*、Dijkstra 等)就靠它运行。

什么是节点和边?

现实中的城市道路被抽象成数学里的图(Graph):

节点(Node)= 路口 / 转弯点
边  (Edge)= 连接两个节点的路段

举个例子:

[节点 A:某个十字路口] ──── 500米 ──── [节点 B:下一个路口]
                              ↑
                        这条线就是一条"边"
                        边上记着:长度 500m、限速 50km/h、单行道否

整座城市的路网就是成千上万个节点和边组成的大网络。


文件格式:Parquet + zstd 压缩

Parquet 是一种专为数据分析设计的列式存储格式, 配合 zstd 压缩算法,是目前压缩比最高、读写最快的开源数据格式之一。

和其他格式的对比(以纽约为例,约 137 万条边):

格式 文件大小 读取速度 说明
GraphML(XML) ~800 MB 慢 纯文本,极度冗余
GraphML.gz ~80 MB 慢 压缩后,但读取仍需解析 XML
GeoPackage ~150 MB 中 GIS 软件友好
Parquet + zstd ~20–40 MB 极快 本项目采用,推荐

nodes.parquet — 节点文件

每一行是城市里的一个路口或转弯点。

列名 类型 含义
osmid 整数 OpenStreetMap 节点唯一 ID
x 浮点数 投影坐标 X(单位:米)
y 浮点数 投影坐标 Y(单位:米)
lon 浮点数 经度(WGS84,如 -87.6)
lat 浮点数 纬度(WGS84,如 41.8)
geometry Point 节点的地理坐标点对象
street_count 整数 该节点连接的道路数量

投影坐标 vs 经纬度:

  • 经纬度(lon/lat)是球面角度,不能直接算距离
  • 投影坐标(x/y)已换算为平面直角坐标,单位是米,可以直接用勾股定理算距离
  • A* 算法的启发函数用 x/y 算欧几里得距离,精确且快

edges.parquet — 边文件

每一行是连接两个节点的一段道路。

列名 类型 含义
u 整数 起点节点的 osmid
v 整数 终点节点的 osmid
key 整数 同一对节点间若有多条路,用 key 区分(通常为 0)
length 浮点数 路段长度(米)
highway 字符串 道路类型(motorway / primary / residential 等)
maxspeed 字符串 限速(如 "50",单位 km/h,可能为空)
oneway 布尔值 是否单行道(True = 只能从 u 走到 v)
geometry LineString 路段的实际弯曲形状
name 字符串 路名(如 "Michigan Avenue",可能为空)

为什么 length 很重要:
Dijkstra 和 A* 的"边权重"就是用 length(找最短距离)
或 length / maxspeed(找最短时间)来设置的。


四、cache/ — 临时缓存(跑完可以删)

OSMnx 在下载地图数据时,会把从 OpenStreetMap 服务器拿到的原始 HTTP 响应 保存到 cache/ 目录。

作用:如果渲染过程中断,重启时可以直接从缓存读数据, 不用重新联网下载,速度快很多(几秒 vs 几分钟)。

跑完之后:所有城市都渲染完、parquet 都存好之后, cache/ 目录就没用了,可以直接删掉:

rm -rf map/cache/

五、怎么在代码里读取这些数据?

读节点和边(最常用)

import geopandas as gpd

nodes = gpd.read_parquet('map/graphs/Chicago_nodes.parquet')
edges = gpd.read_parquet('map/graphs/Chicago_edges.parquet')

print(nodes.head())   # 查看前几行节点
print(edges.head())   # 查看前几行边
print(f"节点数: {len(nodes)}, 边数: {len(edges)}")

还原成 NetworkX 图(供算法直接使用)

import osmnx as ox
import geopandas as gpd

nodes = gpd.read_parquet('map/graphs/Chicago_nodes.parquet')
edges = gpd.read_parquet('map/graphs/Chicago_edges.parquet')

# 恢复 MultiIndex(u, v, key)
edges = edges.set_index(['u', 'v', 'key'])

# 还原为 NetworkX 有向图
G = ox.graph_from_gdfs(nodes, edges)

# 然后就可以跑算法了
import networkx as nx
path = nx.shortest_path(G, source=节点A_id, target=节点B_id, weight='length')

只用 pandas(不需要地理功能)

import pandas as pd

edges = pd.read_parquet('map/graphs/Chicago_edges.parquet')

# 只看边的长度和道路类型
print(edges[['u', 'v', 'length', 'highway']].head(10))

六、数据来源

所有数据来自 OpenStreetMap(OSM),通过 osmnx 库自动下载。

  • OSM 是"地图界的维基百科",全球志愿者共同维护,开源免费
  • 数据使用 ODbL 协议(开放数据库许可证),学术和非商业用途无限制
  • 不同城市的数据质量有差异:欧美城市覆盖非常完整,非洲部分城市可能有缺失

最后更新:2026-05-30