cesium------常用笔记
程序员文章站
2022-05-27 14:42:06
...
// 打开深度检测,那么在地形以下的对象不可见
viewer.scene.globe.depthTestAgainstTerrain = true;
//createWorldTerrain辅助函数去创建 Cesium全球地形 .
viewer.terrainProvider = Cesium.createWorldTerrain({
requestWaterMask : true, //告知Cesium去请求额外的水面数据
requestVertexNormals : true //告知Cesium去请求额外的光照数据
});
viewer.scene // 这个类控制了我们的viewer中所有的图形元素
// 开启全球光照
viewer.scene.globe.enableLighting = true;
在初始化视图之前,先学下基本的cesium 类型:
Cartesian3 : 三维笛卡尔(直角)坐标 – 当用来表示位置的时候,这个坐标指在地固坐标系(Earth fixed-frame (ECEF))下,相对地球中心的坐标位置,单位是米。
Cartographic :使用经纬度(弧度)和高度(WGS84地球高程)描述的三维坐标 。
HeadingPitchRoll :在ENU(East-North-Up)坐标系中,相对坐标轴的旋转(弧度)。Heading 相对负z轴(垂直向下). Pitch 相对负y轴. Roll相对正x轴.
Quaternion :使用四维坐标描述的三维旋转。
这是在Cesium的scene中摆放对象的基本类型,Cesium提供了一系列的方便的转换函数。具体请查看cesium文档。
Camera 是 viewer.scene的一个属性,用来控制当前可见范围。
一些最常用的方法:
Camera.setView(options) : 立即设置相机位置和朝向。
Camera.zoomIn(amount) : 沿着相机方向移动相机。
Camera.zoomOut(amount) : 沿着相机方向远离
Camera.flyTo(options) : 创建从一个位置到另一个位置的相机飞行动画。
Camera.lookAt(target, offset) : 依据目标偏移来设置相机位置和朝向。
Camera.move(direction, amount) : 沿着direction方向移动相机。
Camera.rotate(axis, angle) : 绕着任意轴旋转相机。
Cartesian3表示位置,
HeadingPitchRoll表示朝向。
Cesium使用 JulianDate 描述某个时刻。
下面是一些关于scene中时间的配置选项:
// 设置时钟和时间线
viewer.clock.shouldAnimate = true; // 当viewer开启后,启动动画
viewer.clock.startTime = Cesium.JulianDate.fromIso8601("2017-07-11T16:00:00Z");
viewer.clock.stopTime = Cesium.JulianDate.fromIso8601("2017-07-11T16:20:00Z");
viewer.clock.currentTime = Cesium.JulianDate.fromIso8601("2017-07-11T16:00:00Z");
viewer.clock.multiplier = 2; // 设置加速倍率
viewer.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER; // tick computation mode(还没理解具体含义)
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; // 循环播放
viewer.timeline.zoomTo(viewer.clock.startTime, viewer.clock.stopTime); // 设置时间的可见范围
Cesium支持流行的矢量格式GeoJson和KML,同时也支持自定义格式 CZML。无论最初是什么格式,所有的空间矢量数据在Cesium里都是使用Entity 相关API去展示的, Entity是一种对几何图形做空间和时间展示的数据对象。sandcastle 里提供了很多简单的entity。
//使用 KmlDataSource.load(optinos) 来从KML文件中读取点位数据。
var kmlOptions = {
camera : viewer.scene.camera,
canvas : viewer.scene.canvas,
clampToGround : true //控制数据是否贴地
};
// 从这个KML的url里加载POI点位 : http://catalog.opendata.city/dataset/pediacities-nyc-neighborhoods/resource/91778048-3c58-449c-a3f9-365ed203e914
var geocachePromise = Cesium.KmlDataSource.load('./Source/SampleData/sampleGeocacheLocations.kml', kmlOptions);
geocachePromise.then(function(dataSource) {
// 把所有entities添加到viewer中显示
viewer.dataSources.add(dataSource);
// 获得entity列表
var geocacheEntities = dataSource.entities.values;
for (var i = 0; i < geocacheEntities.length; i++) {
var entity = geocacheEntities[i];
if (Cesium.defined(entity.billboard)) {
// 对这个entity设置样式
}
}
});
if (Cesium.defined(entity.billboard)) {
// 调整垂直方向的原点,保证图标里的针尖对着地表位置
entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
// 去掉文字的显示
entity.label = undefined;
// 设置可见距离
entity.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10.0, 20000.0); //控制只显示和相机一定距离内的点.
}
// 设置样式代码,entity.properties来存储GeoJson的属性。
// 把properties里的neighborhood设置到name
entity.name = entity.properties.neighborhood
// 为了避免所有多边形颜色都相同,可以使用一个随机颜色 Color去设置每个多边形的 ColorMaterialProperty属性。
// 设置一个随机半透明颜色
entity.polygon.material = Cesium.Color.fromRandom({
red : 0.1,
maximumGreen : 0.5,
minimumBlue : 0.5,
alpha : 0.6
});
// 设置这个属性让多边形贴地,ClassificationType.CESIUM_3D_TILE 是贴模型,ClassificationType.BOTH是贴模型和贴地
entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;
// 获取多边形的positions列表 并计算它的中心点
var polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;
var polyCenter = Cesium.BoundingSphere.fromPoints(polyPositions).center;
polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);
entity.position = polyCenter;
// 生成文字标注
entity.label = {
text : entity.name,
showBackground : true,
scale : 0.6,
horizontalOrigin : Cesium.HorizontalOrigin.CENTER,
verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
distanceDisplayCondition : new Cesium.DistanceDisplayCondition(10.0, 8000.0),
disableDepthTestDistance : 100.0 // 确保这个标注不会被其他对象盖住
};
// 基于无人机轨迹的位置点,自动计算朝向
drone.orientation = new Cesium.VelocityOrientationProperty(drone.position);
//为了飞行路径更平滑,可以如下修改配置 :
// 光滑的路径插值
drone.position.setInterpolationOptions({
interpolationDegree : 3,
interpolationAlgorithm : Cesium.HermitePolynomialApproximation
});
// 3D Tiles,它是一个流式载入海量各种类型得空间三维数据的开放协议,使用一种类似Cesium的地形和影像数据切片技术,3d tiles格式使原先那些不可能做可视化交互的大模型数据能够展示出来,包括建筑物数据、CAD(或者BIM)模型,点云,倾斜模型。
//使用 Cesium3DTileset 类添加整个纽约的真实建筑物模型,改进了可视化效果的真实性。
// 加载纽约建筑物模型
var city = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({ url: Cesium.IonResource.fromAssetId(3839) }))
// 调整3dtile模型的高度,让他刚好放在地表
//把数据当前的包围球转为Cartographic,就能计算出模型现在相对于地面的偏移,然后增加这个偏移值,然后重设modelMatrix:
var heightOffset = -32;
city.readyPromise.then(function(tileset) {
// Position tileset
var boundingSphere = tileset.boundingSphere;
var cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation); //通过 modelMatrix,我们可以调整这个数据的位置。
});
// 根据Cesium3DTileFeature模型属性去修改某一部分甚至某一栋建筑物的颜色(RGB和透明度)
var defaultStyle = new Cesium.Cesium3DTileStyle({
color : "color('white', 0.3)", //0.3为设置建筑物半透明状
show : true
});
city.style = defaultStyle; //这个样式只是简单的让纽约的所有建筑都可见。把它设置到 city.style就可以看到可视化效果。
下面是一个依据建筑高度去着色的示例:
var heightStyle = new Cesium.Cesium3DTileStyle({
color : {
conditions : [
["${height} >= 300", "rgba(45, 0, 75, 0.5)"],
["${height} >= 200", "rgb(102, 71, 151)"],
["${height} >= 100", "rgb(170, 162, 204)"],
["${height} >= 50", "rgb(224, 226, 238)"],
["${height} >= 25", "rgb(252, 230, 200)"],
["${height} >= 10", "rgb(248, 176, 87)"],
["${height} >= 5", "rgb(198, 106, 11)"],
["true", "rgb(127, 59, 8)"]
]
}
});
// 为了在这些样式之间切换,增加代码去监听HTML的输入框变化:
var tileStyle = document.getElementById('tileStyle');
function set3DTileStyle() {
var selectedStyle = tileStyle.options[tileStyle.selectedIndex].value;
if (selectedStyle === 'none') {
city.style = defaultStyle;
} else if (selectedStyle === 'height') {
city.style = heightStyle;
} else if (selectedStyle === 'transparent') {
city.style = transparentStyle;
}
}
tileStyle.addEventListener('change', set3DTileStyle);
// 拾取技术(picking),它能够根据一个屏幕上的像素位置返回三维场景中的对象信息。
有好几种拾取:
Scene.pick : 返回窗口坐标对应的图元的第一个对象。
Scene.drillPick :返回窗口坐标对应的所有对象列表。
Globe.pick : 返回一条射线和地形的相交位置点。
因为我们想实现鼠标滑过的高亮效果,首先需要创建一个鼠标事件处理器。 ScreenSpaceEventHandler是可以处理一系列的用户输入事件的处理器. ScreenSpaceEventHandler.setInputAction()``](/Cesium/Build/Documentation/ScreenSpaceEventHandler.html#setInputAction) 监听某类型的用户输入事件 -- [ScreenSpaceEventType`用户输入事件类型,做为一个参数传递过去。这里我们设置一个回调函数来接受鼠标移动事件:
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function(movement) {}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// 我们使用一个变量来存储上次的高亮图标,当鼠标不在它上面的时候,恢复它原来的样式。
这是包含高亮和不高亮完整功能的代码:
var previousPickedEntity = undefined;
handler.setInputAction(function(movement) {
var pickedPrimitive = viewer.scene.pick(movement.endPosition);
var pickedEntity = (Cesium.defined(pickedPrimitive)) ? pickedPrimitive.id : undefined;
// 取消上一个高亮对象的高亮效果
if (Cesium.defined(previousPickedEntity)) {
previousPickedEntity.billboard.scale = 1.0;
previousPickedEntity.billboard.color = Cesium.Color.WHITE;
}
// 当前entity高亮
if (Cesium.defined(pickedEntity) && Cesium.defined(pickedEntity.billboard)) {
pickedEntity.billboard.scale = 2.0;
pickedEntity.billboard.color = Cesium.Color.ORANGERED;
previousPickedEntity = pickedEntity;
}
//这是相机模式代码:
function setViewMode() {
if (droneModeElement.checked) {
viewer.trackedEntity = drone; // 相机也能和目标之间保持一个固定的偏移距离
} else {
viewer.trackedEntity = undefined; // 切换到*模式
viewer.scene.camera.flyTo(homeCameraView); //返回到初始位置。
}
}
// 只需要把这个函数绑定到HTML元素的change事件上。当我们双击entity的时候,就会自动进行跟随模式。
var freeModeElement = document.getElementById('freeMode');
var droneModeElement = document.getElementById('droneMode');
function setViewMode() {
if (droneModeElement.checked) {
viewer.trackedEntity = drone;
} else {
viewer.trackedEntity = undefined;
viewer.scene.camera.flyTo(homeCameraView);
}
}
freeModeElement.addEventListener('change', setCameraMode);
droneModeElement.addEventListener('change', setCameraMode);
//如果用户通过点击跟踪无人机,添加一些处理去自动更新UI界面:
viewer.trackedEntityChanged.addEventListener(function() {
if (viewer.trackedEntity === drone) {
freeModeElement.checked = false;
droneModeElement.checked = true;
}
});
// 通过设置EntityCollection的 show 属性来控制。只需要设置一次neighborhoods.show属性即可控制所有entity的可见性。
var neighborhoodsElement = document.getElementById('neighborhoods');
neighborhoodsElement.addEventListener('change', function (e) {
neighborhoods.show = e.target.checked;
});
// 因为3D Tiles数据可能不是瞬间载入,可以添加一个载入指示器,当所有切片都载入后隐藏。
// 当城市数据初始化完成后,移除加载指示器
var loadingIndicator = document.getElementById('loadingIndicator');
loadingIndicator.style.display = 'block';
city.readyPromise.then(function () {
loadingIndicator.style.display = 'none';
});
上一篇: Map pins