Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn instructions had wrong distance when using multiple segments #646

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion js/control/Export.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,17 +322,39 @@ BR.Export._concatTotalTrack = function (segments) {
}
if (fp.voicehints) {
if (!p.voicehints) p.voicehints = [];
let prevHintIdx = p.voicehints.length - 1;
let hintDistanceSum = 0;
for (const fpHint of fp.voicehints) {
const hint = fpHint.slice();
hint[0] += coordOffset;
hintDistanceSum += hint[3];
p.voicehints.push(hint);
}
// fix the distance for the last turn in a segment
//
// Problem: In a segmented route where each segment is requested
// separately the server can't see that we intend to go further.
// Therefore the last voicehints/turn can only contain the
// distance till the end of that segment.
// However: The distance from the start of segment to the next
// turn is missing.
// Furthermore the server never reports the distance from the
// start to the first turn. So we have to calculate that too.
if (prevHintIdx >= 0) {
let firstHintDistance = parseInt(fp['track-length'], 10) - hintDistanceSum;
p.voicehints[prevHintIdx][3] += firstHintDistance;
}
} else if (p.voicehints && p.voicehints.length) {
p.voicehints[p.voicehints.length - 1][3] += parseInt(fp['track-length'], 10);
}
} else {
// clone
properties = Object.assign({}, feature.properties);
if (properties.voicehints) {
if (properties.voicehints && properties.voicehints.length) {
properties.voicehints = properties.voicehints.slice();
const last = properties.voicehints.length - 1;
// may be modified to fix distance-to-next
properties.voicehints[last] = properties.voicehints[last].slice();
}
if (properties.times) {
properties.times = properties.times.slice();
Expand Down
74 changes: 62 additions & 12 deletions tests/control/Export.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,64 @@ const fs = require('fs');
const indexHtmlString = fs.readFileSync('index.html', 'utf8');
const indexHtml = new DOMParser().parseFromString(indexHtmlString, 'text/html');

// &lonlats=8.467712,49.488117;8.469354,49.488394;8.470556,49.488946;8.469982,49.489176 + turnInstructionMode=2
// Geojson results created by server for
// * lonlats=8.467712,49.488117;8.469354,49.488394;8.470556,49.488946;8.469982,49.489176
// * with turnInstructionMode=2
//
// a) Each segment separate
// * curl "https://brouter.de/brouter?lonlats=8.467712,49.488117|8.469354,49.488394&profile=trekking&alternativeidx=0&format=geojson&profile:turnInstructionMode=2"
// * repeated for each segment and copied together
const segments = require('./data/segments.json');
// b) All segments in a single request
// * curl "https://brouter.de/brouter?lonlats=8.467712,49.488117|8.469354,49.488394|8.470556,49.488946|8.469982,49.489176&profile=trekking&alternativeidx=0&format=geojson&profile:turnInstructionMode=2" > ./data/segments.json
const brouterTotal = require('./data/brouterTotal.json');

function allowRoundigDifference(obj, field, client, brouter) {
if (obj[field] === client) {
obj[field] = brouter;
}
}

// resolve intended/accepted differences before comparing
function adopt(total, brouterTotal) {
// BRouter total aggregates messages over segments, client total does not,
// but that's Ok, so just fix for the test comparison
const messages = total.features[0].properties.messages;
const message = messages[4].slice();
messages[4] = message;
message[3] = (+message[3] + +messages[2][3] + +messages[3][3]).toString();
message[6] = (+message[6] + +messages[2][6] + +messages[3][6]).toString();
messages.splice(2, 2);

// fix minor float rounding difference
total.features[0].properties.times[6] = 28.833; // 28.832

total.features[0].properties.name = brouterTotal.features[0].properties.name;
let messages = total.features[0].properties.messages;

// Time & Energy are totals: Client restart those at segment boundary
let offsetTime = 0,
offsetEnergy = 0;
for (let i = 1; i < messages.length; i++) {
// 3 - distance, 9 - WayTags, 11 - Time, 12 - Energy
let message = messages[i].slice();
messages[i] = message;
if (message[9] === messages[i - 1][9]) {
messages[i - 1][3] = (+message[3] + +messages[i - 1][3]).toString();
offsetTime = +messages[i - 1][11];
messages[i - 1][11] = (+message[11] + +messages[i - 1][11]).toString();
offsetEnergy = +messages[i - 1][12];
messages[i - 1][12] = (+message[12] + +messages[i - 1][12]).toString();
messages.splice(i, 1);
i--;
} else {
message[11] = (+message[11] + offsetTime).toString();
message[12] = (+message[12] + offsetEnergy).toString();
}
}

allowRoundigDifference(total.features[0].properties, 'total-energy', '6835', '6837');
allowRoundigDifference(total.features[0].properties, 'total-time', '69', '68');
allowRoundigDifference(total.features[0].properties, 'filtered ascend', '3', '2');
allowRoundigDifference(total.features[0].properties, 'plain-ascend', '2', '-1');

allowRoundigDifference(total.features[0].properties.messages[2], 11, '41', '42');
allowRoundigDifference(total.features[0].properties.messages[2], 12, '4201', '4202');
allowRoundigDifference(total.features[0].properties.messages[3], 11, '57', '58');
allowRoundigDifference(total.features[0].properties.messages[3], 12, '5817', '5818');
allowRoundigDifference(total.features[0].properties.messages[4], 11, '66', '68');
allowRoundigDifference(total.features[0].properties.messages[4], 12, '6835', '6837');

allowRoundigDifference(total.features[0].properties.times, 7, 58.182, 58.183);
}

let track;
Expand Down Expand Up @@ -66,6 +105,17 @@ test('total track', () => {
expect(total).toEqual(brouterTotal);
});

test('hint distance fix', () => {
const segmentsCopy = JSON.parse(JSON.stringify(segments, null, 2));

// general case already tested

// special case: second segment without hint
segmentsCopy[1].feature.properties.voicehints = null;
let total = BR.Export._concatTotalTrack(segmentsCopy);
expect(total.features[0].properties.voicehints[0][3]).toEqual(294);
});

test('include route points', () => {
const latLngs = [L.latLng(0, 0), L.latLng(1, 1), L.latLng(2, 2)];
const exportRoute = new BR.Export();
Expand Down
87 changes: 44 additions & 43 deletions tests/control/data/brouterTotal.json
Original file line number Diff line number Diff line change
@@ -1,45 +1,46 @@
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"creator": "BRouter-1.1",
"name": "brouter_1615489279610_0",
"track-length": "388",
"filtered ascend": "1",
"plain-ascend": "0",
"total-time": "44",
"total-energy": "4420",
"cost": "703",
"voicehints": [
[1,5,0,88.0,89],
[6,2,0,99.0,-90],
[7,2,0,10.0,-90]
],
"messages": [
["Longitude", "Latitude", "Elevation", "Distance", "CostPerKm", "ElevCost", "TurnCost", "NodeCost", "InitialCost", "WayTags", "NodeTags"],
["8468340", "49488794", "101", "89", "1000", "0", "0", "0", "0", "highway=residential surface=asphalt cycleway=lane oneway=yes lcn=yes smoothness=good route_bicycle_icn=yes route_bicycle_ncn=yes route_bicycle_rcn=yes", ""],
["8469852", "49489230", "100", "299", "1150", "0", "270", "0", "0", "highway=residential surface=asphalt oneway=yes smoothness=good", ""]
],
"times": [0,9.592,12.271,14.13,19.406,22.134,28.833,37.817,38.938,44.217]
},
"geometry": {
"type": "LineString",
"coordinates": [
[8.467714, 49.488115, 101.5],
[8.468340, 49.488794, 101.5],
[8.468586, 49.488698, 101.5],
[8.468743, 49.488636, 101.5],
[8.469161, 49.488473, 101.75],
[8.469355, 49.488395, 102.0],
[8.469971, 49.488151, 103.5],
[8.470671, 49.488909, 99.5],
[8.470561, 49.488951, 99.5],
[8.469984, 49.489178, 100.0]
]
}
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"creator": "BRouter-1.7.0",
"name": "brouter_trekking_0",
"track-length": "382",
"filtered ascend": "2",
"plain-ascend": "-1",
"total-time": "68",
"total-energy": "6837",
"cost": "696",
"voicehints": [
[1,5,0,138.0,89],
[6,2,0,98.0,-90],
[7,2,0,58.0,-90]
],
"messages": [
["Longitude", "Latitude", "Elevation", "Distance", "CostPerKm", "ElevCost", "TurnCost", "NodeCost", "InitialCost", "WayTags", "NodeTags", "Time", "Energy"],
["8468340", "49488794", "101", "88", "1000", "0", "0", "0", "0", "highway=residential surface=asphalt oneway=yes lcn=yes cycleway:right=lane cycleway:left=no smoothness=good route_bicycle_icn=yes route_bicycle_rcn=yes", "", "14", "1478"],
["8469971", "49488151", "103", "138", "1150", "0", "90", "0", "0", "highway=residential surface=asphalt oneway=yes oneway:bicycle=no smoothness=good", "", "42", "4202"],
["8470671", "49488909", "99", "98", "1150", "0", "90", "0", "0", "highway=residential surface=asphalt oneway=yes smoothness=good", "", "58", "5818"],
["8469935", "49489198", "100", "58", "1150", "0", "90", "0", "0", "highway=residential surface=asphalt oneway=yes oneway:bicycle=no smoothness=good", "", "68", "6837"]
],
"times": [0,14.784,18.312,20.496,26.725,29.906,42.02,58.183,59.679,68.367]
},
"geometry": {
"type": "LineString",
"coordinates": [
[8.467714, 49.488114, 101.5],
[8.468340, 49.488794, 101.5],
[8.468586, 49.488698, 101.5],
[8.468743, 49.488636, 101.5],
[8.469161, 49.488473, 101.75],
[8.469355, 49.488395, 103.5],
[8.469971, 49.488151, 103.5],
[8.470671, 49.488909, 99.5],
[8.470561, 49.488951, 100.0],
[8.469984, 49.489178, 100.0]
]
}
]
}
}
]
}
Loading
Loading