【Python実践編】pyprojライブラリで高精度な方位角計算を簡単に!(2点間の角度計算シリーズ 第2回) 🛰️

「前回、mathライブラリで方位角を計算したけど、もっと正確な方法はないの?」
「地球が完全な球じゃないことまで考えて計算したい!」
「プロが使うような、本格的な地理空間計算をPythonで手軽にやってみたい!」

こんにちは! Pythonプログラミング探検隊、隊長のPythonistaです! 前回の第1回では、Pythonの標準ライブラリであるmathモジュールだけを使って、地球を完全な球と仮定した方位角の計算に挑戦しましたね。三角関数を駆使して、地理的な問題を解き明かすプログラミングの面白さを感じていただけたかと思います。

しかし、あの方法はあくまで「近似」でした。今回は、その限界を超えるための**「プロの道具」**、地理空間計算ライブラリpyprojをご紹介します。このライブラリを使えば、地球のより正確な形(回転楕円体)を考慮した、非常に高精度な方位角計算が、驚くほど簡単なコードで実現できてしまいます。コードはよりシンプルに、結果はより正確になる魔法のようなライブラリの世界へようこそ!


1. なぜ`pyproj`なのか? - 地球の本当の形「回転楕円体」

前回の計算では、地球を完全な球体として扱いました。しかし、実際の地球は自転の遠心力によって、赤道方向に少しだけ膨らんだ「ミカン」のような形をしています。この形状のことを、測地学では回転楕円体(ellipsoid)と呼びます。 ※天文学辞典出典

短距離の計算ではこの差はごく僅かですが、大陸をまたぐような長距離の計算になると、この地球の「潰れ」が無視できないほどの誤差を生み出します。GPSなどが利用する世界標準の測地系であるWGS84も、この回転楕円体モデルに基づいています。

pyprojライブラリは、このような複雑な回転楕円体モデル上での測地線(2点間の最短距離)や方位角の計算を、高精度に行ってくれる専門的なツールなのです。


2. `pyproj`のインストールと使い方

2.1. ライブラリのインストール

まずはpipでpyprojをインストールしましょう。ターミナルやコマンドプロンプトで以下のコマンドを実行してください。

pip install pyproj

2.2. `pyproj`を使った方位角の計算

pyprojを使った方位角の計算は驚くほどシンプルです。以下の関数を見てみましょう。

from pyproj import Geod

def calculate_bearing(lat1, lon1, lat2, lon2):
    """
    2点の緯度経度から方位角を計算する関数 (pyproj版)。
    Args:
        lat1 (float): 始点の緯度
        lon1 (float): 始点の経度
        lat2 (float): 終点の緯度
        lon2 (float): 終点の経度
    Returns:
        float: 始点から見た終点の方位角(0-360度)
    """
    # 1. WGS84楕円体モデル(GPSなどで使用される標準的なモデル)を指定
    geod = Geod(ellps='WGS84')
    
    # 2. 2点間の前方方位角、後方方位角、距離を計算
    # ★★★ 超重要ポイント ★★★
    # inv()メソッドの引数は (経度1, 緯度1, 経度2, 緯度2) の順序です!
    fwd_azimuth, back_azimuth, distance = geod.inv(lon1, lat1, lon2, lat2)
    
    # 3. 前方方位角 (fwd_azimuth) は -180 から 180 の範囲で返ってくるため、
    #    一般的な方位角 (0から360) に変換する
    if fwd_azimuth < 0:
        fwd_azimuth += 360
        
    return fwd_azimuth

コードのポイント解説:

  • Geod(ellps='WGS84'): まず、計算の基準となる地球のモデル(測地系)を指定して、Geodオブジェクトを作成します。'WGS84'はGPSで使われている世界標準なので、通常はこれを指定すればOKです。
  • geod.inv(...): このメソッドが実際の計算を行う心臓部です。これは「測地線問題の逆問題」を解くもので、2点の座標から、その間の距離と、それぞれの点から見た相手の方位角を計算してくれます。
    • fwd_azimuth (forward azimuth): 始点から見た終点の方位角(前方方位角)。これが私たちが求めたい値です。
    • back_azimuth (back azimuth): 終点から見た始点の方位角(後方方位角)。
    • distance: 2点間の最短距離(メートル単位)。
  • 引数の順序: 非常に重要な注意点として、geod.inv()に渡す座標の順序は「経度、緯度」の順番です。緯度経度の順番で渡してしまうと、全く異なる結果になるので注意しましょう。
  • 角度の変換: pyprojが返す方位角は-180°〜180°の範囲(真北を0°として東が+、西が-)なので、if文を使って0°〜360°の一般的な方位角の表現に変換しています。

3. 2つの方法を徹底比較!

それでは、前回作成したmath版の関数と、今回のpyproj版の関数で、計算結果がどれくらい違うのかを比較してみましょう。

# (ここまでに、第1回で作成した calculate_bearing_simple 関数と、
#  今回作成した calculate_bearing 関数の両方を定義しておく)

# --- 比較1:短距離(東京駅 → 東京タワー) ---
lat_start_jp, lon_start_jp = 35.681236, 139.767125
lat_end_jp, lon_end_jp = 35.658581, 139.745433

bearing_simple_jp = calculate_bearing_simple(lat_start_jp, lon_start_jp, lat_end_jp, lon_end_jp)
bearing_pyproj_jp = calculate_bearing(lat_start_jp, lon_start_jp, lat_end_jp, lon_end_jp)

print("\n--- 短距離での比較 (東京駅 → 東京タワー) ---")
print(f"math版 (球体モデル):      {bearing_simple_jp:.6f} 度")
print(f"pyproj版 (楕円体モデル):   {bearing_pyproj_jp:.6f} 度")
print(f"差: {abs(bearing_simple_jp - bearing_pyproj_jp):.6f} 度")


# --- 比較2:長距離(東京 → ニューヨーク) ---
# 始点:東京 (ざっくりとした座標)
lat_start_world, lon_start_world = 35.68, 139.76
# 終点:ニューヨーク (ざっくりとした座標)
lat_end_world, lon_end_world = 40.71, -74.00

bearing_simple_world = calculate_bearing_simple(lat_start_world, lon_start_world, lat_end_world, lon_end_world)
bearing_pyproj_world = calculate_bearing(lat_start_world, lon_start_world, lat_end_world, lon_end_world)

print("\n--- 長距離での比較 (東京 → ニューヨーク) ---")
print(f"math版 (球体モデル):      {bearing_simple_world:.6f} 度")
print(f"pyproj版 (楕円体モデル):   {bearing_pyproj_world:.6f} 度")
print(f"差: {abs(bearing_simple_world - bearing_pyproj_world):.6f} 度")

実行結果 (例):

--- 短距離での比較 (東京駅 → 東京タワー) ---
math版 (球体モデル):      205.411703 度
pyproj版 (楕円体モデル):   205.556715 度
差: 0.145012 度

--- 長距離での比較 (東京 → ニューヨーク) ---
math版 (球体モデル):      18.733979 度
pyproj版 (楕円体モデル):   19.932822 度
差: 1.198843 度

この結果から、短距離では差はごくわずかですが、長距離になると**1度以上の無視できない差**が生まれることが分かります。これは、航空機のルート計算などでは非常に大きな違いとなります。


4. まとめ:いつ、どちらを使うべきか?

2つの方法を比較して、それぞれの特徴が見えてきました。

mathライブラリ版 pyprojライブラリ版
精度 低い(地球を球体と仮定) 高い(回転楕円体モデルを使用)
コードの簡潔さ やや複雑(三角関数の計算式が必要) 非常にシンプル(専門の関数を呼び出すだけ)
依存性 なし(標準ライブラリのみ) 外部ライブラリのインストールが必要
おすすめの用途 学習目的、原理の理解、精度を問わない短距離計算 全ての実用的なアプリケーション、正確性が求められる計算

結論として、「原理を学ぶために一度mathライブラリで自作してみるのは素晴らしい学習体験だが、実際のアプリケーションで方位角計算が必要になったら、迷わずpyprojのような専門ライブラリを使うべき」と言えるでしょう。車輪の再発明を避け、信頼性の高い専門的なツールを適切に使いこなすことは、優れたプログラマーの重要なスキルの一つです。

この2部構成のシリーズを通して、地理空間計算の面白さと、専門ライブラリのありがたみを感じていただけたなら幸いです!

その他の投稿はこちら

コメント

このブログの人気の投稿

タイトルまとめ

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

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