凹みTips

C++、JavaScript、Unity、ガジェット等の Tips について雑多に書いています。

Hyperlapse で環状八号線を南下する動画を Google ストリートビューからつくってみた

はじめに

HyperlapseGoogle ストリートビューから取得した画像を用いてタイムラプス動画を作ってくれます。

コードは github に公開されており、覗いてみると分かる通り JS で記述されています。

同作者の 3D ストリートビュービューワ GSVPano.js を用いて作られた WebGL ベースのアプリで、ヌルサクで動きます。
今回はこれを使って環八を走ってみる動画を作ってみました。

出来た動画

ブラウザ上で動かしたものをキャプりました。

大体 30 秒くらいで環八を北から南へ走り抜け…てるはずです、多分。

解説

examples/simple.html のコードを読むと、Google Maps API V3DirectionsService API でルートを取得していることが分かります。

var directions_service = new google.maps.DirectionsService();
var route = {
	request:{
		origin: new google.maps.LatLng(37.816480000000006,-122.47825,37),
		destination: new google.maps.LatLng(37.81195,-122.47773000000001),
		travelMode: google.maps.DirectionsTravelMode.DRIVING
	}
};
directions_service.route(route.request, function(response, status) {
	if (status == google.maps.DirectionsStatus.OK) {
		hyperlapse.generate( {route:response} );
	} else {
		console.log(status);
	}
});

DirectionsService API で良い感じのルートが取得出来れば所望のルートのタイムラプス動画が得られるわけです。しかしながら、普通に始点と終点を与えるだけでは最短ルートを通ってしまうので、環八を通ってくれません。そこで、ルートを良い感じに指定してあげる必要があります。

解説を見ると waypoints というパラメタでルートを詳細に指定できるようです。

そこでおもむろに Wikipedia を開きます。

ここにある Google マップのリンクをクリックすると、以下のように環八を Google マップ上にルート表示させることができます。

API のドキュメントを見ると、ビジネス用途でなければウェイポイントの最大指定数は 8 個までのようなので、ルートが変わらないよう適当に差っ引きます。で、以下の4点になりました。

35.783763,139.72059
35.733511,139.614653
35.599529,139.669251
35.542205,139.79226

これを waypoints として与えて route 部分を以下の様なコードに書き換えます。

var route = {
	request : {
		origin      : new google.maps.LatLng(35.783763,139.72059),
		destination : new google.maps.LatLng(35.542205,139.79226),
		waypoints   : [
			{ location : '35.733511,139.614653' },
			{ location : '35.599529,139.669251' }
		],
		travelMode  : google.maps.DirectionsTravelMode.DRIVING
	}
};

また、viewer.html から hyperlapse クラスの設定をパクってちょっといじっておきます。

var hyperlapse = new Hyperlapse(document.getElementById('pano'), {
	fov: 80,
	millis: 20,
	width: window.innerWidth,
	height: window.innerHeight,
	zoom: 2,
	use_lookat: false,
	distance_between_points: 5,
	max_points: 5000,
});

use_lookat を true にして lookat を LatLng で指定してやると、その方角をずっと見てくれるようになるのですが今回はドライビング気分に浸るため false にしました。

コード全容

点数を多くしたり zoom の値を大きくして綺麗な動画にしたかったのですが、手持ちの MBA のメモリでは足りずクラッシュしてしまいました。無念。

<!DOCTYPE html>
<html>
<head>
	<title>Simple Example</title>

	<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false" type="text/javascript"></script>
	<script src="js/three.min.js"></script>
	<script src="js/GSVPano.js"></script>
	<script src="../src/Hyperlapse.js"></script>
	<script>

		function init() {
			var hyperlapse = new Hyperlapse(document.getElementById('pano'), {
				fov: 80,
				millis: 30,
				width: window.innerWidth,
				height: window.innerHeight,
				zoom: 1,
				use_lookat: false,
				distance_between_points: 5,
				max_points: 1000,
			});

			hyperlapse.onError = function(e) {
				console.log(e);
			};

			hyperlapse.onRouteComplete = function(e) {
				hyperlapse.load();
			};

			hyperlapse.onLoadComplete = function(e) {
				alert('go!');
				hyperlapse.play();
			};

			// Google Maps API stuff here...
			var directions_service = new google.maps.DirectionsService();

			var route = {
				request : {
					origin      : new google.maps.LatLng(35.783763,139.72059),
					destination : new google.maps.LatLng(35.542205,139.79226),
					waypoints   : [
						{ location : '35.733511,139.614653' },
						{ location : '35.599529,139.669251' }
					],
					travelMode  : google.maps.DirectionsTravelMode.DRIVING
				}
			};

			directions_service.route(route.request, function(response, status) {
				if (status == google.maps.DirectionsStatus.OK) {
					hyperlapse.generate( {route:response} );
				} else {
					console.log(status);
				}
			});

		}

		window.onload = init;

	</script>
</head>
<body>
	<div id="pano"></div>
</body>
</html>

おわりに

本当はグレートバリアリーフの海中動画を作りたかった…のですが、DirectionsService に対応していなかったので断念。
国内の町中のようにゴミゴミした場所だと何が起きてるか分からない感じもあるので、サンプルの動画のように海外の広い所を対象にする方が綺麗な感じになりますね。工夫次第で色んな動画が作れそうで面白そうです。