文章目录
0.引言
现有的gis开发方向较流行的是webgis开发,其中Cesium是一款开源的WebGIS库,主要用于实时地球和空间数据的可视化和分析。它提供了丰富的地图显示和数据可视化功能,并能实现三维可视化开发。本文介绍Cesium中的坐标系统及相互转换关系,讲解如何在构造的三维场景中交互绘制点、线、面、体等多种空间对象并对这些空间对象进行管理。
1.坐标系统
Cesium中经常会涉及各类数据的加载、浏览,以及不同数据之间的坐标转换,所以我们不得不弄清楚Cesium中常用的坐标系统,以及不同坐标系统之间的转换关系和转换方法等。这里主要介绍Cesium中常用的WGS-84坐标系(包括弧度和度的形式)、世界坐标系(笛卡儿空间直角坐标系)及平面坐标系,并介绍这些坐标系统之间的转换关系和转换方法。
(1)坐标系统相互转换代码

4_1_坐标转换.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.0">
<title>场景绘制篇_坐标转换</title>
<script src="./Build/Cesium/Cesium.js"></script>
<link rel="stylesheet" href="./Build/Cesium//Widgets/widgets.css">
<style>
html,
body,
#cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="cesiumContainer">
</div>
<script>
Cesium.Ion.defaultAccessToken = '你的token';
var viewer = new Cesium.Viewer("cesiumContainer", {
animation: false, //是否显示动画工具
timeline: false, //是否显示时间轴工具
fullscreenButton: false, //是否显示全屏按钮工具
});
viewer.scene.globe.depthTestAgainstTerrain = true
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
//屏幕坐标
console.log('屏幕坐标:', movement.position);
//屏幕坐标 转 世界坐标(场景坐标,包括地形、倾斜摄影模型等的坐标)
var cartesian3= viewer.scene.pickPosition(movement.position); //注意此处的屏幕坐标一定要在球上,否则结果为undefined
console.log('屏幕坐标转世界坐标(场景):', cartesian3);
//屏幕坐标 转 世界坐标(地表坐标,包括地形但不包括模型、倾斜摄影等)
var ray = viewer.camera.getPickRay(movement.position);
var cartesian3 = viewer.scene.globe.pick(ray, viewer.scene);
console.log('屏幕坐标转世界坐标(地表):', cartesian3);
//屏幕坐标 转 世界坐标(椭球面坐标,不包括地形、模型、倾斜摄影等)
var cartesian3= viewer.scene.camera.pickEllipsoid(movement.position)
console.log('屏幕坐标转世界坐标(椭球面):', cartesian3);
//世界坐标 转 屏幕坐标
var cartesian2 = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, cartesian3)
console.log('世界坐标转屏幕坐标:', cartesian2);
//世界坐标 转 WGS84坐标,结果为弧度形式
var cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
console.log('世界坐标转WGS84弧度坐标:', cartographic);
//WGS84弧度坐标 转 经纬度坐标
longitude = Cesium.Math.toDegrees(cartographic.longitude);
latitude = Cesium.Math.toDegrees(cartographic.latitude);
height = cartographic.height;
console.log('WGS84弧度坐标转WGS84经纬度坐标:' + longitude + ',' + latitude + ',' + height);
//WGS84经纬度坐标 转 弧度坐标
var radians = Cesium.Cartographic.fromDegrees(longitude, latitude, height);
console.log('WGS84经纬度转WGS84弧度坐标', radians);
//WGS84经纬度坐标 转 世界坐标
var position = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
console.log('WGS84经纬度转世界坐标', position);
//WGS84弧度坐标 转 世界坐标
var position2 = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height);
console.log('WGS84弧度转世界坐标', position2);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
</script>
</body>
</html>
(2)结果输出
运行代码后出现网页地球,按F12,调出控制台,点击球体一个位置,下图右侧控制台显示屏幕点坐标及其他坐标转换结果。

2.几何图形绘制
几何图形绘制一直以来都是GIS必备的基础功能之一,例如,点、线、面的绘制在各种GIS中屡见不鲜,而Cesium不仅支持点、线、面的绘制,还支持柱体、椭球体、盒子及三维模型等几何图形的绘制。
Cesium在几何图形绘制方面提供了两种不同类型的API:一种是较为高级的,不需要使用者对计算机图形学有很深的理解,可以直接拿来使用的API,即Entity API;另一种是面向图形开发人员的,更为复杂的API,即Primitive API。对于新手来说,本书推荐使用Entity API,因为Entity API本质上是对Primitive API的二次封装,目的是让使用者不必对计算机图形学有多么高深的理解,就能轻松绘制出各式各样的几何图形。
2.1Entity绘制实体
Entity通过Entity类实现实体绘制,支持点、线、面、椭球体、广告牌、盒子、标签、模型、墙等多种实体的绘制。用户可以手动创建实体并将它们添加到场景中,或者由数据源(如CzmlDataSource和GeoJsonDataSource)进行添加。此处以手动创建并添加实体为例来介绍各种类型的实体绘制方式。
(1)关键代码

4_2.1_Entity方式直接绘制.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.0">
<title>绘制实体_Entity方式</title>
<script src="./Build/Cesium/Cesium.js"></script>
<link rel="stylesheet" href="./Build/Cesium//Widgets/widgets.css">
<!-- <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script> -->
<style>
html,
body,
#cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
.toolbar {
position: absolute;
top: 10px;
left: 20px;
background-color: rgb(0, 0, 0, 0);
}
</style>
</head>
<body>
<div id="cesiumContainer">
</div>
<div id="menu" class="toolbar">
<select id="dropdown" onchange="addEntity()">
<option value="null">null</option>
<option value="addPoint">添加点</option>
<option value="addLines">添加线</option>
<option value="addPolygon">添加面</option>
<option value="addRectangle">添加矩形</option>
<option value="addEllipse">添加椭圆</option>
<option value="addCylinder">添加圆柱体</option>
<option value="addCorridor">添加走廊</option>
<option value="addWall">添加墙</option>
<option value="addBox">添加方盒</option>
<option value="addEllipsoid">添加球体</option>
<option value="addModel">添加模型</option>
<option value="addBillboard">添加广告牌</option>
</select>
<select id="dropdown2" onchange="removeEntity()">
<option value="null">null</option>
<option value="removePoint">删除点</option>
<option value="removeLines">删除线</option>
<option value="removePolygon">删除面</option>
<option value="removeRectangle">删除矩形</option>
<option value="removeEllipse">删除椭圆</option>
<option value="removeCylinder">删除圆柱体</option>
<option value="removeCorridor">删除走廊</option>
<option value="removeWall">删除墙</option>
<option value="removeBox">删除方盒</option>
<option value="removeEllipsoid">删除球体</option>
<option value="removeModel">删除模型</option>
<option value="removeBillboard">删除广告牌</option>
</select>
</div>
<script>
Cesium.Ion.defaultAccessToken =
'你的token';
var viewer = new Cesium.Viewer("cesiumContainer", {
animation: false, //是否显示动画工具
timeline: false, //是否显示时间轴工具
fullscreenButton: false, //是否显示全屏按钮工具
});
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(118, 32, 6000000),
orientation: {
heading: 0.010152402293521767,
pitch: -1.5705337480193866,
roll: 0.00003681052934645379
},
})
// 点
var addPoint = {
id: 'point',
name: '点',
show: true, //显示.
position: Cesium.Cartesian3.fromDegrees(118, 32, 0.0),
point: {
color: Cesium.Color.BLUE, //颜色
pixelSize: 5, //点大小
}
}
// 线
var addLine = {
id: 'line',
name: '线',
show: true, //显示
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([118, 30, 119, 32, 116, 35]),
width: 1, //线条粗细
material: Cesium.Color.RED, //线条材质
//clampToGround: true
}
}
//面
var addPolygon = {
id: 'polygon',
name: '面',
show: true,
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray([118, 30, 119, 32, 116, 32, 116, 30]),
//outline: false,
material: Cesium.Color.RED.withAlpha(0.4),
}
}
//矩形
var addRectangle = {
id: 'rectangle',
name: '矩形',
show: true,
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(80.0, 30.0, 100.0, 35.0),
material: Cesium.Color.BLUE.withAlpha(0.5),
/* height:0,
outline: true,
outlineWidth:10,
outlineColor: Cesium.Color.BLUE */
}
}
//椭圆
var addEllipse = {
id: 'ellipse',
name: '椭圆',
show: true,
position: Cesium.Cartesian3.fromDegrees(103.0, 40.0),
ellipse: {
semiMinorAxis: 250000.0, //短半轴
semiMajorAxis: 400000.0, //长半轴
material: Cesium.Color.RED.withAlpha(0.5),
/* height:0,
outline: true,
outlineColor: Cesium.Color.RED */
}
}
//圆柱体
var addCylinder = {
id: 'cylinder',
name: '圆柱体',
show: true,
//位置
position: Cesium.Cartesian3.fromDegrees(100.0, 40.0, 200000.0),
cylinder: {
length: 400000.0, //圆柱长度
topRadius: 200000.0, //顶面半径
bottomRadius: 200000.0, //底面半径
material: Cesium.Color.GREEN.withAlpha(0.6),
outline: false,
outlineColor: Cesium.Color.DARK_GREEN
}
}
//走廊
var addCorridor = {
id: 'corridor',
name: '走廊',
show: true,
corridor: {
positions: Cesium.Cartesian3.fromDegreesArray([
100.0, 40.0,
105.0, 40.0,
105.0, 35.0
]),
width: 200000.0,
material: Cesium.Color.YELLOW.withAlpha(0.5),
/* height:0,
outline: true, //外轮廓线
outlineColor: Cesium.Color.RED */
}
}
//墙
var addWall = {
id: 'wall',
name: '墙',
show: true,
wall: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights([
107.0, 43.0, 200000.0,
97.0, 43.0, 100000.0,
97.0, 40.0, 100000.0,
107.0, 40.0, 100000.0,
107.0, 43.0, 100000.0
]),
material: Cesium.Color.GREEN
}
}
//方盒
var addBox = {
id: 'box',
name: '方盒',
show: true,
position: Cesium.Cartesian3.fromDegrees(110, 35, 200000.0),
box: {
dimensions: new Cesium.Cartesian3(400000.0, 300000.0, 400000.0), //指定框的长度,宽度和高度
material: Cesium.Color.BLUE
}
}
//球体
var addEllipsoid = {
id: 'ellipsoid',
name: '椭球体',
show: true,
position: Cesium.Cartesian3.fromDegrees(107.0, 40.0, 300000.0),
ellipsoid: {
radii: new Cesium.Cartesian3(200000.0, 200000.0, 300000.0), //椭球的半径
material: Cesium.Color.BLUE.withAlpha(0.5),
outline: true,
outlineColor: Cesium.Color.WHITE
}
}
// 模型
var heading = Cesium.Math.toRadians(60); //60度航向
var pitch = 0; //俯仰角
var roll = 0; //翻滚角
var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
var addModel = {
id: 'model', //id唯一
name: '小车模型', // 名称
show: true, //显示
position: Cesium.Cartesian3.fromDegrees(118, 30, 5000), // 小车位置
orientation: Cesium.Transforms.headingPitchRollQuaternion(Cesium.Cartesian3.fromDegrees(118, 30, 5000),
hpr), //飞机航向
model: {
uri: './3D格式数据/glTF/CesiumMilkTruck.gltf',
minimumPixelSize: 300, //模型最小
maximumScale: 50000, //模型最大
//color: Cesium.Color.ORANGE, // 模型颜色
scale: 30000, //当前比例
}
}
//广告牌
var addBillboard = {
id: 'billboard',
name: '广告牌',
show: true,
position: Cesium.Cartesian3.fromDegrees(108, 30, 50),
billboard: {
image: './RasterImage/图片/single.jpg',
scale: 0.1, //比例
}
}
var dropdown = document.getElementById('dropdown');
var dropdown2 = document.getElementById('dropdown2');
function addEntity() {
switch (dropdown.value) {
case 'addPoint':
viewer.entities.add(addPoint);
break;
case 'addLines':
viewer.entities.add(addLine);
break;
case 'addPolygon':
viewer.entities.add(addPolygon);
break;
case 'addRectangle':
viewer.entities.add(addRectangle);
break;
case 'addEllipse':
viewer.entities.add(addEllipse);
break;
case 'addCylinder':
viewer.entities.add(addCylinder);
break;
case 'addCorridor':
viewer.entities.add(addCorridor);
break;
case 'addWall':
viewer.entities.add(addWall);
break;
case 'addBox':
viewer.entities.add(addBox);
break;
case 'addEllipsoid':
viewer.entities.add(addEllipsoid);
break;
case 'addModel':
viewer.entities.add(addModel);
break;
case 'addBillboard':
viewer.entities.add(addBillboard);
break;
default:
break;
}
}
function removeEntity() {
switch (dropdown2.value) {
case 'removePoint':
viewer.entities.removeById("point");
break;
case 'removeLines':
viewer.entities.removeById("line");
break;
case 'removePolygon':
viewer.entities.removeById("polygon");
break;
case 'removeRectangle':
viewer.entities.removeById("rectangle");
break;
case 'removeEllipse'

最低0.47元/天 解锁文章
1374

被折叠的 条评论
为什么被折叠?



