From 09ad21a26f7a834adea5eb219f711b84522b1656 Mon Sep 17 00:00:00 2001 From: Quincy Morgan Date: Wed, 8 Jan 2020 12:03:30 -0500 Subject: [PATCH] Improve "add a bridge/tunnel" fixes by basing the structure length on the crossed feature type, not a fixed constant (re: #7202) --- modules/osm/way.js | 36 ++++++++++++++++++++++++++++ modules/validations/crossing_ways.js | 30 +++++++++++++++++------ 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/modules/osm/way.js b/modules/osm/way.js index d8e70d81a..9c18a38ea 100644 --- a/modules/osm/way.js +++ b/modules/osm/way.js @@ -102,6 +102,42 @@ Object.assign(osmWay.prototype, { }, + // the approximate width of the line based on its tags except its `width` tag + impliedLineWidthMeters: function() { + var averageWidths = { + highway: { // width is for single lane + motorway: 5, motorway_link: 5, trunk: 4.5, trunk_link: 4.5, + primary: 4, secondary: 4, tertiary: 4, + primary_link: 4, secondary_link: 4, tertiary_link: 4, + unclassified: 4, road: 4, living_street: 4, bus_guideway: 4, pedestrian: 4, + residential: 3.5, service: 3.5, track: 3, cycleway: 2.5, + bridleway: 2, corridor: 2, steps: 2, path: 1.5, footway: 1.5 + }, + railway: { // width includes ties and rail bed, not just track gauge + rail: 2.5, light_rail: 2.5, tram: 2.5, subway: 2.5, + monorail: 2.5, funicular: 2.5, disused: 2.5, preserved: 2.5, + miniature: 1.5, narrow_gauge: 1.5 + }, + waterway: { + river: 50, canal: 25, stream: 5, tidal_channel: 5, fish_pass: 2.5, drain: 2.5, ditch: 1.5 + } + }; + for (var key in averageWidths) { + if (this.tags[key] && averageWidths[key][this.tags[key]]) { + var width = averageWidths[key][this.tags[key]]; + if (key === 'highway') { + var laneCount = this.tags.lanes && parseInt(this.tags.lanes, 10); + if (!laneCount) laneCount = this.isOneWay() ? 1 : 2; + + return width * laneCount; + } + return width; + } + } + return null; + }, + + isOneWay: function() { // explicit oneway tag.. var values = { diff --git a/modules/validations/crossing_ways.js b/modules/validations/crossing_ways.js index cfd129680..0d57993c5 100644 --- a/modules/validations/crossing_ways.js +++ b/modules/validations/crossing_ways.js @@ -475,10 +475,10 @@ export function validationCrossingWays(context) { var resultWayIDs = [selectedWayID]; - var crossingWayID = this.issue.entityIds[0]; + var crossedWayID = this.issue.entityIds[0]; var edge = this.issue.data.edges[1]; if (this.issue.entityIds[0] === selectedWayID) { - crossingWayID = this.issue.entityIds[1]; + crossedWayID = this.issue.entityIds[1]; edge = this.issue.data.edges[0]; } @@ -488,14 +488,30 @@ export function validationCrossingWays(context) { var edgeNodes = [graph.entity(edge[0]), graph.entity(edge[1])]; - var crossingWay = graph.hasEntity(crossingWayID); - // use the width of the crossing feature as the structure length, if available - var widthMeters = crossingWay && crossingWay.tags.width && parseFloat(crossingWay.tags.width); + var crossedWay = graph.hasEntity(crossedWayID); + // use the explicit width of the crossed feature as the structure length, if available + var widthMeters = crossedWay && crossedWay.tags.width && parseFloat(crossedWay.tags.width); + if (!widthMeters) { + widthMeters = crossedWay && crossedWay.impliedLineWidthMeters(); + } + if (widthMeters) { + if (getFeatureTypeForTags(crossedWay.tags) === 'railway') { + // rail bridges are generally much wider than the rail bed itself, compensate + widthMeters *= 2; + } + } else { + // should ideally never land here since all rail/water/road tags should have implied width + widthMeters = 8; + } + + // add padding since the structure must extend past the edges of the crossed feature + widthMeters += 4; + // clamp the width to a reasonable range - if (widthMeters) widthMeters = Math.min(Math.max(widthMeters, 0.5), 50); + widthMeters = Math.min(Math.max(widthMeters, 4), 50); // the proposed length of the structure, in decimal degrees - var structLength = (widthMeters && geoMetersToLon(widthMeters, crossingLoc[1])) || 0.00008; + var structLength = geoMetersToLon(widthMeters, crossingLoc[1]); var halfStructLength = structLength / 2; var angle = geoVecAngle(edgeNodes[0].loc, edgeNodes[1].loc);