JavaScriptでPROJ4JSを用いて旧日本測地系（SRID=4301）から世界測地系(SRID=4326)へ測地系変換

# JavaScriptで測地系変換
## 測地系って？
　地球の座標を表現する緯度経度は様々な種類があり、同じ緯度経度でも異なる場所を示す場合があります。

![michi_mayou.png](https://qiita-image-store.s3.amazonaws.com/0/53918/78cd38f1-1150-0ae2-ff62-d5f7f2ccc420.png)


　日本では、明治時代から使い続けてきた日本測地系では地球全体の測量をするには誤差があるため、世界測地系へ変更されました。（[測量法が平成14年４月１日に施行](http://www.gsi.go.jp/LAW/jgd2000-AboutJGD2000.htm)）

# PROJ4JSで変換
異なる測地系間で座標を変換するには、楕円体である地球の形状が仇となり複雑な計算が必要になります。
C言語で[proj.4](http://proj4.org/) というライブラリがオープンソース系ではメジャーであり、PROJ4JS(http://proj4js.org/) はそのJavaScript版です。

## PROJ4JSの導入
### npmを利用する方法
Webブラウザだけではなく、node.jsなどでも利用する場合はnpmをおすすめします。

```shell
npm install proj4
bower install proj4
jam install proj4
component install proj4js/proj4js
```
### CDNを利用する場合
Webブラウザでの利用では、こちらの方法が簡単なのでおすすめです。
JavaScriptのライブラリが既にWebサーバに公開されているので、リンクするだけで利用可能です。

下記のサイトに移動し、最新のライブラリのURLをゲットしましょう。
https://cdnjs.com/libraries/proj4js

現時点での最新版ライブラリのURL
https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.4.4/proj4.js

# サンプルコード

測地系を変換するには、ライブラリにその測地系を明示する必要があります。
PROJ4JSには下記の３種類とその別名が登録されています。

1. 'EPSG:4326', which has the following alias
 - 'WGS84'
2. 'EPSG:4269'
 - 'EPSG:3857', which has the following aliases
3. 'EPSG:3785'
 - 'GOOGLE'
 - 'EPSG:900913'
 - 'EPSG:102113'

日本測地系は未登録なので、
　測地系の名称`"EPSG:4301"`と
　仕様を`"+proj=longlat +ellps=bessel+towgs84=-146.414,507.337,680.507,0,0,0,0 +no_defs"`を登録する必要があります。

世界には様々な測地系があります。
こちらのサイト（ http://spatialreference.org/ ）には、測地系ごとのPROJ4JSの記述方法もまとめられていますが、初心者にはやや難しい内容です。（日本測地系の記載は恐らく間違っていますのでご注意を）

## 日本測地系から世界測地系に変換する関数

```javascript
/* 測地系リストの追加 */
proj4.defs([
    ["EPSG:4301", //東京測地系/日本測地系 SRID=4301
        "+proj=longlat +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +no_defs"
    ]
]);

/**
 * tokyo2world(日本測地系から世界測地系に変換)
 * @param {lon} num - 日本測地系の経度
 * @param {lat} num - 日本測地系の緯度
 * @return {array} 0：世界測地系の経度 １:世界測地系の緯度
 **/
function tokyo2world(lon, lat) { 
    var ret = proj4("EPSG:4301", "EPSG:4326", [lon, lat]);
    return ret;
}
var ans = tokyo2world(135.0, 40);
console.log(ans[0], ans[1]);
```

## 世界測地系に日本測地系変換する関数

```javascript
/* 測地系リストの追加 */
proj4.defs([
    ["EPSG:4301", //東京測地系/日本測地系 SRID=4301
        "+proj=longlat +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +no_defs"
    ]
]);
/**
 * world2tokyo(世界測地系から日本測地系に変換)
 * @param {lon} num - 世界測地系の経度
 * @param {lat} num - 世界測地系の緯度
 * @return {array} 0：日本測地系の経度 １:日本測地系の緯度
 **/
function world2tokyo(lon, lat) { 
     var ret = proj4("EPSG:43２6", "EPSG:4301", [lon, lat]);
    return ret;
}
```

## Webブラウザ用のサンプル

CDNからJavaScriptライブラリを読み込み、日本測地系から世界測地系、世界測地系から日本測地系への変換を実施します。
結果は、コンソールログへの出力のみですのでお気をつけ下さい。

```html
<html>
<head>
    <meta charset="utf-8">
    <script src="//cdnjs.cloudflare.com/ajax/libs/proj4js/2.4.4/proj4.js"></script>
    <title>PROJ4JS</title>
</head>

<body>
    <script>
        /* 測地系リストの追加 */
        proj4.defs([
            ["EPSG:4301", //東京測地系/日本測地系 SRID=4301
                "+proj=longlat +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +no_defs"
            ],
            ["EPSG:4612", //日本測地系/JGD2000 SRID=4612
                "+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs"
            ]
        ]);

        /**
         * tokyo2world(日本測地系から世界測地系に変換)
         * @param {lon} num - 日本測地系の経度
         * @param {lat} num - 日本測地系の緯度
         * @return {array} 0：世界測地系の経度 １:世界測地系の緯度
         **/
        function tokyo2world(lon, lat) {
            var ret = proj4("EPSG:4301", "EPSG:4326", [lon, lat]);
            return ret;
        }
        /**
         * world2tokyo(世界測地系から日本測地系に変換)
         * @param {lon} num - 世界測地系の経度
         * @param {lat} num - 世界測地系の緯度
         * @return {array} 0：日本測地系の経度 １:日本測地系の緯度
         **/
        function world2tokyo(lon, lat) {
            var ret = proj4("EPSG:4326", "EPSG:4301", [lon, lat]);
            return ret;
        }

        var ans = tokyo2world(135.0, 40.0);
        console.log("日本測地系から世界測地系:" + ans[0] + " : " + ans[1]);

        var ans = world2tokyo(135.0, 40.0);
        console.log("世界測地系から日本測地系:" + ans[0] + " : " + ans[1]);
    </script>
</body>
</html>
```

# まとめ
PROJ4JSで測地系変換を実施する方法を紹介しました。
緯度経度を取り扱う際に、「あれ、位置がおかしいぞ！」という事がありましたら、PROJ4JSを思い出して頂ければと思います。