zoukankan      html  css  js  c++  java
  • 使用 Cesium 动态加载 GeoJSON 数据

    前言

    需求是这样的,我需要在地图中显示 08 年到现在的地震情况,地震都是发生在具体的时间点的,那么问题就来了,如何实现地震情况按照时间动态渲染而不是一次全部加载出来。

    一、 方案分析

    这里面牵扯到两个问题:第一个是如何加载 GeoJSON 格式的数据,其实也就是矢量数据,因为矢量数据之间是可以任意转换的;第二个是如何让加载的数据根据自身的时间显示。

    所以就有两种解决问题的思路了:第一种,一次加载 GeoJSON 中所有数据,然后逐个设置显示时间;第二种,逐个加载 GeoJSON 中数据,并设置每个对象的显示时间。

    下面我们就一步步来实现解决方案。

    二、 解决方案

    先来看一下整体效果:

    2.1 加载 GeoJSON 数据

    Cesium基础使用介绍一文中已经介绍了如何加载多种格式矢量数据,加载 GeoJSON 数据已经写出了两种方式,第一种是整体读取的,明显无法满足我们的需求,那么就只能寻求第二种方式了:

    Cesium.GeoJsonDataSource.load('data/earthquake.geojson').then(function(dataSource) {
        viewer.dataSources.add(dataSource);
    
        var entities = dataSource.entities.values;
    
        for (var i = 0; i < entities.length; i++) {
            var entity = entities[i];
            entity.billboard = undefined;
            entity.point = new Cesium.PointGraphics({
                color: Cesium.Color.RED,
                pixelSize: 10
            });
        }
    });
    

    这里需要注意一个细节,地震数据为点状数据,需要先设置 entity.billboard = undefined,而后再设置 entity.point 来显示点状元素,否则会显示一个图标而不是点。

    这样看上去是逐一添加了点状元素,但是我们的问题并没有解决,所有地震点还是全部显示出来了,并没有按照时间显示。

    2.2 空间对象按照时间显示

    查阅了很多资料,发现可以通过设置对象的 availability 属性来控制对象的显示时间,这正是我需要的,于是修改如下:

        Cesium.GeoJsonDataSource.load('data/earthquake.geojson').then(function(dataSource) {
            viewer.dataSources.add(dataSource);
    
            var entities = dataSource.entities.values; 
    
            for (var i = 0; i < entities.length; i++) {
                var entity = entities[i];
                entity.billboard = undefined;
                entity.point = new Cesium.PointGraphics({
                    color: Cesium.Color.RED,
                    pixelSize: 10
                });
                entity.availability = new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
                    start: Cesium.JulianDate.fromIso8601(entity.properties.date),
                    stop: addDay(Cesium.JulianDate.fromIso8601(entity.properties.date))
                })]);
            }
        });
    });
    

    可以看到只是多加了 entity.availability = ... 一项,这样就能够按照时间显示,主要是其中的 start 和 stop 属性,控制显示的时间范围。date 是 GeoJSON 中数据的一个字段,格式为 '2008-01-01',当然你也可以使用其他格式,在此处进行自定义处理即可,addDay 用于控制显示一天,此处不用多考虑。

    2.3 GeoJSON 的另外一种读取方式

    写到这里问题已经解决了,但是这里再说一个小插曲。刚开始的时候我将 availability 属性直接写到了 point 里,无法得到结果,于是怀疑是此方法走不通,又思考和搜索了片刻,找到了另一种读取 GeoJSON 的方法,如下:

    Cesium.loadJson('data/boundary/earthquake.geojson').then(function(jsonData) {
        for (var i =0 ;i<=jsonData.features.length; i++) {
            var ifeature = jsonData.features[i];
            viewer.entities.add({
                position: Cesium.Cartesian3.fromDegrees(ifeature.geometry.coordinates[0], ifeature.geometry.coordinates[1]),
                availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
                    start: Cesium.JulianDate.fromIso8601(ifeature.properties.date),
                    stop: addDay(Cesium.JulianDate.fromIso8601(ifeature.properties.date))
                })]),
                point: {
                    pixelSize: 10,
                    color: Cesium.Color.RED
                }
            });
        }
    });
    
    

    这同样能达到效果,这就是刚开始讨论时描述的逐个读取数据,这与前一种方式不同的是此处读取到的是逐个的 feature 对象(前一种直接读取 entity 对象),根据 feature 生成 entity 对象,再使用 viewer.entities.add 将对象添加到场景中,每个对象单独根据时间设置 availability 属性,这样同样达到了效果。

    当此种方式达到效果的时候,再回头来看第一种方式豁然开朗,读取到的 entity 就是一个真实的 entity 对象,于是将 availability 从 point 中移出到外面便达到了效果。

    2.4 问题分析

    两种方式都能达到效果,而我在刚开始的时候对细节、对 cesium 的各个对象并没有理解的那么透彻,只是看到了表面现象,当研究的稍微深入的时候对整个 cesium 框架也就有了更多的理解,于是条条道路通罗马。

    三、 总结

    本文简单介绍了如何动态的根据时间加载 GeoJSON 对象,一定要保持深度思考的习惯,凡事不能只看到表面,应该多一些深入的思考。

  • 相关阅读:
    AtCoder Beginner Contest 205
    Codeforces Round #725 (Div. 3)
    Educational Codeforces Round 110 (Rated for Div. 2)【A
    Codeforces Round #722 (Div. 2)
    AtCoder Beginner Contest 203(Sponsored by Panasonic)
    AISing Programming Contest 2021(AtCoder Beginner Contest 202)
    PTA 520 钻石争霸赛 2021
    Educational Codeforces Round 109 (Rated for Div. 2)【ABCD】
    AtCoder Beginner Contest 200 E
    Educational Codeforces Round 108 (Rated for Div. 2)【ABCD】
  • 原文地址:https://www.cnblogs.com/shoufengwei/p/8883013.html
Copyright © 2011-2022 走看看