この 2 か所がニューヨーク市のツアーに含まれているとします。では、どれだけ離れているのでしょうか。約 200 年前の数値計算でこの質問に答えます。
緯度と経度から直線距離を計算する
距離を計算する最も簡単な方法は、数学をベースにしたものです。Haversine 公式として知られていますが、球面三角法を使用して 2 点間の大円距離を決定します。この直線距離近似の公式に関する詳細は
ウィキペディア にあります。
計算結果を可視化するために、2 つのマーカーの間にポリラインを描いてみましょう。このために、JavaScript でマーカーの後に次の行を加えます。
// Draw a line showing the straight distance between the markers
var line =
new google.maps.Polyline({path: [dakota, frick], map: map});
地図をリロードすると、セントラルパークの一方の側からもう一方の側まで、2 つのマーカーを接続する濃い色の斜めの線が表示されます。Haversine 公式を JavaScript で定義することで、2 つのマーカー間の直線距離であるポリラインの長さを決定することができます。
initMap
関数の前に、この関数を JavaScript に追加します。
function haversine_distance(mk1, mk2) {
var R = 3958.8; // Radius of the Earth in miles
var rlat1 = mk1.position.lat() * (Math.PI/180);
// Convert degrees to radians
var rlat2 = mk2.position.lat() * (Math.PI/180);
// Convert degrees to radians
var difflat = rlat2-rlat1; // Radian difference (latitudes)
var difflon = (mk2.position.lng()-mk1.position.lng())
* (Math.PI/180); // Radian difference (longitudes)
var d = 2 * R
* Math.asin(Math.sqrt(Math.sin(difflat/2)*Math.sin(difflat/2)
+Math.cos(rlat1)*Math.cos(rlat2)
*Math.sin(difflon/2)*Math.sin(difflon/2)));
return d;
}
この関数は 2 つのマーカーオブジェクトをもとに、2 地点間の距離をマイルで返します。キロメートルにするには、
R = 6371.0710
を設定します。Haversine 公式を適用する前に、関数は各マーカーの緯度と経度のポイントをラジアンに変換します。
関数を呼び出してマップの下に距離を記載するには、
initMap
のポリラインの下にこのコードを追加します。
// Calculate and display the distance between markers
var distance = haversine_distance(mk1, mk2);
document.getElementById('msg').innerHTML
= "Distance between markers: " + distance.toFixed(2) + " mi.";
マップをロードすると、次のように表示されます。
これで、ダコタとフリック コレクションの間の直線距離が 0.60 マイルであることがわかりました(JavaScript の
toFixed
関数を使用して小数点以下 2 桁は四捨五入しています)。
もちろん、鳩でもない限り、2 つの場所の移動距離はもっと長くなるでしょう。地図を見ていただければわかるように、セントラルパークを横切る道路には小道さえもありません。Haversine 公式は基本的な近似には役立ちますが、多くのユースケース、特に都市内では不十分です。より正確な移動距離を知るには、Maps JavaScript API の別の機能を使用する必要があります。
Maps JavaScript API でルートを検索する
直線距離が適切でない場合、移動距離を決定するためには公式以外のものが必要になります。運転ルートは Google マップで最も人気のある機能の 1 つですが、この機能が API を介して利用できるようになったのは当然のことかもしれません。サーバー側のリクエストに対しては
Directions API を、ウェブ上のクライアント側のリクエストに対しては Maps JavaScript API の Directions サービス を使用できます。
すでに地図はセットしてあるので、以下の
initMap
関数をコピー&ペーストしてください。
let directionsService = new google.maps.DirectionsService();
let directionsRenderer = new google.maps.DirectionsRenderer();
directionsRenderer.setMap(map); // Existing map object displays directions
// Create route from existing points used for markers
const route = {
origin: dakota,
destination: frick,
travelMode: 'DRIVING'
}
directionsService.route(route,
function(response, status) { // anonymous function to capture directions
if (status !== 'OK') {
window.alert('Directions request failed due to ' + status);
return;
} else {
directionsRenderer.setDirections(response); // Add route to the map
var directionsData = response.routes[0].legs[0];
// Get data about the mapped route
if (!directionsData) {
window.alert('Directions request failed');
return;
}
else {
document.getElementById('msg').innerHTML +=
" Driving distance is " + directionsData.distance.text +
" (" + directionsData.duration.text + ").";
}
}
});
Directions サービスの呼び出しが成功すると、マップ上にルートが追加されます。また、マップの下のメッセージ部分に距離が表示されます。
運転ルートが直線距離よりもはるかに長いことは明らかです。また、応答データを掘り下げることで、走行距離(1.6 マイル、直線距離に比べて 2.5 倍)、および推定所要時間を知ることができます。応答データからの関連セクションの JSON 形式の表現は次のとおりです。
"routes": [{
"legs": [
{
"distance": {
"text": "1.6 mi",
value: 2619
},
{
"duration": {
"text": "9 mins",
value: 516
}
}
}
]
}]
この例では運転ルートを使用しましたが、ルートオブジェクトの
travelMode
フィールドには他の値も設定できます。Directions サービスでは、
BICYCLING
、
TRANSIT
、
WALKING
の値を設定することができます (注:”
TRANST
"は日本では使用できません)。適切なモードに調整し、コードを再実行して、結果がどのように変化するかをご覧ください。
どちらの距離を使用するか?
先に述べた 2 つのタイプの距離は、さまざまな状況で有効です。ユーザーに最高のエクスペリエンスを提供するには、それぞれを適切な状況で使用する必要があります。
外部サービスを呼び出さずに素早く計算するには、直線距離を使用できます。このチュートリアルで使用した Haversine 関数を組み込む必要はありますが、必要なのは、ブラウザー内で正確な結果を得るためのマップ座標だけです。ただし、その名前が示すように、単純な直線の距離になります。道路、障害物、交通状況といったものは反映されません。
もう一つが、道のりの長さです。これには、避けられない回り道やそのエリアの交通状況が考慮されます。この計算は複雑であり、道のりの長さは、Directions サービスの呼び出しを必要とします。Directions サービスは、マップ上に視覚的にプロットするためにルートの所要時間と経路を返します。
世界中の距離を測定する場合でも、町全体の距離を測定する場合でも、以上説明したアプローチは、ユーザーの周辺状況の理解や意思決定の手助けとなります。ユーザーがここからあそこまで行くことを支援するためのさらに多くのツールを調べるには、
Google Maps Platform のルートに関する API 群 をご覧ください。
Google Maps Platform に関する詳しい情報は
こちら をご覧ください。ご質問やご意見はページ右上の「お問い合わせ」より承っております。
Posted by
丸山 智康 (Tomoyasu Maruyama) - Google Maps テクニカルアカウントマネージャ
この記事は Google の Software Engineer である Sonia Rode による Google Maps Platform Blog の記事 " How to calculate distances on a map with the Maps JavaScript API " を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。
地図を見るだけで、ある地点について把握できることはたくさんあります。その近くに何があるのか、その場所までの距離は比較的近いのかどうか。地図の縮尺を見ればその目的地までのおおよその距離もわかります。さらに、Google Maps Platform を使えば、2 地点間の距離を直線距離と最短経路の長さとして定量化することができます。これらの 2 つは異なるアプローチであり、ユーザーの異なる問題やアクションを解決します。本記事では、上述の複数地点間の距離の求め方について、直線距離や最短経路がどのような時に必要となるのか、どのようにして使うのかについて説明します。
それでは実際に、JavaScript を使用して、地図上にいくつかの距離をプロットしてみましょう。距離を計算するには出発地点と到着地点の 2 地点が必要となので、Google マップに 2 つのマーカーを追加してみます。
<!DOCTYPE html>
<html>
<head>
<style>
/* Set the size of the div element that contains the map */
#map {
height: 400px;
width: 600px;
}
</style>
</head>
<body>
<!--The div elements for the map and message -->
<div id="map"></div>
<div id="msg"></div>
<script>
// Initialize and add the map
var map;
function initMap() {
// The map, centered on Central Park
const center = {lat: 40.774102, lng: -73.971734};
const options = {zoom: 15, scaleControl: true, center: center};
map = new google.maps.Map(
document.getElementById('map'), options);
// Locations of landmarks
const dakota = {lat: 40.7767644, lng: -73.9761399};
const frick = {lat: 40.771209, lng: -73.9673991};
// The markers for The Dakota and The Frick Collection
var mk1 = new google.maps.Marker({position: dakota, map: map});
var mk2 = new google.maps.Marker({position: frick, map: map});
}
</script>
<!--Load the API from the specified URL --
<remember to replace YOUR_API_KEY-->
<script async defer
src="https://maps.googleapis.com/maps/api/js?
key=YOUR_API_KEY&callback=initMap">
</script>
</body>
</html>
地図上には、セントラルパークとその近くにある 2 つのランドマークが示されています。ジョン レノンの家としておそらく最も有名なダコタと、アートギャラリーのフリック コレクションです。
この 2 か所がニューヨーク市のツアーに含まれているとします。では、どれだけ離れているのでしょうか。約 200 年前の数値計算でこの質問に答えます。
緯度と経度から直線距離を計算する
距離を計算する最も簡単な方法は、数学をベースにしたものです。Haversine 公式として知られていますが、球面三角法を使用して 2 点間の大円距離を決定します。この直線距離近似の公式に関する詳細はウィキペディア にあります。
計算結果を可視化するために、2 つのマーカーの間にポリラインを描いてみましょう。このために、JavaScript でマーカーの後に次の行を加えます。
// Draw a line showing the straight distance between the markers
var line =
new google.maps.Polyline({path: [dakota, frick], map: map});
地図をリロードすると、セントラルパークの一方の側からもう一方の側まで、2 つのマーカーを接続する濃い色の斜めの線が表示されます。Haversine 公式を JavaScript で定義することで、2 つのマーカー間の直線距離であるポリラインの長さを決定することができます。
initMap
関数の前に、この関数を JavaScript に追加します。
function haversine_distance(mk1, mk2) {
var R = 3958.8; // Radius of the Earth in miles
var rlat1 = mk1.position.lat() * (Math.PI/180);
// Convert degrees to radians
var rlat2 = mk2.position.lat() * (Math.PI/180);
// Convert degrees to radians
var difflat = rlat2-rlat1; // Radian difference (latitudes)
var difflon = (mk2.position.lng()-mk1.position.lng())
* (Math.PI/180); // Radian difference (longitudes)
var d = 2 * R
* Math.asin(Math.sqrt(Math.sin(difflat/2)*Math.sin(difflat/2)
+Math.cos(rlat1)*Math.cos(rlat2)
*Math.sin(difflon/2)*Math.sin(difflon/2)));
return d;
}
この関数は 2 つのマーカーオブジェクトをもとに、2 地点間の距離をマイルで返します。キロメートルにするには、R = 6371.0710
を設定します。Haversine 公式を適用する前に、関数は各マーカーの緯度と経度のポイントをラジアンに変換します。
関数を呼び出してマップの下に距離を記載するには、initMap
のポリラインの下にこのコードを追加します。
// Calculate and display the distance between markers
var distance = haversine_distance(mk1, mk2);
document.getElementById('msg').innerHTML
= "Distance between markers: " + distance.toFixed(2) + " mi.";
マップをロードすると、次のように表示されます。
これで、ダコタとフリック コレクションの間の直線距離が 0.60 マイルであることがわかりました(JavaScript の toFixed
関数を使用して小数点以下 2 桁は四捨五入しています)。
もちろん、鳩でもない限り、2 つの場所の移動距離はもっと長くなるでしょう。地図を見ていただければわかるように、セントラルパークを横切る道路には小道さえもありません。Haversine 公式は基本的な近似には役立ちますが、多くのユースケース、特に都市内では不十分です。より正確な移動距離を知るには、Maps JavaScript API の別の機能を使用する必要があります。
Maps JavaScript API でルートを検索する
直線距離が適切でない場合、移動距離を決定するためには公式以外のものが必要になります。運転ルートは Google マップで最も人気のある機能の 1 つですが、この機能が API を介して利用できるようになったのは当然のことかもしれません。サーバー側のリクエストに対しては Directions API を、ウェブ上のクライアント側のリクエストに対しては Maps JavaScript API の Directions サービス を使用できます。
すでに地図はセットしてあるので、以下の initMap
関数をコピー&ペーストしてください。
let directionsService = new google.maps.DirectionsService();
let directionsRenderer = new google.maps.DirectionsRenderer();
directionsRenderer.setMap(map); // Existing map object displays directions
// Create route from existing points used for markers
const route = {
origin: dakota,
destination: frick,
travelMode: 'DRIVING'
}
directionsService.route(route,
function(response, status) { // anonymous function to capture directions
if (status !== 'OK') {
window.alert('Directions request failed due to ' + status);
return;
} else {
directionsRenderer.setDirections(response); // Add route to the map
var directionsData = response.routes[0].legs[0];
// Get data about the mapped route
if (!directionsData) {
window.alert('Directions request failed');
return;
}
else {
document.getElementById('msg').innerHTML +=
" Driving distance is " + directionsData.distance.text +
" (" + directionsData.duration.text + ").";
}
}
});
Directions サービスの呼び出しが成功すると、マップ上にルートが追加されます。また、マップの下のメッセージ部分に距離が表示されます。
運転ルートが直線距離よりもはるかに長いことは明らかです。また、応答データを掘り下げることで、走行距離(1.6 マイル、直線距離に比べて 2.5 倍)、および推定所要時間を知ることができます。応答データからの関連セクションの JSON 形式の表現は次のとおりです。
"routes": [{
"legs": [
{
"distance": {
"text": "1.6 mi",
value: 2619
},
{
"duration": {
"text": "9 mins",
value: 516
}
}
}
]
}]
この例では運転ルートを使用しましたが、ルートオブジェクトの travelMode
フィールドには他の値も設定できます。Directions サービスでは、BICYCLING
、 TRANSIT
、 WALKING
の値を設定することができます (注:”TRANST
"は日本では使用できません)。適切なモードに調整し、コードを再実行して、結果がどのように変化するかをご覧ください。
どちらの距離を使用するか?
先に述べた 2 つのタイプの距離は、さまざまな状況で有効です。ユーザーに最高のエクスペリエンスを提供するには、それぞれを適切な状況で使用する必要があります。
外部サービスを呼び出さずに素早く計算するには、直線距離を使用できます。このチュートリアルで使用した Haversine 関数を組み込む必要はありますが、必要なのは、ブラウザー内で正確な結果を得るためのマップ座標だけです。ただし、その名前が示すように、単純な直線の距離になります。道路、障害物、交通状況といったものは反映されません。
もう一つが、道のりの長さです。これには、避けられない回り道やそのエリアの交通状況が考慮されます。この計算は複雑であり、道のりの長さは、Directions サービスの呼び出しを必要とします。Directions サービスは、マップ上に視覚的にプロットするためにルートの所要時間と経路を返します。
世界中の距離を測定する場合でも、町全体の距離を測定する場合でも、以上説明したアプローチは、ユーザーの周辺状況の理解や意思決定の手助けとなります。ユーザーがここからあそこまで行くことを支援するためのさらに多くのツールを調べるには、Google Maps Platform のルートに関する API 群 をご覧ください。
Google Maps Platform に関する詳しい情報はこちら をご覧ください。ご質問やご意見はページ右上の「お問い合わせ」より承っております。
Posted by 丸山 智康 (Tomoyasu Maruyama) - Google Maps テクニカルアカウントマネージャ