# 平台介绍

# Cesium ion

是一个提供瓦片图和3D地理空间数据的平台,Cesium ion支持把数据添加到用户自己的CesiumJS应用中
Cesium ion (opens new window)

# CesiumJS

国外一个基于JavaScript编写的使用WebGL的地图引擎。Cesium支持3D,2D,2.5D形式的地图展示,可以自行绘制图形,高亮区域,并提供良好的触摸支持,且支持绝大多数的浏览器和mobile

# Cesium for Unreal

可以将 3D 真实世界的地理空间数据加载到虚幻引擎中使用,也就是说游戏中虚拟世界它可以来源于我们物理设备采集的真实世界的空间数据
Cesium for Unreal (opens new window)
Cesium for Unreal学习地址 (opens new window)
虚幻引擎 (opens new window)

# 目录介绍

# 跟路径文件

CHANGES.md:Cesium每个版本的变更记录以及每个版本修复了哪些功能
gulpfile.cjs:记录了cesium的所有打包流程
index.html:这个就不用多说了,Web导航首页
package.json:一个用于包的依赖管理文件
README.md:项目的入门手册,里面介绍了整个项目的使用、功能等等
server.cjs:Cesium内置的Node服务器文件,命令npm install、 npm run start

# Apps文件夹

CesiumViewer:一个简单的Cesium初始化示例
SampleData:所有示例代码所用到的数据,如json、geoJson、topojson、kml、czml、gltf、3dtiles等
Sandcastle:Ceisum的示例程序代码就存储在此文件夹里
TimelineDemo:时间轴示例代码

# Build文件夹

Cesium:压缩后的Cesium库,项目中主要使用
CesiumUnminified:未压缩的Cesium库,可用于项目调试
Documentation:API文档目录

# 其他文件夹

Source:Cesium源码,涉及到的所有类的源码和自定义shader(渲染)源码都存储在此文件夹里
Specs:自动化单元测试,Cesium采用了单元测试Jasmine框架 ,可以实现接口的自动化测试
ThirdParty:Cesium中接口实现和单元测试所依赖的外部第三方库,比如代码编辑器codemirror、单元测试框架库jasmine、javascript语法和风格的检查工具jshint等

# viewer参数

animation //默认值:true,是否创建动画小器件,左下角仪表
baseLayerPicker //默认值:true,是否创建右上角底图选择器小部件
fullscreenButton //默认值:true,是否创建右下角全屏按钮小部件
vrButton //默认值:false,是否创建右下角VR按钮小部件
geocoder //默认值:true,是否创建右上角搜索框
homeButton //默认值:true,是否创建主页按钮小部件
infoBox //默认值:true,是否创建信息框小部件
sceneModePicker //默认值:true,是否创建场景模式选择器小部件,3D,2D,哥伦布视图(2.5D)
sceneMode //默认值:SceneMode.SCENE3D,设置初始场景模式,与【sceneModePicker】对应
selectionIndicator //默认值:true,是否创建选择指示符小部件,选中后实体本身会出现一个绿色方块
timeline //默认值:true,是否创建下方时间线小部件
navigationHelpButton //默认值:true,是否创建右上角导航帮助按钮
navigationInstructionsInitiallyVisible //默认值:true,初始化地球时导航说明是否可见
scene3DOnly //默认值:false,是否只使用3D场景,所有几何图形以3D模式绘制以节约GPU资源
shouldAnimate //默认值:false,用来控制是否通过旋转控件,旋转场景,优先级大于clockViewModel
clockViewModel //默认值:new ClockViewModel(clock),设置用于控制当前时间的时钟视图模型
fullscreenElement //默认值:document.body,当全屏按钮被按下时将被置于全屏模式的元素或元素ID。此处注意,这里的默认值是body,也就是说如果三维地球在body下首个div上渲染时才能完成真正的三维地球全屏
selectedImageryProviderViewModel //当前基础影像图层的视图模型,如果未提供,则使用第一个可用的基础图层, 即imageryProviderViewModels 中的第一个。仅当 baseLayerPicker 设置为true时,此值才有效
imageryProviderViewModels //默认值:createDefaultImageryProviderViewModels(),从 BaseLayerPicker 中可选择的 ProviderViewModels 数组。仅当 baseLayerPicker 设置为true时,此值才有效
selectedTerrainProviderViewModel //当前基础地形图层的视图模型,如果未提供,则使用第一个可用的基础图层, 即imageryProviderViewModels 中的第一个。仅当 baseLayerPicker 设置为true时,此值才有效
terrainProviderViewModels //默认值:createDefaultTerrainProviderViewModels(),从 BaseLayerPicker 中可选择的 ProviderViewModels 数组。仅当 baseLayerPicker 设置为true时,此值才有效
imageryProvider //默认值:createWorldImagery(),初始化三维地球时使用的影像提供程序,仅当 baseLayerPicker 设置为false时,此值才有效。此处实测结果是,当 baseLayerPicker 为false时也会生效,只是无法在 baseLayerPicker 所列出图层中显示
terrainProvider //默认值:new EllipsoidTerrainProvider(),初始化三维地球时使用的地形提供程序。如果想要加载官方服务器地形的话,可使用Cesium.createWorldTerrain()函数
skyBox //默认值:无,设置渲染星空的天空盒。如果不设置,则会使用默认的星空,如果设置为false,则不会渲染任何星空,太阳,月亮等
skyAtmosphere //默认值:无,蔚蓝的天空和围绕在三维地球周边的辉光,也就是所谓的大气层
useDefaultRenderLoop //默认值:true,如果需要控制渲染循环
targetFrameRate //默认值:无,控制渲染循环的目标帧率
showRenderLoopErrors //默认值:true,在渲染循环出错时会自动为用户显示一个包含错误信息的html面板
automaticallyTrackDataSourceClocks //默认值:true,则此小部件将自动跟踪新添加的数据源的时钟设置,并在数据源的时钟发生更改时进行更新。如果要独立配置时钟,请将其设置为false
mapProjection //默认是EPSG:4326,即WGS84经纬度投影,new GeographicProjection(),还可以选择EPSG:3875,即WGS84-WEB墨卡托投影,new WebMercatorProjection()
dataSources //默认值:new DataSourceCollection(),小部件可视化的数据源集合
shadows //默认值:false,确定光源是否投射阴影
terrainShadows //默认值:ShadowMode.RECEIVE_ONLY,确定地形是否从光源投射或接收阴影,默认只接收阴影
  ShadowMode.DISABLED //代表物体不接收和投射阴影
  ShadowMode.ENABLED //代表物体接收和投射阴影
  ShadowMode.CAST_ONLY //代表物体只投射阴影
  ShadowMode.RECEIVE_ONLY //代表物体只接收阴影
useBrowserRecommendedResolution //默认值:true,以浏览器推荐的分辨率渲染,并忽略window.devicePixelRatio
contextOptions //默认值:无,传递给场景(scene)的与options相对应的上下文和WebGL创建属性
globe //默认值:new Globe(mapProjection.ellipsoid),场景(scene)中使用的地球仪。如果设置为false,则不会添加地球仪
orderIndependentTranslucency //默认值:true,如果设置为true,并且配置支持它,则使用顺序独立半透明
creditContainer //默认值:无,是否显示版权信息,可以将它赋值给一个空的div的id
creditViewport //默认值:无,包含 CreditDisplay 创建的credit信息弹出窗口的DOM元素或元素ID。如果未指定,则将credit信息添加到小部件上
mapMode2D //默认值:MapMode2D.INFINITE_SCROLL,确定2D地图是否可旋转或可以在水平方向上无限滚动,默认无线卷动
  ROTATE //2D视图下不能无限滚动,但可以绕z轴旋转
  INFINITE_SCROLL //可以无限滚动,但是无法绕z轴旋转
projectionPicker //默认值:false,将创建投影选择器(ProjectionPicker)小部件
requestRenderMode //默认值:false,渲染帧只会在场景中发生变化时才会发生
maximumRenderTimeChange //默认值:0.0,如果 requestRenderMode 为true,这个值定义了在请求渲染之前允许的模拟时间的最大变化

# CesiumWidget模块

实例化Viewer必定会实例化一个CesiumWidget。CesiumWidget实际上代表的是三维数据可视区域,而Viewer除了包括可视区域,还包括各种控件(时间轴、右上角各种按钮、搜索框、时间拨盘等),更像是一个总体承载容器。Viewer能通过extend()方法扩充自定义的控件。

真正使用WebGL绘图的,还不是CesiumWidget模块,而是在CesiumWidget中实例化的Scene模块。 不过,CesiumWidget起了一个桥梁的作用,它将构造时传递的DOM元素(或ID选择器)再内嵌了一个canvas元素,再将此canvas元素传递给Scene,让Scene接着绘图。

CesiumWidget模块

# 坐标介绍

Cesium中常用的坐标系主要有两种:WGS84坐标系和笛卡尔空间直角坐标系

# WGS84坐标系

  • WGS84经纬度坐标系(没有实际的对象)
  • WGS84弧度坐标系(Cartographic)
//longitude, latitude 为弧度,height 为高度meters
new Cesium.Cartographic(longitude, latitude, height)

# 笛卡尔空间坐标系

主要是用来做空间位置的变化如平移、旋转和缩放等等,它的坐标原点在椭球的中心

  • 平面坐标系(Cartesian2):屏幕坐标系
new Cesium.Cartesian2(x, y)
  • 笛卡尔空间直角坐标系(Cartesian3):世界坐标
new Cesium.Cartesian3(x, y, z)
  • 4D笛卡尔坐标系(Cartesian4):三维坐标上增加一行,看作Cartesian3即可,基本无实际运用场景
new Cesium.Cartesian4(x, y, z, w)

# 坐标转换

# 经纬度和弧度的转换

var radians=Cesium.Math.toRadians(degrees) //经纬度转弧度
var degrees=Cesium.Math.toDegrees(radians) //弧度转经纬度

// 圆的周长是半径的 2π倍,所以一个周角(360度)是 2πR
// 半圆的长度是半径的 π倍,所以一个平角(180度)是 πR
// 角度转弧度: π / 180 × 角度
// 弧度变角度: 180 / π × 弧度 

# WGS84经纬度坐标和WGS84弧度坐标系(Cartographic)的转换

//方法一:
var longitude = Cesium.Math.toRadians(longitude1) //longitude1为经度
var latitude= Cesium.Math.toRadians(latitude1) //latitude1为纬度
var cartographic = new Cesium.Cartographic(longitude,latitude,height)

//方法二: longitude和latitude为经纬度
var cartographic= Cesium.Cartographic.fromDegrees(longitude,latitude,height)

//方法三:longitude和latitude为弧度值
var cartographic= Cesium.Cartographic.fromRadian(longitude,latitude,height)

# WGS84坐标系和笛卡尔空间直角坐标系(Cartesian3)的转换

通过经纬度进行转换

//高度默认值为0,可以不用填写;longitude和latitude为经纬度
var position = Cesium.Cartesian3.fromDegrees(longitude,latitude,height)
//coordinates格式为不带高度的数组。例如:[-115.0,37.0,-107.0,33.0]
var positions = Cesium.Cartesian3.fromDegreesArray(coordinates)
//coordinates格式为带有高度的数组。例如:[-115.0,37.0,100.0,-107.0,33.0,150.0]
var positions = Cesium.Cartesian3.fromDegreesArrayHeights(coordinates)

通过弧度进行转换

//通过弧度转换也有上面的3种方法
Cesium.Cartesian3.fromRadians
Cesium.Cartesian3.fromRadiansArray
Cesium.Cartesian3.fromRadiansArrayHeights

//其他方法
Cesium.Cartographic.fromDegrees(longitude,latitude,height)
Cesium.Ellipsoid.WGS84.cartographicToCartesian(position)
Cesium.Ellipsoid.WGS84.cartographicArrayToCartesianArray([position1,position2,position3])

# 笛卡尔空间直角坐标系转换为WGS84

//得到WGS84弧度坐标系
Cesium.Cartographic.fromCartesian(cartesian3)
Cesium.Ellipsoid.WGS84.cartesianToCartographic(cartesian3)
Cesium.Ellipsoid.WGS84.cartesianArrayToCartographicArray([cartesian1,cartesian2,cartesian3])

# 平面坐标系(Cartesian2)和笛卡尔空间直角坐标系(Cartesian3)的转换

  • 平面坐标系转笛卡尔空间直角坐标系

这里注意的是当前的点(Cartesian2)必须在三维球上,否则返回的是undefined;通过ScreenSpaceEventHandler回调会取到的坐标都是Cartesian2

  • 屏幕坐标转场景坐标(获取倾斜摄影或模型点击处的坐标)

这里的场景坐标是包含了地形、倾斜摄影表面、模型的坐标。
通过viewer.scene.pickPosition(movement.position)获取,根据窗口坐标,从场景的深度缓冲区中拾取相应的位置,返回笛卡尔坐标。

var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
     var position = viewer.scene.pickPosition(movement.position);
     console.log(position);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
 
//  注:若屏幕坐标处没有倾斜摄影表面、模型时,获取的笛卡尔坐标不准,
//  此时要开启地形深度检测
//  viewer.scene.globe.depthTestAgainstTerrain = true;默认为false
  • 屏幕坐标转地表坐标(获取加载地形后对应的经纬度和高程)

这里是地球表面的世界坐标,包含地形,不包括模型、倾斜摄影表面

var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
handler.setInputAction(function (movement) {
        var ray = viewer.camera.getPickRay(movement.position)
        var position = viewer.scene.globe.pick(ray, viewer.scene)
        console.log(position)
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// 注:通过测试,此处得到的坐标通过转换成wgs84后,height的为该点的地形高程值。
  • 笛卡尔空间直角坐标系转平面坐标系
//结果是Cartesian2对象,取出X,Y即为屏幕坐标
var cartesian2= Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene,cartesian3)
  • 笛卡尔空间坐标转为屏幕坐标

可以通过场景对象scene的cartesianToCanvasCoordinates 方法进行获取。返回转换成在画布的位置坐标

var position = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
scene.cartesianToCanvasCoordinates(position)

# 计算方法

计算两个三维坐标系之间的距离

var d = Cesium.Cartesian3.distance(
    new Cesium.Cartesian3(pick1.x, pick1.y, pick1.z), 
    new Cesium.Cartesian3(pick3.x, pick3.y, pick3.z)
); //pick1、pick3都是三维坐标系

# 空间位置变换

经纬度转换到笛卡尔坐标系后就能用计算机图形学中的仿射变换知识进行空间位置变换如平移旋转缩放。

Cesium为我们提供了很有用的变换工具类:

  • Cesium.Matrix3:3x3矩阵,用于描述旋转变换
  • Cesium.Matrix4:4x4矩阵,用于描述旋转加平移变换
  • Cesium.Quaternion:四元数,用于描述围绕某个向量旋转一定角度的变换

# 地图纠偏

# 使用cesium接口

在已知地图中心点的坐标偏移经纬度具体数值的基础上,可以使用ImageryProvider的tilingScheme的rectangleNortheastInMeters,rectangleSouthwestInMeters进行设置,实现加载地图时动态纠偏

# 使用插件

直接引入下载的插件打包好的cesium.map.min.js (opens new window)即可

<script src="https://cdn.jsdelivr.net/npm/@dvgis/cesium-map"></script>
// 添加高德地图并使用插件纠偏
viewer.imageryLayers.addImageryProvider(new Cesium.AmapImageryProvider({
    style: 'img',
    crs: 'WGS84'
}));

# 颜色设置

# 创建指定颜色

//cesium使用0-1区间值
var Color = Cesium.Color(1, 0, 0, 1)

//rgba()格式,其中rgba参数取值范围,皆是0-255
var Color = Cesium.Color.fromBytes(5, 28, 74, 255)

//32位GRBA值
var Color = Cesium.Color.fromRgba(0x67ADDFFF)

//HSL 色相角、饱和度值、亮度值、Alpha,cesium使用0-1区间值
var Color = Cesium.Color.fromHsl(1,0.1,0.5,0.5)

//CSS 设置
var Color = Cesium.Color.fromCssColorString('#EDB9B5').withAlpha(0.6)

// 还原
var rgba = Color.toBytes()
var css = Color.toCssColorString()
var hsl = Color.toHsl()

# 创建随机颜色

var Color = new Cesium.Color.fromRandom ({
	minimumRed : 0.75,
	maximumRed : 1,
    minimumGreen : 0.75,
    maximumGreen : 1,
    minimumBlue : 0.75,
    maximumBlue : 1,
    minalpha : 0.5,
    maxalpha : 1.0
})

# 时间转换

朱利安时间格式转为北京时间格式

var 朱利安 = viewer.clock.currentTime; //模拟获取当前时间轴的时间
var 北京时间 = new Date(朱利安.toString());
var 时间戳 = 北京时间.getTime();

北京时间格式转为朱利安时间格式

var 北京时间 = “”;//2022-06-24 13:14:31
var 中国标准时间 = new Date(北京时间)//Fri Jun 24 2022 16:19:05 GMT+0800 (中国标准时间)
var 朱利安 = Cesium.JulianDate.fromDate(中国标准时间);

时间戳转为朱利安时间格式

var 时间戳 = 0//9999999999999
var 中国标准时间 = new Date(时间戳)// Fri Jun 24 2022 16:19:05 GMT+0800 (中国标准时间)
var 朱利安 = Cesium.JulianDate.fromDate(中国标准时间);

# 地形瓦片

高程数据一般是 .tif 文件格式,在应用到 Cesium 前,需要将其转换成瓦片文件。cesium目前支持的格式有下面的两种地形格式,分别是:

  • Quantized-Mesh(推荐使用)
  • HeightMap(已经废弃)

# 地形文件制作有三种途径:

  • 使用 Cesiumlab2 工具进行处理,该软件可生产 Quantized-Mesh 和 HeightMap 两种格式的地形文件
  • 使用 gdal2srtmtiles.py 脚本进行处理,需要安装依赖工具库
  • 使用 Cesium Terrain Builder 开源工具进行处理,需要编译安装相关软件
//Quantized-Mesh数据格式
//http://192.168.2.22:9003/terrain/layer.json 使用的时候去掉layer.json
{"attribution":"http://www.cesiumlab.com","available":[[{"endX":1,"endY":0,"startX":0,"startY":0}],[{"endX":3,"endY":1,"startX":2,"startY":0}],[{"endX":7,"endY":3,"startX":6,"startY":2}],[{"endX":13,"endY":5,"startX":12,"startY":4}],[{"endX":27,"endY":11,"startX":26,"startY":10}],[{"endX":53,"endY":23,"startX":52,"startY":22}],[{"endX":105,"endY":45,"startX":104,"startY":44}],[{"endX":211,"endY":91,"startX":210,"startY":88}],[{"endX":423,"endY":181,"startX":420,"startY":178}],[{"endX":845,"endY":363,"startX":842,"startY":358},{"endX":847,"endY":363,"startX":846,"startY":358}],[{"endX":1689,"endY":725,"startX":1684,"startY":716},{"endX":1691,"endY":725,"startX":1690,"startY":716},{"endX":1695,"endY":725,"startX":1692,"startY":716}],[{"endX":3377,"endY":1451,"startX":3370,"startY":1432},{"endX":3383,"endY":1451,"startX":3378,"startY":1432},{"endX":3391,"endY":1451,"startX":3384,"startY":1432}],[{"endX":6753,"endY":2903,"startX":6742,"startY":2902},{"endX":6753,"endY":2901,"startX":6740,"startY":2866},{"endX":6767,"endY":2903,"startX":6754,"startY":2866},{"endX":6781,"endY":2903,"startX":6768,"startY":2866}],[{"endX":13507,"endY":5805,"startX":13492,"startY":5804},{"endX":13489,"endY":5805,"startX":13484,"startY":5804},{"endX":13507,"endY":5803,"startX":13480,"startY":5732},{"endX":13535,"endY":5805,"startX":13508,"startY":5732},{"endX":13561,"endY":5805,"startX":13536,"startY":5732}],[{"endX":27015,"endY":11595,"startX":26964,"startY":11594},{"endX":27015,"endY":11609,"startX":26986,"startY":11608},{"endX":27015,"endY":11597,"startX":26966,"startY":11596},{"endX":26977,"endY":11609,"startX":26968,"startY":11608},{"endX":27015,"endY":11607,"startX":26982,"startY":11606},{"endX":26979,"endY":11607,"startX":26966,"startY":11606},{"endX":27015,"endY":11605,"startX":26962,"startY":11598},{"endX":27015,"endY":11593,"startX":26960,"startY":11466},{"endX":27069,"endY":11609,"startX":27016,"startY":11466},{"endX":27123,"endY":11609,"startX":27070,"startY":11466}],[{"endX":53955,"endY":23215,"startX":53934,"startY":23214},{"endX":53931,"endY":23209,"startX":53926,"startY":23208},{"endX":53961,"endY":23209,"startX":53934,"startY":23208},{"endX":54031,"endY":23219,"startX":53976,"startY":23218},{"endX":54031,"endY":23187,"startX":53926,"startY":23186},{"endX":54031,"endY":23213,"startX":53966,"startY":23212},{"endX":53959,"endY":23213,"startX":53934,"startY":23210},{"endX":54031,"endY":23189,"startX":53928,"startY":23188},{"endX":54031,"endY":23215,"startX":53968,"startY":23214},{"endX":54031,"endY":23191,"startX":53930,"startY":23190},{"endX":54031,"endY":23217,"startX":53972,"startY":23216},{"endX":54031,"endY":23201,"startX":53926,"startY":23200},{"endX":53953,"endY":23219,"startX":53936,"startY":23216},{"endX":54031,"endY":23199,"startX":53924,"startY":23196},{"endX":54031,"endY":23195,"startX":53932,"startY":23192},{"endX":54031,"endY":23211,"startX":53964,"startY":23208},{"endX":54031,"endY":23207,"startX":53924,"startY":23202},{"endX":54031,"endY":23185,"startX":53920,"startY":22934},{"endX":54139,"endY":23219,"startX":54032,"startY":22934},{"endX":54247,"endY":23219,"startX":54140,"startY":22934}]],"bounds":[116.20011806488,35.9881639480591,117.989602088928,37.5410127639771],"description":"http://www.cesiumlab.com","extensions":["octvertexnormals"],"format":"quantized-mesh-1.0","maxzoom":15,"minzoom":0,"name":"world","projection":"EPSG:4326","scheme":"tms","tilejson":"1.0","tiles":["{z}/{x}/{y}.terrain"],"version":"1.0.0"}

# 集成到Cesium

  • 将高程数据 terrain_tiles 文件夹放在 HelloWorld 项目目录的 Assets 目录下
  • 在 Cesium 应用代码中添加地形提供者 terrainProvider
// 创建地形提供者
var terrainProvider=new Cesium.CesiumTerrainProvider({
  url: Cesium.buildModuleUrl("Assets/terrain_tiles") // 指定地形文件的路径
});

// 在观察器中指定地形提供者
let viewer = new Cesium.Viewer("cesiumContainer",{
  geocoder:false, // 关闭查找位置工具
  homeButton:false, // 禁用Home按钮
  sceneModePicker:false, // 禁用视景模式拾取器
  baseLayerPicker:false, // 禁用数据层拾取器
  terrainProvider:terrainProvider, // 启用地形提供者
  navigationHelpButton:false, // 禁用导航按钮
  animation:false, // 禁用动画部件
  timeline:false, // 禁用时间线
  fullscreenButton:false, // 禁用全屏按钮

  // 使用自带的离线影像作为纹理贴图
  imageryProvider: new Cesium.TileMapServiceImageryProvider({
	url: Cesium.buildModuleUrl("Assets/TMS/tiles")
  }),

});

# HeadingPitchRoll

HeadingPitchRoll其实也就是欧拉(Euler)角
HeadingPitchRoll
机体坐标系与地面坐标系的关系是三个Euler角:yaw,pitch,roll,反应了飞机相对地面的姿态。
也就是说Yaw对应的是Heading。其实用Heading来表示是非常好的,Heading头朝向,更形象。

//获取方式
viewer.camera.heading
viewer.camera.pitch
viewer.camera.position

# Heading值

偏航角的值,是控制机体头的朝向位置,这个角的改变,也就是左右方向的改变
heading

# Pitch值

俯仰角的值,从上图来看是控制机体上下方向的改变,值为正是顺时针旋转;为负则相反。当然,这个是根据坐标轴来旋转的,要是进行了翻滚就不一定是上下旋转了;如果还将头朝向的方向看作前方,其实还是可以看作上下旋转的
heading

# Roll值

俯仰角的值,从上图来看是控制机体上下方向的改变,值为正是顺时针旋转;为负则相反。当然,这个是根据坐标轴来旋转的,要是进行了翻滚就不一定是上下旋转了;如果还将头朝向的方向看作前方,其实还是可以看作上下旋转的
roll

# HeadingPitchRange

从HeadingPitchRange的名字就可以看出和HeadingPitchRoll是类似的,没错他们的Headiing值、Pitch值所代表的意思是一样的,不一样的就是Range值
Range值所代表的是一个半径值

# 3D Tiles

3DTiles数据集是cesium小组AnalyticlGraphics与2016年3月定义的一种数据集,3DTiles数据集以分块、分级渲染,将大数据量三维数据以分块,分层的形式组织起来,可以大量减轻浏览器和GPU的负担是一个优秀的,并且格式公开的数据格式
3D Tiles将用于流式传输3D内容,包括建筑物,树木,点云和矢量数据

# CZML数据

CZML是cesium中很重要的一个概念,CZML使得cesium很酷很炫地展示动态数据成为可能。某种程度上说, Cesium 和 CZML的关系就像 Google Earth 和 KML。

CZML文档包含一个JSON数组,数组中每个对象都是一个CZML数据包(packet),其中第一个packet是CZML的固定格式,只有设定这个固定的packet,Cesium才会识别这是CZML,否则当作普通数组处理。

{
  "id": "document",//id:固定值
  "name": "CZML Path",//name:可自定义设置值
  "version": "1.0",//version:CZML版本,CZL目前只有1.0版本,固定值
  "clock": { //设置CZML的时间信息,可选项
    "interval": "2012-08-04T10:00:00Z/2012-08-04T15:00:00Z",
    "currentTime": "2012-08-04T10:00:00Z",
    "multiplier": 10
  }
}

完整的CZML至少包合两个packet,第一个用于标识CZML,第二个packet对应一个场景中的对象,例如一架飞机。

[
 //packet one
  { 
    "id": "document",
    "name": "CZML Path",
    "version": "1.0",
    "clock": {
      "interval": "2012-08-04T10:00:00Z/2012-08-04T15:00:00Z",
      "currentTime": "2012-08-04T10:00:00Z",
      "multiplier": 10
    }
  },
  
  //packet two
  //定义了一个“GroundControlStation"对象,它拥有 一个固定坐标为(-75.0,40.0)的WGS-84坐标
  //随后蓝色的点将会绘制在其坐标位置处。
  { 
    "id": "GroundControlStation",
    "position": {
      "cartographicDegrees": [
        -75.5,
        40.0,
        0.0
      ]
    },
    "point": {
      "color": {
        "rgba": [
          0,
          0,
          255,
          255
        ]
      }
    }
  }
]

CZML能表示的内容类型非常丰富,既包括基础图形绘制,也支持三维模型、墙、路径、标签、公告板等对象,而且为每个对象设置了丰富的属性。

# 两种动态可视化机制

  • 按时间间隔描述变化:是指CZML属性值在一段时间内是一个固定值,而在另一段时间是另一个固定值
  • 按时间戳描述变化:是指每个时间节点对应一个值,通过差值算法推算两个时间节点之间的值

# 按时间间隔描述变化

通常情况下CZML的属性值是一个数组,数组中的每个元素对应一个不同的时间和属性值。对于时间间隔,使用interval属性,通过ISO 8601 interval格式的字面值表示,这种表示方法的好处是不需要进行时差计算,不需要换算到协调世界时。

{
	"id":"myObject",
	"someProperty":[
    {
			"interval" : "2012-04-30T12:00:00Z/13:00:00Z"
      "number" : 5
    },
    {
   		"interval":"2012-04-30T13:00:00/14:00:00Z",
   		"number": 6
    }
  ]
}

这里定义了一个someProperty属性,它包含两个时间间隔:第一个是从 12点到13点,属性值为5;第二个是从13点到14点,属性值为6。在时间由第一个间隔变化到第二个间隔的时候,属性值会瞬间从5变到6。

# 按时间戳描述变化

上文按时间间隔可描述属性的离散动态变化,但不具有连续变化效果,而按照时间截采样差值可生成光滑连续的动态变化效果。CZML(1.0版)只有数值型属性才可按时间戳描述动态变化,如position、color、scale等。

CZML插值属性:

//使用ISO 8601规范来表示日期和时间
epoch:string类型

//在时间间隔内下一个采样的时间,可以通过ISO 8061方式,也可以通过历元秒数来定义
nextTime:string或numbe类型

//在时间间隔内前一个采样的时间,可以通过ISO 8061方式,也可以通过历元秒数来定义
previousTime:string或number类型

//用于插值的算法,有LAGTANGE,HERMITE和GEODESIC方法等,默认是LAGRANGE
//如果位置不在该采样区间,那么这个属性值会被忽略
InterpolationAlgorithm:string类型

//定义了用来插值所所使用的多项式次数,1表示线性差值,2表示二次插值法,默认为1
//如果使用GEODESIC插值算法,那么这个属性将被忽略
interpolationDegree:number类型

下述示例代码表示从12点开始的2分钟内坐标变化的情况,采用拉格朗日5次多项式插值方法,形成光滑连续的变化过程。nextTime和reviousTime通常与分包(packet)结合在一起。

{
  "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",
    "interpolationDegree": 5
  }
}

# CZML流式加载

如果将整个CZML文件放在一个大JSON数组中,会使增量加载变得很困难。虽然浏览器允许访问没有读取完的流数据,但是解析不完整的数据需要漫长而烦琐的字符串操作。为了使过程更高效,CZML使用浏览器的server-sentevents(EventSource)API来处理流数据。在实际操作中,每个CZML packet会被作为单独的一个事件传输到客户端,如下所示:

event:czml
data{
 // packet one
}
event:czml
data: {
 // packet two
}

当览器接收到一个packet后就会发出一个事件,事件中会包含刚刚接收到的数据。此时可以通过增量方式高效地处理CAML数据。目前为止,我们都是使用packet来描述对象。packet包含了所有这个对象的图形属性。除此之外,还可以使用其他的方式,例如一个CZML文件或流可以包含多个packet,每个parcket都有相同的id。分别描述同一个对象的不同方面的属性。

事实上在大多数情况下使用两个packet来描述一个对象。 当对象属性跨越多个时间间隔,或者一个时间间隔有很多个时间戳采样时,这样做就很有用。通过将一个属性定义打包进多个packet中,可以使数据更快地传输到Cesium中,减少用户等待的时间。

分包过程中,如果CZML属性按照时间间隔变化,那么同一个packet或多个packet之间,虽然不要求属性值必须按时间递增描述,为了清晰易读还是尽量按照时间顺序描述。分包时如果CZML按时间戳内插属性值,同一个packet必须按 照时间递增顺序描述属性值,多个packet 不要求必须按时间递增记录,倘若多个packet没有按时间递增记录属性,应指定priviousTime或nextTime属性,以免造成内插错误。下面代码中packet1和packet2不连续,通过设定priviousTime和nextTime,packetl执行完后直接执行packet3,再执行packet2。

{
  //packet 1
  "id": "myObject1",
  "someInterpolatableProperty": {
    "epoch": "2012-04-30T12:00:00Z",
    "cartesian": [
      0.0,1.0,2.0,3.0,
      1.0,4.0,5.0,6.0,
      2.0,7.0,8.0,9.0,
      3.0,10.1,11.0,12.0
    ],
    "previousTime": -1.0,
    "nextTime": 4.0
  }
},
{
//packet 2
"id": "myObject1",
"someInterpolatableProperty": {
   "cartesian":[
    8.0,25.0,26.0,27.0,
    9.0,28.0,29.0,30.0,
    10.0,31.0,32.0,33.0],
    "previousTime": 8.0,
    "nextTime": 11.0
    }
},
{
  //packet 3
  "id": "myObject1",
  "someInterpolatableProperty": {
    "cartesian":[
      4.0,13.0,14.0,15.0,
      5.0,16.0,17.0,18.0,
      6.0,19.0,20.0,21.0,
      7.0,22.0,23.0,24.0
    ],
    "previousTime": 4.0,
    "nextTime": 8.0
  }
}

实际开发过程中时间间隔和时间戳可以混合使用,如不同时间间隔内可设定时间戳进行属性值内插。CZML的packet还有一个特别的额外属性availability ,它表示packet在什么时间段内是可用的。在此时间段则调用对应时间段的数据,否则数据不显示。同一对象若有不同packet, 默认最后一个packet的availability属性发挥作用。

# 轨迹数据可视化

轨迹数据视化原理则是将时刻与坐标点相对应,按照时间顺序通过某种插值方法将轨迹点连成条光滑的轨迹曲线。 为了更加通真显示轨迹动态效果,通常每条轨迹会有一个实物模型,如车辆、飞机或人物用于真实刻画不同情景下的轨迹特点。

轨迹动态可视化核心要素是时间和对应坐标点,展示地理时空动态变化特征是Cesium的一大特色。Cesium 默认添加时间控件Animation和Timeline。

如果动态轨迹点是以实物模型的样式展示,如飞机模型,则飞机机头方向随着轨迹走势一直变化,Cesium有专门的转向函数orientation。

//创建CZXL对象
var czml = [{
    // 创建第一个package
    // 固定格式
    "id": "document",
    // 固定版本1.0
    "version" : "1.0",
    // clock必须在package1中设置
    "clock": {
        //时间间隔
        "interval": "2019-08-04T16:00:00Z/2019-08-04T16:30:00Z",
        //设定当前时间节点
        "currentTime": "2012-08-0416.00:00",
        //设定时间速率为10
        "multiplier": 10
     }
},
{
    //创建第二个package
    //轨迹id
    "id" :"7808F0",
    //轨迹可视的时间间隔
    "availability" :"2019-08-04T16:00Z/2019-08-0416:30:00Z",
    "position": {
        "epoch": " 2019-08-04T16:00:00+00:00",
        //轨迹显示初始时刻点"cartographicDegrees"
        "cartographicDegrees": [  //参数分别对应:时刻/秒、经度、纬度、高程
            0, 114.835342, 34.490276, 10081,
            4, 114.836441, 34.501282, 10088,
            12, 114.837006, 34.506821, 10088,
            14, 114.838486, 34.522442, 10081,
            18, 114.83947, 34.532593, 10081,
            33, 114.841576, 34.554005, 10081,
            36, 114.842316, 34.561501, 10081,
            40, 114.843674, 34.575806, 10073
        ]
    },
    //可视化模型
    "model":{"gltf":"Cesium_Air.glb","scale":1,"minimumPixeSize":40},
    "orientation":{
       //设置模型转向方法,根据position进行四元数方向转换
       "velocityReference":"# position"
    } 
}];
// 通过CzmlDataSource添加CZML对象
viewer.dataSources.add(Cesium.CzmlDataSource.load(czml))

# 加载CZML数据

var viewer = new Cesium.Viewer('cesiumContainer');
var dataSourcePromise = Cesium.CzmlDataSource.load(czml);
viewer.dataSources.add(dataSourcePromise);
viewer.zoomTo(dataSourcePromise);

# Property机制

Property最大的特点就是和时间关联,能够在不同的时间可以动态地返回不同的属性值,如空间位置。

Cesium中有关Property的类非常之多,但仔细看还是有其分类的。首先Property作为基类或抽象类,定义了所有属性的接口规范,不能直接被实例化。

Property机制

# 基本Property类型

# ConstantProperty

虽然我们并没有在Cesium的开发中应用到ConstantProperty,但它却是最常用的一个Property,其值不会随时间的变化而变化

var blueBox = viewer.entities.add({
   name: "Blue box",
   position: Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 30.0),
   box: {
	 dimensions: new Cesium.Cartesian3(400.0, 300.0, 500.0),
	 material: Cesium.Color.BLUE,
   },
});

//添加ConstantProperty的方式:
var blueBox = viewer.entities.add({
   name: "Blue box",
   position: new Cesium.ConstantProperty(Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 30.0)),
   box: {
 	 dimensions: new Cesium.ConstantProperty(new Cesium.Cartesian3(400.0, 300.0, 500.0)),
	 material: Cesium.Color.BLUE,
   },
});

两种实现的本质和最终的效果都是一样的。虽然ConstantProperty的值不会随时间的变化而变化,但并不代表其不可修改,我们可以通过setValue方法来修改其属性值。类似的还包括ConstantPositionProperty

# SampleProperty

通过给定多个不同时间点的Sample,然后在每两个时间点之间进行线性插值的一种Property

逐渐变长的盒子 (opens new window)

// 创建盒子
var blueBox = viewer.entities.add({
    name : 'Blue box',
    position: Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 300000.0),
    box : {
        dimensions : new Cesium.Cartesian3(400000.0, 300000.0, 500000.0),
        material : Cesium.Color.BLUE,
        outline: true,
    }
});

var property = new Cesium.SampledProperty(Cesium.Cartesian3);
property.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), 
	               new Cesium.Cartesian3(400000.0, 300000.0, 200000.0));

property.addSample(Cesium.JulianDate.fromIso8601('2019-01-03T00:00:00.00Z'), 
	               new Cesium.Cartesian3(400000.0, 300000.0, 700000.0));

blueBox.box.dimensions = property;

# TimeIntervalCollectionProperty

用来指定各个具体的时间段的属性值,每个时间段内的属性值是恒定的,并不会发生变化,除非已经进入到下一个时间段

跳跃式的的盒子 (opens new window)

var property = new Cesium.TimeIntervalCollectionProperty(Cesium.Cartesian3);

property.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
	iso8601 : '2019-01-01T00:00:00.00Z/2019-01-01T12:00:00.00Z',
	isStartIncluded : true,
	isStopIncluded : false,
	data : new Cesium.Cartesian3(400000.0, 300000.0, 200000.0)
}));
property.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
	iso8601 : '2019-01-01T12:00:01.00Z/2019-01-02T00:00:00.00Z',
	isStartIncluded : true,
	isStopIncluded : false,
	data : new Cesium.Cartesian3(400000.0, 300000.0, 400000.0)
}));
property.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
	iso8601 : '2019-01-02T00:00:01.00Z/2019-01-02T12:00:00.00Z',
	isStartIncluded : true,
	isStopIncluded : false,
	data : new Cesium.Cartesian3(400000.0, 300000.0, 500000.0)
}));
property.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
	iso8601 : '2019-01-02T12:00:01.00Z/2019-01-03T00:00:00.00Z',
	isStartIncluded : true,
	isStopIncluded : true,
	data : new Cesium.Cartesian3(400000.0, 300000.0, 700000.0)
}));

blueBox.box.dimensions = property;

# CompositeProperty

CompositeProperty的意思是组合的Property,可以把不同类型的ConstantProperty、SampleProperty、TimeIntervalCollectionProperty等Property组合在一起来操作。比如前一个时间段需要线性运动,后一段时间再跳跃式运动

// 1 sampledProperty
var sampledProperty = new Cesium.SampledProperty(Cesium.Cartesian3);
sampledProperty.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), 
	new Cesium.Cartesian3(400000.0, 300000.0, 200000.0));

sampledProperty.addSample(Cesium.JulianDate.fromIso8601('2019-01-02T00:00:00.00Z'), 
	new Cesium.Cartesian3(400000.0, 300000.0, 400000.0));

// 2 ticProperty
var ticProperty = new Cesium.TimeIntervalCollectionProperty();
ticProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
	iso8601 : '2019-01-02T00:00:00.00Z/2019-01-02T06:00:00.00Z',
	isStartIncluded : true,
	isStopIncluded : false,
	data : new Cesium.Cartesian3(400000.0, 300000.0, 400000.0)
}));
ticProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
	iso8601 : '2019-01-02T06:00:00.00Z/2019-01-02T12:00:00.00Z',
	isStartIncluded : true,
	isStopIncluded : false,
	data : new Cesium.Cartesian3(400000.0, 300000.0, 500000.0)
}));
ticProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
	iso8601 : '2019-01-02T12:00:00.00Z/2019-01-02T18:00:00.00Z',
	isStartIncluded : true,
	isStopIncluded : false,
	data : new Cesium.Cartesian3(400000.0, 300000.0, 600000.0)
}));
ticProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
	iso8601 : '2019-01-02T18:00:00.00Z/2019-01-03T23:00:00.00Z',
	isStartIncluded : true,
	isStopIncluded : true,
	data : new Cesium.Cartesian3(400000.0, 300000.0, 700000.0)
}));

// 3 compositeProperty
var compositeProperty = new Cesium.CompositeProperty();
compositeProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
	iso8601 : '2019-01-01T00:00:00.00Z/2019-01-02T00:00:00.00Z',
	data : sampledProperty
}));
compositeProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
	iso8601 : '2019-01-02T00:00:00.00Z/2019-01-03T00:00:00.00Z',
	isStartIncluded : false,
	isStopIncluded : false,
	data : ticProperty
}));

// 4 设置position
blueBox.box.dimensions = compositeProperty;

# PositionProperty

PositionProperty和Property一样,是一个虚类,并不能直接实例化,他扩展了Property的接口,增加了用于定义position坐标系原点的参考框架referenceFrame,同时只能用来表示position

  • FIXED:相当于以地球的中心作为坐标系的原点
  • INERTIAL:相当于以太阳系的质心为原点的坐标架偏移到地球的中心来

# SampledPositionProperty

SampledPositionProperty和SampledProperty原理都是一样的

var property = new Cesium.SampledPositionProperty();

property.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), 
	               Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 300000.0));

property.addSample(Cesium.JulianDate.fromIso8601('2019-01-03T00:00:00.00Z'), 
	               Cesium.Cartesian3.fromDegrees(-114.0, 45.0, 300000.0));

blueBox.position = property;

他俩都有一个特有的方法setInterpolationOptions用于修改不同的插值方式:

  • LinearApproximation:线性插值
entity.position.setInterpolationOptions({
    interpolationDegree : 1,
    interpolationAlgorithm : Cesium.LinearApproximation
});
  • LagrangePolynomialApproximation:拉格朗日插值
entity.position.setInterpolationOptions({
    interpolationDegree : 5,
    interpolationAlgorithm : Cesium.LagrangePolynomialApproximation
});
  • HermitePolynomialApproximation:埃尔米特插值
entity.position.setInterpolationOptions({
    interpolationDegree : 2,
    interpolationAlgorithm : Cesium.HermitePolynomialApproximation
});

详细的线性插值方式和插值效果请查看Cesium官方示例 (opens new window)

# MaterialProperty

MaterialProperty是用来专门表示材质的Property,它对Property进行了扩展,增加了getType方法,用来获取材质类型,MaterialProperty也是一个虚基类

各种派生类使用上大同小异,我们以ColorMaterialProperty来说明一下

# ColorMaterialProperty

基本设置,颜色不变

blueBox.box.material = new Cesium.ColorMaterialProperty(new Cesium.Color(0, 1, 0));
// 以上代码等同于
// blueBox.box.material = new Cesium.Color(0, 1, 0);

如果希望Color动起来的话,也是可以的。ColorMaterialProperty的内部有一个color属性,可以赋予一个SampledProperty来实现动态效果

颜色变化的效果 (opens new window)

var colorProperty = new Cesium.SampledProperty(Cesium.Color);

colorProperty.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), 
	new Cesium.Color(0, 1, 0));

	colorProperty.addSample(Cesium.JulianDate.fromIso8601('2019-01-03T00:00:00.00Z'), 
	new Cesium.Color(0, 0, 1));

blueBox.box.material = new Cesium.ColorMaterialProperty(colorProperty);

# 其他类型的Property

# CallbackProperty

CallbackProperty是自由度最高的一种Property,让用户通过自定义,回调函数,来返回需要的值。回调函数中,用户可以使用time来给定value,也可以以自己的方式给给定

自己手动调整的方式盒子逐渐变长 (opens new window)

var l = 200000.0;
var property = new Cesium.CallbackProperty(function (time, result) {
	result = result || new Cesium.Cartesian3(0, 0, 0);

	l += 10000.0;
	if (l > 700000.0) {
		l = 200000.0;
	}

	result.x = 400000.0;
	result.y = 300000.0;
	result.z = l;

	return result;
}, false);

blueBox.box.dimensions = property;

根据time来设置Plygon的大小

function callback(time, result) {
	//let seconds = Date.now()
	var txf = Math.floor(time.secondsOfDay);
	console.log(seconds)
	if (txf %1000 === 0) {
		result = Cesium.Cartesian3.fromDegreesArray([-115.0, 37.0,
		                                            -115.0, 32.0,
													-107.0, 33.0, 
													-102.0, 31.0, 
													-102.0, 35.0]);
	}
	else {
		result = Cesium.Cartesian3.fromDegreesArray([-116, 37.0,
		                                             -115.0, 32.0, 
													 -107.0, 33.0, 
													 -102.0, 31.0]);
	}
	return new Cesium.PolygonHierarchy(result);
}

var redPolygon = viewer.entities.add({
	name : '11111',
	polygon : {
		hierarchy : new Cesium.CallbackProperty(callback, false),
		material : Cesium.Color.RED
	}
});

# ReferenceProperty

该Property可以直接链接到别的对象的Property上,相当于引用,省得自己构建了

比如这里我创建了一个红色的盒子redBox,希望它和之前的蓝色盒子一起变大

var collection = viewer.entities;
redBox.box.dimensions = new Cesium.ReferenceProperty(collection, blueBox.id, 
													['box', 'dimensions']);

ReferenceProperty构造函数的参数有三个:

  • targetCollection:用来指定需要引用的对象所属的collection
    • 如果没有自己专门创建EntityCollection的话,可以直接使用viewer.entities
  • targetId:参数传递所指对象的id
  • targetPropertyNames:指定属性的位置的数组,如果是有层级的属性,可以依次写入
    • 如 ['billboard', 'scale'] 指定的是entity.billboard.scale 属性

# PropertyBag

PropertyBag虽然不是以Property结尾,但实际上也是一个Property。它的特点是可以包装一个对象(JS中的对象概念),该对象的每一个属性(JS中的属性概念),都可以作为一个动态的Property

比如之前修改dimensions的话,dimensions是作为一个Cartesian3类型变量整体封装到Property中去的,如果我们只想修改dimensions的x。则可以使用PropertyBag来实现,代码如下:

var zp = new Cesium.SampledProperty(Number);
zp.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), 200000.0);
zp.addSample(Cesium.JulianDate.fromIso8601('2019-01-03T00:00:00.00Z'), 700000.0);

blueBox.box.dimensions = new Cesium.PropertyBag({
	x: 400000.0,
	y: 300000.0,
	z: zp
});

效果和sampleProperty类似,但是修改的只是dimensions的x

# PropertyArray

ropertyArray和上述的PropertyBag类似,只是其内部封装了一个数组而已

# VelocityOrientationProperty

该Property用来描述Entity的position的位置变化,来计算出移动的方向,最后把速度方向输出成Orientation。Cesium自带的示例中有一个Interpolation中有其用法

将Entity的postion速度转换成Orientation旋转。使用方法如下:

var position = new Cesium.SampledProperty();
position.addSamples(...);var entity = viewer.entities.add({
  position : position,
  orientation : new Cesium.VelocityOrientationProperty(position)
}));

# VelocityVectorProperty

与上面的Property类似,把速度方向转成Cartesian3向量。使用示例如下:

blueBox.box.show = false;
blueBox.billboard = {
	scale: 0.05,
	image : 'https://upload-images.jianshu.io/upload_images/80648-5dfe8a3ea2c250be.png',
	alignedAxis : new Cesium.VelocityVectorProperty(blueBox.position, true)
};

可见图像的摆放方向和位置移动的方向保持一致。效果 (opens new window)

# NodeTransformationProperty

专门用于生成 TranslationRotationScale对象的属性,包括平移、旋转、缩放,用于控制模型矩阵变化的。关于此Property,Cesium没有过多的介绍,但可以通过变相方式去使用

var emitterModelMatrix = new Cesium.Matrix4();
var translation = new Cesium.Cartesian3();
var rotation = new Cesium.Quaternion();
var hpr = new Cesium.HeadingPitchRoll();
var trs = new Cesium.TranslationRotationScale();

function computeEmitterModelMatrix() {
  hpr = Cesium.HeadingPitchRoll.fromDegrees(0.0, 0.0, 0.0, hpr);
  trs.translation = Cesium.Cartesian3.fromElements(
	-4.0,
	0.0,
	1.4,
	translation
  );
  trs.rotation = Cesium.Quaternion.fromHeadingPitchRoll(hpr, rotation);

  return Cesium.Matrix4.fromTranslationRotationScale(
	trs,
	emitterModelMatrix
  );
}

# 坡度和坡向

# 坡度

坡度(slope)是地表单元陡缓的程度,通常把坡面的垂直高度h和水平距离l的比叫做坡度(或叫做坡比)用字母i表示。【即坡角的正切值(可写作:i=tan坡角)】。坡度的表示方法有百分比法、度数法、密位法和分数法四种,其中以百分比法和度数法较为常用。

坡度

  • 百分比法:表示坡度最为常用的方法,即两点的高程差与其水平距离的百分比
坡度 = (高程差/水平距离)x100%

//坡度3% 是指水平距离每100米,垂直方向上升(下降)3米
//1%是指水平距离每100米,垂直方向上升(下降)1米
  • 度数法:用度数来表示坡度,利用反三角函数计算而得
tanα(坡度)= 高程差/水平距离  =>  α(坡度)= arctan(高程差/水平距离)

// 如果将高程增量百分比视为高程增量除以水平增量后再乘以 100,就可以更好地理解高程增量百分比

czm_materialInput.slope 表示坡度,用角度来表示,单位弧度,范围是从0到0.5*pi,相当于表示从水平到竖直的程度。纹理坐标0对应水平坡度,纹理坐标1对应垂直坡度。

坡度

# 坡向

坡向(aspect) 是指地形坡面的朝向。坡向用于识别出从每个像元到其相邻像元方向上值的变化率最大的下坡方向。坡向可以被视为坡度方向。坡向是一个角度,将按照顺时针方向进行测量,角度范围介于 0(正东)到 360(仍是正东)之间,即完整的圆。不具有下坡方向的平坦区域将赋值为-1。

坡度

czm_materialInput.aspect 表示坡向,用角度来表示,单位弧度,按照东北西南的顺序表示方向。即正东向为起始0弧度,再向左转圈,正北向为pi/2弧度(90度), 正西向为 pi弧度(180度),正南向为 1.5*pi弧度(270度)。

坡度

# 坡度坡向计算方法

坡度计算一般采用拟合曲面法。拟合曲面一般采用二次曲面,即3×3的窗口,如图所示。每个窗口的中心为一个高程点。

坡度坡向计算方法

图中中心点e的坡度和坡向的计算公式如下:

坡度坡向计算方法