はじめに
Cesium.jsのCZMLを利用すると、時間経過とともにオブジェクトを移動させることができます。本記事では、この機能を利用して自動車が地上を走るアニメーションを作成するサンプル手順を示します。
走行ルートの作成
ルートの作成方法はイロイロあるかと思いますが、ここではQGIS上で道路をデジタイズして作成する方法を紹介します。
QGISを起動後、下敷きとなる地図を表示し、ルートをデジタイズするためのLineString形式のベクタレイヤを作成します。レイヤ種別はメモリレイヤでも構いませんが、座標系は投影座標系で作成してください。
レイヤを作成したら、下図のように走行ルートをデジタイズます。
ルートを作成したら、Processing Toolboxから【Points along geometry】を選択します。
このツールはLineStringレイヤに対して連続線分上に一定間隔の点を発生させるというものです。ここでは100m間隔で点を発生させています。
実行すると下図のようになります。
最後に、生成したポイントレイヤの点の座標をCZML用に出力します。ここでは以下のようなPythonスクリプトを作成してPythonコンソールに出力しました。
# ポイントレイヤをアクティブにしておく
layer = iface.activeLayer()
feat = QgsFeature()
feature_iter = layer.getFeatures()
# CZML用に座標系を経緯度に変換
ct = QgsCoordinateTransform(
iface.mapCanvas().mapSettings().destinationCrs(),
QgsCoordinateReferenceSystem("EPSG:4612"),
QgsProject.instance().transformContext())
time = 0
while feature_iter.nextFeature(feat):
pnt = feat.geometry()
pnt.transform(ct)
coord_str = "{}, {:.11f}, {:.11f}, 0,".format(time, pnt.vertexAt(0).x(), pnt.vertexAt(0).y())
print(coord_str)
# ポイントからポイントへの移動時間を秒単位で指定
# 点間隔が100なので、こうすると秒速10mとなる
time += 10
実行するとPythonコンソールに座標が出力されます。
この出力結果をとりあえずどこかに保存しておきます。以上でQGISの作業は完了です。
Cesium Sandcastleで実行してみる
Cesium Sandcastleはブラウザ上でCesium.jsのコードを実行することができるサイトです。サイトの左上の[New Sandcastle]をクリックするとコードエディタが開きます。
走行用のCZMLは以下のようになります。CZMLの詳細な説明はドキュメントを参照してください。
// Cesium ionのアクセストークンを記述する
Cesium.Ion.defaultAccessToken = "your-access-token";
try {
// Japan Regional Terrainを使用してビュアーを作成
const viewer = new Cesium.Viewer("cesiumContainer", {
terrainProvider:
await Cesium.CesiumTerrainProvider.fromIonAssetId(2767062),
});
// ついでにRapan 3D Buildingsもロード
const tileset = viewer.scene.primitives.add(
await Cesium.Cesium3DTileset.fromIonAssetId(2602291),
);
// 自動車アセット
const resource = "https://sandcastle.cesium.com/SampleData/models/GroundVehicle/GroundVehicle.glb";
// 走行アニメーション用のCZML
const czml = [
{
id: "document",
name: "CZML Path",
version: "1.0",
clock: {
// アニメーションの時刻を指定
"interval": "2012-08-04T10:00:00Z/2012-08-04T19:30:00Z",
"currentTime": "2012-08-04T10:00:00Z",
"multiplier": 10
}
},
{
id: "path",
name: "Cesium Milk Tunk",
// 上記のアニメーション時刻と合わせる
availability: "2012-08-04T10:00:00Z/2012-08-04T19:30:00Z",
// パスの表示属性
path: {
material: {
polylineOutline: {
color: { rgba: [255, 192, 9, 192] },
outlineColor: { rgba: [255, 192, 9, 192] }
},
},
outlineWidth: 5,
width: 8,
leadTime: 10,
trailTime: 1000,
resolution: 5
},
model: {
gltf: resource,
// このエントリを記述するとオブジェクトが地上に置かれる
heightReference: "CLAMP_TO_GROUND",
},
position: {
epoch: "2012-08-04T10:00:00Z",
interpolationDegree: 1,
cartographicDegrees: [
// ここにQGISからの点列の座標値を貼り付ける
]
},
orientation: {
// このエントリを記述すると、モデルの方向が進行方向に向けられる
velocityReference: "#position"
}
},
];
// CZMLをビューに追加
const dataSourcePromise = viewer.dataSources.add(
Cesium.CzmlDataSource.load(czml),
);
// カメラがCZMLの自動車を追随するように指定
dataSourcePromise
.then(function (dataSource) {
viewer.trackedEntity = dataSource.entities.getById("path");
})
.catch(function (error) {
window.alert(error);
});
} catch (error) {
console.log(error);
}
上記のコードをSandcastleのコードエディタに貼り付けて[Run]をクリック(またはF8キーを押下)すると以下のように表示されます。
実行画面左下のAnimation widgetにある[Play forward]を押すと車が走り出します。
おわりに
本記事ではQGISで走行ルートを作成しましたが、GPSログから座標列を作成して利用することもできるでしょう。また、今回は地上で自動車を走らせていますが、CZMLの座標列にZ座標も付与して空中を飛行させるなどといった応用が可能です。イロイロと試してみてください。
本記事で紹介したサンプルコードはココから見ることができます。








