5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Sandcastleで始めるCESIUM ion 超入門(連載 第2回)

Last updated at Posted at 2025-06-08

はじめに

第1回は Cesium ion(セジウムアイオン)にアカウントを作って、3D可視化環境の Sandcastle(サンドキャッスル)を試しました。

今回はいよいよ実践編です。国土交通省のプロジェクト PLATEAU(プラトー)が提供する、日本全国の高精度な3D都市モデルを使って、リアルな都市空間をブラウザ上に再現してみましょう。

Sandcastle で JavaScript のコードを少しずついじっていきますよ!

連載第2回のステップ

  1. PLATEAU の地形モデルと 3D都市モデルを読み込む
  2. 3D地形モデルを見てみる
  3. 3D都市モデルを見てみる
  4. 熱気球の 3Dモデルを街の上空に配置する

Step 1: PLATEAUの地形モデルと3D都市モデルを読み込む

PLATEAUの地形モデルは、国土地理院が全国をカバーして作っている「基盤地図情報 数値標高モデル(DEM:デム)5mメッシュ」から作られています。メッシュサイズが 5m の DEM はこんな感じでかなり細かいので、詳細な地形が表現できます。なお、5m メッシュ標高が未整備の場所では 10m DEM が使われています。

5mメッシュはこんな感じ
5mmesh.png

そしてなんと、東京都23区では 1mメッシュ!という超細かい DEM が提供されていますので、こんな感じのシャキっと綺麗に角が立った 3D地形を見ることができます。

千鳥ヶ淵.png

では前説はこれくらいにして、早速やって行きましょう♪

Cesium ion アカウントにログイン

まずは Cesium ion のアカウントにログインします。

CesiumIonにログイン.png

アカウントを作れていない人は、第1回を見てくださいね。

Sandcastleで始めるCESIUM ion 超入門(連載 第1回)
https://qiita.com/YutakaYasoshima/items/aafd8155f78e8801f6e2

ログインしたら「My Assets」タブを見てみましょう。
前回、Google Photorealistic 3D Tiles を My Assets に追加したのが残っていると思います。

MyAssets.png

今回は、My Assets に PLATEAU の地形モデルと建物モデルを追加します。

Asset Depot から選ぶ

隣の「Asset Depot(アセットデポ)」タブを選択すると、たくさんのアセットが並んでいます。

この中から「Japan」で始まる2行を見つけて「+」ボタンを押します。これらは、PLATEAU プロジェクトで作成された 3D地形モデルと 3D建物モデルです。

Japan_Asset_Depot.png

もう一度「My Assets」タブに戻って見ると、選択した 2つのデータが追加されています。

MyAssetにPLATEAUデータ追加済み.png


追加された2個のデータ

  1. PLATEAU Terrain(プラトーテレイン)
     Terrain とは 3D地形モデルのことです。場所によって 1mメッシュ、5mメッシュ、10mメッシュと細かさが違いますが、PLATEAU Terrain は日本全国をカバーしていますので、どこまでもスクロールして、地形を眺めて楽しめるデータです。

  2. PLATEAU 3D建物モデル
     2025年5月11日までに、国内 236都市の 3D建物モデルが完成して、オープンデータとして公開されています。

先に、PLATEAU の 3D地形モデルの方から Sandcastle で表示してみましょう。

Step 2: PLATEAU の 3D地形モデルを見てみる

「My Assets」タブで Japan Regional Terrain(ジャパン リージョナル テレイン)を見つけましょう。

Terrainを表示.png

初期表示は地球全体になりますが、地球儀を回して日本を拡大すると、綺麗な地形を見ることができます。

最初の地形表示.png

しかしその前に、ちょっとまった!

もう第2回ですから、左側のコード部分も観察しておきましょう。

PLATEAU Terrain( 3D地形モデル)のコードを見てみる
とても短いので、恐れるに足らず。2つのブロックしかありません。

地形表示コード.png

まずは先頭のこの部分から。

// Grant CesiumJS access to your ion assets
Cesium.Ion.defaultAccessToken = "****ここは自分のアクセストークンが書かれています****";

これは、AccessToken(アクセストークン)と言って、自分の Cesium ion アカウントにアクセスするための、専用のトークン(鍵として働く秘密の文字列)です。それぞれのアカウントに個別のトークンが割り当てられています。

コメントの表記について

この後のコードにも出てくるのですが、
// こんなふうにスラッシュ2個があったら、その右側に書いてあることは、コメントです。プログラムコードに書き込まれた、いわゆる「メモ」です。

コメントはプログラムの動作の説明や、数値の意味など、後で見た時にコレ何だったけ?と思うようなところに細かく入れることになっています。頑張ってコードを書いて徹夜しちゃった翌朝には、内容などすっかり忘却の彼方...なんてことがありますからね😅

コードにコメントをいっぱい入れるのは、とっても良い習慣、良いプログラマです。

コードにはクドいくらいにコメントを入れよう!


さて、次の部分はここ。 ```js try { const viewer = new Cesium.Viewer("cesiumContainer", { terrainProvider: await Cesium.CesiumTerrainProvider.fromIonAssetId(2767062), }); } catch (error) { console.log(error); } ``` try で始まるブロックは、  ```{カッコで囲まれた中} ``` の実行をトライする、という意味です。
ここで大切なのはここだけ。
terrainProvider:
  await Cesium.CesiumTerrainProvider.fromIonAssetId(2767062)

これは、Cesium ion のアセットID「2767062」が地形データなのですが、それを
 CesiumTerrainProvider(セジウム テレインプロバイダー:地形配信元)
として使おうとしています。

そして、2767062 と言えば...実はさっき見ています。

これ。
ここで登録した地形データ (2767062) を呼び出しているのですね。

TerrainのAssetID.png

まとめると、この画面でやっていることは2個でした。

まとめ
 Cesium ion のアクセストークンを渡す

// Grant CesiumJS access to your ion assets
Cesium.Ion.defaultAccessToken = "Cesium.Ion.defaultAccessToken = "****ここは自分のアクセストークンと差し替えて****";";

 登録しておいた AssetID 2767062PALTEAU 地形データ)を呼び出す。

try {
  const viewer = new Cesium.Viewer("cesiumContainer", {
    terrainProvider:
      await Cesium.CesiumTerrainProvider.fromIonAssetId(2767062),
  });
} catch (error) {
  console.log(error);
}

これで、コードの説明はおしまい。

せっかくなので、地球儀を回して富士山を見ておきます...😆

日本人ならやっぱり富士山.png

地図を回しても、左側のコード自体は変わらないですね。
カメラの現在位置は、Cesium.jsの内部に保持されているので、
ユーザーが地図を操作してもプログラムコードが書き換わることはありません。

Step 3: PLATEAU の 建物モデルを見てみる

続けて、PLATEAUの 3D建物を見てみましょう。

My Assetsタブを選択して、 Japan 3D Building Data を見つけてください。その行を選択したら、左下の Open complete code example をクリックします。

建物を表示.png

最初から日本付近が拡大されていますね。

建物の初期表示.png

そして、グリグリっと拡大すると、東京タワーだってちゃんと再現されています!
PLATEAU の3D建物モデル、すごいですね。

東京タワー.png


PLATEAU 3D建物表示のコードを観察
ここで、左側のコード表示にご注目。
ここの部分です。

建物に地形がついてくる.png

これ、さっき地形のコードを見たときに、同じようなことが書いてありましたよね!
ここのところ、そっくりですね。

地形のコード.png

これらは、両方とも PLATEAU Terrain データを呼び出しています。


あらためて、建物のコードを見ていきます。
// Grant CesiumJS access to your ion assets
Cesium.Ion.defaultAccessToken = "Cesium.Ion.defaultAccessToken = "****ここには自分のアクセストークンが書かれています****";";

const viewer = new Cesium.Viewer("cesiumContainer", {
  terrainProvider: await Cesium.CesiumTerrainProvider.fromIonAssetId(
    2767062,
  ),
});
viewer.scene.globe.depthTestAgainstTerrain = true;

try {
  const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(2602291);
  viewer.scene.primitives.add(tileset);
  await viewer.zoomTo(tileset);

  // Apply the default style if it exists
  const extras = tileset.asset.extras;
  if (
    Cesium.defined(extras) &&
    Cesium.defined(extras.ion) &&
    Cesium.defined(extras.ion.defaultStyle)
  ) {
    tileset.style = new Cesium.Cesium3DTileStyle(extras.ion.defaultStyle);
  }
} catch (error) {
  console.log(error);
}

最初の部分は、地形のコードと同じで、Cesium ion のアクセストークンが書いてあります。
// Grant CesiumJS access to your ion assets
Cesium.Ion.defaultAccessToken = "****自分のアクセストークンが表示される

ご注目いただきたいのは、次のブロック。
const viewer = new Cesium.Viewer("cesiumContainer", {
  terrainProvider: await Cesium.CesiumTerrainProvider.fromIonAssetId(
    2767062,
  ),
});

地形のコードとは微妙に書き方が違いますが、ここで、PALTEAU 地形データを呼び出しています。

あれれ?
さっきの操作では、PLATEAU 建物を選んで Sandcatsle を開いただけのに、なぜか、選んでもいない PLATEAU 地形まで、勝手についてきているぞ!?

PLATEAU 建物には PLATEAU 地形が勝手についてくる


そうなんです。
これは、Cesium 君(Cesium 社の誰かさん)が親切心からやってくれていることで、PLATEAU の建物を Sandcatsle で使う時には、PLATEAU 地形も一緒に組み込んでくれるという🥺 素晴らしい仕組みになっているんですね。

Cesium ion で標準的に使われる地形は、 Cesium World Terrein(セジウム ワールド テレイン)というものです。これは第1回の最初で出てきましたが、世界向けの製品なので、日本の国交省プロジェクト PLATEAU が独自に作っている建物とは相性が悪いのです。

PLATEAU 建物には PLATEAU 地形を合わせないと具合悪い

日本のプロジェクトである PLATEAU では、地面の高さの基準を 「東京湾平均海面」 としています。国内で「標高」と呼ばれている高さは全て、この「東京湾平均海面」を 0m とした高さで統一されています。この時点ですでに、世界基準で作られている地形とは、ぴったり合わない予感しかしませんよね。

実際に PLATEAU の3D建物モデルを Cesium World Terrein に配置しても、高さが全く合わずに地面から浮いた感じになってしまいます。

なぜ、高さの一致しない地形が存在するのかの理由を説明するには、お話が長くなりますので、また次回、あるいは番外編で扱おうと思います。とりあえず、Sandcatsle を使っている間は Cesium 君の粋な計らいで、PLATEAU の建物は PLATEAU Terrain とセットで扱われますのでご安心を。

Step 4: 気球の3Dモデルを街の上空に配置する

せっかく、東京タワーまで見られたのですから、上空に何か飛ばしてみようではありませんか。

実際のところ、3Dプロジェクトで PLATEAU の3D都市モデルだけで完結することはほとんどなくて、大概は他の 3Dモデルと組み合わせて、あれこれと楽しんだり、分析したり、という事になると思います。そうしたことも Sandcatsle でサクッとできちゃいますので、まずはやってみましょう。

気球の 3Dモデルを配置してみる

熱気球を配置するのは今回作った、PLATEAU 3D建物の上にしましょう。
PLATEATU の建物を読み込んだら、左側のコードに少し呪文を加えます。

現在のコードの下に次を追加します。
コードをこの下に書き足す.png

コード全体を入れ替えるのではなく、コードの最後に追加です。


// 気球を追加する位置を設定する
const balloonPosition = Cesium.Cartesian3.fromDegrees(139.7457, 35.6586, 450.0);   // 概ね東京タワー付近、地上450m

const balloonEntity = viewer.entities.add({
  name: "Hot Air Balloon",
  position: balloonPosition,
  model: {
    uri: "https://sandcastle.cesium.com/SampleData/models/CesiumBalloon/CesiumBalloon.glb",
  },
});

// 気球にカメラをズーム
viewer.zoomTo(balloonEntity, new Cesium.HeadingPitchRange(
  Cesium.Math.toRadians(0),   // heading(方位)
  Cesium.Math.toRadians(-20), // pitch(見下ろし)
  400                         // range(距離m)
));

中身をみて行きましょう。

(139.7457, 35.6586, 450.0) の3つの数値は、それぞれ
 東経 139.7457°
 北緯 35.6586°
 標高 450.0m
を表しています。

そして、const balloonPosition = Cesium.Cartesian3.fromDegrees によって、カッコ内の緯度、経度、高さを balloonPosition に保存しています。

ここの数値を変えれば、好きな場所(緯度経度)、好きな高さに気球を配置できます。


次のブロックには、熱気球のモデルの名前と配置する位置 3Dモデルのファイルを書いてあります。

名前はこれです。name: "Hot Air Balloon"
クリックした時に表示される名前を設定しています。ここを日本語で「熱気球」などと変えてもOKです。

position: balloonPosition

では、上の方で balloonPosition に設定した気球の表示位置を読み込ませています。

最後にこの部分で、表示させる気球の 3Dモデルを指定しています。

model: {
  uri: "https://sandcastle.cesium.com/SampleData/models/CesiumBalloon/CesiumBalloon.glb",
}

次の部分で気球にズームしています。
ズームは簡単で、ズームする対象を指定して、カメラ位置(視点)を設定するだけ。

viewer.zoomTo(balloonEntity, new Cesium.HeadingPitchRange はこの一行でカメラをズームする呪文になっています。

 balloonEntity には、何行か上の「balloonEntity = ...」のとこで設定した、3Dモデルの情報が入っています。

そして、その対象物に対して、カメラの方位、見上げあるいは見下ろし角、カメラとの距離を指定します。
 Cesium.Math.toRadians(0), // heading(方位)
 Cesium.Math.toRadians(-20), // pitch(見下ろし)
 400 // range(距離m)

heading:北を 0°としたカメラの向きを角度で表したもの
pitch:水平を 0°としたときに下方向のカメラの角度
range:対象物までの距離(m)

完成したコードはこうなります。
もし自分の Sandcatsle で上手く動かない場合は、下記のものと貼り替えてみてください。

// Grant CesiumJS access to your ion assets
// 自分のアカウントのアセットを追加する
Cesium.Ion.defaultAccessToken = "****ここは自分のアクセストークンと差し替えて****";

// Terrain(地形モデル)の指定
// PLATEAUのTerrain(地形データ)の AssetID をCesiumTerrainProvider に指定して、Cesium.Viewerを開く
const viewer = new Cesium.Viewer("cesiumContainer", {
  terrainProvider: await Cesium.CesiumTerrainProvider.fromIonAssetId(2767062),  });

// 地下に埋まっているものを表示しない呪文
viewer.scene.globe.depthTestAgainstTerrain = true;

//ここから
try {
  const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(2602291);    //PLATEAUの3D建物モデル
  viewer.scene.primitives.add(tileset);
  await viewer.zoomTo(tileset);   //建物3Dにズームする。あとで気球にズームするので、この行は削除してOK。

  // Apply the default style if it exists
  const extras = tileset.asset.extras;
  if (
    Cesium.defined(extras) &&
    Cesium.defined(extras.ion) &&
    Cesium.defined(extras.ion.defaultStyle)
  ) {
    tileset.style = new Cesium.Cesium3DTileStyle(extras.ion.defaultStyle);
  }
} catch (error) {
  console.log(error);
}

// 気球を追加する
const balloonPosition = Cesium.Cartesian3.fromDegrees(139.7457, 35.6586, 450.0);   // 概ね東京タワー付近、地上450m

const balloonEntity = viewer.entities.add({
  name: "Hot Air Balloon",
  position: balloonPosition,
  model: {
    uri: "https://sandcastle.cesium.com/SampleData/models/CesiumBalloon/CesiumBalloon.glb",
  },
});

// 気球にカメラをズーム
viewer.zoomTo(balloonEntity, new Cesium.HeadingPitchRange(
  Cesium.Math.toRadians(0),   // heading(方位)
  Cesium.Math.toRadians(-20), // pitch(見下ろし)
  400                         // range(距離m)
));

いかがですか? 下の絵みたいに、東京タワーの横に、ちっちゃい熱気球が出てきたら勝利です!🎉

マウスで地図を拡大縮小しているうちに、気球がどこかに行ってしまったら「Run (F8)」ボタンを押して、コードを再実行してください。最初の表示に戻ります。

そうそう、Cesium は、その時間の太陽高度を再現しようとするので、夜見ると、何だか暗い感じの画面になります。そんなときは、タイムラインの青ボールを動かして、いい感じの日当たりになるように、調整してみてください。

実行とタイムライン操作.png

おわりに

Sandcatsle を使うと、ブラウザだけでプログラムコードをいじりながら、3D地図で遊べてしまいましたね。

このままずっと遊び続けても良いのですが、次回はちょっと頑張って、自分のパソコンの中にコードを動かす環境を作ります。そうすると、Sandcastle で動かしたコードを自分のパソコンにコピペして、Sandcastle 無しでもプログラミングを楽しめるようになります。

さらに、自分のパソコン環境で動かしたコードを、そのままホームページに掲載して、他の人たちに見てもらうことも出来るようになります!


例えば、今回のコードもこんな感じで公開すれば、みんなに見てもらえます。

↑このコードのように、Cesium ion の アクセストークンをコード内に書く場合には以下の設定を行いましょう。
①あたらしくトークンを作る
②読み込み専用(ReadOnly)にする
③このアクセストークンで利用できる AssetID を制限する。

こんな感じです。

新しくトークンを作る
CreateToken.png

**ReadOnly(読み込み専用)にする
AccessToken設定.png

さらに、設定欄の下の方に、このアクセストークンで利用できる Assett ID を制限できる場所があります。

このトークンで使える Assest ID を制限する
使えるAssetを制限する.png

これらの設定はいつでも変更可能です。

第2回はこれでおしまい😃
ちょっと長めでしたか?ご感想をいただけたら嬉しいです。

これまでの連載記事

第1回では Cesium ion のアカウントの作り方をご紹介しています。

Sandcastleで始めるCESIUM ion 超入門(連載 第1回)
https://qiita.com/YutakaYasoshima/items/aafd8155f78e8801f6e2

5
1
1

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
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?