无论是前端或是后端,在日常开发中,或多或少都会接触 GIS 相关的业务或者功能开发。很多没有接触过GIS的,或者没有接触过打算接触的开发者可能会在工作闲暇之余思考,什么是 GIS ? 怎么会有这么多类型的 GIS 数据格式?为什么有这么多不同名称的坐标系?本文将从 GIS 的定义、数据格式、坐标系、地图瓦片、常用工具和地图常见错误这几个方面进行介绍。
以上这些概念在博主专栏《GIS入门笔记》也都有对应详细的科普文章,有兴趣的同学们可以订阅一下看看,作为参考。
什么是GIS?
GIS 是地理信息系统的简称。
ESRI 对GIS的解释:
地理信息系统 (GIS) 是一个创建、管理、分析和绘制所有类型数据的系统。GIS 将数据连接到地图,将位置数据(事物所在位置)与所有类型的描述性信息(事物在该位置的情况)集成到一起。这可以为适用于自然科学和几乎所有行业的制图和分析提供基础。GIS 帮助用户了解模式、关系和地理环境。其优势包括改善沟通、提高效率以及更好地管理和决策。
在科技飞速发展的今天,我们几乎每天都在跟位置信息打交道。无论是日常通勤中的开车或者打车,还是餐饮外卖,又或是电商购物、收发快递等等,都离不开位置信息。而 GIS
就是关于位置的一门学科。GIS
学科帮助我们更好地利用地理空间数据与其他行业的技术相结合,GIS
的应用面非常广泛,几乎能与各行各业相结合衍生出很多应用方向。
常见的GIS格式?
那么到底常见的 GIS 数据格式有哪些呢?
- 首先 GIS 数据分为
矢量
和栅格
,栅格这里就不讲了,可以理解为图片像素类的数据都可称为栅格数据,矢量主要常见的有以下几种:
ShapeFile
这个格式是 ESRI
(美国环境系统研究所,相当于设计圈的 adobe 公司的地位吧)研制的一种工业界的标准交换格式,几乎所有的开源及商业软件均支持,感兴趣的可以官方的ShapeFile文件的白皮书 https://www.esri.com/content/dam/esrisites/sitecore-archive/Files/Pdfs/library/whitepapers/pdfs/shapefile.pdf ,它必须至少由三个文件组成:.shp 要素几何
、.shx 形状索引
、.dbf 属性数据
,通常还会包含以下文件:.prj 投影
描述:
因此 shapefile 是表示一组文件的集合,所以在使用的过程中通常以压缩包的形式存在,切记拷贝的时候别只拷贝了一个文件!不过这种格式虽然作为标准格式但是也有着一些缺点,通常我们程序员们并不是很偏爱这个格式,这里就不过多介绍。使用上可以通过 https://github.com/calvinmetcalf/shapefile-js 等诸多开源库进行转换到
GeoJSON
进行使用。
GeoJson
这是我们GIS开发人员最常接触的格式了,GeoJSON
使用 JSON
的数据格式来表达地理数据,所以它本质上还是 JSON
,只不过遵循特定的规范罢了,所以不要觉得它很长很难读,只要理解了其结构原理之后,它对你来说就是再普通不过了。GeoJSON
规范上描述有很多,这里不一一赘述,我们来讲一下最常用的格式要素集(FeatureCollection
):
GeoJSON
原则上包含类型type
描述,要素集(FeatureCollection
) 顾名思义也就是要素(Feature
)的集合(Collection
),所以其类型(type
)为 FeatureCollection
,既然是要素(Feature
)的集合,自然是有 features 这个属性,那么何为要素(Feature
)呢?看下图:
其实要素(Feature
)也就是几何(Geometry
)加属性(Properties
),为什么这么说?比如我们要去公司,那么公司的这个位置就是一个点的几何(Geometry
),它是一个类型(type)为点(Point)的数据,我们对它的坐标(coordinates
)可以使用 [经度,纬度] 来表示这个点,它的名称(name)就是其一个属性,当然它可以拥有一堆属性,使用key-value
的格式进行描述即可。
相信读到这里,大家可以对这类我们常用的要素集(FeatureCollection
) 形式的GeoJSON
格式有一定的了解了,“属性(Properties
)”大家可以理解,那么几何(Geometry
)类型那么多,如何去描述线以及面呢?
GeoJSON 支持以下要素类型:
- 点(包括地址和位置)
- 线段(包括街道、公路和边界)
- 面(包括国家/地区、省和土地区块)
- 点、线或面要素的多部分集合
可以参考下面两张图:
在 GeoJSON
矢量数据使用坐标对(coordinates
)来描述几何图形的组成(以下均以经纬度坐标做讲解)
点(Point)
使用 [经度,纬度]来描述点的横纵坐标,在实际工作中我们很容易搞反这个经纬度,首先要记住经度(longitude)范围是[-180,180]
,纬度(latitude)范围是[-90,90]
,那么大于90
或者小于90
的一定不会是纬度,另外我们中国所覆盖的范围大约是经度73.66~135.05
,纬度3.86~53.55
,因此在国内项目上可以通过坐标范围来判定经纬度顺序,习惯上经度缩写为lng(取巧的记法就是,一般在国内很多地方情况下长(long)的为经度!),纬度缩写为lat。
线(LineString)
按照我们平时绘制折线的画法一样,一个点接着一个点的绘制,用
GeoJSON
的表达上就是一堆具有顺序的点 [[lng1,lat1],[lng2,lat2],[lng3,lat3]]
的集合
面(Polygon多边形)
在存储表达上跟线很像,比线多了一层[ ],细心的朋友可以发现其第一个点跟最后一个点是相同的,其实想想很容易明白,首尾相接的线段可不就是围成了一个面嘛,那为啥会多出一层呢?因为我们日常接触的面还会有中间带孔洞的形式,例如行政区划中很特殊的人文现象——飞地,这里比较有特色的就是黑龙江在内蒙古境内大兴安岭的一块飞地——加格达奇区。下图内蒙古红框镂空处就是黑龙江的飞地-加格达奇区:
另外,最新的 GeoJSON
规范上规定了第一个面必须是外环,其他的为内环,并且新的标准还规定了其必须遵循右手法则,也就是说,外环为逆时针方向,孔为顺时针方向,这块在使用 d3
或者在 WebGL
中使用一定要注意。
需要注意一点是,虽然要素集(
FeatureCollection
)并没有去约束存储的要素的几何类型,但是还是强烈建议大家在使用的时候,一个要素集(FeatureCollection
)尽量存放同一种几何类型,避免点线面共存的情况。更多详细的GeoJSON
格式介绍可以看 rfc7946 规范 https://datatracker.ietf.org/doc/html/rfc7946
TopoJSON
TopoJSON
是 d3.js 作者发明的一种针对 GeoJSON
的紧凑的压缩格式,虽然在可读性上降低了,但是可以有效减少数据大小,并且保证拓扑上的正确,因其在编码的时候有效消除了冗余,通过共享边的形式存储,并且在存储上可以对整数坐标采用量化压缩,在简化数据需要保证原拓扑关系的时候相当有用,这里不再赘述,更多介绍可以查看作者的 https://github.com/topojson/topojson 这个库。
WKT/WKB
WKT(Well-known Text) 使用文本表达几何对象的一种标记语言。WKB(Well-known Binary) 使用二进制表达几何对象的一种标记语言。
- 下图分表是使用WKT与GeoJSON分别描述同一几何的差异:
可以看出其主要还是为了表达几何对象,相较 GeoJSON 而言,其无法存储属性数据,这种数据格式在很多数据库中都用以表达几何数据类型,日常开发中可以方便地使用 https://github.com/cschwarz/wkx 来进行格式转换。
KML/KMZ
Keyhole Markup Language,谷歌地球等使用 xml 来表达地理数据的一种格式,这里我们只要知晓这种格式即可,不常用,如果遇到可以通过 https://github.com/mapbox/togeojson 来进行转换。
常见坐标系
可以说坐标系也是理解 GIS 数据的一个很头疼的问题,这还仅仅只是我们在非专业 GIS 系统中接触到一部分就很让人晕头转向,比如:
那么结合这张图带大家梳理一下这些常见的坐标系:坐标系——一种用于表示地理要素、影像和观察值位置的参照系统,为定义真实世界的位置提供了框架。类型上又分为:
1. 地理坐标系
基于球体或旋转椭球体,地理坐标系(GCS)使用三维球面来定义地球上的位置,通常我们使用经纬度来表达位置。
2. 投影坐标系
由于地球是一个球面,而地图受限于存储介质(纸张、沙盘、书本、屏幕)原因,需要使用二维平面来表达三维的地球,而将地球表面展开成地图平面必然会产生裂隙或褶皱,因此需要采用一定的数学方法将曲面展成平面,而且使其变形较小,这就是投影坐标系的意义所在。%0D%0A%0D%0A投影坐标系在二维平面中进行定义,投影坐标系始终基于地理坐标系,通过格网上的 x,y 坐标来标识位置,其原点位于格网中心。每个位置均具有两个值,这两个值是相对于该中心位置的坐标。一个指定其水平位置,另一个指定其垂直位置,在二维空间范围内,投影坐标系的长度、角度和面积恒定。
这里帮大家理一下关系:WGS84 通过国测局一次加密偏移后为 GCJ02(国测局2002)坐标系,BD09在此基础上进行了二次加密,而国家大地2000(CGCS2000)则是我们国家目前在推的标准规范平时精度要求不高,我们可以约等同于 WGS84。
- 投影坐标系:主流是墨卡托(Mercator)投影,另外有经纬度投影,主要被国家天地图所使用
- 墨卡托(Mercator)投影,又名“等角正轴圆柱投影”,荷兰地图学家墨卡托(Mercator)在1569年拟定,假设地球被围在一个中空的圆柱里,其赤道与圆柱相接触,然后再假想地球中心有一盏灯,把球面上的图形投影到圆柱体上,再把圆柱体展开,这就是一幅标准纬线为零度(即赤道)的“墨卡托投影”绘制出的世界地图。
首先我们看看真实的地球:
而 Web 墨卡托则是墨卡托投影的一种变体,将表示地球的参考椭球体也就是上图真实的🌏近似的作为正球体(一个标准的地球半径球)处理来方便进行投影,如下图:
其优点是一种等角投影可以保证方向的正确,因此广泛用于导航海航,但是缺点在纬度越高变形越大:
最先由谷歌地图进行使用,现在被广泛使用,如高德地图、腾讯地图、天地图web墨卡托版、mapbox 等。
早期谷歌给取了一个叫
EPSG:900913
的Code,仔细看 900913 是不是很像 google,后来EPSG协会又使用过EPSG:3785
和EPSG:3857
,包括 ArcGIS 使用过ESRI:102100
及ESRI:102113
来表示它,不过目前我们广泛还是使用EPSG:3857
来描述,对 Web 墨卡托感兴趣的还可以看看博主的《Web墨卡托投影介绍》 有更为详细的介绍。通过以上介绍,再回看开始的那张图是不是可以理解一部分相关坐标系的基本知识啦!
地图瓦片
为什么要使用地图瓦片?
地理数据本身的大数据属性,如此大的数据量自然无法一次在客户端很好的呈现,那么为了解决这样的问题,谷歌推出了栅格切片技术,通过在空间上分层(不同层级展示不同粒度的数据)、平面上分块(只展示感兴趣区域内的的数据),并且按照制定的规则在服务器端预先切好这些数据瓦片进行分发,通过客户端来调度这些瓦片的展示,这也就是我们经常看到的地图能快速展示的原因。
总结一下这种方案的优点:
-
- 按需渐进加载
-
- 高效缓存提升显示效率
-
- 加载简单,跨终端设备(桌面、移动端)
-
- 传输高效、减少服务端压力%0D%0A5. 原始数据保密
什么是地图切片?
采用预生成的方法存放在服务器端,然后根据用户提交的不同请求,把相应的地图瓦片发送给客户端的过程,它是一种多分辨率层次模型(LOD),从瓦片金字塔底层到顶层,分辨率越来越低,但表示的地理范围不变。
常见切片规范
- 谷歌XYZ:Z 表示缩放层级,XY 的原点在左上角,X 从左向右,Y 从上向下
- TMS:OGC 标准,Z的定义与谷歌相同,XY 的原点在左下角,X 从左向右,Y 从下向上
- QuadTree:微软 Bing 地图使用的编码规范,Z的定义与谷歌相同,同一层级的瓦片不用 XY 两个维度表示,而只用一个整数表示,该整数服从四叉树编码规则
- 百度XYZ:Z 从1开始,在最高级就把地图分为四块瓦片,XY 的原点在经度为0纬度为0的位置,X 从左向右,Y 从下向上
google切片方案:
百度切片方案:
常见切片规范的瓦片序号对比
常见地图瓦片地址
可以将上述地址放到《OpenLayers6入门,OpenLayers加载离线瓦片xyz地图,vue项目如何使用离线瓦片》的代码中替换一下就可以看到地图。
常见工具推荐
-
QGIS
桌面级开源 GIS 软件,可以说是开源的 ArcGIS,类似于设计师的 Photoshop,日常可以方便地使用它来进行数据生产、编辑、处理、制图。 -
mapshaper
在线使用 https://mapshaper.org/ ,也可以通过 npm install -g mapshaper 离线使用,可以方便的进行 geojson、topojson、shapefile 显示及转换,当然这不是它最强大的地方,它强大之处在于可以方便的进行可视化的简化地理数据,这还只是它的一个最常用的能力,它还有更多功能等待你的挖掘。 -
GDAL
可以说是 GIS 底层人人必会的 GIS 库,使用 C++ 编写,使用上也有 Python 和 Node 的绑定库,这里不对此赘述。 -
ogr2ogr
安装 GDAL 的时候一般带的工具命令库,几乎支持任意地理格式之间的转换,例如转换 shp 到 geojson 仅需下面的一条命令即可将 building.shp 文件保留height、type字段并转换为坐标精度保留六位小数的geojson格式。