はじめに
仕事である特定の2点間の距離を計測する必要が出てきたので
以前他のPJで使用されていた、Turf.jsというライブラリがあったので試してみました。
作業環境
- node 12.0.0
- npm 6.9.0
- Turf.js 6.9.0
前提条件
- 複数の箇所の緯度・経度をデータとして持っている
- データはjson形式のファイル(lists.json)
- できれば外部ファイルに書き出して確認したい
- 上記と、ある特定の一点との距離を計測する必要がある
- 地球上(球面状)の2点間の計算
[
{
"NAME": "名古屋駅",
"LATITUDE": 35.170406,
"LONGITUDE": 136.881695,
"Distance": 267.50358367757696
},
{
"NAME": "大阪駅",
"LATITUDE": 34.702485,
"LONGITUDE": 135.495951,
"Distance": 403.0278954652313
}
]
事前準備
まずは今回の作業を行うのにディレクトリを作っておきます。
mkdir turf_test
cd turf_test
Turf.jsについて
参考にさせていただいたスライドからそのまま引用すると
軽量・高速・オープンなWeb地図用のGISライブラリ
とあります。
公式サイトを見る限りかなり色々できそうです。
ただ色々できる分、全て入れるとかなりの容量になります。
npm install @turf/turf
上記コマンドでインストールをすると本体や関連しているライブラリ含めて、17.3MBあります。
全て入れた状態でも使用はできるんですが、公式サイトを見る限りかなりモジュール化が徹底されているようなので、用途に沿ったものだけを入れていきます。
ここで前提条件を思い出します。
基本的には2点間の計測ができれば良いので、それを実現できそうなものを公式サイトから探しました。
distanceがそれに該当しそうです。
distanceの説明
記載されている説明を直訳します。(ありがとうgoogle翻訳)
Calculates the distance between two points in degrees, radians, miles, or kilometers. This uses the Haversine formula to account for global curvature.
2つのポイント間の距離を度、ラジアン、マイル、またはキロメートルで計算します。これは、Haversine公式を使用して、全体的な曲率を考慮します。
説明を見る限りでは今回の要件を満たしていそうです。
というわけでこれをインストールしていきます。
distanceの実装
該当の機能の説明を見る限り@turf/distance
だけあれば十分なようです。
インストールします。
npm init
npm install @turf/distance
ちなみにこのモジュールだけだと、131KBだけです。
まずは公式に載っている通りの内容を実行してみます。
今回はターミナルから直接叩くことを想定しています。
ファイルの作成。
touch index.js
今回は東京駅から名古屋駅までの距離を計測します。
まずは公式サイトに載っているテストコードを掲載
var from = turf.point([-75.343, 39.984]);
var to = turf.point([-75.534, 39.123]);
var options = {units: 'miles'};
var distance = turf.distance(from, to, options);
ちなみに公式はライブラリが全部入っている前提のコードのようなので、以下のように変更しました。
// turf.js呼び出し
const { point } = require('@turf/helpers')
const distance = require('@turf/distance').default
const from = point([139.766765, 35.681283]); //[経度, 緯度] 東京駅
const to = point([136.881695, 35.170406]); //[経度, 緯度] 名古屋駅
const options = { units: 'kilometers' }; // degrees, radians, miles, kilometersが指定可能
const result = distance(from, to, options);
console.log(result) // 267.50358367757696
node index.js
// consoleに右記が出力 → 267.50358367757696
だいたい267Kmほどの距離があるようです。
試しにgooglemapでも距離計測をしておきます。
おおよそあっています。
ファイルの外部読み込みから、吐き出しまで
- 複数の箇所の緯度・経度をデータとして持っている
- データはjson形式のファイル(lists.json)
- できれば外部ファイルに書き出して確認したい
上記も含めてコードに落とし込みました。
これを実行すると該当のディレクトリにresults.json
が吐き出されます。
Node.jsにおける外部ファイルの読み込み、書き出しの説明に関しては割愛します。
// turf.js
const { point } = require('@turf/helpers')
const distance = require('@turf/distance').default
// 設定ファイルの読み込み
const fs = require('fs');
const util = require('util');
const readFile = util.promisify(fs.readFile);
let results = []
const now = new Date()
const isNumber = (value => {
return ((typeof value === 'number') && (isFinite(value)));
})
let errorTarget = ''
readFile('lists.json', 'utf-8')
.then((data) => {
lists = JSON.parse(data);
lists.forEach((d, index) => {
if ((d.LONGITUDE && d.LATITUDE) && (isNumber(d.LONGITUDE) && isNumber(d.LATITUDE))) {
let pt1 = point([139.766765, 35.681283], { 'name': '東京駅' })
let pt2 = point([Number(d.LONGITUDE), Number(d.LATITUDE)], { 'name': d.name })
const result = distance(pt1, pt2, { units: 'kilometers' })
d.DISTANCE = result
results.push(d)
}
})
})
.catch((err) => {
console.log(err)
throw err;
}).finally(() => {
fs.writeFileSync(`results.json`, JSON.stringify(results, null, ' '));
})
生成物
最終的に吐き出された生成物は以下です。
[
{
"NAME": "名古屋駅",
"LATITUDE": 35.170406,
"LONGITUDE": 136.881695,
"DISTANCE": 267.50358367757696
},
{
"NAME": "大阪駅",
"LATITUDE": 34.702485,
"LONGITUDE": 135.495951,
"DISTANCE": 403.0278954652313
}
]
まとめ
初めはgoogleのAPIを有料になってでも叩かないとあかんかなーと思っていたんですが、
意外と簡単にいけてびっくりしました。
公式サイト見る限りかなり多機能なので、他にも活用してみたいものです。
最後まで読んでくださってありがとうございました。