Cesium 中的数据加载

Cesium 中的数据加载

我们在之前的 Cesium 入门 章节当中介绍了 Cesium 的基本使用方式,我们知道了如何使用 Cesium 去实例化一个干净的地球实例,本章当中我们就更进一步,来看看如何使用 Cesium 来加载各种数据

我们会从基础的影像数据、地形图数据,到矢量数据、空间可视化实体数据,以及三维方面的模型数据和瓦片数据来分类进行介绍,下面我们就先从最为基础的影像数据加载开始看起

加载影像数据

我们都知道,无论是二维地图还是三维地图,如果缺少了底图影像或电子地图,都是不完整的,Cesium 为我们提供了 ImageryLayerCollectionImageryLayer 以及相关的 ImageryProvider 类来加载不同的影像图层,虽然 Cesium 把此类图层叫做 Imagery*,但并不是特指卫星影像数据,还包括一些互联网地图、TMSWMSWMTS、单个图片等

ImageryLayer 类

Cesium.ImageryLayer 类用于表示 Cesium 中的影像图层,它就相当于皮毛、衣服,将数据源包裹在内,它需要数据源(imageryProvider)为其提供内在丰富的地理空间信息和属性信息,同时通过该类还能设置影像图层相关属性,比如透明度、亮度、对比度、色调等

ImageryProvider 类

我们可以将 ImageryProvider 看作是影像图层的数据源(包裹在 ImageryLayer 类内部),我们想使用哪种影像图层数据或服务就用对应的 ImageryProvider 子类去加载就行,目前 Cesium 提供了以下 14ImageryProvider,如下图所示

每个类别的含义简介如下,我们会在后面分条目来详细进行介绍

  • ArcGisMapServerImageryProvider - ArcGIS OnlineServer 的相关服务
  • BingMapsImageryProvider - Bing 地图影像,可以指定 mapStyle,详见 BingMapsStyle
  • GoogleEarthEnterpriseImageryProvider - 企业级服务
  • GridImageryProvider - 展示内部渲染网格划分情况,了解每个瓦片的精细度,便于调试地形和图像渲染问题
  • IonImageryProvider - Cesium Icon 的在线服务,默认全局基础图像图层
  • MapboxImageryProvider - Mapbox 影像服务,根据 mapId 指定地图风格
  • MapboxStyleImageryProvider - Mapbox 影像服务,根据 styleId 指定地图风格
  • OpenStreetMapImageryProvider - OSM 影像服务,根据不同的 url 选择不同的风格
  • SingleTileImageryProvider - 单张图片的影像服务,适合离线数据或对影像数据要求并不高的场景下
  • TileCoordinatesImageryProvider - 渲染每一个瓦片的范围,方便调试
  • TileMapServiceImageryProvider - 根据 MapTiler 规范,可以下载瓦片,发布服务,类似 ArcGIS 影像服务的过程
  • UrlTemplateImageryProvider - 指定 urlformat 模版,方便用户实现自己的 Provider,比如国内的高德,腾讯等影像服务,url 都是一个固定的规范,都可以通过该 Provider 轻松实现,而 OSM 也是通过该类实现的
  • WebMapServiceImageryProvider - 符合 WMS 规范的影像服务都可以通过该类封装,指定具体参数实现
  • WebMapTileServiceImageryProvider - 服务 WMTS 1.0.0 规范的影像服务都可以通过该类实现,比如国内的天地图

ImageryLayerCollection 类

Cesium.ImageryLayerCollection 类是 ImageryLayer 类对象的容器,它可以装载、放置多个 ImageryLayerImageryProvider 类对象,而且它内部放置的 ImageryLayerImageryProvider 类对象是有序的

Cesium.Viewer 类对象中包含的 imageryLayers 属性就是 ImageryLayerCollection 类的实例,它包含了当前 Cesium 应用程序所有的 ImageryLayer 类对象,即所有影像图层,所以 Cesium 中的影像图层可以添加多个

影像亮度调整

这里我们多看一点,就是当我们加载影像后是可以拿到影像实例 imagery 的,此时我们可以通过 brightness 属性来调节影像亮度,取值范围是 0 ~ 1,默认为 1

1
imagery.brightness = 0.9

加载不同类型的影像图层

下面我们就来看看如何使用 Cesium 来加载不同类型的影像图层,根据上面提供的 Provider 可知,目前 Cesium1.75 版本)支持 14 种类型的影像图层

ArcGisMapServerImageryProvider

主要用于加载 ArcGIS 影像,支持 ArcGIS OnlineServer 的相关服务,开篇第一个我们稍微介绍的详细一些,首先新建了一个加载影像图层的数据源 arcgisProvider

1
2
3
4
var arcgisProvider = new Cesium.ArcGisMapServerImageryProvider({
// url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer',
url: 'https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer',
})

但是将数据源添加至 ImageryLayer 类容器进行渲染的话则是有两种方法,第一种是在初始化 viewer 实例时的 options 配置中,我们可以直接在 options 对象的 imageryProvider 属性中放置数据源即可

1
2
3
new Cesium.Viewer('cesiumContainer', {
imageryProvider: arcgisProvider,
})

另一种方式则是使用 viewer 实例中 imageryLayers 属性的 addImageryProvider 方法来添加即可

1
var imagery = viewer.imageryLayers.addImageryProvider(arcgisProvider)

完整代码如下

1
2
3
4
5
6
7
var viewer = new Cesium.Viewer('cesiumContainer')

var arcgisProvider = new Cesium.ArcGisMapServerImageryProvider({
url: 'https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer',
})

viewer.imageryLayers.addImageryProvider(arcgisProvider)

最终的影像效果预览如下

BingMapsImageryProvider

Bing 地图影像,可以指定 mapStyle,详见 BingMapsStyle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var viewer = new Cesium.Viewer('cesiumContainer')

var bingStyle = [
Cesium.BingMapsStyle.AERIAL_WITH_LABELS,
Cesium.BingMapsStyle.COLLINS_BART,
Cesium.BingMapsStyle.CANVAS_GRAY,
Cesium.BingMapsStyle.CANVAS_LIGHT,
Cesium.BingMapsStyle.CANVAS_DARK,
Cesium.BingMapsStyle.ORDNANCE_SURVEY,
Cesium.BingMapsStyle.ROAD,
Cesium.BingMapsStyle.AERIAL,
]

var bingMapProvider = new Cesium.BingMapsImageryProvider({
url: 'https://dev.virtualearth.net',
key: 'AmXdbd8UeUJtaRSn7yVwyXgQlBBUqliLbHpgn2c76DfuHwAXfRrgS5qwfHU6Rhm8',
mapStyle: bingStyle[7],
})

viewer.imageryLayers.addImageryProvider(bingMapProvider)

影像预览如下

GoogleEarthEnterpriseImageryProvider

使用谷歌 Earth 企业 REST API 提供瓦片图像,可与 Google Earth Enterprise3D Earth API 一起使用

1
2
3
4
5
6
7
8
9
10
11
var viewer = new Cesium.Viewer('cesiumContainer')

var geeMetadata = new Cesium.GoogleEarthEnterpriseMetadata(
'http://www.earthenterprise.org/3d'
)

var googleEarthProvider = new Cesium.GoogleEarthEnterpriseImageryProvider({
metadata: geeMetadata,
})

viewer.imageryLayers.addImageryProvider(googleEarthProvider)

因加载谷歌 Earth 的瓦片影像需要翻墙,这里就不展示影像预览了

GridImageryProvider

展示内部渲染网格划分情况,了解每个瓦片的精细度,便于调试地形和图像渲染问题,一般用于开发调试,这里我们就使用 ArcGIS 影像为例

1
2
3
4
5
6
7
8
9
10
11
12
13
var viewer = new Cesium.Viewer('cesiumContainer')

var arcgisProvider = new Cesium.ArcGisMapServerImageryProvider({
url: 'https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer',
})

viewer.imageryLayers.addImageryProvider(arcgisProvider)

var gridImagery = new Cesium.GridImageryProvider()
var gridImageryLayer = viewer.imageryLayers.addImageryProvider(gridImagery)

// 将图层置顶
viewer.imageryLayers.raiseToTop(gridImageryLayer)

影像预览如下

IonImageryProvider

Cesium Icon 的在线服务,默认全局基础图像图层(当前为 Bing Maps

1
2
3
4
5
var viewer = new Cesium.Viewer('cesiumContainer')

viewer.imageryLayers.addImageryProvider(
new Cesium.IonImageryProvider({ assetId: 3954 })
)

影像预览如下

MapboxImageryProvider

Mapbox 影像服务,根据 mapId 指定地图风格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var viewer = new Cesium.Viewer('cesiumContainer')

var mapIds = [
'mapbox.satellite',
'mapbox.streets',
'mapbox.streets-basic',
'mapbox.light',
'mapbox.streets-satellite',
'mapbox.wheatpaste',
'mapbox.comic',
'mapbox.outdoors',
'mapbox.run-bike-hike',
'mapbox.pencil',
'mapbox.pirates',
'mapbox.emerald',
'mapbox.high-contrast',
]

viewer.imageryLayers.addImageryProvider(
new Cesium.MapboxImageryProvider({
mapId: mapIds[0],
accessToken: 'pk.eyJ1IjoibHM4NzAwNjEwMTEiLCJhIjoiY2tqYXZlZ2JrMDI5bTJzcDJmdDNteGhsNyJ9.0wTn4B1ce9Q4U5GnPso5iA',
})
)

影像预览如下

MapboxStyleImageryProvider

Mapbox 影像服务,根据 styleId 指定地图风格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var viewer = new Cesium.Viewer('cesiumContainer')

var styleIds = [
'streets-v11',
'outdoors-v11',
'light-v10',
'dark-v10',
'satellite-v9',
'msatellite-streets-v11',
]

viewer.imageryLayers.addImageryProvider(
new Cesium.MapboxStyleImageryProvider({
styleId: styleIds[0],
accessToken: 'pk.eyJ1IjoibHM4NzAwNjEwMTEiLCJhIjoiY2tqYXZlZ2JrMDI5bTJzcDJmdDNteGhsNyJ9.0wTn4B1ce9Q4U5GnPso5iA',
})
)

影像预览如下

OpenStreetMapImageryProvider

OSM 影像服务,根据不同的 url 选择不同的风格

1
2
3
4
5
6
7
8
9
10
var viewer = new Cesium.Viewer('cesiumContainer')

viewer.imageryLayers.addImageryProvider(
new Cesium.OpenStreetMapImageryProvider({
url: 'https://a.tile.openstreetmap.org/',
minimumLevel: 0,
maximumLevel: 18,
fileExtension: 'png',
})
)

影像预览如下

SingleTileImageryProvider

单张图片的影像服务,适合离线数据或对影像数据要求并不高的场景下

1
2
3
4
5
6
7
var viewer = new Cesium.Viewer('cesiumContainer')

viewer.imageryLayers.addImageryProvider(
new Cesium.SingleTileImageryProvider({
url: './images/worldimage.jpg',
})
)

影像预览如下

TileCoordinatesImageryProvider

展示内部渲染网格瓦片划分情况,包括网格瓦片等级、xy 序号,便于调试地形和图像渲染问题,当然也可以和 GridImageryProvider 一起叠加使用

1
2
3
4
5
6
7
8
9
10
11
12
13
var viewer = new Cesium.Viewer('cesiumContainer')

var imagelayer = new Cesium.SingleTileImageryProvider({
url: './images/worldimage.jpg',
})

viewer.imageryLayers.addImageryProvider(imagelayer)

var tileCoordinates = new Cesium.TileCoordinatesImageryProvider()
var tileCoordinatesLayer = viewer.imageryLayers.addImageryProvider(tileCoordinates)

//将图层置顶
viewer.imageryLayers.raiseToTop(tileCoordinatesLayer)

影像预览如下

TileMapServiceImageryProvider

访问瓦片图的 Rest 接口,瓦片图被转换为 MapTilerGDAL2Tiles

1
2
3
4
5
6
7
8
var viewer = new Cesium.Viewer('cesiumContainer')

var imagelayer = new Cesium.TileMapServiceImageryProvider({
url: '//cesiumjs.org/tilesets/imagery/blackmarble',
maximumLevel: 8,
})

viewer.imageryLayers.addImageryProvider(imagelayer)

因通常使用较少,这里暂时就不展示影像预览了

UrlTemplateImageryProvider

指定 urlformat 模版,方便用户实现自己的 Provider,比如国内的高德,腾讯等影像服务,url 都是一个固定的规范,都可以通过该 Provider 轻松实现,而 OSM 也是通过该类实现的

以下是使用 xyz 方式加载上面加载过的 OSM 影像服务

1
2
3
4
5
6
7
8
var viewer = new Cesium.Viewer('cesiumContainer')

var osmImageryProvider = new Cesium.UrlTemplateImageryProvider({
url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: ['a', 'b', 'c'],
})

viewer.imageryLayers.addImageryProvider(osmImageryProvider)

影像预览如下

这里需要注意参数 subdomains,它表示子域,subdomains 参数数组中的四个值可以替换 url 中的 {s},也就是改变不同的请求 URL,从而提高加载数据的速度

另外也可以加载高德影像,代码如下

1
2
3
4
5
6
7
8
9
10
viewer.imageryLayers.remove(viewer.imageryLayers.get(0))

var imagery = viewer.imageryLayers.addImageryProvider(
new Cesium.UrlTemplateImageryProvider({
maximumLevel: 18, // 最大缩放级别
url: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
style: 'default',
format: 'image/png',
})
)

影像预览如下

WebMapServiceImageryProvider

符合 WMS 规范的影像服务都可以通过该类封装,指定具体参数实现

1
2
3
4
5
6
7
8
9
10
11
12
var viewer = new Cesium.Viewer('cesiumContainer')

var provider = new Cesium.WebMapServiceImageryProvider({
url: 'https://nationalmap.gov.au/proxy/http://geoserver.nationalmap.nicta.com.au/geotopo_250k/ows',
layers: 'Hydrography:bores',
parameters: {
transparent: true,
format: 'image/png',
},
})

viewer.imageryLayers.addImageryProvider(provider)

影像预览如下

WebMapTileServiceImageryProvider

服务 WMTS 1.0.0 规范的影像服务都可以通过该类实现,比如国内的天地图,其中 url 字段中的 tk 为天地图服务 token,去天地图官网注册申请一个即可,下面是加载天地图的影像

1
2
3
4
5
6
7
8
9
10
11
var viewer = new Cesium.Viewer('cesiumContainer')

var tiandituProvider = new Cesium.WebMapTileServiceImageryProvider({
url: 'http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=ebf64362215c081f8317203220f133eb',
layer: 'tdtBasicLayer',
style: 'default',
format: 'image/jpeg',
show: false,
})

viewer.imageryLayers.addImageryProvider(tiandituProvider)

影像预览如下

另外,我们可以发现在加载后的地图上是没有标注的,如果我们需要额外加载标柱,可以像下面这样操作

1
2
3
4
5
6
7
8
9
10
var label = viewer.imageryLayers.addImageryProvider(
new Cesium.WebMapTileServiceImageryProvider({
url: 'http://t0.tianditu.com/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default.jpg' + '&tk=' + '19b72f6cde5c8b49cf21ea2bb4c5b21e',
layer: 'tdtAnnoLayer',
style: 'default',
maximumLevel: 18, // 最大缩放级别
format: 'image/jpeg',
show: false,
})
)

如下是天地图标注预览

加载地形数据

我们在上面介绍了如何使用 Cesium 内置接口来操作影像数据,但是在一些应用场景中我们需要操作地形数据,例如模拟逼真的三维场景、与高程相关的一些空间分析和计算等

为此 Cesium 提供了 TerrainProvider 基类,该 Provider 负责每一个 Tile 对应的地形数据的构建,定义了一套地形 Provider 所需要实现的接口和规范,但本身并不会参与其中的操作,基于此类,Cesium 为我们封装了五个现成的继承类操作地形数据,如下图所示

不过不像我们之前介绍的影像图层有专门的 ImageryLayer 来进行处理,Cesium 中的地形类是直接通过不同的 terrainProvider 来进行控制的,然后把某一个实例化的 terrainProvider 赋值给 Viewer.terrainProvider 来控制地形数据的显隐,所以 Cesium 中的地形图层只能有一个

加载不同的地形数据

Cesium 支持渐进流式加载和渲染全球高精度地形,并且包含海、湖、河等水面效果,相对 2D 地图,山峰、山谷等其他地形特征的更适宜在这种 3D 地球中展示

Cesium 支持两种类型的地形,STK World TerrainSmall Terrain,不过针对于这两种类型的地形,我们在这里不做过多的介绍,可以参考 这篇文章 来了解更多

地形数据集是巨大的,通常都是 GB 或者 TB 级别,在普通 3D 引擎中,使用底层图形 API 去高效实现地形数据的可视化需要做很多事情,幸好 Cesium 已经帮助我们完成了这个体力活,我们只需要写几行代码就可以实现对应的功能,而这些都是 terrainProvider 的功劳,下面我们就来主要看看 Cesium 中常用的三个 terrainProvider

EllipsoidTerrainProvider

EllipsoidTerrainProviderGlobe 默认采用的地形 Provider,该 Provider 不支持水面,没有法向量,所以即使开启光照,对 Tile 也是无效的,但是它提供了一个全球范围内高度为 0 的地形,不需要额外的地形文件,就可以实时的自己来构建这个高度为 0Mesh,对那些没有网络环境,或网络不理想,或不需要地形的应用,EllipsoidTerrainProvider 提供了最简单的,无需额外负担的地形数据来构网

另外 EllipsoidTerrainProvider 具有其它 terrainProvider 不具备的属性 tileScheme,该属性是 Provider 内部地球网格的剖分方式,通常是 WGS84 坐标,也可以选择墨卡托坐标系,Cesium 中目前支持 WGS1984 和墨卡托投影两种

TerrainImagery 分别采用自己的 TileScheme,比如目前 Terrain 默认采用 WGS1984 的坐标系,这和经纬高的真实数据更接近,而目前 Imagery 影像服务基本都是墨卡托投影

鉴于此,为了使数据的加载性能更好,可以让地形的 TileScheme 和影像的保持一致,都设置成墨卡托投影

1
2
3
var ellipsoidProvider = new Cesium.EllipsoidTerrainProvider()

viewer.terrainProvider = ellipsoidProvider

ArcGISTiledElevationTerrainProvider

ArcGIS 的地形,这个可以说是一个真实的(凹凸的)高度图,原理和 EllipsoidTerrainProvider 如出一辙,因此同样的不支持法线,水面,但可以选择 TileScheme,与 EllipsoidTerrainProvider 不一样之处在于每一个切片会根据 ArcGIS 规范请求一张图片,该图片中的像素对应的值就是该像素对应的高度,真的是名副其实的高度图

1
2
3
4
5
6
var terrainProvider = new Cesium.ArcGISTiledElevationTerrainProvider({
url: 'https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer',
token: 'KED1aF_I4UzXOHy3BnhwyBHU4l5oY6rO6walkmHoYqGp4XyIWUd5YZUC1ZrLAzvV40pR6gBXQayh0eFA8m6vPg..'
})

viewer.terrainProvider = terrainProvider

CesiumTerrainProvider

Cesium 标准地形,在该 Provider 中支持两种地形格式,一种是高度图(目前 Cesium 已经废弃 ),另一种则是 TIN 网格的 STK 地形

Cesium 厉害的之处就在于目前采用 STK 的地形服务,并通过 QuantizedMeshTerrainData 封装了 STK 地形数据格式,它的优点是支持水面和法线,同时数据量比较小

1
2
3
4
5
6
7
var terrainProvider = new Cesium.CesiumTerrainProvider({
url: Cesium.IonResource.fromAssetId(3956),
requestWaterMask: true, // 请求水体效果所需要的海岸线数据
requestVertexNormals: true, // 请求地形照明数据
})

viewer.terrainProvider = terrainProvider

加载矢量数据

我们在之前的章节当中介绍了 Cesium 如何加载影像数据和地形数据,本小结当中我们来看一下 Cesium 是如何加载矢量数据的,不过在此之前,我们得先来了解一下什么是矢量数据

矢量数据

矢量数据(Vector Data)是用 xyz 坐标表示地图图形或地理实体位置的数据,一般是通过记录坐标的方式来尽可能将地理实体的空间位置表现的准确无误,常见的矢量数据有点、线、面等格式

我们使用矢量数据的原因就是因为矢量数据具有数据结构紧凑、冗余度低、有利于网络和检索分析、图形显示质量好、精度高等优点,目前最常见的矢量数据格式就是 Shapefile(简称 SHP),它是由 Esri 公司开发的一种空间数据开放格式,同时 Shapefile 也成为了 GIS 行业的标准,几乎所有的商业和开源 GIS 软件都支持 Shapefile,通常情况下一个 Shapefile 通常指带有 .shp.shx.dbf 和其他扩展名且前缀名称一致的文件(.prj.sbn 等)集合

一个 Shapefile 必须包含的文件有下面这些

  • 主文件(*.shp) - 存储地理要素的几何信息
  • 索引文件(*.shx) - 存储要素几何图形的索引信息
  • dBase 表文件(*.dbf) - 存储地理要素的属性信息(非几何信息)

除此之外还有可选的文件有下面这些

  • 空间参考文件(.prj) - 存储空间参考信息,即地理坐标系统信息和投影坐标系统信息,使用 well-known 文本格式(WKT)进行描述
  • 几何体的空间索引文件(.sbn.sbx)、只读的 Shapefiles 的几何体的空间索引文件(.fbn.fbx)等等

只可惜 Cesium 却不能直接加载 .shp 文件,如果想加载 .shp 文件可以参考 CesiumVectorTile 这个库,Cesium 直接支持的矢量数据格式包括 GeoJSONTopoJSONKML 以及具有时间特性的 CZML,并以 DataSouce 后缀去命名相关的类

GeoJSON

GeoJSON 是用于描述地理空间信息的数据格式,它不是一种新的格式,其语法规范是符合 JSON 格式的,只不过对其名称进行了规范,专门用于表示地理信息,GeoJSON 的最外层是一个单独的对象(object),这个对象可表示

  • ① 几何体(Geometry
  • ② 特征(Feature
  • ③ 特征集合(FeatureCollection

最外层的 GeoJSON 里可能包含有很多子对象,每一个 GeoJSON 对象都有一个 type 属性,表示对象的类型,其 type 的值可以是 PointMultiPointLineStringMultiLineStringPolygonMultiPolygonGeometryCollectionFeatureFeatureCollection,下面是一个 GeoJSON 特征集合示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [102.0, 0.5] },
"properties": { "prop0": "value0" }
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[102.0, 0.0],
[103.0, 1.0],
[104.0, 0.0],
[105.0, 1.0]
]
},
"properties": {
"prop0": "value0",
"prop1": 0.0
}
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[100.0, 0.0],
[101.0, 0.0],
[101.0, 1.0],
[100.0, 1.0],
[100.0, 0.0]
]
]
},
"properties": {
"prop0": "value0",
"prop1": { "this": "that" }
}
}
]
}

TopoJSON

TopoJSONGeoJSON 按拓扑学编码后的扩展形式,是由 D3 的作者 Mike Bostock 制定的,相比 GeoJSON 直接使用 PolygonPoint 之类的几何体来表示图形的方法,TopoJSON 中的每一个几何体都是通过将共享边(被称为 arcs)整合后组成的,对比简易图如下

TopoJSON 使用坐标(点)、弧(线、多边形)来表示地理图形,它由 transformobjectsarcs 三部分组成,其中

  • transform 描述了变换参数
  • objects 描述地理实体包含空间及属性信息
  • arcs 描述了有向弧的空间关系,弧由一系列起点及相对于起点的有向偏移坐标表示,基于这种弧的存储方式可以表达出拓扑关系

由于弧只记录一次及地理坐标使用整数,不使用浮点数,相对于 GeoJSONTopoJSON 消除了冗余,文件大小缩小了 80% 左右,不过概念总是那么的抽象,为了表达得更形象些,我们来看下面这个示例

下面的 TopoJSON 在地图上加载后就和上图所呈现效果是一样的,也就是一个长方形和一条直线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
"type": "Topology",
"transform": {
"scale": [1, 1], // 缩放比例
"translate": [0, 0] // 相对于原点([0, 0])的偏移量
},
"objects": {
"two-squares": {
"type": "GeometryCollection",
"geometries": [
{"type": "Polygon", "arcs": [[0, 1]], "properties": { "name": "Left_Polygon" }},
{"type": "Polygon", "arcs": [[2, -1]], "properties": { "name": "Right_Polygon" }}
]
},
"one-line": {
"type": "GeometryCollection",
"geometries": [
{"type": "LineString", "arcs": [3], "properties": { "name": "Under_LineString" }}
]
},
"two-places": {
"type": "GeometryCollection",
"geometries": [
{"type": "Point", "coordinates": [0, 0], "properties": { "name": "Origine_Point" }},
{"type": "Point", "coordinates": [0, -1], "properties": { "name": "Under_Point" }}
]
}
},
"arcs": [
[ [1, 2], [0, -2] ],
[ [1, 0], [-1, 0], [0, 2], [1, 0] ],
[ 1, 2], [1, 0], [0, -2], [-1, 0] ],
[ [0, -1], [2, 0] ]
]
}

下面是一些在线工具推荐

另外,官方提供的示例代码如下

1
2
3
4
5
6
7
8
9
var viewer = new Cesium.Viewer('cesiumContainer')

viewer.dataSources.add(
Cesium.GeoJsonDataSource.load('../../SampleData/ne_10m_us_states.topojson', {
stroke: Cesium.Color.HOTPINK,
fill: Cesium.Color.PINK.withAlpha(0.5),
strokeWidth: 3,
})
)

效果是下面这样的

KML

KML (keyhole markup language)是一种基于 XML 语法格式的文件,用来描述和存储地理信息数据(点、线、面、多边形、多面体以及模型等),通常应用于 Google 地球相关软件中(Google EarthGoogle Map 等),它跟 XML 文件最大的不同就是 KML 描述的是地理信息数据,同时 KML 已正式被 OGC 采用,成为 OGC 众多规范中的一个,KML 文件有两个文件扩展名,分别为 .KML.KMZ(一个或几个 KML 文件的压缩集,采用 zip 格式压缩)

Cesium1.7 版开始就支持 KML,不过目前对 KML 的支持还不完整,但是支持大量的标准以及 Googlegx 扩展名称空间,有关支持哪些内容和不支持哪些内容的详细列表,请参见 KML Support

这里我们直接来看示例,代码如下

1
2
3
4
5
6
7
var viewer = new Cesium.Viewer('cesiumContainer')

Cesium.KmlDataSource.load('../../SampleData/kml/facilities/facilities.kml', {
camera: viewer.scene.camera,
canvas: viewer.scene.canvas,
}
)

效果是下面这样的

CZML

关于 CZML 我们在之前的章节当中已经梳理过了,我们在这里也就只简单的提及一二,CZML 是一种 JSON 格式的字符串,用于描述与时间有关的动画场景,CZML 包含点、线、地标、模型和其他的一些图形元素,并指明了这些元素如何随时间而变化

Cesium 拥有一套富客户端 API,通过 CZML 采用数据驱动的方式,不用写代码我就可以使用通用的 Cesium viewer 构建出丰富的场景,某种程度上说,CesiumCZML 的关系就像 Google EarthKML 的关系,两者都是用于描述其各自客户端中的场景的数据格式,并且旨在由各种各样的应用程序生成,甚至可能是手工编写的

下面是一个典型的 CZML 数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[
// packet one
{
"id": "GroundControlStation",
"position": { "cartographicDegrees": [-75.5, 40.0, 0.0] },
"point": {
"color": { "rgba": [0, 0, 255, 255] }
}
},
// packet two
{
"id": "PredatorUAV",
// ...
}
]

如上 CZML 片段描述了两个数据包,每个数据包都有一个 id 标识它描述的对象的属性,id 不一定要求是 GUID,但它们确实需要唯一地标识 CZML 源中的单个对象,如果 id 未指定,Cesium 将自动生成一个唯一的,但是这会阻止以后的数据包引用该对象,例如向该对象添加更多数据

id 属性之外,还包含更多的属性用于定义要绘制对象的属性,在上面的示例中,我们在 WGS 84(-75.5, 40.0, 0.0) 位置中指定了一个 idGroundControlStation 的对象,并在其位置绘制了一个蓝色的点

详细的数据结构和更多的属性可参考官方提供的 数据结构数据包,这里我们就不详细展开了

另外,CZML 比较特殊的是跟时间序列相关的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
// ...
"someInterpolatableProperty": {
"cartesian": [
"2012-04-30T12:00Z", 1.0, 2.0, 3.0, // 表示当时间为 2012-04-30T12:00Z,坐标为 (1, 2, 3)
"2012-04-30T12:01Z", 4.0, 5.0, 6.0, // 表示当时间为 2012-04-30T12:01Z,坐标为 (4, 5, 6)
"2012-04-30T12:02Z", 7.0, 8.0, 9.0 // 表示当时间为 2012-04-30T12:02Z,坐标为 (7, 8, 9)
]
}
},
{
// ...
"someInterpolatableProperty": {
"epoch": "2012-04-30T12:00Z", // 表示时间起点为 2012-04-30T12:00:00
"cartesian": [
0.0, 1.0, 2.0, 3.0, // 从起点开始,第 0 秒时坐标为 (1, 2, 3)
60.0, 4.0, 5.0, 6.0, // 从起点开始,第 60 秒时坐标为 (4, 5, 6)
120.0, 7.0, 8.0, 9.0 // 从起点开始,第 120 秒时坐标为 (7, 8, 9)
]
}
},
{
// ...
"someInterpolatableProperty": {
"epoch": "2012-04-30T12:00Z",
"cartesian": [
0.0, 1.0, 2.0, 3.0,
60.0, 4.0, 5.0, 6.0,
120.0, 7.0, 8.0, 9.0
],
"interpolationAlgorithm": "LAGRANGE", // 插值算法为 LAGRANGE,还有 HERMITE 和 GEODESIC
"interpolationDegree": 5 // 1 为线性插值,2 为平方插值
},
}

定义了一个 CZML 后,就可以把它载入到场景中,就能获得该对象的动态效果,示例代码如下

1
2
3
4
5
6
7
8
var viewer = new Cesium.Viewer('cesiumContainer', {
animation: true,
shouldAnimate: true,
})

viewer.dataSources.add(
Cesium.CzmlDataSource.load('../../SampleData/Vehicle.czml')
)

下面是加载 Cesium 官网提供的 Vehicle.czml 数据示例的效果,我们可以看到一辆小车正在缓缓移动,可通过动画控制器对小车进行快进、暂停、倒放、回放等等操作

# GIS

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×