3D Tiles Feature Picking.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">  <!-- Use Chrome Frame in IE -->
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <meta name="description" content="Pick features in a 3D Tiles tileset.">
    <meta name="cesium-sandcastle-labels" content="Showcases, 3D Tiles">
    <title>3D Tiles Feature Picking</title>
    <script type="text/javascript" src="../Sandcastle-header.js"></script>
    <script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
    <script type="text/javascript">
        require.config({
            baseUrl : '../../../Source',
            waitSeconds : 60
        });
    </script>
</head>

<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
    @import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<script id="cesium_sandcastle_script">
    function startup(Cesium) {
        'use strict';
        //Sandcastle_Begin
        // 三维瓷砖特征提取,包含悬停及选择行为。
        // 建立纽约开放数据门户网站提供的数据: http://www1.nyc.gov/site/doitt/initiatives/3d-building.page
        Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiMGRjM2QxYi04ODM2LTQzMDEtOGJmOS1mNDlkY2Q2NjE4MjciLCJpZCI6MjU5LCJpYXQiOjE1MjU5NjYyMDd9.xW9loNLo68KE3ReAHd-Lp73M8qJKhI9vA0wYL-qJX_I';
        var viewer = new Cesium.Viewer('cesiumContainer', {
            terrainProvider: Cesium.createWorldTerrain()
        });
        // true时,原语(如广告牌、折线、标签等)应该根据地形表面进行深度测试,
        // false时,这类原语应该总是绘制在地形的上边,除非它们位于地球的另一边。
        // 基于地形的深度测试原语的缺点是,轻微的数值噪声或地形细节水平的切换有时会使表面上的原语消失在它下面。
        // 默认值:false。
        viewer.scene.globe.depthTestAgainstTerrain = true;

        // 设置摄像机初始视图为曼哈顿
        var initialPosition = Cesium.Cartesian3.fromDegrees(-74.01881302800248, 40.69114333714821, 753);
        // Cesium.HeadingPitchRoll.fromDegrees(heading, pitch, roll, result) → HeadingPitchRoll
        var initialOrientation = new Cesium.HeadingPitchRoll.fromDegrees(21.27879878293835, -21.34390550872461, 0.0716951918898415);
        // 设置摄影机位置、方向和变换。
        viewer.scene.camera.setView({
            // 目的地,相机在WGS 84(World)坐标的最终位置 或 从自顶向下视图中的可见矩形的最终位置。
            destination: initialPosition,
            // 视角方向
            orientation: initialOrientation,
            // 变换矩阵表示摄像机的参考帧。
            endTransform: Cesium.Matrix4.IDENTITY
        });

        // 加载纽约市建筑群瓦片集。
        var tileset = new Cesium.Cesium3DTileset({ url: Cesium.IonResource.fromAssetId(5741) });
        // viewer.scene.primitives,原语集。
        // 将原语添加到集合中。
        viewer.scene.primitives.add(tileset);

        // nameOverlay, “名称div”, 用于在鼠标悬浮在特性上时,显示该特性的名称。
        var nameOverlay = document.createElement('div');
        // viewer.container,获取viewer的父容器,此处相当于body(我猜的)
        // 给视图添加兄弟元素div。
        viewer.container.appendChild(nameOverlay);
        // 给“名称div”添加样式(类)。
        nameOverlay.className = 'backdrop';
        // 先不显示。
        nameOverlay.style.display = 'none';
        // “名称div”的位置,“绝对定位”。
        nameOverlay.style.position = 'absolute';
        // 初始化“名称div”的位置(左下角)。
        nameOverlay.style.bottom = '0';
        nameOverlay.style.left = '0';
        nameOverlay.style['pointer-events'] = 'none';
        // “名称div”的内边距4px。
        nameOverlay.style.padding = '4px';
        // “名称div”的背景颜色,“黑色”。
        nameOverlay.style.backgroundColor = 'black';

        // 初始化当前选定特性的信息(以备当有特性选中时,对selected进行赋值操作)。
        var selected = {
            feature: undefined,
            // new Cesium.Color(red, green, blue, alpha),
            // 使用红色、绿色、蓝色和alpha值指定的颜色,范围从0(无强度)到1.0(完全强度)。
            originalColor: new Cesium.Color()
        };

        // selectedEntity,用于保存当前选中的特性信息,该信息用于信息框的显示。
        var selectedEntity = new Cesium.Entity();

        // new Cesium.ScreenSpaceEventHandler(element),
        // element(类型Canvas,默认document)要向其添加事件的元素,
        // 处理用户输入事件。当用户输入时,可以添加自定义函数来执行。

        // 获得默认的左击处理程序,用于在左击未选择某个特性时使用。
        // getInputAction(type, modifier),返回要在输入事件上执行的函数。
        var clickHandler = viewer.screenSpaceEventHandler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);

        // PostProcessStageLibrary,包含用于创建常见的后处理阶段的函数。
        // Cesium.PostProcessStageLibrary.isSilhouetteSupported(scene) → Boolean
        // 是否支持剪影阶段。此阶段需要WEBGL_depth_texture扩展。
        // 如果支持剪影(轮廓),鼠标悬浮在特征上时,特征轮廓为蓝色;鼠标单击时轮廓为绿色
        if (Cesium.PostProcessStageLibrary.isSilhouetteSupported(viewer.scene)) {
            // 支持剪影(轮廓)
            var silhouetteBlue = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
            silhouetteBlue.uniforms.color = Cesium.Color.BLUE;
            silhouetteBlue.uniforms.length = 0.01;
            silhouetteBlue.selected = [];

            var silhouetteGreen = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
            silhouetteGreen.uniforms.color = Cesium.Color.LIME;
            silhouetteGreen.uniforms.length = 0.01;
            silhouetteGreen.selected = [];

            viewer.scene.postProcessStages.add(Cesium.PostProcessStageLibrary.createSilhouetteStage([silhouetteBlue, silhouetteGreen]));

            // 悬停时,使一个特性(未被选中的)呈现蓝色轮廓。
            viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
                // 如果先前高亮显示了某个特性,撤消高亮显示。
                silhouetteBlue.selected = [];
                // 选择一个新特性。
                var pickedFeature = viewer.scene.pick(movement.endPosition);
                if (!Cesium.defined(pickedFeature)) {
                    nameOverlay.style.display = 'none';
                    return;
                }
                // 鼠标悬停的位置有一个特性,所以显示它的“名称div”。
                nameOverlay.style.display = 'block';
                // 确定“名称div”的位置。
                nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + 'px';
                nameOverlay.style.left = movement.endPosition.x + 'px';
                // 获取该特性的名称。
                var name = pickedFeature.getProperty('name');
                // 如果没有定义名称,则获取该特性的id作为名称。
                if (!Cesium.defined(name)) {
                    name = pickedFeature.getProperty('id');
                }
                // 把该特性的名称写到“名称div”里。
                nameOverlay.textContent = name;
                // 如果尚未选中,则突出显示该特性。
                if (pickedFeature !== selected.feature) {
                    silhouetteBlue.selected = [pickedFeature];
                }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

            // 单击时,剪影选中的特性,并在信息框中显示元数据。
            viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
                // 如果之前选择了某个特性,则撤消突出显示。
                silhouetteGreen.selected = [];
                // 选择一个新特性。
                var pickedFeature = viewer.scene.pick(movement.position);
                if (!Cesium.defined(pickedFeature)) {
                    clickHandler(movement);
                    return;
                }
                // 如果尚未选择该特性,则选择它。
                if (silhouetteGreen.selected[0] === pickedFeature) {
                    return;
                }
                // 保存所选特性的原始颜色。
                var highlightedFeature = silhouetteBlue.selected[0];

                if (pickedFeature === highlightedFeature) {
                    silhouetteBlue.selected = [];
                }

                // 突出显示新选中的特性。
                silhouetteGreen.selected = [pickedFeature];
                // 保存当前选中的特性,到selected。
                selected.feature = pickedFeature;
                selected.originalColor = pickedFeature.color;
                // console.log("selected.feature:", selected.feature);


                // 设置特性信息框描述
                var featureName = pickedFeature.getProperty('name');
                selectedEntity.name = featureName;
                selectedEntity.description = 'Loading <div class="cesium-infoBox-loading"></div>';
                viewer.selectedEntity = selectedEntity;
                selectedEntity.description = '<table class="cesium-infoBox-defaultTable">' +
                                                '<tbody>';

                // 获取当前选中实体的所有属性名的数组及其长度,
                // 并打印到控制台上。
                var propertyNames = pickedFeature.getPropertyNames();
                var length = propertyNames.length;
                for (var i = 0; i < length; ++i) {
                    var propertyName = propertyNames[i];
                    console.log(propertyName + ': ' + pickedFeature.getProperty(propertyName));
                    selectedEntity.description += '<tr><th>'+ propertyName + '</th><td>' + pickedFeature.getProperty(propertyName) + '</td></tr>';
                }
                selectedEntity.description += '</tbody>' +
                    '</table>';
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
        }
        // 如果不支持剪影(轮廓),鼠标悬浮在特征上时,特征颜色变黄;单击变绿。
        else {
            // Silhouettes are not supported. Instead, change the feature color.

            // Information about the currently highlighted feature
            var highlighted = {
                feature : undefined,
                originalColor : new Cesium.Color()
            };

            // Color a feature yellow on hover.
            viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
                // If a feature was previously highlighted, undo the highlight
                if (Cesium.defined(highlighted.feature)) {
                    highlighted.feature.color = highlighted.originalColor;
                    highlighted.feature = undefined;
                }
                // Pick a new feature
                var pickedFeature = viewer.scene.pick(movement.endPosition);
                if (!Cesium.defined(pickedFeature)) {
                    nameOverlay.style.display = 'none';
                    return;
                }
                // A feature was picked, so show it's overlay content
                nameOverlay.style.display = 'block';
                nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + 'px';
                nameOverlay.style.left = movement.endPosition.x + 'px';
                var name = pickedFeature.getProperty('name');
                if (!Cesium.defined(name)) {
                    name = pickedFeature.getProperty('id');
                }
                nameOverlay.textContent = name;
                // Highlight the feature if it's not already selected.
                if (pickedFeature !== selected.feature) {
                    highlighted.feature = pickedFeature;
                    Cesium.Color.clone(pickedFeature.color, highlighted.originalColor);
                    pickedFeature.color = Cesium.Color.YELLOW;
                }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

            // Color a feature on selection and show metadata in the InfoBox.
            viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
                // If a feature was previously selected, undo the highlight
                if (Cesium.defined(selected.feature)) {
                    selected.feature.color = selected.originalColor;
                    selected.feature = undefined;
                }
                // Pick a new feature
                var pickedFeature = viewer.scene.pick(movement.position);
                if (!Cesium.defined(pickedFeature)) {
                    clickHandler(movement);
                    return;
                }
                // Select the feature if it's not already selected
                if (selected.feature === pickedFeature) {
                    return;
                }
                selected.feature = pickedFeature;
                // Save the selected feature's original color
                if (pickedFeature === highlighted.feature) {
                    Cesium.Color.clone(highlighted.originalColor, selected.originalColor);
                    highlighted.feature = undefined;
                } else {
                    Cesium.Color.clone(pickedFeature.color, selected.originalColor);
                }
                // Highlight newly selected feature
                pickedFeature.color = Cesium.Color.LIME;
                // Set feature infobox description
                var featureName = pickedFeature.getProperty('name');
                selectedEntity.name = featureName;
                selectedEntity.description = 'Loading <div class="cesium-infoBox-loading"></div>';
                viewer.selectedEntity = selectedEntity;
                selectedEntity.description = '<table class="cesium-infoBox-defaultTable"><tbody>' +
                    '<tr><th>BIN</th><td>' + pickedFeature.getProperty('BIN') + '</td></tr>' +
                    '<tr><th>DOITT ID</th><td>' + pickedFeature.getProperty('DOITT_ID') + '</td></tr>' +
                    '<tr><th>SOURCE ID</th><td>' + pickedFeature.getProperty('SOURCE_ID') + '</td></tr>' +
                    '<tr><th>Longitude</th><td>' + pickedFeature.getProperty('longitude') + '</td></tr>' +
                    '<tr><th>Latitude</th><td>' + pickedFeature.getProperty('latitude') + '</td></tr>' +
                    '<tr><th>Height</th><td>' + pickedFeature.getProperty('height') + '</td></tr>' +
                    '<tr><th>Terrain Height (Ellipsoid)</th><td>' + pickedFeature.getProperty('TerrainHeight') + '</td></tr>' +
                    '</tbody></table>';
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
        }

        //Sandcastle_End
        Sandcastle.finishedLoading();
    }

    if (typeof Cesium !== 'undefined') {
        startup(Cesium);
    }
    else if (typeof require === 'function') {
        require(['Cesium'], startup);
    }
</script>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/weixin_42193179/article/details/87630542