GPSに関わる要チェックワード「測地系」の意味とそれにまつわる変換式
携帯のGPS機能について調べていると、必ず出会う言葉「測地系」。前々回、前回の各キャリア別の位置情報取得方法内でも出た言葉でもあります。僕も初めて、仕事の中でGPSを扱っていたら「測地系」って言葉に遭遇し、悩まされました。
そこで、今回は「測地系」を僕なりの解釈で意味の説明をしたいと思います。そして、測地系にまつわる変換式についても書きます。
関連記事:
測地系とは-日本に存在する2つの測地系-
測地系とは、地球上のある地点の緯度経度及び標高を表すための「ものさし」といったところです。その測地系が、ここ日本では「日本測地系」と「世界測地系(WGS84)」2つの測地系に大体分かれます。
日本測地系と世界測地系の誤差
日本では、元々明治時代に東京湾の平均海面を基準とした独自の天文観測方法により測定した日本測地系を使っていました。 しかし、技術の進歩と共に日本測地系よりも正確な世界測地系が誕生しました。日本測地系は名前の通り、とてもローカルな測地系で且つ古く、東京付近では世界測地系との誤差が450m程度あります。 また東京付近では、日本測地系の数値と世界測地系の数値との間で、緯度が約+12秒、経度が約-12秒のずれがあります。
下の図が、日本測地系と世界測地系の誤差のイメージです。
そこで、2002年に測量法の改正があり、日本でもローカルすぎる日本測地系はやめて、ITRF(国際地球基準座標系)に準拠した世界測地系を利用することが決まりました。
しかし、未だに測地系が統一されておらず、日本測地系と世界測地系が入り混じっているのが現状です。
測地系で注意すべきこと
測量法改正から6年たった今でも2つの測地系が混在している現状からして、あと向こう数年はこの状況が続くでしょう。そのため携帯のGPS機能を利用し、位置情報を取得したサービスを行う際は注意が必要です。注意点としては、利用するAPIに情報を渡す前に日本測地系→世界測地系や世界測地系→日本測地系に位置情報を変換する作業が必要になります。以下の表が僕が把握している地図サービスと測地系の現状です。
地図サービス | 測地系 |
---|---|
GoogleMapsApi | 世界測地系 |
MapFan,マピオンなど日本中心の地図サービス | 日本測地系 |
測地系にまつわる変換式
では実際に日本測地系→世界測地系、世界測地系→日本測地系の変換はどのようにすればよいのでしょう。実は、次のような変換式があります。
目的 | 変換式 |
---|---|
日本測地系 ↓ 世界測地系 |
lonW = lonJ – latJ * 0.000046038 – lonJ * 0.000083043 + 0.010040 latW = latJ – latJ * 0.00010695 + lonJ * 0.000017464 + 0.0046017 |
世界測地系 ↓ 日本測地系 |
lonJ = lonW + latW * 0.000046047 + lonW * 0.000083049 – 0.010041 latJ = latW + latW * 0.00010696 – lonW * 0.000017467 – 0.0046020 |
(lonW=世界測地系の経度 , latW=世界測地系の緯度 , lonJ=日本測地系の経度 , latJ=日本測地系の緯度)
上記の変換式内の緯度経度はすべて度表示である必要があります。そのため、実際にAPIを利用する際は、 携帯から取得した度分秒表示の位置情報を度表記に変換する必要があります。
下記にJavaで度分秒表記から度表記に変換した例を示します。
/** * キャリアに応じて度分秒表示を度表示に変換する. * * @param dms 緯度または経度 * @param carrier キャリア * @return double 度表示の緯度または経度 */ public static String dms2Deg(String dms, String carrier) { String[] parsed = dms.split("."); double deg = Double.parseDouble(parsed[0]); double min = Double.parseDouble(parsed[1]); double sec = Double.parseDouble(parsed[2]); double secDecimal = Double.parseDouble(parsed[3]); double d = 0; if ("au".equals(carrier) || "softbank".equals(carrier)) { d = deg + (((min * 60 + sec + secDecimal / 10) * 1000) / 3600000); } else { d = deg + (((min * 60 + sec + secDecimal / 100) * 1000) / 3600000); } String d1 = String.valueOf(d); String result = StringUtils.division(d1, 1, 5); return result; }
ここで覚えておきたいことは1度=60分=3600秒であることです。これを踏まえて度表示に変換する場合は、取得した位置情報を「.」毎に切り分け、度(deg)以下の分(min)と秒(sec,secDecimal)を秒表示に変換し、足します。その後、整数化して360000で割った数と度(deg)を足した数が度表示になります。さらに上記の変換例ではau、SoftBankとdocomoで取得できる位置情報の桁数が異なるので、キャリアによって条件分岐を行っています。
度表示の変換例ですでにわかったと思いますが、度分秒表示を秒表示に変換する場合の変換例も下記に示します。
/** * 度分秒表示を秒表示に変換する. * * @param dms 緯度または経度 * @return double 秒表示の緯度または経度 */ private static double dms2Sec(String dms) { String[] parsed = dms.split("."); double deg = Double.parseDouble(parsed[0]); double min = Double.parseDouble(parsed[1]); double sec = Double.parseDouble(parsed[2]); double secDecimal = Double.parseDouble(parsed[3]); degSec = deg * 3600; minSec = min * 60; secDecimalSec = secDecimal / 100; double result = deg + min + sec + secDecimalSec; return result; }
このように日本では測地系が入り混じってるために面倒な計算を行わなくてはいけません。皆様、地図サービスを利用する際は、「測地系」にくれぐれもご注意ください。次回は取得した位置情報を元に2点間の距離を計算する方法について書きたいと思います。
参考サイト:
世界測地系移項の概要
関連記事:
非公開情報だよ!au GPSの使い方
DoCoMo、SoftBankのGPSを使った位置情報取得って、どうなってるの?