地理空间数据基础

做地图可视化,第一件事就是搞懂地理空间数据。说白了,就是弄清楚「地球上的某个点,在计算机里怎么表示、怎么存、怎么用」。我刚开始接触这块时,也被一堆术语搞得头晕——经纬度、坐标系、GeoJSON……今天咱们一个一个捋清楚。

核心要点:地理空间数据的本质,就是用数字描述地球上的位置和形状。经纬度是基础,数据格式是载体,坐标系是规则。

经纬度坐标系——地球的「网格」

经纬度,大家中学地理都学过。但做开发时,有几个细节我吃过亏。

经度(Longitude):范围 -180° 到 180°,东经为正,西经为负。
纬度(Latitude):范围 -90° 到 90°,北纬为正,南纬为负。

嗯,这里要注意:顺序问题。很多新手会搞混。在 GeoJSON 标准里,顺序是 [经度, 纬度],也就是 [lng, lat]。但有些库(比如某些老版本的地图 API)用的是 [lat, lng]。我曾经因为这个顺序搞反,画出来的点跑到了非洲……排查了半天。

我的习惯:写代码时,我会在注释里明确标注「经度在前,纬度在后」,或者直接用命名参数。避免自己坑自己。

常见地理数据格式

实际项目中,地理数据不会只传一对经纬度。我们需要一种结构化的方式,来描述点、线、面,以及它们的属性。下面这三种格式,你一定会遇到。

GeoJSON——最通用的格式

GeoJSON 是基于 JSON 的轻量级格式。我特别喜欢它,因为前端直接就能用,不需要额外解析。

一个典型的 GeoJSON 长这样:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [116.397, 39.908]
      },
      "properties": {
        "name": "天安门",
        "city": "北京"
      }
    }
  ]
}

支持的类型有:Point、MultiPoint、LineString、MultiLineString、Polygon、MultiPolygon。说白了,点、线、面都能表达。

避坑指南:我曾经处理过一个 200MB 的 GeoJSON 文件,浏览器直接卡死。后来发现,数据量大的时候,GeoJSON 的冗余度很高。建议用 TopoJSON 或者服务端切片。

Shapefile——GIS 界的「老大哥」

Shapefile 是 ESRI 公司推出的格式,虽然名字叫「文件」,其实是一组文件的集合。至少需要 .shp(几何数据)、.shx(索引)、.dbf(属性数据)三个文件。

说实话,Shapefile 在 Web 开发中不太常用。因为它是二进制格式,前端不能直接解析。但如果你做后端数据处理,或者跟 GIS 系统对接,就绕不开它。

我一般用 Python 的 geopandas 库来读取:

import geopandas as gpd

gdf = gpd.read_file("path/to/file.shp")
print(gdf.head())

TopoJSON——更聪明的编码

TopoJSON 是 GeoJSON 的「压缩版」。它把共享的边界只存一次,而不是每个多边形都存一遍。你想想看,如果两个相邻的省份,它们的边界线是重合的。GeoJSON 会存两次,TopoJSON 只存一次。

实际效果:文件体积能减少 50%-80%。我在做全国地图时,用 TopoJSON 替代 GeoJSON,加载速度明显提升。

坐标参考系统(CRS)

这个问题,很多人一开始会忽略。为什么?因为大部分 Web 地图(比如 Leaflet、Mapbox)默认用的是 WGS 84 坐标系,也就是 GPS 用的那个。但如果你做专业 GIS 分析,或者对接国内的数据,事情就复杂了。

常见的 CRS 有:

EPSG 编码 名称 用途
4326 WGS 84 GPS、Web 地图通用
3857 Web Mercator Google Maps、OpenStreetMap
4490 CGCS2000 中国国家大地坐标系
4547 高斯-克吕格投影 中国大比例尺地形图

为什么会这样?因为地球是椭球体,地图是平面。从椭球到平面,需要「投影」。不同的投影,适用于不同的场景。

我的建议:做 Web 可视化,统一用 EPSG:4326 存数据,用 EPSG:3857 渲染。后端分析时,再根据需求做投影转换。Python 里用 pyproj 或 geopandas.to_crs() 就能搞定。

地理编码与逆地理编码

这两个概念,说白了就是「地址 ↔ 坐标」的互相转换。

  • 地理编码:把「北京市东城区东长安街」变成 [116.397, 39.908]
  • 逆地理编码:把 [116.397, 39.908] 变成「北京市东城区东长安街」

实际项目中,我经常用地理编码来处理用户输入的地址。比如用户填了个「朝阳区望京SOHO」,我需要把它变成坐标点,才能在地图上展示。

常用的服务有:

  • 高德地图 API(国内数据最准)
  • 百度地图 API(有自己的坐标系,需要偏移)
  • Nominatim(OpenStreetMap 的免费服务,适合全球数据)

注意:不同厂商的坐标系不一样。高德用的是 GCJ-02(火星坐标系),百度用的是 BD-09。如果你混用,坐标会偏移几百米。我曾经踩过这个坑,后来统一用高德的数据源,再用 coordTransform 库做转换。

知识体系总览

下面这张图,帮你把本章的核心逻辑串起来:

地理空间数据知识体系 经纬度坐标系 常见数据格式 坐标参考系统 (CRS) 地理编码 GeoJSON Shapefile TopoJSON WGS 84 Web Mercator CGCS2000 正向编码 逆编码 核心:用数字描述地球上的位置和形状 经纬度是基础 → 格式是载体 → 坐标系是规则

嗯,总结一下。地理空间数据这块,说白了就是三件事:用什么坐标(经纬度)、怎么存(GeoJSON 等格式)、怎么转(CRS 和编码)。把这些搞清楚了,后面的地图可视化就顺了。

可可精品资料库