当前位置: 首页 > news >正文

Cesium实现三维可视化一般步骤

在项目的开发过程中用到在底图显示三维可视化图形,涉及到加载大批量的数据,经过查阅资料,决定采用Cesium设计一个实现方案,在底图显示3d模型以及与3d模型之间的一系列交互行为,下面分步骤详细进行介绍:

  1. 创建查看器—将查看器添加到指定的铯容器cesiumContainer,可以实现底图的切换,加载天地图。代码如下所示:
var viewer = new Cesium.Viewer('cesiumContainer', {
        imageryProvider : new Cesium.createOpenStreetMapImageryProvider({
            url : 'https://a.tile.openstreetmap.org/'
        }),
        baseLayerPicker : false,
        animation : false,
        timeline : false,
        fullscreenButton : false,
        infoBox : false,
        homeButton : false
    });

2.相机控制—由属性viewer.scene控制当前可见的内容,可以通过设置相机的位置和方向来控制相机切换视角,也可以使用cesium相机API来设置相机的位置和方向。

//Create an initial camera view
    var initialPosition = new Cesium.Cartesian3.fromDegrees(-73.848114468289017509, 40.824512895646692812, 2631.082799425431);
    var initialOrientation = new Cesium.HeadingPitchRoll.fromDegrees(7.1077496389876024807, -31.987223091598949054, 0.025883251314954971306);
    var homeCameraView = {
        destination : initialPosition,
        orientation : {
            heading : initialOrientation.heading,//围绕负z轴的旋转
            pitch : initialOrientation.pitch,//围绕负y轴的旋转
            roll : initialOrientation.roll//围绕正x轴的旋转
        }
    };
    viewer.scene.camera.setView(homeCameraView);  //将相机设定在特定的位置和方向

3.加载样式实体—为了便于观看,cesium支持流行的矢量格式GeoJson和KML,以及我们专门为描述cesium中称为CZML的场景而开发的开放格式。其中DataSource只是定义了一个接口,需要的确切类型的数据源将取决于数据格式。

(1) KML使用KmlDataSource,通过调用KmlDataSource.load(optinos)几个选项从KML文件中读取我们的示例geocache点。对于KmlDataSource,需要相机和画布选项。该clampToGround选项支持地面夹紧,这是一种流行的显示选项,可使地形几何实体(如多边形和椭圆)符合地形而不是曲线到WGS84椭球表面。

var kmlOptions = {
        camera : viewer.scene.camera,//相机选项
        canvas : viewer.scene.canvas,//画布选项
        clampToGround : true
    };
    // Load geocache points of interest from a KML file
    var geocachePromise = Cesium.KmlDataSource.load('./SampleData/kml/bikeRide.kml', kmlOptions);
    // Add geocache billboard entities to scene and style them
    geocachePromise.then(function(dataSource) {
        // Add the new data as entities to the viewer
        viewer.dataSources.add(dataSource);
        // Get the array of entities
        var geocacheEntities = dataSource.entities.values;
        for (var i = 0; i < geocacheEntities.length; i++) {
            var entity = geocacheEntities[i];
            if (Cesium.defined(entity.billboard)) {
                // Adjust the vertical origin so pins sit on terrain
                entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
                // Disable the labels to reduce clutter
                entity.label = undefined;
                // Add distance display condition
                entity.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10.0, 20000.0);
                // Compute latitude and longitude in degrees
                var cartographicPosition = Cesium.Cartographic.fromCartesian(entity.position.getValue(Cesium.JulianDate.now()));
                var latitude = Cesium.Math.toDegrees(cartographicPosition.latitude);
                var longitude = Cesium.Math.toDegrees(cartographicPosition.longitude);
                // Modify description
                var description = '<table class="cesium-infoBox-defaultTable cesium-infoBox-defaultTable-lighter"><tbody>';
                description += '<tr><th>' + "Latitude" + '</th><td>' + latitude + '</td></tr>';
                description += '<tr><th>' + "Longitude" + '</th><td>' + longitude + '</td></tr>';
                description += '</tbody></table>';
                entity.description = description;
            }
        }
    });
(2) GeoJson与加载KML的过程非常相似,在这种情况下,可以使用GeoJsonDataSource代替,和前面的数据源一样,需要将viewer.dataSources添加数据到场景中。这种加载方式只是实现的平面的,可以通过自行设置高度entity.polygon.extrudedHeight读取每个实体属性中的高度
使建筑物看起来有一定的高度,切换视角,达到三维效果;加载geojson文件添加鼠标交互行为不生效;使用这种方式加载大批量的建筑物会造成浏览器卡顿甚至崩溃。
var geojsonOptions = {
        clampToGround : true
    };
    // Load neighborhood boundaries from KML file
    var neighborhoodsPromise = Cesium.GeoJsonDataSource.load('./SampleData/test.geojson', geojsonOptions);

    // Save an new entity collection of neighborhood data
    var neighborhoods;
    neighborhoodsPromise.then(function(dataSource) {
        // Add the new data as entities to the viewer
        var city = viewer.dataSources.add(dataSource);
        neighborhoods = dataSource.entities;
        // Get the array of entities
        var neighborhoodEntities = dataSource.entities.values;
        for (var i = 0; i < neighborhoodEntities.length; i++) {
            var entity = neighborhoodEntities[i];
            if (Cesium.defined(entity.polygon)) {
                // entity styling code here
                entity.name = entity.properties.neighborhood;
       //          entity.polygon.material = Cesium.Color.fromRandom({
                //     red : 0.4,
                //     maximumGreen :0.8,
                //     minimumBlue : 0.6,
                //     alpha :1
                // });
                entity.polygon.material = Cesium.Color.YELLOW;
                entity.polygon.outline = false;
                // Tells the polygon to color the terrain. ClassificationType.CESIUM_3D_TILE will color the 3D tileset, and ClassificationType.BOTH will color both the 3d tiles and terrain (BOTH is the default)
                entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;
                // Generate Polygon position
                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.polygon.extrudedHeight = entity.properties.height;
                // entity.polygon.height = entity.properties.height;
                // Generate labels
                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
                };
            }
        }
        //加载的建筑物的总数
        console.log(neighborhoodEntities.length);
    });
(3) Cesium支持基于glTF(GL传输格式)加载3D模型,加载模型与迄今为止我们使用过的任何其他类型的可视化没有什么不同,所需要的只是实体的位置和glTF模型的一个URL;每个模型都有自己的原始COLLADA文件(.dae)和glTF文件(.gltf),在Cesium中我们不需要原始的COLLADA文件,需要的只是经过3d
max转化后的gltf文件以及相应的贴图文件。(例子中定位到宾夕法尼亚州埃克斯顿就是通过加载.gltf格式的数据渲染到地图上)。
var scene = viewer.scene;
    var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
    Cesium.Cartesian3.fromDegrees(-75.62898254394531, 40.02804946899414, 0.0));
    var model = scene.primitives.add(Cesium.Model.fromGltf({
        url : './SampleData/models/CesiumGround/Cesium_Ground.gltf',
        modelMatrix : modelMatrix,
        scale : 200.0
    }));

4、 鼠标交互—只有在加载3d Tiles的时候,才可以用鼠标实现交互选择和样式改变,否则这些模型将无法以交互方式查看。在这种情况下可以加载大批量的模型建筑物信息。例如viewer.scene.primitives.add(new Cesium.Cesium3DTileset({ url: Cesium.IonResource.fromAssetId(3839) }));显示纽约所有的建筑物完整的3d模型,从而为三维可视化添加真实感。

说明:如果要加载大批量的模型,以dataSource加载geojson文件的方法可能会造成浏览器卡顿甚至崩溃的现象;3d Tiles才是实现加载大规模场景应用的最佳选择,而且依赖于3d Tiles还可以实现鼠标交互改变样式等。

相关文章:

  • Vue2.0 探索之路——生命周期和钩子函数的一些理解
  • vuejs实践todolist列表
  • vue中的watch监听事件机制
  • CommonJS、AMD、CMD的区别
  • npm局部安装和全局安装文件的区别
  • querySelector操作dom的用法
  • webpack打包文件出错
  • npm中的--save-dev与--save的区别
  • vue-router路由导航钩子
  • javascript本地上传并解析excel文件
  • echarts柱状图的x轴文字纵向显示
  • ajax实现跨域请求的几种方式--前端
  • css3-单位px与vw,rem的区别
  • openlayers4通过拖动滑动条设置图层颜色透明度
  • openlayers4判断一个点是否在闭合图形的内部
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • css系列之关于字体的事
  • JAVA之继承和多态
  • leetcode46 Permutation 排列组合
  • Mysql优化
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • 高程读书笔记 第六章 面向对象程序设计
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 如何优雅地使用 Sublime Text
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 项目实战-Api的解决方案
  • 智能合约Solidity教程-事件和日志(一)
  • 函数计算新功能-----支持C#函数
  • ​ArcGIS Pro 如何批量删除字段
  • "无招胜有招"nbsp;史上最全的互…
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • (06)金属布线——为半导体注入生命的连接
  • (11)MATLAB PCA+SVM 人脸识别
  • (12)Hive调优——count distinct去重优化
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (33)STM32——485实验笔记
  • (BFS)hdoj2377-Bus Pass
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (Matlab)基于蝙蝠算法实现电力系统经济调度
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (转)Google的Objective-C编码规范
  • (转)Linux整合apache和tomcat构建Web服务器
  • ******之网络***——物理***
  • .java 指数平滑_转载:二次指数平滑法求预测值的Java代码
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .net 简单实现MD5
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • ?
  • @Autowired注解的实现原理