日本はイルミネーション輝く冬が到来。海外ではFOSS4Gのイベントが開催されていますが、私は日本で今日も路線バスに乗って出かけているのであります。
ときたま、路線バスに乗ってGPSロギングをするときがあるのですが、GPSのロギングでよく使われるファイルフォーマットとしてGPXファイルがあります。
この記事では、簡単にGPXファイルの説明と、GPXファイルがQGISやMapLibreで読み込めるのか述べていきます。
GPXファイルとは
GPXとは GPS Exchange Format の略で、GPSを使って位置情報を記録するデバイスでよく用いられているXMLのオープンフォーマットです。
GPXでは、主に3種類のタイプが定義できます。下記に各種類のサンプルのGPXファイルを示していますが、1つのファイルにまとめることもできます。GPXの詳しい書き方は 公式ドキュメント をご覧ください。
種類 | 概要 | 説明 |
---|---|---|
wptType | ウェイポイント | GPSで取得したWGS84座標のポイントを表現しています。 |
rteType | ルート | 複数のポイントに順序を付与して1つのルートを表現しています。 |
trkType | トラック | 過去にどのような点をを通ったのかを表現します。各ポイントにタイムスタンプを付与することが多い。 |
wptType(ウェイポイント)
wpt
タグで1つずつポイントの情報を定義しています。
<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.1" creator="santen-ichiyon"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1">
<metadata>
<name>ExampleGPX</name>
<author>santen-ichiyon</author>
</metadata>
<wpt lat="35.681111" lon="139.766667">
<ele>3.5</ele>
<name>Tokyo Station</name>
</wpt>
<wpt lat="35.628222" lon="139.738694">
<ele>3.2</ele>
<name>Shinagawa Station</name>
</wpt>
<wpt lat="35.690833" lon="139.700278">
<ele>37.6</ele>
<name>Shinjuku Station</name>
</wpt>
<wpt lat="35.729722" lon="139.710861">
<ele>32.7</ele>
<name>Ikebukuro Station</name>
</wpt>
<wpt lat="35.713889" lon="139.777222">
<ele>11.2</ele>
<name>Ueno Station</name>
</wpt>
</gpx>
rteType(ルート)
rte
の中に複数個の rtept
を定義して、ルートを表現しています。
<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.1" creator="santen-ichiyon"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1">
<metadata>
<name>ExampleGPX</name>
<author>santen-ichiyon</author>
</metadata>
<rte>
<name>Example Route</name>
<rtept lat="35.713586" lon="139.777218">
<ele>5.1</ele>
</rtept>
<rtept lat="35.713451" lon="139.777545">
<ele>3.3</ele>
</rtept>
<rtept lat="35.713334" lon="139.777803">
<ele>2.8</ele>
</rtept>
<rtept lat="35.713107" lon="139.777658">
<ele>2.9</ele>
</rtept>
<rtept lat="35.712846" lon="139.777449">
<ele>2.8</ele>
</rtept>
</rte>
</gpx>
trkType(トラック)
トラックは、1つの trk
タグの中に複数のセグメントタグ ( trkseg
) が宣言できるというのが特徴です。
<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.1" creator="santen-ichiyon"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1">
<metadata>
<name>ExampleGPX</name>
<author>santen-ichiyon</author>
</metadata>
<trk>
<name>Example Track</name>
<trkseg>
<trkpt lat="35.713586" lon="139.777218">
<ele>5.1</ele>
<time>2024-12-07T12:00:00Z</time>
</trkpt>
<trkpt lat="35.713451" lon="139.777545">
<ele>3.3</ele>
<time>2024-12-07T12:00:02Z</time>
</trkpt>
<trkpt lat="35.713334" lon="139.777803">
<ele>2.8</ele>
<time>2024-12-07T12:00:05Z</time>
</trkpt>
<trkpt lat="35.713107" lon="139.777658">
<ele>2.9</ele>
<time>2024-12-07T12:00:07Z</time>
</trkpt>
<trkpt lat="35.712846" lon="139.777449">
<ele>2.8</ele>
<time>2024-12-07T12:00:10Z</time>
</trkpt>
</trkseg>
</trk>
</gpx>
QGISで読み込む
GPXファイルはQGISファイルで読み込むことができます。実際にウェイポイントのファイルをQGISに読み込むんでみると、どのアイテムを読み込むのか選択するダイアログがでてきます。
ウェイポイントしか記載されていないGPXでも、一応ルートとトラック関連のジオメトリ個数を出してくれて、選択もできます。
「レイヤを追加」をクリックすると、以下の画像のようにQGISでウェイポイントが描画できます(ポイントの大きさを変えて表示しています)。
同じように、ルートやトラックのデータもそれぞれ読み込みます。ルートとトラックは、ポイントをつなげたラインデータと、それを構成するポイントが表示できます。
ルート単体のサンプルファイル
トラック単体のサンプルファイル
MapLibreで読み込む
MapLibreでGPXを読み込むときは、自分でXMLをパースしてGeoJSONなどMapLibreで読み込めるファイル形式に変換する手法もありますが、 maplibre-gl-vector-text-protocol というライブラリを使ってGPXファイルを読み込むという手法もあります。
今回は、後者の手法でGPXファイルを読み込み、MapLibreで地図上にGPXファイルのジオメトリを描画してみます。
フォルダ構成はこんな感じです。
index.html
に、 maplibre-gl-vector-text-protocol のスクリプトを読み込みます。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ExampleGPXMapLibre</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://unpkg.com/maplibre-gl@4.1.3/dist/maplibre-gl.js"></script>
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@4.1.3/dist/maplibre-gl.css">
<link href="./index.css" rel="stylesheet">
</head>
<body>
<div id="map"></div>
</body>
<!-- maplibre-gl-vector-text-protocolの外部スクリプトを追加 -->
<script src="https://loc8.us/maplibre-gl-vector-text-protocol/dist/maplibre-gl-vector-text-protocol.js"></script>
<script src="./index.js"></script>
</html>
index.css
は省略しますが、HTMLの map
ドキュメントを画面いっぱいに広げているスタイルを書いています。
index.js
ではMapLibreの初期化をして、その後に GPXファイルのプロトコルを追加しています。
マップ読み込み後の処理として、いつものようにSourceとLayerを追加します。ここでGPXファイルを読み込む際には、addSource の data で gpx://
をつけて GPX ファイルを定義します。
また、GPXをパースしたあとにGeoJSONに変換される仕組みとなっているため、 addSource の type には "geojson"
を定義します。
addLayerでライン用のレイヤーとポイント用のレイヤーを定義することで、QGISと同じようにポイントとラインの描画ができます。
var map = new maplibregl.Map({
container: "map",
style: "https://tile.openstreetmap.jp/styles/osm-bright-ja/style.json",
center: [139.777218, 35.713586],
zoom: 19,
});
// GPXファイルを読み込むためのプロトコルを追加
maplibregl.addProtocol("gpx", VectorTextProtocol.VectorTextProtocol);
map.on("load", () => {
map.addSource("sample-gpx-source", {
// GeoJSONに変換されるため、typeは "geojson" を定義
type: "geojson",
// gpx:// をつける必要あり
data: "gpx://./data/trkTypeSample.gpx",
});
// ラインを描画
map.addLayer({
id: "sample-gpx-line-layer",
type: "line",
source: "sample-gpx-source",
paint: {
"line-color": "#000",
"line-width": 2,
},
});
// ポイントを描画
map.addLayer({
id: "sample-gpx-point-layer",
type: "circle",
source: "sample-gpx-source",
paint: {
"circle-color": "#000",
"circle-radius": 5,
},
});
});
このように記述して実際に動かしてみると、GPXファイルに記録されている点と、それをつなぎ合わせたラインが表示されます。