Add “Maximum Speed” to analysis sidebar
It shows the distribution of maximum speeds for all ways on the current route (if that data is available, otherwise it’s summed up under “unknown”). `maxspeed:forward` and `maxspeed:backward` is respected in conjunction with `reversedirection`. Hovering/clicking table rows to highlight matching segments on the route work the identical to the other analysis tables. Additionally, all tags in the analysis tab (way type, surface, smoothness) are translateable now. The values were added to `en.json`. Some HTML is rendered with template literals now, instead of concatenating strings. Variable declarations were changed from `var` to `const`/`let`.
This commit is contained in:
parent
76f31aeb2b
commit
a285751416
3 changed files with 177 additions and 95 deletions
|
|
@ -350,10 +350,6 @@ table.dataTable.track-analysis-table tfoot td {
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-analysis-title {
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-analysis-distance {
|
.track-analysis-distance {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,14 +75,14 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
/**
|
/**
|
||||||
* Everytime the track changes this method is called:
|
* Everytime the track changes this method is called:
|
||||||
*
|
*
|
||||||
* - calculate statistics (way type, surface, smoothness)
|
* - calculate statistics (way type, max speed, surface, smoothness)
|
||||||
* for the whole track
|
* for the whole track
|
||||||
* - renders statistics tables
|
* - renders statistics tables
|
||||||
* - create event listeners which allow to hover/click a
|
* - create event listeners which allow to hover/click a
|
||||||
* table row for highlighting matching track segments
|
* table row for highlighting matching track segments
|
||||||
*
|
*
|
||||||
* @param {Polyline} polyline
|
* @param {Polyline} polyline
|
||||||
* @param {Array} segments
|
* @param {Array} segments route segments between waypoints
|
||||||
*/
|
*/
|
||||||
update(polyline, segments) {
|
update(polyline, segments) {
|
||||||
if (!this.active) {
|
if (!this.active) {
|
||||||
|
|
@ -105,7 +105,7 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
this.trackPolyline = polyline;
|
this.trackPolyline = polyline;
|
||||||
this.trackEdges = new BR.TrackEdges(segments);
|
this.trackEdges = new BR.TrackEdges(segments);
|
||||||
|
|
||||||
var analysis = this.calcStats(polyline, segments);
|
const analysis = this.calcStats(polyline, segments);
|
||||||
|
|
||||||
this.render(analysis);
|
this.render(analysis);
|
||||||
|
|
||||||
|
|
@ -132,6 +132,7 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
calcStats(polyline, segments) {
|
calcStats(polyline, segments) {
|
||||||
const analysis = {
|
const analysis = {
|
||||||
highway: {},
|
highway: {},
|
||||||
|
maxspeed: {},
|
||||||
surface: {},
|
surface: {},
|
||||||
smoothness: {},
|
smoothness: {},
|
||||||
};
|
};
|
||||||
|
|
@ -175,14 +176,19 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
segments[segmentIndex].feature.properties.messages[messageIndex][3]
|
segments[segmentIndex].feature.properties.messages[messageIndex][3]
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case 'maxspeed':
|
||||||
case 'surface':
|
case 'surface':
|
||||||
case 'smoothness':
|
case 'smoothness':
|
||||||
if (typeof analysis[tagName][wayTagParts[1]] === 'undefined') {
|
if (typeof analysis[tagName][wayTagParts[1]] === 'undefined') {
|
||||||
|
let formattedName = i18next.t([
|
||||||
|
'sidebar.analysis.data.' + tagName + '.' + wayTagParts[1],
|
||||||
|
wayTagParts[1],
|
||||||
|
]);
|
||||||
|
if (tagName.indexOf('maxspeed') === 0) {
|
||||||
|
formattedName += ' km/h';
|
||||||
|
}
|
||||||
analysis[tagName][wayTagParts[1]] = {
|
analysis[tagName][wayTagParts[1]] = {
|
||||||
formatted_name: i18next.t(
|
formatted_name: formattedName,
|
||||||
'sidebar.analysis.data.' + tagName + '.' + wayTagParts[1],
|
|
||||||
wayTagParts[1]
|
|
||||||
),
|
|
||||||
name: wayTagParts[1],
|
name: wayTagParts[1],
|
||||||
subtype: '',
|
subtype: '',
|
||||||
distance: 0.0,
|
distance: 0.0,
|
||||||
|
|
@ -209,6 +215,10 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
* are dropped. If no specialized surface/smoothness tag is found, the default value
|
* are dropped. If no specialized surface/smoothness tag is found, the default value
|
||||||
* is returned, i.e. `smoothness` or `surface`.
|
* is returned, i.e. `smoothness` or `surface`.
|
||||||
*
|
*
|
||||||
|
* Also, maxspeed comes in different variations, e.g. `maxspeed`, `maxspeed:forward`,
|
||||||
|
* `maxspeed:backward`. Depending on the existence of the `reversedirection` field
|
||||||
|
* we can select the correct value.
|
||||||
|
*
|
||||||
* @param wayTags tags + values for a way segment
|
* @param wayTags tags + values for a way segment
|
||||||
* @param routingType currently only 'cycling' is supported, can be extended in the future (walking, driving, etc.)
|
* @param routingType currently only 'cycling' is supported, can be extended in the future (walking, driving, etc.)
|
||||||
* @returns {*[]}
|
* @returns {*[]}
|
||||||
|
|
@ -242,6 +252,19 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tagName === 'maxspeed:forward' && !wayTags.includes('reversedirection=yes')) {
|
||||||
|
normalizedWayTags['maxspeed'] = tagValue;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (tagName === 'maxspeed:backward' && wayTags.includes('reversedirection=yes')) {
|
||||||
|
normalizedWayTags['maxspeed'] = tagValue;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (tagName === 'maxspeed') {
|
||||||
|
normalizedWayTags[tagName] = tagValue;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
normalizedWayTags[tagName] = tagValue;
|
normalizedWayTags[tagName] = tagValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -279,10 +302,10 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
sortAnalysisData(analysis) {
|
sortAnalysisData(analysis) {
|
||||||
var analysisSortable = {};
|
const analysisSortable = {};
|
||||||
var result = {};
|
const result = {};
|
||||||
|
|
||||||
for (var type in analysis) {
|
for (const type in analysis) {
|
||||||
if (!analysis.hasOwnProperty(type)) {
|
if (!analysis.hasOwnProperty(type)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -290,18 +313,24 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
result[type] = {};
|
result[type] = {};
|
||||||
analysisSortable[type] = [];
|
analysisSortable[type] = [];
|
||||||
|
|
||||||
for (var name in analysis[type]) {
|
for (const name in analysis[type]) {
|
||||||
if (!analysis[type].hasOwnProperty(name)) {
|
if (!analysis[type].hasOwnProperty(name)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
analysisSortable[type].push(analysis[type][name]);
|
analysisSortable[type].push(analysis[type][name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
analysisSortable[type].sort(function (a, b) {
|
if (type === 'maxspeed') {
|
||||||
return b.distance - a.distance;
|
analysisSortable[type].sort(function (a, b) {
|
||||||
});
|
return parseInt(a.name) - parseInt(b.name);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
analysisSortable[type].sort(function (a, b) {
|
||||||
|
return b.distance - a.distance;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
for (var j = 0; j < analysisSortable[type].length; j++) {
|
for (let j = 0; j < analysisSortable[type].length; j++) {
|
||||||
result[type][analysisSortable[type][j].formatted_name] = analysisSortable[type][j];
|
result[type][analysisSortable[type][j].formatted_name] = analysisSortable[type][j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -317,8 +346,8 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
getTrackType(wayTags) {
|
getTrackType(wayTags) {
|
||||||
for (var i = 0; i < wayTags.length; i++) {
|
for (let i = 0; i < wayTags.length; i++) {
|
||||||
var wayTagParts = wayTags[i].split('=');
|
const wayTagParts = wayTags[i].split('=');
|
||||||
if (wayTagParts[0] === 'tracktype') {
|
if (wayTagParts[0] === 'tracktype') {
|
||||||
return wayTagParts[1];
|
return wayTagParts[1];
|
||||||
}
|
}
|
||||||
|
|
@ -331,21 +360,19 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
* @param {Object} analysis
|
* @param {Object} analysis
|
||||||
*/
|
*/
|
||||||
render(analysis) {
|
render(analysis) {
|
||||||
var $content = $('#track_statistics');
|
const $content = $('#track_statistics');
|
||||||
|
|
||||||
$content.html('');
|
$content.html('');
|
||||||
$content.append(
|
$content.append($(`<h4 class="track-analysis-heading">${i18next.t('sidebar.analysis.header.highway')}</h4>`));
|
||||||
$('<h4 class="track-analysis-heading">' + i18next.t('sidebar.analysis.header.highway') + '</h4>')
|
|
||||||
);
|
|
||||||
$content.append(this.renderTable('highway', analysis.highway));
|
$content.append(this.renderTable('highway', analysis.highway));
|
||||||
$content.append(
|
$content.append($(`<h4 class="track-analysis-heading">${i18next.t('sidebar.analysis.header.surface')}</h4>`));
|
||||||
$('<h4 class="track-analysis-heading">' + i18next.t('sidebar.analysis.header.surface') + '</h4>')
|
|
||||||
);
|
|
||||||
$content.append(this.renderTable('surface', analysis.surface));
|
$content.append(this.renderTable('surface', analysis.surface));
|
||||||
$content.append(
|
$content.append(
|
||||||
$('<h4 class="track-analysis-heading">' + i18next.t('sidebar.analysis.header.smoothness') + '</h4>')
|
$(`<h4 class="track-analysis-heading">${i18next.t('sidebar.analysis.header.smoothness')}</h4>`)
|
||||||
);
|
);
|
||||||
$content.append(this.renderTable('smoothness', analysis.smoothness));
|
$content.append(this.renderTable('smoothness', analysis.smoothness));
|
||||||
|
$content.append($(`<h4 class="track-analysis-heading">${i18next.t('sidebar.analysis.header.maxspeed')}</h4>`));
|
||||||
|
$content.append(this.renderTable('maxspeed', analysis.maxspeed));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -356,67 +383,45 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
* @returns {jQuery}
|
* @returns {jQuery}
|
||||||
*/
|
*/
|
||||||
renderTable(type, data) {
|
renderTable(type, data) {
|
||||||
var index;
|
let index;
|
||||||
var $table = $(
|
const $table = $(`<table data-type="${type}" class="mini stripe dataTable track-analysis-table"></table>`);
|
||||||
'<table data-type="' + type + '" class="mini cell-border stripe dataTable track-analysis-table"></table>'
|
const $thead = $('<thead></thead>');
|
||||||
);
|
|
||||||
var $thead = $('<thead></thead>');
|
|
||||||
$thead.append(
|
$thead.append(
|
||||||
$('<tr>')
|
$('<tr>')
|
||||||
.append(
|
.append(
|
||||||
'<th class="track-analysis-header-category">' +
|
`<th class="track-analysis-header-category">${i18next.t('sidebar.analysis.table.category')}</th>`
|
||||||
i18next.t('sidebar.analysis.table.category') +
|
|
||||||
'</th>'
|
|
||||||
)
|
)
|
||||||
.append(
|
.append(
|
||||||
$(
|
$(`<th class="track-analysis-header-distance">${i18next.t('sidebar.analysis.table.length')}</th>`)
|
||||||
'<th class="track-analysis-header-distance">' +
|
|
||||||
i18next.t('sidebar.analysis.table.length') +
|
|
||||||
'</th>'
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$table.append($thead);
|
$table.append($thead);
|
||||||
var $tbody = $('<tbody></tbody>');
|
const $tbody = $('<tbody></tbody>');
|
||||||
|
|
||||||
var totalDistance = 0.0;
|
let totalDistance = 0.0;
|
||||||
|
|
||||||
for (index in data) {
|
for (index in data) {
|
||||||
if (!data.hasOwnProperty(index)) {
|
if (!data.hasOwnProperty(index)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var $row = $(
|
const $row = $(`<tr data-name="${data[index].name}" \
|
||||||
'<tr data-name="' +
|
data-subtype="${data[index].subtype}" \
|
||||||
data[index].name +
|
data-distance="${data[index].distance}"></tr>`);
|
||||||
'" data-subtype="' +
|
$row.append(`<td class="track-analysis-title">${data[index].formatted_name}</td>`);
|
||||||
data[index].subtype +
|
$row.append(`<td class="track-analysis-distance">${this.formatDistance(data[index].distance)} km</td>`);
|
||||||
'" data-distance="' +
|
|
||||||
data[index].distance +
|
|
||||||
'"></tr>'
|
|
||||||
);
|
|
||||||
$row.append('<td class="track-analysis-title">' + data[index].formatted_name + '</td>');
|
|
||||||
$row.append(
|
|
||||||
'<td class="track-analysis-distance">' + this.formatDistance(data[index].distance) + ' km</td>'
|
|
||||||
);
|
|
||||||
$tbody.append($row);
|
$tbody.append($row);
|
||||||
totalDistance += data[index].distance;
|
totalDistance += data[index].distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalDistance < this.totalRouteDistance) {
|
if (totalDistance < this.totalRouteDistance) {
|
||||||
$tbody.append(
|
$tbody.append(
|
||||||
$(
|
$(`<tr data-name="internal-unknown" data-distance="${this.totalRouteDistance - totalDistance}"></tr>`)
|
||||||
'<tr data-name="internal-unknown" data-distance="' +
|
.append($(`<td class="track-analysis-title">${i18next.t('sidebar.analysis.table.unknown')}</td>`))
|
||||||
(this.totalRouteDistance - totalDistance) +
|
|
||||||
'"></tr>'
|
|
||||||
)
|
|
||||||
.append(
|
|
||||||
$('<td class="track-analysis-title">' + i18next.t('sidebar.analysis.table.unknown') + '</td>')
|
|
||||||
)
|
|
||||||
.append(
|
.append(
|
||||||
$(
|
$(
|
||||||
'<td class="track-analysis-distance">' +
|
`<td class="track-analysis-distance">${this.formatDistance(
|
||||||
this.formatDistance(this.totalRouteDistance - totalDistance) +
|
this.totalRouteDistance - totalDistance
|
||||||
' km</td>'
|
)} km</td>`
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
@ -427,12 +432,12 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
$table.append(
|
$table.append(
|
||||||
$('<tfoot></tfoot>')
|
$('<tfoot></tfoot>')
|
||||||
.append('<tr></tr>')
|
.append('<tr></tr>')
|
||||||
.append($('<td>' + i18next.t('sidebar.analysis.table.total_known') + '</td>'))
|
.append($(`<td>${i18next.t('sidebar.analysis.table.total_known')}</td>`))
|
||||||
.append(
|
.append(
|
||||||
$(
|
$(
|
||||||
'<td class="track-analysis-distance track-analysis-distance-total">' +
|
`<td class="track-analysis-distance track-analysis-distance-total">${this.formatDistance(
|
||||||
this.formatDistance(totalDistance) +
|
totalDistance
|
||||||
' km</td>'
|
)} km</td>`
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
@ -451,13 +456,13 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
handleHover(event) {
|
handleHover(event) {
|
||||||
var $tableRow = $(event.currentTarget);
|
const $tableRow = $(event.currentTarget);
|
||||||
var $table = $tableRow.parents('table').first();
|
const $table = $tableRow.parents('table').first();
|
||||||
var dataType = $table.data('type');
|
const dataType = $table.data('type');
|
||||||
var dataName = $tableRow.data('name');
|
const dataName = $tableRow.data('name');
|
||||||
var trackType = $tableRow.data('subtype');
|
const trackType = $tableRow.data('subtype');
|
||||||
|
|
||||||
var polylinesForDataType = this.getPolylinesForDataType(dataType, dataName, trackType);
|
const polylinesForDataType = this.getPolylinesForDataType(dataType, dataName, trackType);
|
||||||
|
|
||||||
this.highlightedSegments = L.layerGroup(polylinesForDataType).addTo(this.map);
|
this.highlightedSegments = L.layerGroup(polylinesForDataType).addTo(this.map);
|
||||||
},
|
},
|
||||||
|
|
@ -467,11 +472,11 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleSelected(event) {
|
toggleSelected(event) {
|
||||||
var tableRow = event.currentTarget;
|
const tableRow = event.currentTarget;
|
||||||
var $table = $(tableRow).parents('table').first();
|
const $table = $(tableRow).parents('table').first();
|
||||||
var dataType = $table.data('type');
|
const dataType = $table.data('type');
|
||||||
var dataName = $(tableRow).data('name');
|
const dataName = $(tableRow).data('name');
|
||||||
var trackType = $(tableRow).data('subtype');
|
const trackType = $(tableRow).data('subtype');
|
||||||
|
|
||||||
if (tableRow.classList.toggle('selected')) {
|
if (tableRow.classList.toggle('selected')) {
|
||||||
if (this.highlightedSegment) {
|
if (this.highlightedSegment) {
|
||||||
|
|
@ -505,13 +510,13 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
* @returns {Polyline[]}
|
* @returns {Polyline[]}
|
||||||
*/
|
*/
|
||||||
getPolylinesForDataType(dataType, dataName, trackType) {
|
getPolylinesForDataType(dataType, dataName, trackType) {
|
||||||
var polylines = [];
|
const polylines = [];
|
||||||
var trackLatLngs = this.trackPolyline.getLatLngs();
|
const trackLatLngs = this.trackPolyline.getLatLngs();
|
||||||
|
|
||||||
for (var i = 0; i < this.trackEdges.edges.length; i++) {
|
for (let i = 0; i < this.trackEdges.edges.length; i++) {
|
||||||
if (this.wayTagsMatchesData(trackLatLngs[this.trackEdges.edges[i]], dataType, dataName, trackType)) {
|
if (this.wayTagsMatchesData(trackLatLngs[this.trackEdges.edges[i]], dataType, dataName, trackType)) {
|
||||||
var matchedEdgeIndexStart = i > 0 ? this.trackEdges.edges[i - 1] : 0;
|
const matchedEdgeIndexStart = i > 0 ? this.trackEdges.edges[i - 1] : 0;
|
||||||
var matchedEdgeIndexEnd = this.trackEdges.edges[i] + 1;
|
const matchedEdgeIndexEnd = this.trackEdges.edges[i] + 1;
|
||||||
polylines.push(
|
polylines.push(
|
||||||
L.polyline(
|
L.polyline(
|
||||||
trackLatLngs.slice(matchedEdgeIndexStart, matchedEdgeIndexEnd),
|
trackLatLngs.slice(matchedEdgeIndexStart, matchedEdgeIndexEnd),
|
||||||
|
|
@ -559,19 +564,44 @@ BR.TrackAnalysis = L.Class.extend({
|
||||||
return this.singleWayTagMatchesData('surface', parsed, dataName);
|
return this.singleWayTagMatchesData('surface', parsed, dataName);
|
||||||
case 'smoothness':
|
case 'smoothness':
|
||||||
return this.singleWayTagMatchesData('smoothness', parsed, dataName);
|
return this.singleWayTagMatchesData('smoothness', parsed, dataName);
|
||||||
|
case 'maxspeed':
|
||||||
|
return this.singleWayTagMatchesData('maxspeed', parsed, dataName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
singleWayTagMatchesData(category, parsedData, lookupValue) {
|
singleWayTagMatchesData(category, parsedData, lookupValue) {
|
||||||
var foundValue = null;
|
if (typeof lookupValue === 'number') {
|
||||||
|
lookupValue = lookupValue.toString();
|
||||||
|
}
|
||||||
|
|
||||||
for (var iterationKey in parsedData) {
|
let foundValue = null;
|
||||||
if (iterationKey.indexOf(category) !== -1) {
|
|
||||||
foundValue = parsedData[iterationKey];
|
// We need to handle `maxspeed:forward` and `maxspeed:backward` separately
|
||||||
break;
|
// from all other tags, because we need to consider the `reversedirection`
|
||||||
}
|
// tag.
|
||||||
|
// Test URL: http://localhost:3000/#map=15/52.2292/13.6204/standard&lonlats=13.61948,52.231611;13.611327,52.227431
|
||||||
|
if (
|
||||||
|
category === 'maxspeed' &&
|
||||||
|
parsedData.hasOwnProperty('maxspeed:forward') &&
|
||||||
|
!parsedData.hasOwnProperty('reversedirection')
|
||||||
|
) {
|
||||||
|
foundValue = parsedData['maxspeed:forward'];
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
category === 'maxspeed' &&
|
||||||
|
parsedData.hasOwnProperty('maxspeed:backward') &&
|
||||||
|
parsedData.hasOwnProperty('reversedirection') &&
|
||||||
|
parsedData.reversedirection === 'yes'
|
||||||
|
) {
|
||||||
|
foundValue = parsedData['maxspeed:backward'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the special handling for `maxspeed` didn't find a result,
|
||||||
|
// check wayTags for matching property:
|
||||||
|
if (foundValue === null && parsedData.hasOwnProperty(category)) {
|
||||||
|
foundValue = parsedData[category];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lookupValue === 'internal-unknown' && foundValue === null) {
|
if (lookupValue === 'internal-unknown' && foundValue === null) {
|
||||||
|
|
|
||||||
|
|
@ -285,10 +285,66 @@
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"analysis": {
|
"analysis": {
|
||||||
|
"data": {
|
||||||
|
"highway": {
|
||||||
|
"footway": "Footway",
|
||||||
|
"path": "Path",
|
||||||
|
"residential": "Residential",
|
||||||
|
"cycleway": "Cycleway",
|
||||||
|
"track": "Track",
|
||||||
|
"service": "Service",
|
||||||
|
"tertiary": "Tertiary",
|
||||||
|
"secondary": "Secondary",
|
||||||
|
"primary": "Primary",
|
||||||
|
"trunk": "Trunk",
|
||||||
|
"motorway": "Motorway",
|
||||||
|
"motorway_link": "Motorway Link",
|
||||||
|
"primary_link": "Primary Link",
|
||||||
|
"secondary_link": "Secondary Link",
|
||||||
|
"tertiary_link": "Tertiary Link",
|
||||||
|
"trunk_link": "Trunk Link",
|
||||||
|
"living_street": "Living Street",
|
||||||
|
"pedestrian": "Pedestrian",
|
||||||
|
"road": "Road",
|
||||||
|
"bridleway": "Bridleway",
|
||||||
|
"steps": "Steps",
|
||||||
|
"sidewalk": "Sidewalk",
|
||||||
|
"crossing": "Crossing",
|
||||||
|
"unclassified": "Unclassified"
|
||||||
|
},
|
||||||
|
"surface": {
|
||||||
|
"asphalt": "Asphalt",
|
||||||
|
"cobblestone": "Cobblestone",
|
||||||
|
"compacted": "Compacted",
|
||||||
|
"dirt": "Dirt",
|
||||||
|
"fine_gravel": "Fine Gravel",
|
||||||
|
"grass": "Grass",
|
||||||
|
"gravel": "Gravel",
|
||||||
|
"ground": "Ground",
|
||||||
|
"paved": "Paved",
|
||||||
|
"sand": "Sand",
|
||||||
|
"unpaved": "Unpaved",
|
||||||
|
"wood": "Wood",
|
||||||
|
"concrete": "Concrete",
|
||||||
|
"paving_stones": "Paving Stones",
|
||||||
|
"sett": "Sett"
|
||||||
|
},
|
||||||
|
"smoothness": {
|
||||||
|
"excellent": "Excellent",
|
||||||
|
"good": "Good",
|
||||||
|
"intermediate": "Intermediate",
|
||||||
|
"bad": "Bad",
|
||||||
|
"very_bad": "Very Bad",
|
||||||
|
"horrible": "Horrible",
|
||||||
|
"very_horrible": "Very Horrible",
|
||||||
|
"impassable": "Impassable"
|
||||||
|
}
|
||||||
|
},
|
||||||
"header": {
|
"header": {
|
||||||
"highway": "Highway",
|
"highway": "Highway",
|
||||||
"smoothness": "Smoothness",
|
"smoothness": "Smoothness",
|
||||||
"surface": "Surface"
|
"surface": "Surface",
|
||||||
|
"maxspeed": "Maximum Speed"
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"category": "Category",
|
"category": "Category",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue