LoginSignup
1
1

More than 1 year has passed since last update.

「Cesium」を利用して、任意の座標から高度の取得及び設定方法

Posted at

はじめに

GPS経路情報をCesium上で表示させましたが、Cesiumの地形情報と高度があっていなかっため、うまく表示ができませんでした。

そこで、任意の座標から、Cesiumの地形情報からの高度を取得し、自動車の高度に設定してみました。高度の取得には、clampToHeight()メソッドを利用します。

提供される高度は準拠楕円体からの高さ(Ellipsoid.WGS84)楕円体高になります。
これは、平均海面からの高度である標高ではありません。なので、海でサンプリングした場合、必ずしも0.0になるとは限りません。

あと、自動車の方向が自動で変わらなかったので、自動車位置の差から角度を計算し、設定しました。角度設定には、HeadingPitchRollクラスを使いました。

実は、「Cesium」のデモサイトではほとんどか3Dモデルの角度設定にorientationのunitQuaternionを使って設定しているのですが、設定値が不明でうまくいきませんでした。そのため、あきらめて、HeadingPitchRollクラスを使いました。

このクラスではそれぞれの軸の角度を設定するだけなので、設定値が簡単に変更できました。heading,pitch,rollにそれぞれの軸の角度を設定すると、3Dモデルが回転します。Cesiumのサンプルには、なぜかこの処理がなく、自動で向きが変わっています。

以下、高度の取得及び設定プログラムです。今回は経路と自動車の位置でデータを分けています。
※czmlには、clampToGroundをtrueにしていましたが、高度の設定はされていませんでした。czmlの設定に問題があったのかもしれません。

以下参考ソースです。

index.html
<!DOCTYPE html>
<html lang="ja">`
  <head>
    <title>Hello World!</title>
    <link rel="stylesheet" href="../Build/CesiumUnminified/Widgets/widgets.css" />
    <script src="../Build/CesiumUnminified/Cesium.js"></script>
    <style>
      html,
      body,
      #cesiumContainer {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden;
      }
    </style>
  </head>
  <body>
    <div id="cesiumContainer"></div>
    <script>
      var viewer = new Cesium.Viewer("cesiumContainer", {
        terrainProvider: Cesium.createWorldTerrain(),
      });
      var scene = viewer.scene;
      var clock = viewer.clock;

      var czmlOptions = {
          clampToGround: true
      };

      var entity;
      var positionProperty;
      var prePosition;

      viewer.dataSources.add(Cesium.CzmlDataSource.load('../Datas/clampToGround_load5.czml', czmlOptions)).then(function (ds) {
          entity = ds.entities.getById("Vehicle");
          viewer.trackedEntity = entity;
          positionProperty = entity.position;
          start();
      });

      viewer.dataSources.add(Cesium.CzmlDataSource.load('../Datas/clampToGround_load6.czml', czmlOptions));

       function start() {
          var objectsToExclude = [entity];
          scene.postRender.addEventListener(function () {
            var position = positionProperty.getValue(clock.currentTime);
            if (position === undefined) {
                return;
            };
            entity.position = scene.clampToHeight(position, objectsToExclude);
            if (prePosition !== undefined) {
                entity.orientation = calculateOrientation(prePosition, position);
            }
            prePosition = position;
          });
      } 
      function calculateOrientation(oldPosition, newPosition) {
            var dX = oldPosition.x - newPosition.x;
            var dY = oldPosition.y - newPosition.y;

            var offSet =  Cesium.Math.toRadians(135);
            var heading = Math.atan2(dX, dY) - offSet;
            if (heading > Cesium.Math.TWO_PI) {
                heading -= Cesium.Math.TWO_PI;
            }

            var pitch = 0;
            var roll = 0;

            var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
            var orientation = Cesium.Transforms.headingPitchRollQuaternion(oldPosition, hpr);
            return orientation;
      }
    </script>
  </body>
</html>

以下、画面イメージです。
sampleTerrain2.png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1