Format Locus voice hint, with additional hint data

This commit is contained in:
Norbert Renner 2021-02-24 19:52:45 +01:00
parent a9d27b4674
commit fd0ece0d31
5 changed files with 152 additions and 39 deletions

View file

@ -1,25 +1,29 @@
BR.Gpx = {
format: function (geoJson, turnInstructionMode = 0) {
if (!geoJson) return '';
format: function (geoJson, turnInstructionMode = 0, transportMode = 'bike') {
if (!geoJson?.features) return '';
const trkNameTransform = {
trk: function (trk, feature, coordsList) {
// name as first tag, by using assign and in this order
return Object.assign(
{
name: feature.properties.name,
},
trk
);
},
};
let gpxTransform = trkNameTransform;
if (turnInstructionMode > 0) {
BR.Gpx._addVoiceHints(geoJson, turnInstructionMode);
const voiceHints = BR.voiceHints(geoJson);
gpxTransform = voiceHints.getGpxTransform(turnInstructionMode, transportMode);
}
let gpx = togpx(geoJson, {
featureTitle: function () {},
featureDescription: function () {},
transform: {
trk: function (trk, feature, coordsList) {
return {
name: feature.properties.name,
trkseg: trk.trkseg,
};
},
wpt: function (wpt, feature, coord, index) {
return Object.assign(wpt, feature.properties);
},
},
transform: gpxTransform,
});
const statsComment = BR.Gpx._statsComment(geoJson);
gpx = '<?xml version="1.0" encoding="UTF-8"?>' + statsComment + gpx;
@ -27,13 +31,6 @@ BR.Gpx = {
return gpx;
},
_addVoiceHints: function (geoJson, turnInstructionMode) {
if (!geoJson.features) return;
const voiceHints = BR.voiceHints(geoJson);
voiceHints.add(turnInstructionMode);
},
// <!-- track-length = 319 filtered ascend = 2 plain-ascend = -1 cost=533 energy=.0kwh time=44s -->
_statsComment: function (geoJson) {
const props = geoJson.features?.[0].properties;
@ -68,8 +65,8 @@ BR.Gpx = {
// Remove all the newlines and then remove all the spaces between tags
xml = xml.replace(/\s*(\r\n|\n|\r)\s*/gm, ' ').replace(/>\s+</g, '><');
// break into lines, keep trkpt with subelement ele in single line
const reg = /(>)(<)(?!ele|\/trkpt)(\/?)/g;
// break into lines
const reg = /(>)(<)(\/?)/g;
let pad = 0;
xml = xml.replace('<metadata/>', '');

View file

@ -9,7 +9,7 @@
}
}
class RoundaboutCommand {
class RoundaboutCommand extends Command {
constructor(command, exitNumber) {
this.name = command.name + exitNumber;
this.locus = command.locus + exitNumber;
@ -19,7 +19,7 @@
}
}
class RoundaboutLeftCommand {
class RoundaboutLeftCommand extends RoundaboutCommand {
constructor(command, exitNumber) {
this.name = command.name + -exitNumber;
this.locus = command.locus + -exitNumber;
@ -64,17 +64,99 @@
}
},
add: function (turnInstructionMode) {
if (!this.voicehints) return;
createWpt: function (coord, properties) {
return Object.assign(
{
'@lat': coord[1],
'@lon': coord[0],
},
properties
);
},
for (const hint of this.voicehints) {
const [indexInTrack, commandId, exitNumber] = hint;
const coord = this.track.geometry.coordinates[indexInTrack];
const cmd = this.getCommand(commandId, exitNumber);
const properties = { name: cmd.message, sym: cmd.symbol.toLowerCase(), type: cmd.symbol };
getGpxTransform: function (turnInstructionMode, transportMode) {
const mode = turnInstructionMode;
const transform = {
gpx: function (gpx, features) {
for (const hint of this.voicehints) {
const [indexInTrack, commandId, exitNumber, distance, time] = hint;
let speed;
if (time > 0) {
speed = distance / time;
}
this.geoJson.features.push(turf.point(coord.slice(0, 2), properties));
}
const coord = this.track.geometry.coordinates[indexInTrack];
const cmd = this.getCommand(commandId, exitNumber);
if (!cmd) {
console.error(`no voicehint command for id: ${commandId} (${hint})`);
continue;
}
let properties;
if (mode === 2) {
const extensions = {};
// TODO 'locus:' namespace gets removed
extensions['locus:rteDistance'] = distance;
if (time > 0) {
extensions['locus:rteTime'] = time;
extensions['locus:rteSpeed'] = speed;
}
extensions['locus:rtePointAction'] = cmd.locus;
properties = {
ele: coord[2],
name: cmd.message,
extensions: extensions,
};
} else if (mode === 5) {
properties = { name: cmd.message, sym: cmd.symbol.toLowerCase(), type: cmd.symbol };
} else {
console.error('unhandled turnInstructionMode: ' + mode);
}
const wpt = this.createWpt(coord, properties);
gpx.wpt.push(wpt);
}
if (mode === 2) {
// hack to insert attribute after the other `xmlns`s
gpx = Object.assign(
{
'@xmlns': gpx['@xmlns'],
'@xmlns:xsi': gpx['@xmlns:xsi'],
'@xmlns:locus': 'http://www.locusmap.eu',
},
gpx
);
}
return gpx;
}.bind(this),
trk: function (trk, feature, coordsList) {
const properties = {
name: feature.properties.name,
};
const getLocusRouteType = (transportMode) => {
switch (transportMode) {
case 'car':
return 0;
case 'bike':
return 5;
default:
return 3; // foot
}
};
if (mode === 2) {
properties.extensions = {
'locus:rteComputeType': getLocusRouteType(transportMode),
'locus:rteSimpleRoundabouts': 1,
};
}
return Object.assign(properties, trk);
},
};
return transform;
},
getCommand: function (id, exitNumber) {