在cesium地图中指定经纬度点绘制指定高度的柱子

本文提供了一个在Cesium地图上根据经纬度点和指定高度绘制柱子的代码示例。数据以JSON格式输入,包含经度、维度和高度信息。示例还展示了如何创建自定义的DataSource类来处理WebGLGlobe格式的数据,并提供了加载和显示数据的方法。
摘要由CSDN通过智能技术生成


本文记录了在cesium地图中指定经纬度点绘制指定高度的柱子的代码。

一、效果展示

结果如下图示,在指定经纬度点绘制指定高度的柱子。

在这里插入图片描述

二、输入格式

输入的文件格式是json格式,数据格式如下所示,三个三个一组,分别是经度维度和高度。

 //WebGL Globe JSON is an array of series, where each series itself is an
//array of two items, the first containing the series name and the second
//being an array of repeating latitude, longitude, height values.
/
/Here's a more visual example.
      [["series1",[latitude, longitude, height, ... ]
       ["series2",[latitude, longitude, height, ... ]]

在这里插入图片描述

三、完整代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <!-- 包含 CesiumJS 的 JavaScript 和 CSS 文件 -->
  <script src="cesium/Build/Cesium/Cesium.js"></script>
  <link rel="stylesheet" href="cesium/Build/Cesium/Widgets/widgets.css">
</head>

<body>
  <div id="cesiumContainer"></div>
  <script type="module">

    /**
 * 这个类是一个自定义 DataSource 的示例。它加载 Google 的 WebGL Globe(https://github.com/dataarts/webgl-globe)
 * 定义的 JSON 数据。
 * @alias WebGLGlobeDataSource
 * @constructor
 *
 * @param {string} [name] 此数据源的名称。如果未定义,将从 URL 中派生名称。
 *
 * @example
 * const dataSource = new Cesium.WebGLGlobeDataSource();
 * dataSource.loadUrl('sample.json');
 * viewer.dataSources.add(dataSource);
 */
    function WebGLGlobeDataSource(name) {
      // 所有公共配置都被定义为 ES5 属性
      // 这些是 "私有" 变量及其默认值。
      this._name = name;
      this._changed = new Cesium.Event();
      this._error = new Cesium.Event();
      this._isLoading = false;
      this._loading = new Cesium.Event();
      this._entityCollection = new Cesium.EntityCollection();
      this._seriesNames = [];
      this._seriesToDisplay = undefined;
      this._heightScale = 10000000;
      this._entityCluster = new Cesium.EntityCluster();
    }

    Object.defineProperties(WebGLGlobeDataSource.prototype, {
      // 以下属性必须由所有 DataSource 实例实现

      /**
       * 获取此实例的可读名称。
       * @memberof WebGLGlobeDataSource.prototype
       * @type {String}
       */
      name: {
        get: function () {
          return this._name;
        },
      },
      /**
       * 由于 WebGL Globe JSON 不是时间动态的,此属性始终为未定义。
       * @memberof WebGLGlobeDataSource.prototype
       * @type {DataSourceClock}
       */
      clock: {
        value: undefined,
        writable: false,
      },
      /**
       * 获取 Entity 实例的集合。
       * @memberof WebGLGlobeDataSource.prototype
       * @type {EntityCollection}
       */
      entities: {
        get: function () {
          return this._entityCollection;
        },
      },
      /**
       * 获取一个值,指示数据源当前是否正在加载数据。
       * @memberof WebGLGlobeDataSource.prototype
       * @type {Boolean}
       */
      isLoading: {
        get: function () {
          return this._isLoading;
        },
      },
      /**
       * 获取在底层数据发生变化时将被触发的事件。
       * @memberof WebGLGlobeDataSource.prototype
       * @type {Event}
       */
      changedEvent: {
        get: function () {
          return this._changed;
        },
      },
      /**
       * 获取在处理过程中遇到错误时将被触发的事件。
       * @memberof WebGLGlobeDataSource.prototype
       * @type {Event}
       */
      errorEvent: {
        get: function () {
          return this._error;
        },
      },
      /**
       * 获取数据源启动或停止加载时将被触发的事件。
       * @memberof WebGLGlobeDataSource.prototype
       * @type {Event}
       */
      loadingEvent: {
        get: function () {
          return this._loading;
        },
      },

      // 这些属性特定于此 DataSource。

      /**
       * 获取系列名称的数组。
       * @memberof WebGLGlobeDataSource.prototype
       * @type {string[]}
       */
      seriesNames: {
        get: function () {
          return this._seriesNames;
        },
      },
      /**
       * 获取或设置要显示的系列的名称。WebGL JSON 被设计为一次只能查看一个系列。
       * 有效值在 seriesNames 属性中定义。
       * @memberof WebGLGlobeDataSource.prototype
       * @type {String}
       */
      seriesToDisplay: {
        get: function () {
          return this._seriesToDisplay;
        },
        set: function (value) {
          this._seriesToDisplay = value;

          // 遍历所有实体,并仅在它们属于当前系列时将其 show 属性设置为 true。
          const collection = this._entityCollection;
          const entities = collection.values;
          collection.suspendEvents();
          for (let i = 0; i < entities.length; i++) {
            const entity = entities[i];
            entity.show = value === entity.seriesName;
          }
          collection.resumeEvents();
        },
      },
      heightScale: {
        get: function () {
          return this._heightScale;
        },
        set: function (value) {
          if (value <= 0) {
            throw new Cesium.DeveloperError("value must be greater than 0");
          }
          this._heightScale = value;
        },
      },
      /**
       * 获取或设置应该显示此数据源的标志。
       * @memberof WebGLGlobeDataSource.prototype
       * @type {Boolean}
       */
      show: {
        get: function () {
          return this._entityCollection;
        },
        set: function (value) {
          this._entityCollection = value;
        },
      },
      /**
       * 获取或设置此数据源的聚类选项。此对象可在多个数据源之间共享。
       * @memberof WebGLGlobeDataSource.prototype
       * @type {EntityCluster}
       */
      clustering: {
        get: function () {
          return this._entityCluster;
        },
        set: function (value) {
          if (!Cesium.defined(value)) {
            throw new Cesium.DeveloperError("value 必须被定义。");
          }
          this._entityCluster = value;
        },
      },
    });

    /**
     * 异步加载提供的 URL 中的 GeoJSON,替换任何现有数据。
     * @param {object} url 要处理的 URL。
     * @returns {Promise} 将在加载 GeoJSON 时解析的 Promise。
     */
    WebGLGlobeDataSource.prototype.loadUrl = function (url) {
      if (!Cesium.defined(url)) {
        throw new Cesium.DeveloperError("url 是必需的。");
      }

      // 根据 URL 创建一个名称
      const name = Cesium.getFilenameFromUri(url);

      // 如果名称与当前名称不同,则设置名称。
      if (this._name !== name) {
        this._name = name;
        this._changed.raiseEvent(this);
      }

      // 将 URL 加载到 json 对象中,然后用 'load' 函数处理它。
      const that = this;
      return Cesium.Resource.fetchJson(url)
        .then(function (json) {
          return that.load(json, url);
        })
        .catch(function (error) {
          // 如果出现任何错误或异常,将捕获并触发错误事件并拒绝 Promise。
          this._setLoading(false);
          that._error.raiseEvent(that, error);
          return Promise.reject(error);
        });
    };

    /**
     * 加载提供的数据,替换任何现有数据。
     * @param {Array} data 要处理的对象。
     */
    WebGLGlobeDataSource.prototype.load = function (data) {
      //>>includeStart('debug', pragmas.debug);
      if (!Cesium.defined(data)) {
        throw new Cesium.DeveloperError("data 是必需的。");
      }
      //>>includeEnd('debug');

      // 清除可能已经存在的任何数据。
      this._setLoading(true);
      this._seriesNames.length = 0;
      this._seriesToDisplay = undefined;

      const heightScale = this.heightScale;
      const entities = this._entityCollection;

      // 当对大量实体进行更改时,最好在 suspendEvents 中暂停事件。
      // 这将使事件被批处理为最小的函数调用,并在处理结束时(调用 resumeEvents 时)全部发生。
      entities.suspendEvents();
      entities.removeAll();

      // WebGL Globe JSON 是一个系列的数组,其中每个系列本身是一个由两个项组成的数组,
      // 第一个项包含系列名称,第二个项是重复的纬度、经度、高度值数组。
      //
      // 这里有一个更直观的例子。
      //[["series1",[latitude, longitude, height, ... ]
      // ["series2",[latitude, longitude, height, ... ]]

      // 遍历每个系列
      for (let x = 0; x < data.length; x++) {
        const series = data[x];
        const seriesName = series[0];
        const coordinates = series[1];

        // 将系列名称添加到我们可能值的列表中。
        this._seriesNames.push(seriesName);

        // 默认情况下使第一个系列可见
        const show = x === 0;
        if (show) {
          this._seriesToDisplay = seriesName;
        }

        // 现在遍历系列中的每个坐标,并从数据中创建我们的实体。
        for (let i = 0; i < coordinates.length; i += 3) {
          const latitude = coordinates[i];
          const longitude = coordinates[i + 1];
          const height = coordinates[i + 2];

          // 忽略高度为零的线条。
          if (height === 0) {
            continue;
          }

          const color = Cesium.Color.fromHsl(0.6 - height * 0.5, 1.0, 0.5);
          const surfacePosition = Cesium.Cartesian3.fromDegrees(
            longitude,
            latitude,
            0
          );
          const heightPosition = Cesium.Cartesian3.fromDegrees(
            longitude,
            latitude,
            height * heightScale
          );

          // WebGL Globe 只包含线条,所以这是唯一创建的图形。
          const polyline = new Cesium.PolylineGraphics();
          polyline.material = new Cesium.ColorMaterialProperty(color);
          polyline.width = new Cesium.ConstantProperty(2);
          polyline.arcType = new Cesium.ConstantProperty(
            Cesium.ArcType.NONE
          );
          polyline.positions = new Cesium.ConstantProperty([
            surfacePosition,
            heightPosition,
          ]);

          //Polyline 实例本身需要在一个实体上。
          const entity = new Cesium.Entity({
            id: `${seriesName} index ${i.toString()}`,
            show: show,
            polyline: polyline,
            seriesName: seriesName, // 自定义属性,指示系列名称
          });

          // 将实体添加到集合中。
          entities.add(entity);
        }
      }

      // 完成所有数据处理后,调用 resumeEvents 并触发 changed 事件。
      entities.resumeEvents();
      this._changed.raiseEvent(this);
      this._setLoading(false);
    };

    WebGLGlobeDataSource.prototype._setLoading = function (isLoading) {
      if (this._isLoading !== isLoading) {
        this._isLoading = isLoading;
        this._loading.raiseEvent(this, isLoading);
      }
    };

    // 现在我们已经定义了自己的 DataSource,我们可以使用它来加载
    // 任何针对 WebGL Globe 格式化的 JSON 数据。
    const dataSource = new WebGLGlobeDataSource();
    dataSource
      .loadUrl("cesium/Apps/SampleData/HLtest1.json")
      .then(function () {
        // 初始化加载后,创建按钮让用户在系列之间切换。
        function createSeriesSetter(seriesName) {
          return function () {
            dataSource.seriesToDisplay = seriesName;
          };
        }

        for (let i = 0; i < dataSource.seriesNames.length; i++) {
          const seriesName = dataSource.seriesNames[i];
          Sandcastle.addToolbarButton(
            seriesName,
            createSeriesSetter(seriesName)
          );
        }
      });

    // 创建 Viewer 实例并添加 DataSource。
    const viewer = new Cesium.Viewer("cesiumContainer", {
      animation: false,
      timeline: false,
    });
    viewer.clock.shouldAnimate = false;
    viewer.dataSources.add(dataSource);

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

</html>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值