How to analyze GPX file with JavaScript - Part 1

Yes Lee
4 min readSep 26, 2017

--

Viewing elevation profile of GPX file with Google Earth

上山的時候我習慣會用手機的 GPS 記錄行程,下山後再把匯出的 GPX 檔丟到 Google Earth 上分析,看看整趟行程的距離、時間、海拔變化等,就像上圖,是前一陣子去水漾森林的記錄。

因為這樣的分析滿有趣又實用的,所以就想練習下用 JavaScript 做出類似的分析,最後再拿自己做出來的結果(距離、時間)和 Google Earth 來比較。

  1. GPX — GPS eXchange Format
  2. XML to JavaScript Object
  3. Time / Distance between Points

GPX — GPS eXchange Format

首先,根據 wiki,GPX 是用 XML 的格式來記錄 GPS 的,所以是很熟悉的 tag 形式的資料,如下圖。觀察後可以發現,<trkseg> 裡的 <trkpt> 記錄了行程中各點的經緯度、海拔和時間,這就是我們需要的資料啦。

XML to JavaScript Object

接著,為了方便使用 JavaScript 進行分析,所以利用 fast-xml-parser 的幫忙直接把 XML 格式的 GPX 檔轉成一個 JavaScript Object。

const fastXmlParser = require("fast-xml-parser");let parsedGPX = fastXmlParser.parse(
fs.readFileSync("./shui-yang-forest.gpx", "utf8"),
{
attrPrefix: "",
ignoreNonTextNodeAttr: false
}
);
console.log(parsedGPX);
XML 格式的 GPX 檔轉成一個 JavaScript Object
trkpt 的部分

Time / Distance between Points

要算出一個 GPX 的總距離也是滿單純的,把所有點兩兩間的距離算出來再相加就好啦,在這裡,我使用了 node-geo-distance 這個 package 來處理兩點之間的距離計算。

值得一提的是,node-geo-distance 在計算兩點距離時所使用的公式有兩種:
1. 把地球當作球體的 Haversine formula
2. 把地球當作橢圓球體的 Vincenty formula
所以下面也會把兩種結果都算出來一起做個比較。

const geo = require("node-geo-distance");
const points = parsedGPX.gpx.trk.trkseg.trkpt;
let distanceHaversine = 0;
let distanceVincenty = 0;
for (let i = 0; i < points.length - 1; i++) {
const coord1 = ...
const coord2 = ...
distanceHaversine += +geo.haversineSync(coord1, coord2);
distanceVincenty += +geo.vincentySync(coord1, coord2);
}

而總時間的計算就單純使用 Moment.js 啦。

const time = moment(_.last(points).time).diff(points[0].time);

從最後的結果可以發現,距離的部分,用 Haversine formulaVincenty formula 算出來的結果在精確到小數點後 1 位的情況下並沒有差別,而和封面照片中 Google Earth 算出來的 11km 也沒有太大差別,算是OK!

時間的部分也沒有問題,和 Google Earth 的一模一樣, 6hr 33m 13s !

完整程式碼如下:

--

--

Yes Lee
Yes Lee

Written by Yes Lee

Frontend Engineer in Taiwan.

No responses yet