ロカポ (by 有限会社ロケージング) は世界中のどんな場所でも12文字で表すことができる位置情報コード。
緯度経度でいいじゃん……と思わないでもない。
けど、"英英数×4" のフォーマットがおぼえやすくていいのかな?

ロカポのサンプル:

・自由の女神、ニューヨーク、アメリカ (SW8.HQ9.CR8.PU9)
・東京タワー、東京、日本 (SD9.XC4.ER9.CY4)
・ロンドンアイ、ロンドン、イギリス (UL4.MZ7.GB4.TN7)
・サグラダファミリア、バルセロナ、スペイン (SZ4.NE0.YG4.VQ0)
・コロッセオ、ローマ、イタリア (TB3.NX4.FJ3.PA4)

位置情報コード LocaPoint(ロカポ)

とりあえず、Javaでロカポと緯度経度を相互変換するコードを書いてみる。

ロカポのサイトにサンプルがあるから、ほとんど丸写し状態。


/**
 * WGS84測地系における緯度経度と位置情報コードLocaPoint(ロカポ)を相互変換します。
 * 
 * <p>LocaPoint Specification: http://www.locapoint.com/en/spec.html</p>
 * 
 * <p>ロカポの仕様: http://www.locapoint.com/en/spec.html</p>
 * 
 */
public class LocaPoint {
 
  /**
   * WGS84測地系における緯度経度を位置情報コードLocaPoint(ロカポ)へ変換します。
   * @param lat WGS84測地系における緯度
   * @param lon WGS84測地系における経度
   * @return 位置情報コードLocaPoint(ロカポ)
   */
  public static String LatLon2LocaPoint(double lat, double lon) {
 
    double lat_step = Math.floor((lat +  90) / 180.0 * (6760 * 6760));
    double lon_step = Math.floor((lon + 180) / 360.0 * (6760 * 6760));
 
    char[] c = new char[]{
      (char)(floor(lat_step / 1757600) % 26 + 'A'),
      (char)(floor(lat_step /   67600) % 26 + 'A'),
      (char)(floor(lat_step /    6760) % 10 + '0'),
      '.',
      (char)(floor(lon_step / 1757600) % 26 + 'A'),
      (char)(floor(lon_step /   67600) % 26 + 'A'),
      (char)(floor(lon_step /    6760) % 10 + '0'),
      '.',
      (char)(floor(lat_step /     260) % 26 + 'A'),
      (char)(floor(lat_step /      10) % 26 + 'A'),
      (char)(floor(lat_step /       1) % 10 + '0'),
      '.',
      (char)(floor(lon_step /     260) % 26 + 'A'),
      (char)(floor(lon_step /      10) % 26 + 'A'),
      (char)(floor(lon_step /       1) % 10 + '0'),
    };
 
    return new String(c);
  }
 
  /**
   * 位置情報コードLocaPoint(ロカポ)をWGS84測地系における緯度経度へ変換します。
   * @param 位置情報コードLocaPoint(ロカポ)
   * @return WGS84測地系における緯度経度([0]が緯度で、[1]が経度)
   */
  public static double[] LocaPoint2LatLon(String locapoint) {
 
    double[] latlon = new double[2];
 
      latlon[0] =
        (
          ((locapoint.charAt( 0) - 'A') * 1757600) +
          ((locapoint.charAt( 1) - 'A') *   67600) +
          ((locapoint.charAt( 2) - '0') *    6760) +
          ((locapoint.charAt( 8) - 'A') *     260) +
          ((locapoint.charAt( 9) - 'A') *      10) +
          ((locapoint.charAt(10) - '0') *       1)
        )
          * (180.0 / 45697600.0) - 90;
 
      latlon[1] =
        (
          ((locapoint.charAt( 4) - 'A') * 1757600) +
          ((locapoint.charAt( 5) - 'A') *   67600) +
          ((locapoint.charAt( 6) - '0') *    6760) +
          ((locapoint.charAt(12) - 'A') *     260) +
          ((locapoint.charAt(13) - 'A') *      10) +
          ((locapoint.charAt(14) - '0') *       1)
        )
          * (360.0 / 45697600.0) - 180;
 
    return latlon;
  }
 
  private static int floor(double a){ 
    return (int)Math.floor(a);
  }
 
  private LocaPoint() {
    ;
  }
 
  private static void test(double lat, double lon) {
    System.out.println("src " + lat + "," + lon);
    String lp = LatLon2LocaPoint(lat, lon);
    System.out.println(" -> " + lp);
    double[] latlon = LocaPoint2LatLon(lp);
    System.out.println(" -> " + latlon[0] + "," + latlon[1]);
  }
 
  private static void test(String locapoint) {
    System.out.println("src " + locapoint);
    double[] latlon = LocaPoint2LatLon(locapoint);
    System.out.println(" -> " + latlon[0] + "," + latlon[1]);
    String lp = LatLon2LocaPoint(latlon[0], latlon[1]);
    System.out.println(" -> " + lp);
  }
 
  public static void main(String[] args) {
 
    // ロカポのサンプルより
    System.out.println("自由の女神、ニューヨーク、アメリカ");
    test(40.689140, -74.044553);
    test("SW8.HQ9.CR8.PU9");
 
    // ロカポのサンプルより
    System.out.println("東京タワー、東京、日本");
    test(35.658648,139.745664);
    test("SD9.XC4.ER9.CY4");
    
    // Google Maps の検索結果より
    System.out.println("名古屋城、名古屋、日本");
    test(35.188716,136.900034);
  }
 
}

Java/Jakarta の流儀に倣うなら LocaPointUtils みたいなクラス名のほうが良かったかも。

テスト実行結果:


自由の女神、ニューヨーク、アメリカ
src 40.68914,-74.044553
 -> SW8.HQ9.CR8.PU8
 -> 40.68913991106754,-74.0445607646791
src SW8.HQ9.CR8.PU9
 -> 40.68913991106754,-74.04455288680369
 -> SW8.HQ9.CR8.PU9
 
東京タワー、東京、日本
src 35.658648,139.745664
 -> SD9.XC4.ER9.CY4
 -> 35.65864771891739,139.74566366723855
src SD9.XC4.ER9.CY4
 -> 35.65864771891739,139.74566366723855
 -> SD9.XC4.ER8.CY4
 
名古屋城、名古屋、日本
src 35.188716,136.900034
 -> SC1.WX0.NV4.RQ6
 -> 35.18871275515562,136.90003326214065

精度の問題で多少の誤差は出てるみたいだけど、だいたい相互変換できてる。

位置情報ってどうやってクラス表現するんだろう? 緯度経度とロカポは結局同じものを指しているにすぎないんだから Location クラスみたいなものを作って、getLocapo とか getLatLon とかのメソッドを作ったほうがJavaっぽい気がする。コンストラクタは、ロカポが引数なものと、緯度経度が引数のものを作っておいて。でも、精度の問題でクラスがロカポと緯度経度の両方を持つようになりそうだし、うーん。
ま、でも変換用ユーティリティクラスとして作っておいたほうが、あとあと切り替えもできるし、メンドウがなさそうだから、とりあえずこれでいいか……

次に、ロカポ表示機能を Poison Maps Location へ組み込む。

名古屋城のロカポ SC1.WX0.KE3.RA0 はこんな感じで表示。

名古屋城のロカポ LocaPoint for Nagoya Castle

追記: 2006-10-28

ロカポ考案者のNaoさんからメールのお返事をいただけたので、追記。

他にも似たような位置情報をあらわすコードとして、

というのがあるそうな。
でも、これらは……ライセンス料いるっぽい。

Naoさんによるとロカポは、Linuxのようなオープンアーキテクチャにしたいらしい。
まぁ、コード自体をビジネスにするのはキビしいよね。その周辺をビジネスにしたほうが、広まりやすいだろうし。

ロカポは同一のエリアコード内や近隣のエリアコードでは、市外局番のように覚えてしまえるからラク。
ローカルコードも1メートル以下の精度がある。
レストランへの道案内のように10メートル程度の精度で良いときは、***.***.DS*.KR* と4文字だけでじゅうぶん。最後の一桁は不要。って、このメリットはアピールされてないのでは(^_^; アルファベット4文字で良いならだいぶラクになるなぁ。

精度については、このあたり↓がわかりやすい。

(略)前半2つのブロックが広域情報を示し、後半が境域情報になる仕組みで、80cm×80cmの範囲で位置を表現することができる。(略)状況によっては、広域情報を示す最初の2ブロックは省略可能であり、後半ブロックの数字を省略しても8m×8m精度の位置情報を示す事ができるため、口頭での伝達による誤認などを防ぐことができる。(略)

ロケージング、独自開発のジオコードを活用した無料マップ生成サービス : VentureNow(ベンチャー・ナウ)

ロカポを利用したウェブアプリ
ロカポDIYマップ:自分だけのオリジナルマップを作ろう!

デンソーのマップコード
技術開示料が105万円(税込)。
数字だけで構成されているコードなので、携帯電話から入力しやすい。
QRコードといい、デンソーは位置情報に関して携帯電話がメイン・ターゲットなのかな?

NCプロジェクトのNコード
地方自治体・公共団系での実績があるよう。
犬山市都市計画GIS, 小牧市資産税GIS, 愛知県防災情報システム, 堺市上下水道局の消火栓・バルブ類にNコード, 森林学会の樹木管理コード, 芦原市統合型GIS, 羽咋市統合型GIS, ......
使いたいときは、「お問い合わせ」という感じ。

ロカポ ブログ: いろいろな“ジオコード” (ロカポ誕生の記録:5) には、他にもいろいろな位置情報コードが紹介されていて参考になる。

あと、「ロカポ誕生の記録」シリーズはなかなかおもしろい。


コメント

ロカポ考案者のNaoと申します。ロカポを取り上げて頂きどうもありがとうございます。またJavaのコードを作成していただき、ありがとうございました。早速ロカポのサイトからリンクさせていただきたいと思います。
もしよろしければご連絡頂ければ幸いです。

Nao@LocaPoint.com

メール送っておきました > Nao さん

リンクされるのはうれしいので大歓迎です。

tags: zlashdot GIS LocaPoint PoisonMapsLocation

Posted by NI-Lab. (@nilab)