【Pythonで学ぶ地理計算】mathライブラリで2点間の方位角を計算する基礎 🌍

「東京駅から見て、大阪城はどの方角にあるんだろう?」
「2つの緯度経度の情報から、片方がもう片方から見てどの方角にあるか、角度で知りたい!」
「地図アプリみたいな計算って、Pythonでどうやってやるの?」

こんにちは! Pythonプログラミング探検隊、隊長のPythonistaです! 今回から始まる新シリーズでは、プログラミングと地理情報を組み合わせた、少し専門的で非常に面白い「地理空間計算」の世界に足を踏み入れます。

その第一歩として、今回は「2つの地点の緯度経度から、始点から見た終点の方位角(ほういかく)を計算する方法」を探求します。方位角とは、真北を0度として、時計回りに測った角度のことです。例えば、真東は90度、真南は180度、真西は270度となります。

この計算を、まずは外部ライブラリを使わずに、Pythonに標準で付属しているmathモジュールだけを使って実装してみます。三角関数など少し数学的な要素も出てきますが、その原理を理解することで、より深く地理計算の世界を楽しめるようになりますよ。さあ、Pythonで地球を舞台にした計算を始めましょう!


1. 計算の考え方:地球を「完全な球」として捉える

今回私たちが行う計算は、地球を「完全な球体」と仮定した球面三角法(きゅうめんさんかくほう)という考え方に基づいています。※詳しくはwikipediaの説明をご覧ください。

実際の地球は、赤道方向に少し膨らんだ「回転楕円体」に近い形をしていますが、多くのアプリケーションや、特に2点間の距離がそれほど長くない場合には、この「完全な球」というモデルでも非常に精度の良い近似計算が可能です。何より、このモデルは計算の基本的な原理を理解するのに最適です。


2. 方位角計算の「材料」たち

方位角を計算する数式は少し複雑に見えるかもしれませんが、必要な「材料」となるPythonの機能は非常にシンプルです。

2.1. 緯度経度とラジアン (Radian)

私たちが普段使う角度の単位は「度(°)」ですが、Pythonのmathモジュールに含まれる三角関数(sin, cosなど)は、角度の単位として「ラジアン (radian)」を使います。そのため、計算を始める前に、まず緯度と経度を度からラジアンに変換する必要があります。これにはmath.radians()関数が使えます。

import math
# 例: 30度をラジアンに変換
deg = 30.0
rad = math.radians(deg)
print(f"{deg}度は、約{rad:.4f}ラジアンです。")

2.2. 方位を求める三角関数

方位角の計算式は、2点間の緯度と経度の差から、三角関数を使って方位のX成分(東西方向)とY成分(南北方向)を求めるような形になっています。数式の詳細な導出はここでは省略しますが、math.sin(), math.cos()といった基本的な関数が使われます。

2.3. 最終的な角度を求める `math.atan2(y, x)`

方位のY成分とX成分が計算できたら、最終的な角度を求めるために逆三角関数(アークタンジェント)を使います。ここで非常に便利なのがmath.atan2(y, x)関数です。

通常のatan(y/x)と違い、atan2はY成分とX成分を別々に引数として受け取るため、

  • ゼロ除算のエラーが起きない。
  • 北西、南西、南東といった、どの象限の角度なのかを正しく判断してくれる。

という大きなメリットがあります。この関数は、-πからπ(-180度から180度)の範囲で角度(ラジアン)を返してくれます。


3. Pythonコードで実装してみよう

それでは、これらの材料を使って、実際に関数として実装してみましょう。以下の関数は、2点の緯度経度(度単位)を受け取り、始点から見た終点の方位角(0〜360度)を返します。

import math

def calculate_bearing_simple(lat1, lon1, lat2, lon2):
    """
    2点の緯度経度から方位角を計算する関数(簡易版)。
    地球を完全な球体と仮定して計算します。
    """
    # 1. 緯度経度をラジアンに変換
    lat1_rad = math.radians(lat1)
    lon1_rad = math.radians(lon1)
    lat2_rad = math.radians(lat2)
    lon2_rad = math.radians(lon2)

    # 2. 経度の差を計算
    dLon_rad = lon2_rad - lon1_rad

    # 3. 方位角のY成分とX成分を計算
    y = math.sin(dLon_rad) * math.cos(lat2_rad)
    x = math.cos(lat1_rad) * math.sin(lat2_rad) - \
        math.sin(lat1_rad) * math.cos(lat2_rad) * math.cos(dLon_rad)

    # 4. atan2を使ってラジアン単位の角度を計算
    bearing_rad = math.atan2(y, x)

    # 5. ラジアンを度に変換
    bearing_deg = math.degrees(bearing_rad)

    # 6. 角度を0-360度の範囲に正規化
    return (bearing_deg + 360) % 360

最後の(bearing_deg + 360) % 360は、atan2が返す-180〜180度の角度を、0〜360度の一般的な方位角の表現に変換するための便利なテクニックです。


4. 実際に使ってみよう!東京駅から東京タワーはどの方角?

この関数を使って、実際に東京駅から見た東京タワーの方位角を計算してみましょう。

import math

# (ここに上記の calculate_bearing_simple 関数を貼り付ける)
def calculate_bearing_simple(lat1, lon1, lat2, lon2):
    # ... (中略) ...
    return (math.degrees(math.atan2(
        math.sin(math.radians(lon2) - math.radians(lon1)) * math.cos(math.radians(lat2)),
        math.cos(math.radians(lat1)) * math.sin(math.radians(lat2)) - math.sin(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.cos(math.radians(lon2) - math.radians(lon1))
    )) + 360) % 360

# --- ここから実行部分 ---
if __name__ == "__main__":
    # 始点:東京駅の緯度経度 (北緯35.6812度, 東経139.7671度)
    lat_start, lon_start = 35.681236, 139.767125
    
    # 終点:東京タワーの緯度経度 (北緯35.6585度, 東経139.7454度)
    lat_end, lon_end = 35.658581, 139.745433
    
    # 方位角を計算
    bearing = calculate_bearing_simple(lat_start, lon_start, lat_end, lon_end)

    # 結果の表示
    print("--- mathライブラリ版 ---")
    print(f"始点: 東京駅 ({lat_start}, {lon_start})")
    print(f"終点: 東京タワー ({lat_end}, {lon_end})")
    print("-" * 30)
    print(f"始点から終点への方位角は: {bearing:.2f} 度です。")

実行結果:

--- mathライブラリ版 ---
始点: 東京駅 (35.681236, 139.767125)
終点: 東京タワー (35.658581, 139.745433)
------------------------------
始点から終点への方位角は: 205.41 度です。

真南が180度、真西が270度なので、約205度というのは、おおよそ「南南西」の方角にあたります。地図と照らし合わせても、直感に合う結果が得られましたね!


5. まとめと次回予告

今回は、Pythonの標準ライブラリであるmathモジュールだけを使い、2点間の緯度経度から方位角を計算する方法を学びました。

  • 計算の原理が、地球を完全な球と仮定した球面三角法に基づいていること。
  • 計算には、角度の単位を「度」から「ラジアン」に変換する必要があること。
  • math.sin(), math.cos(), そして特にmath.atan2()といった三角関数が中心的な役割を果たすこと。

この方法は、外部ライブラリをインストールすることなく、地理空間計算の基本的な考え方を理解する上で非常に良い練習になります。

しかし、冒頭で述べた通り、この計算は地球を「完全な球」と仮定した近似的なものです。GPSや航空管制など、より高い精度が求められる分野では、地球が赤道方向に少し膨らんだ「回転楕円体」であることを考慮した計算が必要です。 この複雑な計算、自分で実装するのは非常に大変そうですよね?

ご安心ください。次回、第2回では、この地球の正確な形を考慮した高精度な計算を、たった数行のコードで実現してくれる専門ライブラリpyprojをご紹介します。コードはよりシンプルに、そして結果はより正確になる、まさに魔法のようなライブラリです。お楽しみに!

その他の投稿はこちら

コメント

このブログの人気の投稿

タイトルまとめ

これで迷わない!WindowsでPython環境構築する一番やさしい方法 #0

【Python標準ライブラリ完結!】11の冒険をありがとう!君のPython力が飛躍する「次の一歩」とは? 🚀