Skip to content

Commit 99301bd

Browse files
rustyconovertmcw
authored andcommitted
feat: Add parsing of GPX extensions speed, course, hAcc, vAcc (#18)
* Add parsing of GPX extensions speed, course, hAcc, vAcc Apple Watches track additional values that weren't being parsed these are: speed - speed in meters course - bearing hAcc - horizontal accuracy vAcc - vertical accuracy Add support for parsing and storing these values. * Suggestions from PR review
1 parent 29a035f commit 99301bd

File tree

3 files changed

+640
-61
lines changed

3 files changed

+640
-61
lines changed

lib/gpx.js

Lines changed: 77 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import { nodeVal } from "./shared";
22

3+
const attributeNames = [
4+
["speed", "speeds"],
5+
["course", "courses"],
6+
["hAcc", "hAccs"],
7+
["vAcc", "vAccs"],
8+
["heartRate", "heartRates"]
9+
];
10+
311
function getLineStyle(extensions) {
412
const style = {};
513
if (extensions) {
@@ -72,11 +80,28 @@ function coordPair(x) {
7280
ll.push(e);
7381
}
7482
}
75-
return {
83+
const result = {
7684
coordinates: ll,
7785
time: time ? nodeVal(time) : null,
7886
heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null
7987
};
88+
89+
const extensions = get1(x, "extensions");
90+
if (extensions !== null) {
91+
attributeNames
92+
.map(r => r[0])
93+
.filter(n => n !== "heartrate")
94+
.forEach(name => {
95+
const raw = get1(extensions, name);
96+
if (raw !== null) {
97+
const v = parseFloat(nodeVal(raw));
98+
if (!isNaN(v)) {
99+
result[name] = v;
100+
}
101+
}
102+
});
103+
}
104+
return result;
80105
}
81106
function getRoute(node) {
82107
const line = getPoints(node, "rtept");
@@ -98,46 +123,70 @@ function getPoints(node, pointname) {
98123
const line = [];
99124
const times = [];
100125
const l = pts.length;
101-
let heartRates = undefined;
126+
const extendedValues = {};
102127
if (l < 2) return {}; // Invalid line in GeoJSON
103128
for (let i = 0; i < l; i++) {
104129
const c = coordPair(pts[i]);
105130
line.push(c.coordinates);
106131
if (c.time) times.push(c.time);
107-
if (c.heartRate || heartRates) {
108-
if (!heartRates) heartRates = Array(i).fill(null);
109-
heartRates.push(c.heartRate || null);
110-
}
132+
attributeNames
133+
.map(r => r[0])
134+
.forEach(name => {
135+
if (c[name] || extendedValues[name]) {
136+
if (!extendedValues[name]) {
137+
extendedValues[name] = Array(i).fill(null);
138+
}
139+
extendedValues[name].push(c[name] || null);
140+
}
141+
});
111142
}
112-
return {
143+
const result = {
113144
line: line,
114-
times: times,
115-
heartRates: heartRates || []
145+
times: times
116146
};
147+
attributeNames.forEach(n => {
148+
if (extendedValues[n[0]]) {
149+
result[n[1]] = extendedValues[n[0]] || [];
150+
}
151+
});
152+
return result;
117153
}
118154
function getTrack(node) {
119155
const segments = node.getElementsByTagName("trkseg");
120156
const track = [];
121157
const times = [];
122-
const heartRates = [];
158+
const extendedValues = {};
123159
let line;
124160
for (let i = 0; i < segments.length; i++) {
125161
line = getPoints(segments[i], "trkpt");
126162
if (line) {
127163
if (line.line) track.push(line.line);
128164
if (line.times && line.times.length) times.push(line.times);
129-
if (heartRates.length || (line.heartRates && line.heartRates.length)) {
130-
if (!heartRates.length) {
131-
for (let s = 0; s < i; s++) {
132-
heartRates.push(Array(track[s].length).fill(null));
165+
166+
attributeNames
167+
.map(r => r[1])
168+
.forEach(name => {
169+
if (
170+
(extendedValues[name] && extendedValues[name].length) ||
171+
(line[name] && line[name].length)
172+
) {
173+
if (!extendedValues[name]) {
174+
extendedValues[name] = [];
175+
}
176+
if (!extendedValues[name].length) {
177+
for (let s = 0; s < i; s++) {
178+
extendedValues[name].push(Array(track[s].length).fill(null));
179+
}
180+
}
181+
if (line[name] && line[name].length) {
182+
extendedValues[name].push(line[name]);
183+
} else {
184+
extendedValues[name].push(
185+
Array(line.line.length || 0).fill(null)
186+
);
187+
}
133188
}
134-
}
135-
if (line.heartRates && line.heartRates.length) {
136-
heartRates.push(line.heartRates);
137-
} else {
138-
heartRates.push(Array(line.line.length || 0).fill(null));
139-
}
140-
}
189+
});
141190
}
142191
}
143192
if (track.length === 0) return;
@@ -147,8 +196,13 @@ function getTrack(node) {
147196
);
148197
if (times.length)
149198
properties.coordTimes = track.length === 1 ? times[0] : times;
150-
if (heartRates.length)
151-
properties.heartRates = track.length === 1 ? heartRates[0] : heartRates;
199+
attributeNames.forEach(n => {
200+
if (extendedValues[n[1]] && extendedValues[n[1]].length) {
201+
properties[n[1]] =
202+
track.length === 1 ? extendedValues[n[1]][0] : extendedValues[n[1]];
203+
}
204+
});
205+
152206
return {
153207
type: "Feature",
154208
properties: properties,

0 commit comments

Comments
 (0)