C/C++教程

Cesium加载三维路线

本文主要是介绍Cesium加载三维路线,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1. 概述

将路线加载到三维地图中,能直观显示道路的坡度变化,协同DEM和遥感影像,能极大丰富道路的可视化效果

本文此处基于Cesium,加载地形数据,叠加遥感影像,再叠加路网数据,形成三维地图,效果如下:

image-20220506023737750

2. 代码实现

2.1 CDN引入

笔者这里使用 CDN 引入 Cesium,另外后续加载路网数据需要使用Ajax,这里引入jQuery

<!-- Include the CesiumJS JavaScript and CSS files -->
<script src="https://cesium.com/downloads/cesiumjs/releases/1.92/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.92/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

2.2 加载地形

笔者这里使用Cesium的地形数据

// Initialize the Cesium Viewer in the HTML element with the `cesiumContainer` ID.
var viewer = new Cesium.Viewer('cesiumContainer', {
    terrainProvider: Cesium.createWorldTerrain()
});

2.3 加载遥感影像

笔者这里使用Bing的遥感影像

var bingStyle = [
    Cesium.BingMapsStyle.AERIAL_WITH_LABELS,
    Cesium.BingMapsStyle.COLLINS_BART,
    Cesium.BingMapsStyle.CANVAS_GRAY,
    Cesium.BingMapsStyle.CANVAS_LIGHT,
    Cesium.BingMapsStyle.CANVAS_DARK,
    Cesium.BingMapsStyle.ORDNANCE_SURVEY,
    Cesium.BingMapsStyle.ROAD,
    Cesium.BingMapsStyle.AERIAL,
];
var bingMapProvider = new Cesium.BingMapsImageryProvider({
    url: "https://dev.virtualearth.net",
    key: "AmXdbd8UeUJtaRSn7yVwyXgQlBBUqliLbHpgn2c76DfuHwAXfRrgS5qwfHU6Rhm8",
    mapStyle: bingStyle[7],
});
viewer.imageryLayers.addImageryProvider(bingMapProvider);

2.4 设置视点

笔者这里将视点即观察点设置为长沙岳麓山附近

// Fly the camera to Changsha at the given longitude, latitude, and height.
viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(112.9448, 28.1708, 1200),
    orientation: {
        heading: Cesium.Math.toRadians(0.0),
        pitch: Cesium.Math.toRadians(-15.0),
    }
});

2.5 小结测试

到目前为止,整体代码如下:

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="utf-8">
    <!-- Include the CesiumJS JavaScript and CSS files -->
    <script src="https://cesium.com/downloads/cesiumjs/releases/1.92/Build/Cesium/Cesium.js"></script>
    <link href="https://cesium.com/downloads/cesiumjs/releases/1.92/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
</head>

<body>
    <div id="cesiumContainer"></div>
    <script>
        // Your access token can be found at: https://cesium.com/ion/tokens.
        // Replace `your_access_token` with your Cesium ion access token.

        // Cesium.Ion.defaultAccessToken = 'your_access_token';

        // Initialize the Cesium Viewer in the HTML element with the `cesiumContainer` ID.
        var viewer = new Cesium.Viewer('cesiumContainer', {
            terrainProvider: Cesium.createWorldTerrain()
        });

        var bingStyle = [
            Cesium.BingMapsStyle.AERIAL_WITH_LABELS,
            Cesium.BingMapsStyle.COLLINS_BART,
            Cesium.BingMapsStyle.CANVAS_GRAY,
            Cesium.BingMapsStyle.CANVAS_LIGHT,
            Cesium.BingMapsStyle.CANVAS_DARK,
            Cesium.BingMapsStyle.ORDNANCE_SURVEY,
            Cesium.BingMapsStyle.ROAD,
            Cesium.BingMapsStyle.AERIAL,
        ];
        var bingMapProvider = new Cesium.BingMapsImageryProvider({
            url: "https://dev.virtualearth.net",
            key: "AmXdbd8UeUJtaRSn7yVwyXgQlBBUqliLbHpgn2c76DfuHwAXfRrgS5qwfHU6Rhm8",
            mapStyle: bingStyle[7],
        });
        viewer.imageryLayers.addImageryProvider(bingMapProvider);

        // Fly the camera to Changsha at the given longitude, latitude, and height.
        viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(112.9448, 28.1708, 1200),
            orientation: {
                heading: Cesium.Math.toRadians(0.0),
                pitch: Cesium.Math.toRadians(-15.0),
            }
        });

    </script>
    </div>
</body>

</html>

我们测试其效果,笔者这里使用的是VS Code的Live Server插件打开:

image-20220506024724036

2.6 路网加载

路网(Ployline)的加载方式主要有两种:

  • 使用Viewer.entities
  • 使用Cesium.GroundPolylinePrimitive

此处笔者的示例数据如下:

112.91725386767241,28.18088394284931,47.28909519744873
112.91765398304703,28.18080062181755,52.27461015478515
112.94271541045252,28.18907071666184,34.729803589843755
112.94263996370492,28.18929672498712,44.796474171875005
112.94263996370492,28.18929672498712,44.796474171875005
112.94271541045252,28.18907071666184,34.729803589843755
112.94264628370074,28.190083096717974,36.39323925
112.94259227750655,28.18977721403619,24.70917075
112.94259227750655,28.18977721403619,24.70917075
112.94264628370074,28.190083096717974,36.39323925
112.94264628370074,28.190083096717974,36.39323925
112.94255004568583,28.19039785102342,46.969459281249996
112.94255004568583,28.19039785102342,46.969459281249996
112.94264628370074,28.190083096717974,36.39323925
112.94263996370492,28.18929672498712,44.796474171875005
112.942639007202,28.18939392688125,41.37971635546875
112.942639007202,28.18939392688125,41.37971635546875
112.94263996370492,28.18929672498712,44.796474171875005
112.942639007202,28.18939392688125,41.37971635546875
112.94259227750655,28.18977721403619,24.70917075
112.94259227750655,28.18977721403619,24.70917075
112.942639007202,28.18939392688125,41.37971635546875
112.94255707716033,28.19747999678687,78.00138119911344
112.94251096347146,28.197641540468794,62.308529711560176
112.94251096347146,28.197641540468794,62.308529711560176
112.94251086130572,28.19765191789022,62.308529711560176
112.94251086130572,28.19765191789022,62.308529711560176
112.94216077246415,28.19774676732831,88.14892901957208
112.94251096347146,28.197641540468794,62.308529711560176
112.94255707716033,28.19747999678687,78.00138119911344
112.94251086130572,28.19765191789022,62.308529711560176
112.94251096347146,28.197641540468794,62.308529711560176

数据文件的名字为trans_final_map_with_dem.csv,笔者使用Ajax加载并解析

前者Viewer.entities的代码如下:

$.ajax({
    url: 'trans_final_map_with_dem.csv',
    dataType: 'text',
}).done(successFunction);

var groundPolylineGeometryInstances = [];
function successFunction(data) {
    var allRows = data.split(/\r?\n|\r/);
    for (let i = 0; i < allRows.length - 1; i = i + 2) {
        var rowCell1 = allRows[i].split(',');
        var rowCell2 = allRows[i + 1].split(',');

        viewer.entities.add({
            polyline: {
                positions: Cesium.Cartesian3.fromDegreesArrayHeights([
                    rowCell1[0], rowCell1[1],rowCell1[2],
                    rowCell2[0], rowCell2[1],rowCell2[2]
                ]),
                width: 4.0,
                material: Cesium.Color.ORANGE,
                clampToGround: true
            }
        })
    }
}

后者Cesium.GroundPolylinePrimitive的代码如下:

$.ajax({
    url: 'trans_final_map_with_dem.csv',
    dataType: 'text',
}).done(successFunction);

var groundPolylineGeometryInstances = [];
function successFunction(data) {
    var allRows = data.split(/\r?\n|\r/);
    for (let i = 0; i < allRows.length - 1; i = i + 2) {
        var rowCell1 = allRows[i].split(',');
        var rowCell2 = allRows[i + 1].split(',');

        groundPolylineGeometryInstances.push(new Cesium.GeometryInstance({
            geometry: new Cesium.GroundPolylineGeometry({
                positions: Cesium.Cartesian3.fromDegreesArrayHeights([
                    rowCell1[0], rowCell1[1], rowCell1[2],
                    rowCell2[0], rowCell2[1], rowCell2[2]
                ]),
                width: 4.0,
            }),
            attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.ORANGE.withAlpha(1.0))
            }
        }));
    }
    var groundPolylinePrimitive = new Cesium.GroundPolylinePrimitive({
        geometryInstances: groundPolylineGeometryInstances,
        show: true,
        appearance: new Cesium.PolylineColorAppearance()
    });
    viewer.scene.groundPrimitives.add(groundPolylinePrimitive)
}

注意:

  • 笔者这里的数据是每两个点构成一个Polyline,每一行最后是换行符'\n'
  • 数据量大时尽可能使用Cesium.GroundPolylinePrimitive

2.7 最终测试

整体代码如下:

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="utf-8">
    <!-- Include the CesiumJS JavaScript and CSS files -->
    <script src="https://cesium.com/downloads/cesiumjs/releases/1.92/Build/Cesium/Cesium.js"></script>
    <link href="https://cesium.com/downloads/cesiumjs/releases/1.92/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
</head>

<body>
    <div id="cesiumContainer"></div>
    <script>
        // Your access token can be found at: https://cesium.com/ion/tokens.
        // Replace `your_access_token` with your Cesium ion access token.

        // Cesium.Ion.defaultAccessToken = 'your_access_token';

        // Initialize the Cesium Viewer in the HTML element with the `cesiumContainer` ID.
        var viewer = new Cesium.Viewer('cesiumContainer', {
            terrainProvider: Cesium.createWorldTerrain()
        });

        var bingStyle = [
            Cesium.BingMapsStyle.AERIAL_WITH_LABELS,
            Cesium.BingMapsStyle.COLLINS_BART,
            Cesium.BingMapsStyle.CANVAS_GRAY,
            Cesium.BingMapsStyle.CANVAS_LIGHT,
            Cesium.BingMapsStyle.CANVAS_DARK,
            Cesium.BingMapsStyle.ORDNANCE_SURVEY,
            Cesium.BingMapsStyle.ROAD,
            Cesium.BingMapsStyle.AERIAL,
        ];
        var bingMapProvider = new Cesium.BingMapsImageryProvider({
            url: "https://dev.virtualearth.net",
            key: "AmXdbd8UeUJtaRSn7yVwyXgQlBBUqliLbHpgn2c76DfuHwAXfRrgS5qwfHU6Rhm8",
            mapStyle: bingStyle[7],
        });
        viewer.imageryLayers.addImageryProvider(bingMapProvider);

        $.ajax({
            url: 'trans_final_map_with_dem.csv',
            dataType: 'text',
        }).done(successFunction);

        // const polylines = new Cesium.PolylineCollection();
        var groundPolylineGeometryInstances = [];
        function successFunction(data) {
            var allRows = data.split(/\r?\n|\r/);
            for (let i = 0; i < allRows.length - 1; i = i + 2) {
                var rowCell1 = allRows[i].split(',');
                var rowCell2 = allRows[i + 1].split(',');

                //     viewer.entities.add({
                //         polyline: {
                //             positions: Cesium.Cartesian3.fromDegreesArrayHeights([
                //                 rowCell1[0], rowCell1[1],rowCell1[2],
                //                 rowCell2[0], rowCell2[1],rowCell2[2]
                //             ]),
                //             width: 4.0,
                //             material: Cesium.Color.ORANGE,
                //             clampToGround: true
                //         }
                //     })
                // }
                groundPolylineGeometryInstances.push(new Cesium.GeometryInstance({
                    geometry: new Cesium.GroundPolylineGeometry({
                        positions: Cesium.Cartesian3.fromDegreesArrayHeights([
                            rowCell1[0], rowCell1[1], rowCell1[2],
                            rowCell2[0], rowCell2[1], rowCell2[2]
                        ]),
                        width: 4.0,
                    }),
                    attributes: {
                        color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.ORANGE.withAlpha(1.0))
                    }
                }));
                // }
            }
            var groundPolylinePrimitive = new Cesium.GroundPolylinePrimitive({
                geometryInstances: groundPolylineGeometryInstances,
                show: true,
                appearance: new Cesium.PolylineColorAppearance()
            });
            viewer.scene.groundPrimitives.add(groundPolylinePrimitive)
        }

        // Fly the camera to Changsha at the given longitude, latitude, and height.
        viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(112.9448, 28.1708, 1200),
            orientation: {
                heading: Cesium.Math.toRadians(0.0),
                pitch: Cesium.Math.toRadians(-15.0),
            }
        });

    </script>
    </div>
</body>

</html>

最后效果如下:

image-20220506023737750

参考资料

[1]Sandcastle

[2]Polylines on Terrain

[3]cesiumjs/ref-doc/Viewer

[4]遥感影像和DEM数据获取处理、GeoServer切片发布并使用Cesium加载

这篇关于Cesium加载三维路线的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!