Account for the angle of the crossing in the length of structures when applying "add a bridge/tunnel" fixes

This commit is contained in:
Quincy Morgan
2020-01-08 14:11:27 -05:00
parent 09ad21a26f
commit 4adecbb6ac
+32 -18
View File
@@ -3,7 +3,7 @@ import { actionChangeTags } from '../actions/change_tags';
import { actionMergeNodes } from '../actions/merge_nodes';
import { actionSplit } from '../actions/split';
import { modeSelect } from '../modes/select';
import { geoExtent, geoLineIntersection, geoSphericalClosestNode, geoVecAngle, geoMetersToLon, geoVecLength } from '../geo';
import { geoAngle, geoExtent, geoLineIntersection, geoSphericalClosestNode, geoVecAngle, geoMetersToLon, geoVecLength } from '../geo';
import { osmNode } from '../osm/node';
import { osmFlowingWaterwayTagValues, osmPathHighwayTagValues, osmRailwayTrackTagValues, osmRoutableHighwayTagValues } from '../osm/tags';
import { t } from '../util/locale';
@@ -475,44 +475,58 @@ export function validationCrossingWays(context) {
var resultWayIDs = [selectedWayID];
var crossedWayID = this.issue.entityIds[0];
var edge = this.issue.data.edges[1];
var edge, crossedEdge, crossedWayID;
if (this.issue.entityIds[0] === selectedWayID) {
crossedWayID = this.issue.entityIds[1];
edge = this.issue.data.edges[0];
crossedEdge = this.issue.data.edges[1];
crossedWayID = this.issue.entityIds[1];
} else {
edge = this.issue.data.edges[1];
crossedEdge = this.issue.data.edges[0];
crossedWayID = this.issue.entityIds[0];
}
var crossingLoc = this.issue.loc;
var projection = context.projection;
var action = function actionAddStructure(graph) {
var edgeNodes = [graph.entity(edge[0]), graph.entity(edge[1])];
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();
var structLengthMeters = crossedWay && crossedWay.tags.width && parseFloat(crossedWay.tags.width);
if (!structLengthMeters) {
// if no explicit width is set, approximate the width based on the tags
structLengthMeters = crossedWay && crossedWay.impliedLineWidthMeters();
}
if (widthMeters) {
if (structLengthMeters) {
if (getFeatureTypeForTags(crossedWay.tags) === 'railway') {
// rail bridges are generally much wider than the rail bed itself, compensate
widthMeters *= 2;
// bridges over railways are generally much longer than the rail bed itself, compensate
structLengthMeters *= 2;
}
} else {
// should ideally never land here since all rail/water/road tags should have implied width
widthMeters = 8;
// should ideally never land here since all rail/water/road tags should have an implied width
structLengthMeters = 8;
}
// add padding since the structure must extend past the edges of the crossed feature
widthMeters += 4;
var a1 = geoAngle(edgeNodes[0], edgeNodes[1], projection) + Math.PI;
var a2 = geoAngle(graph.entity(crossedEdge[0]), graph.entity(crossedEdge[1]), projection) + Math.PI;
var crossingAngle = Math.max(a1, a2) - Math.min(a1, a2);
if (crossingAngle > Math.PI) crossingAngle -= Math.PI;
// lengthen the structure to account for the angle of the crossing
structLengthMeters = ((structLengthMeters / 2) / Math.sin(crossingAngle)) * 2;
// clamp the width to a reasonable range
widthMeters = Math.min(Math.max(widthMeters, 4), 50);
// add padding since the structure must extend past the edges of the crossed feature
structLengthMeters += 4;
// clamp the length to a reasonable range
structLengthMeters = Math.min(Math.max(structLengthMeters, 4), 50);
// the proposed length of the structure, in decimal degrees
var structLength = geoMetersToLon(widthMeters, crossingLoc[1]);
var halfStructLength = structLength / 2;
var structLengthDeg = geoMetersToLon(structLengthMeters, crossingLoc[1]);
var halfStructLength = structLengthDeg / 2;
var angle = geoVecAngle(edgeNodes[0].loc, edgeNodes[1].loc);