2.5mの分解能で宇宙から標高を計測する、ALOS-PRISM。Tellusの開発環境、Jupyther Notebookを使って富士山付近のデータをエクスポートして、VR表示しました。
「VR fujisan」
マイクラでリアルなマップを再現したい夢、データとプログラミングを使えば簡単に叶います!
作り方
1. Tellusに、Jupyther Notebook か Jupyter Lab を利用申請。
2. 富士山の位置のメッシュを調べる。(タイル座標確認ツール)
3. Jupyter Notebook上、Pythonでプログラムをかく
TOKEN = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" import os, json, requests, math from skimage import io from io import BytesIO import matplotlib.pyplot as plt %matplotlib inline def get_image(zoom, xtile, ytile, opacity=1, r=3, g=2, b=1, rdepth=1, gdepth=1, bdepth=1, preset=None): sname = "aw3d30" url = "https://gisapi.tellusxdp.com/{}/{}/{}/{}.png?opacity={}&r={}&g={}&b={}&rdepth={}&gdepth={}&bdepth={}".format(sname, zoom, xtile, ytile, opacity, r, g, b, rdepth, gdepth, bdepth) if preset is not None: url += '&preset='+preset headers = { "content-type": "application/json", "Authorization": "Bearer " + TOKEN } r = requests.get(url, headers=headers) return io.imread(BytesIO(r.content)) img = get_image(10,906,404) io.imshow(img)
富士山の標高データが画像で表示されます。
4. RGB値が最高になっているようなので、最大値を求めてみる(きっともっとシンプルに書けます)
max = 0 for d in img: n = (d[0] << 16) | (d[1] << 8) | d[2] if n > max: max = n print(max)
結果
12766
富士山の高さは3766mなので、9000ずれた1m単位だと推定。 5. 試しにテキストで表示してみる
for y in range(256): for x in range(256): d = img[x,y] n = (d[0] << 16) | (d[1] << 8) | d[2] n -= 9000 n /= 4000 n = math.floor(n) print(n,end='') print()
それっぽい。
6. JavaScript用に配列データとして出力
h = [] for y in range(256): for x in range(256): d = img[x,y] n = (d[0] << 16) | (d[1] << 8) | d[2] n -= 9000 h.append(n) print(h)
このデータを、fujisan-data.js として保存して、JavaScriptでWebVRを使ったVRアプリをつくって、できあがり!
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>VR fujisan - data by Tellus</title> <script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script> <script src="https://fukuno.jig.jp/app/webvr/fujisan-data.js"></script> </head> <body> <script>"use strict" window.onload = function() { var scene = document.querySelector('a-scene') const r = 1 const rw = 4 // sampling rw * rw const bw = 256 // org data sampling w and h const w = bw / rw let map = [] for (let i = 0; i < w * w; i++) { const x = i % w const y = (i / w) >> 0 const p = x * rw + y * rw * bw const n = HEIGHT[p] map[i] = n } for (let i = 0; i < map.length; i++) { const x = i % w const y = (i / w) >> 0 const h = map[i] * 0.0005 let box = document.createElement('a-box') box.setAttribute('position', { x: (x - w / 2) * r, y: h / 2 * r - 7, z: (y - w / 2) * r }) box.setAttribute('depth', r) box.setAttribute('width', r) box.setAttribute('height', r * h) scene.appendChild(box) } } </script> <a-scene id="scene"> <a-sky color="#000000"></a-sky> <a-light color="blue" position="1 0.1 0.5"></a-light> <a-light color="cyan" position="0.1 4 2"></a-light> </a-scene> </body> </html>
縮尺は適当なのでリアルな富士山ではないですが、これで怪獣や巨人になった気分で富士山付近を歩けます。
VR x Tellus、楽しいですよ!
links
- VRではじめる現代HTML入門 - Oculus Quest x 福井高専生
- 50行で作るVRマイクラ風 / boxcraft for Oculus Quest with A-Frame
- モバイル時代こそバス! つつじバスロケVRビジュアライズ - リアルタイムオープンデータ x Oculus Quest
- 異次元の分かりやすさ、触って学ぶVR数学、ベジェ曲線編 on Oculus Quest