欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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';
});
相关标签: cesium