1. 概述

Cesium的Camera案例,展示了其关于漫游器镜头的控制,能够调整视图的位置。这里改进了一下这个实例,使之能够展示一些自己关注的兴趣点的情况,并总结遇到的问题。

2. 实例

2.1. Camera.html

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="Fly to a specified location or view a geographic rectangle.">
<meta name="cesium-sandcastle-labels" content="Beginner, Tutorials, Showcases">
<title>Cesium Demo</title>
<script type="text/javascript" src="../Build/Cesium/Cesium.js"></script>
<style>
@import url(../Build/Cesium/Widgets/widgets.css); html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
font-family: sans-serif;
background: #000;
} .fullSize {
display: block;
position: absolute;
top: 0;
left: 0;
border: none;
width: 100%;
height: 100%;
} #toolbar {
margin: 5px;
padding: 2px 5px;
position: absolute;
}
</style>
</head> <body>
<div id="cesiumContainer" class="fullSize"></div>
<div id="toolbar">
<select id = "camera_select", class="cesium-button">
<option value="undefined">
相机选项
</option>
<option value="undefined">
飞行至某一点——武汉大学
</option>
<option value="undefined">
飞行至某区域——武汉市
</option>
<option value="undefined">
设置相机点——华中科技大学
</option>
<option value="undefined">
设置相机区域——上海市
</option>
<option value="undefined">
从武大飞向华科
</option>
</select>
</div>
<script src="Camera.js"></script>
</body> </html>

这段代码在数字地球展示组件的基础上新添加了一个视图控制的下拉列表框,选择相应的选项能够将当前的视图调整到对应的位置。

2.2. Camera.js

//Add your ion access token from cesium.com/ion/
Cesium.Ion.defaultAccessToken = '你在Cesium申请的key'; var tdtKey = "你在天地图申请的key"; 'use strict'; //默认BING影像地图
var viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider: Cesium.createWorldImagery({
style: Cesium.IonWorldImageryStyle.AERIAL
}),
baseLayerPicker: false
}); //全球影像中文注记服务
var imageryLayers = viewer.scene.imageryLayers;
var tdtAnnoLayer = imageryLayers.addImageryProvider(new Cesium.WebMapTileServiceImageryProvider({
url: "http://t0.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=" + tdtKey,
layer: "tdtAnnoLayer",
style: "default",
format: "image/jpeg",
tileMatrixSetID: "GoogleMapsCompatible"
})); var camera_select = document.getElementById("camera_select");
if (camera_select) {
camera_select.onchange = function gradeChange() {
switch (camera_select.selectedIndex) {
case 1:
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(114.35231209, 30.53542614, 5000.0),
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
}
});
break;
case 2:
viewer.camera.flyTo({
destination: Cesium.Rectangle.fromDegrees(113.683333, 29.966667, 115.083333, 31.366667)
});
break;
case 3:
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(114.40782845, 30.51011682, 5000.0),
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
}
});
break;
case 4:
viewer.camera.setView({
destination: Cesium.Rectangle.fromDegrees(120.86667, 30.66667, 122.2, 31.883333)
});
break;
case 5: {
var whdxOptions = {
destination: Cesium.Cartesian3.fromDegrees(114.35231209, 30.53542614, 5000.0),
duration: 5,
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
}
};
var hzkjdxOptions = {
destination: Cesium.Cartesian3.fromDegrees(114.40782845, 30.51011682, 5000.0),
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
},
duration: 5,
//flyOverLongitude: Cesium.Math.toRadians(60.0)
}; whdxOptions.complete = function () {
setTimeout(function () {
viewer.camera.flyTo(hzkjdxOptions);
}, 1000);
}; // if (adjustPitch) {
// tokyoOptions.pitchAdjustHeight = 1000;
// laOptions.pitchAdjustHeight = 1000;
// } viewer.camera.flyTo(whdxOptions);
}
break;
default:
break;
}
}
}

这段代码首先添加了Cesium.Viewer默认的Bing影像地图和天地图的中文标注;然后根据id获取HTML页面的下拉列表框控件camera_select;最后根据选项调整相应的相机视图。这里展示了几种调整视图的方式。

2.2.1. 飞行至某一点

设置相机镜头逐渐从当前位置飞行到某一点是通过Cesium.Camera的flyTo()函数实现的,其具体的函数定义如下:

图1:Cesium.Camera的flyTo()函数定义

该函数传入了键值对配置对象,其中destination、orientation这两项,分别表示相机镜头的位置和姿态。本例中相应的代码如下:

viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(114.35231209, 30.53542614, 5000.0),
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
}
});

这段设置相机视图的代码意思就是,将相机的位置移动到经纬度位置(114.35231209, 30.53542614),离地面5000米的点;航向角(heading)设置为0度,俯仰角(pitch)设置为-90度,滚转角(roll)设置为0度。实际页面的显示效果为逐渐飞往某一点:

图2:飞行至武汉大学附近

此时数字地球会显示在武汉大学附近,视线看上去会垂直与地面,并且东西南北方向也基本上与常规地图一致。实际上当不设置姿态参数orientation只设置位置参数destination也能达到同样的效果,说明(0.0,-90.0,0.0)的三个姿态角是设置相机视图的默认值。在Cesium的设定中,heading、pitch、roll的定义如下:

这说明航向角(heading)是绕Z后负方向旋转的角度,俯仰角(pitch)是绕Y轴负方向旋转的角度,滚转角(roll)是绕X轴正方向旋转的角度。那么问题来了,这个定义里面的X、Y、Z轴的指的是什么呢?我这里认为这个函数蕴含了一种视图变换,使得基于相机的视空间坐标系成为一种类似于一种北东地站心坐标系(NED)坐标系,XYZ轴指的正是这个视空间坐标系的XYZ轴。在这个视空间坐标系中,Z轴垂直球面向下(Down),Y轴沿纬线指东(East),X轴沿经线向北(North),而位于视空间坐标系原点的相机的姿态为由南看向北。在这种情况下,只需要使相机绕Y轴正向旋转90度,也就是俯仰角(pitch)设为90,就可以得到视线垂直于地图,东西南北向正常的视图。

2.2.2. 飞行至某区域

flyTo()函数另外一个很有用的功能就是根据设定的范围显示视图,这在显示特定空间的视图时特别有用,例如加载的三维模型的范围,一个地区的范围等等。实现也很很简单,只需要给位置参数destination传入一个Cesium.Rectangle对象即可:

viewer.camera.flyTo({
destination: Cesium.Rectangle.fromDegrees(113.683333, 29.966667, 115.083333, 31.366667)
});

将武汉市的经纬度范围传入,实际的显示结果如下:

图3:飞行至武汉市

2.2.3. 两地之间飞行

flyTo()函数还可以传入一个配置项complete,可以给其设定一个飞行结束后再运行的函数,通过这个配置项可以实现两地或多地飞行:

var whdxOptions = {
destination: Cesium.Cartesian3.fromDegrees(114.35231209, 30.53542614, 5000.0),
duration: 5,
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
}
};
var hzkjdxOptions = {
destination: Cesium.Cartesian3.fromDegrees(114.40782845, 30.51011682, 5000.0),
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
},
duration: 5,
//flyOverLongitude: Cesium.Math.toRadians(60.0)
}; whdxOptions.complete = function () {
setTimeout(function () {
viewer.camera.flyTo(hzkjdxOptions);
}, 1000);
}; // if (adjustPitch) {
// tokyoOptions.pitchAdjustHeight = 1000;
// laOptions.pitchAdjustHeight = 1000;
// } viewer.camera.flyTo(whdxOptions);

这段代码分别定义了两个飞行配置项whdxOptions和hzkjdxOptions,并且给whdxOptions的complete项配置了一个函数,表示完成1S之后,自动进行hzkjdxOptions的飞行。运行结果如下图所示:

图4:武大飞行至华科

2.2.4. 设置视图到某一点

设置当前视图通过setView()函数实现的,它跟flyTo()最大的不同是没有持续时间,没有飞行过程,是立即生效的。其具体的配置选项也比较相似,都是需要设置位置以及姿态:

viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(114.40782845, 30.51011682, 5000.0),
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
}
});

2.2.5. 设置视图到某区域

设置具体的显示范围,也是立即生效,这两个部分因为与flyTo()函数比较类似,就不再具体讲解了。

viewer.camera.setView({
destination: Cesium.Rectangle.fromDegrees(120.86667, 30.66667, 122.2, 31.883333)
});

3. 其他

3.1. 事件及相应函数

Cesium.Camera还提供了当前视图发生变化的事件changed、视图发生移动的事件moveStart/moveEnd,它们都可以通过addEventListener()给其添加相应的响应函数。

3.2. setReferenceFrame

自带案例Camera中还提供了另外一种视图控制方式:

function setReferenceFrame() {
Sandcastle.declare(setReferenceFrame); var center = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883);
var transform = Cesium.Transforms.eastNorthUpToFixedFrame(center); // View in east-north-up frame
var camera = viewer.camera;
camera.constrainedAxis = Cesium.Cartesian3.UNIT_Z;
camera.lookAtTransform(transform, new Cesium.Cartesian3(-120000.0, -120000.0, 120000.0)); // Show reference frame. Not required.
referenceFramePrimitive = scene.primitives.add(new Cesium.DebugModelMatrixPrimitive({
modelMatrix: transform,
length: 100000.0
}));
}

这段代码的意思是选定一个经纬度的点,可以计算出以该点为中心的东北天(ENU)站心坐标系与地心坐标系的转换矩阵,将这个矩阵传入给Cesium.Camera的lookAtTransform函数,从而达到设置视图的目的。但是这样做会导致当前世界坐标系发生变化,当前漫游器的键鼠交互操作不再以地心坐标系原点为中心,而以站心坐标系的原点为中心,导致这个时候的键鼠交互操作难以操作。

3.3. viewInICRF

Cesium默认是基于ITRF,也就是国际地球地心参考框架。自带案例还提供了一种将其转换为ICRF参考框架的视图设置方式。关于ICRF我也不是很了解,查阅网上资料只知道是一种原点在太阳系的质心的天文参考框架,留待以后需要用到的时候再研究。

4. 参考

[1]. 北东地/东北天两种导航坐标系与姿态转换

[2]. Cesium中的相机—HeadingPitchRoll

[3]. Cesium类HeadingPitchRoll及heading、pitch、roll等参数详解

Cesium案例解析(三)——Camera相机的更多相关文章

  1. Cesium案例解析(四)——3DModels模型加载

    目录 1. 概述 2. 代码 3. 解析 4. 参考 1. 概述 Cesium自带的3D Models示例,展示了如何加载glTF格式三维模型数据.glTF是为WebGL量身定制的数据格式,在网络环境 ...

  2. Cesium中级教程3 - Camera - 相机(摄像机)

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ Camera CesiumJS中的Camera控制场景的视图.有 ...

  3. Cesium案例解析(二)——ImageryLayers影像图层

    目录 1. 概述 2. 实例 2.1. ImageryLayers.html 2.2. ImageryLayers.js 2.2.1. 代码 2.2.2. 解析 3. 结果 1. 概述 Cesium支 ...

  4. Cesium案例解析(六)——3DTilesInspector监视器

    目录 1. 概述 2. 案例 1. 概述 3D Tiles作为传输和渲染大规模3D地理空间数据的格式,应对的都是大规模数据的场景,Cesium提供了一个监视3D Tiles数据的监视器,可以通过这个监 ...

  5. Cesium案例解析(五)——3DTilesPhotogrammetry摄影测量3DTiles数据

    目录 1. 概述 2. 案例 3. 结果 1. 概述 3D Tiles是用于传输和渲染大规模3D地理空间数据的格式,例如摄影测量,3D建筑,BIM / CAD,实例化特征和点云等.与常规的模型文件格式 ...

  6. Cesium案例解析(一)——HelloWorld

    目录 1. 概述 2. 实例 2.1. HelloWorld.html 2.2. HelloWorld.js 3. 结果 1. 概述 感觉网上已经有不少关于cesium的教程了,但是学习一个框架最快的 ...

  7. 【Python五篇慢慢弹(5)】类的继承案例解析,python相关知识延伸

    类的继承案例解析,python相关知识延伸 作者:白宁超 2016年10月10日22:36:57 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给 ...

  8. Android Camera 相机程序编写

    Android Camera 相机程序编写 要自己写一个相机应用直接使用相机硬件,首先应用需要一个权限设置,在AndroidManifest.xml中加上使用设备相机的权限: <uses-per ...

  9. 案例解析|政府信息化的BI建设应用 .

    一.行业背景 某建设厅综合监管信息化平台,是政企业务协同的平台之一,同时兼具协作.门户.办公应用集成.用户权限管理等多项功能.在此要求基础上,选择中间件基础技术平台,可以在最大程度满足平台功能需求的前 ...

随机推荐

  1. 基于python的感知机

    一. 1.感知机可以描述为一个线性方程,用python的伪代码可表示为: sum(weight_i * x_i) + bias -> activation #activation表示激活函数,x ...

  2. Centos 7中安装svn服务器,史上最详细

    最近上头安排了帮客户安装svn服务器,用了两种方式安装,yum命令安装,快速简洁容易上手,但是源码安装就比较繁琐,两种方式都试了一下,yum命令基本一个多小时就安装完了,但是源码安装弄了我两天的时间, ...

  3. SpringBoot系列教程之事务传递属性

    200202-SpringBoot系列教程之事务传递属性 对于mysql而言,关于事务的主要知识点可能几种在隔离级别上:在Spring体系中,使用事务的时候,还有一个知识点事务的传递属性同样重要,本文 ...

  4. 前端基础JavaScript

    JavaScript概述 ECMAScript和JavaScript的关系 1996年11月,JavaScript的创造者--Netscape公司,决定将JavaScript提交给国际标准化组织ECM ...

  5. Charles的安装及使用过程

    一.charles的使用 1.1  charles的说明 Charles其实是一款代理服务器,通过过将自己设置成系统(电脑或者浏览器)的网络访问代理服务器,然后截取请求和请求结果达到分析抓包的目的.该 ...

  6. ios--->泛型

    泛型 开发中使用场景: 1.限制集合中的类型,只能检测方法的调用,因为声明的泛型只能存在方法中 2.当一个类在声明的时候,某个对象的属性不确定,只有创建对象的时候才能确定,就可以使用泛型. 使用泛型的 ...

  7. linux--->阿里云centos6.9环境配置安装lnmp

    阿里云centos6.9环境配置安装lnmp mysql安装 本人博客:http://www.cnblogs.com/frankltf/p/8615418.html PHP安装 1.安装依赖关系 yu ...

  8. qt creator源码全方面分析(0)

    本人主攻C++和Qt. 上两天刚研究完Qt install framework(IFW)应用程序安装框架. google没发现有正儿八经的官方文档的翻译,我就进行了翻译哈!! 系列文章具体见:http ...

  9. Activity--Eclipse安装Activity designer插件失败

    案例 今天使用Eclipse 安装Activity designer插件时,出现了如下错误: An error occurred while collecting items to be instal ...

  10. 前端 JS/TS 调用 ASP.NET Core gRPC-Web

    前言 在上两篇文章中,介绍了ASP.NET Core 中的 gRPC-Web 实现 和 在 Blazor WebAssembly 中使用 gRPC-Web,实现了 Blazor WebAssembly ...