在我们的项目中,经常会用到基于 Gis 地图的应用开发,地图在项目中主要用于两个方面:

  1. 大屏可视化应用:

此类应用居多,一般将地图置于应用中心,展示某一城市/区域的地理元素(点位、线路、区域)。可视化地图应用对地图风格展示要求比较高,并支持对图上资源的拾取,联动交互等功能。

  1. 基于地图的业务应用:

此类应用主要用于交警、交通、公安、园区类等业务中,地图作为业务的一个支撑,不仅要展示基本的地理元素,大多数时候还有标绘等功能。此类应用中地图不仅做展示,也相当工具(按照区域查找监控点,区域碰撞等)。
不管是哪种应用,我们经常会接触到 Gis 的一些基本概念,本案例主要在 Gis 数据格式方面做一些总结,便于大家更好地理解 Gis系统,从而更好地使用如Hmap、MineMap、SuperMap 等地图引擎。

先了解下什么是 GIS ?

GIS 是地理信息系统的简称,我们可以参考 ESRI 对它的解释:

地理信息系统 (GIS) 是一个创建、管理、分析和绘制所有类型数据的系统。GIS 将数据连接到地图,将位置数据(事物所在位置)与所有类型的描述性信息(事物在该位置的情况)集成到一起。这可以为适用于自然科学和几乎所有行业的制图和分析提供基础。GIS 帮助用户了解模式、关系和地理环境。其优势包括改善沟通、提高效率以及更好地管理和决策。

GIS 就是这样的一门工具学科,来帮助我们更好地利用空间数据与其他行业技术进行结合,从而进行有效而强大的辅助决策及管理应用,其应用面非常广泛,几乎能与各行各业相结合衍生更多应用方向。


常见的 GIS 数据格式

GIS 数据分为矢量和栅格。
栅格:图片类的数据都可称为栅格数据。
image.png
矢量主要常见的有以下几种:

1. ShapeFile

该格式是 ESRI(美国环境系统研究所)研制的一种工业界的标准交换格式,几乎所有的开源及商业软件均支持,感兴趣的可以参考官方的ShapeFile文件的白皮书
https://www.esri.com/content/dam/esrisites/sitecore-archive/Files/Pdfs/library/whitepapers/pdfs/shapefile.pdf
它必须至少由三个文件组成:.shp 要素几何、.shx 形状索引、.dbf 属性数据,通常还会包含以下文件:.prj 投影描述:
Gis地图常见数据格式总结 - 图2
因此 shapefile 是表示一组文件的集合,所以在使用的过程中通常以压缩包的形式存在,切记拷贝的时候别只拷贝了一个文件,不然会文件缺失而无法正确识别!
使用上可以通过 https://github.com/calvinmetcalf/shapefile-js 等开源库,转换成 GeoJSON 进行使用。

2. GeoJSON

这个就是我们开发人员最常接触的格式了,GeoJSON 使用 JSON 的数据格式来表达地理数据,所以它本质上还是 JSON,只不过遵循特定的规范罢了,所以不要觉得它很长很难读,只要理解了其结构原理之后,它对你来说就是再普通不过了。GeoJSON 规范上描述有很多,这里不一一赘述,我们来讲一下最常用的格式要素集(FeatureCollection):
Gis地图常见数据格式总结 - 图3

GeoJSON 原则上包含类型type描述,要素集(FeatureCollection) 顾名思义也就是要素(Feature)的集合(Collection),所以其类型(type)为 FeatureCollection,既然是要素(Feature)的集合,自然是有 features 这个属性,那么何为要素(Feature)呢?
Gis地图常见数据格式总结 - 图4
其实要素(Feature)也就是几何(Geometry)加属性(Properties)。
比如我们要找一个监控点,那么监控点这个位置就是一个点的几何(Geometry),它是一个类型(type)为点(Point)的数据,我们对它的坐标(coordinates)可以使用 [经度,纬度] 来表示这个点,它的名称(name)就是其一个属性,当然它可以拥有一堆属性,使用key-value的格式进行描述即可。

那么几何(Geometry)类型那么多,如何去描述线以及面呢?
GeoJSON 支持以下要素类型:

  • 点(包括地址和位置)
  • 线串(包括街道、公路和边界)
  • 面(包括国家/地区、省和土地区块)
  • 点、线或面要素的多部分集合

可以参照下面这两个图来看:
简单几何
多部件几何
在 GeoJSON 矢量数据中,使用坐标对(coordinates)来描述几何图形的组成(以下均以经纬度坐标做示例):

点(Point):
Gis地图常见数据格式总结 - 图7

使用 [经度,纬度]来描述点的横纵坐标,在实际工作中我们很容易搞反这个经纬度,首先要记住经度(longitude)范围是[-180,180],纬度(latitude)范围是[-90,90],那么大于90或者小于90的一定不会是纬度,另外我们中国所覆盖的范围大约是经度73.66~135.05,纬度3.86~53.55,因此在国内项目上可以通过坐标范围来判定经纬度顺序,习惯上经度缩写为lng(取巧的记法就是,一般在国内很多地方情况下长(long)的为经度!),纬度缩写为lat。

线(LineString):
Gis地图常见数据格式总结 - 图8

按照我们平时绘制折线的画法一样,一个点接着一个点的绘制,用 GeoJSON 的表达上就是一堆具有顺序的点 [[lng1,lat1],[lng2,lat2],[lng3,lat3]] 的集合。

面(Polygon):
Gis地图常见数据格式总结 - 图9

在存储表达上跟线很像,比线多了一层数组**[]**,细心的话,可以发现其第一个点跟最后一个点是相同的,其实就是首尾相接的线段围成了一个面,那为啥会多出一层呢?因为我们日常接触的面还会有中间带孔洞的形式,例如行政区划中很特殊的人文现象——飞地,这里比较有特色的就是黑龙江在内蒙古境内大兴安岭的一块飞地——加格达奇区。下图内蒙古红框镂空处就是黑龙江的飞地-加格达奇区:
内蒙古
黑龙江

另外,最新的 GeoJSON 规范上规定了第一个面必须是外环,其他的为内环,并且新的标准还规定了其必须遵循右手法则,也就是说,外环为逆时针方向,孔为顺时针方向,这块在使用 d3 或者在 WebGL 中使用一定要注意。

需要注意一点是,虽然要素集(FeatureCollection)并没有去约束存储的要素的几何类型,但是还是强烈建议大家在使用的时候,一个要素集(FeatureCollection)尽量存放同一种几何类型,避免点线面共存的情况。

3. TopoJSON

TopoJSON 是 d3.js 作者发明的一种针对 GeoJSON 的紧凑的压缩格式,虽然在可读性上降低了,但是可以有效减少数据大小,并且保证拓扑上的正确,因其在编码的时候有效消除了冗余,通过共享边的形式存储,并且在存储上可以对整数坐标采用量化压缩,在简化数据需要保证原拓扑关系的时候相当有用。因为我们实际项目中使用不多,这里不再赘述,更多介绍可以查看作者的 https://github.com/topojson/topojson 这个库。

4. WKB/WKT (Well-known text)

WKT(Well-known Text) 使用文本表达几何对象的一种标记语言。
WKB(Well-known Binary) 使用二进制表达几何对象的一种标记语言。

表格中,是 WKT 与 GeoJSON 分别描述同一几何的差异:
Gis地图常见数据格式总结 - 图12

可以看出其主要还是为了表达几何对象,相较 GeoJSON 而言,其无法存储属性数据,这种数据格式在很多数据库中都用以表达几何数据类型,日常开发中可以方便地使用 https://github.com/cschwarz/wkx 来进行格式转换。

5. KML/KMZ

Keyhole Markup Language,谷歌地球等使用 xml 来表达地理数据的一种格式,这里我们只要知晓这种格式即可,不常用,如果遇到可以通过 https://github.com/mapbox/togeojson 来进行转换。