mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-15 13:38:26 +02:00
Merge branch '3076' of https://github.com/Psigio/iD into Psigio-3076
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import _ from 'lodash';
|
||||
/*
|
||||
Order the nodes of a way in reverse order and reverse any direction dependent tags
|
||||
other than `oneway`. (We assume that correcting a backwards oneway is the primary
|
||||
@@ -22,12 +23,23 @@
|
||||
The JOSM implementation was used as a guide, but transformations that were of unclear benefit
|
||||
or adjusted tags that don't seem to be used in practice were omitted.
|
||||
|
||||
Also, each node on the way is examined for its own tags and the following transformations are performed
|
||||
in order to ensure associated nodes (eg a Stop Sign) is also reversed
|
||||
|
||||
Node Keys:
|
||||
direction=forward ⟺ direction=backward
|
||||
direction=left ⟺ direction=right
|
||||
*:forward=* ⟺ *:backward=*
|
||||
*:left=* ⟺ *:right=*
|
||||
|
||||
References:
|
||||
http://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right
|
||||
http://wiki.openstreetmap.org/wiki/Key:direction#Steps
|
||||
http://wiki.openstreetmap.org/wiki/Key:incline
|
||||
http://wiki.openstreetmap.org/wiki/Route#Members
|
||||
http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
|
||||
http://wiki.openstreetmap.org/wiki/Tag:highway%3Dstop
|
||||
http://wiki.openstreetmap.org/wiki/Key:traffic_sign#On_a_way_or_area
|
||||
*/
|
||||
export function actionReverse(wayId, options) {
|
||||
var replacements = [
|
||||
@@ -69,6 +81,36 @@ export function actionReverse(wayId, options) {
|
||||
}
|
||||
|
||||
|
||||
function reverseDirectionTags(node) {
|
||||
// Update the direction based tags as appropriate then return an updated node
|
||||
return node.update({tags: _.transform(node.tags, function(acc, tagValue, tagKey) {
|
||||
// See if this is a direction tag and reverse (or use existing value if not recognised)
|
||||
if (tagKey === 'direction') {
|
||||
acc[tagKey] = {forward: 'backward', backward: 'forward', left: 'right', right: 'left'}[tagValue] || tagValue;
|
||||
} else {
|
||||
// Use the reverseKey method to cater for situations such as traffic_sign:forward=stop
|
||||
// This will pass through other tags unchanged
|
||||
acc[reverseKey(tagKey)] = tagValue;
|
||||
}
|
||||
return acc;
|
||||
}, {})});
|
||||
}
|
||||
|
||||
|
||||
function reverseTagsOnNodes(graph, nodeIds) {
|
||||
// Reverse the direction of appropriate tags attached to the nodes (#3076)
|
||||
return _(nodeIds)
|
||||
// Get each node from the graph
|
||||
.map(function(nodeId) { return graph.entity(nodeId);})
|
||||
// Check tags on the node, if there aren't any, we can skip
|
||||
.filter(function(existingNode) { return existingNode.tags !== undefined;})
|
||||
// Get a new version of each node with the appropriate tags reversed
|
||||
.map(function(existingNode) { return reverseDirectionTags(existingNode);})
|
||||
// Chain together consecutive updates to the graph for each updated node and return
|
||||
.reduce(function (accGraph, value) { return accGraph.replace(value); }, graph);
|
||||
}
|
||||
|
||||
|
||||
return function(graph) {
|
||||
var way = graph.entity(wayId),
|
||||
nodes = way.nodes.slice().reverse(),
|
||||
@@ -87,6 +129,8 @@ export function actionReverse(wayId, options) {
|
||||
});
|
||||
});
|
||||
|
||||
return graph.replace(way.update({nodes: nodes, tags: tags}));
|
||||
// Reverse any associated directions on nodes on the way and then replace
|
||||
// the way itself with the reversed node ids and updated way tags
|
||||
return reverseTagsOnNodes(graph, nodes).replace(way.update({nodes: nodes, tags: tags}));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -156,4 +156,158 @@ describe('iD.actionReverse', function () {
|
||||
graph = iD.actionReverse(way.id)(graph);
|
||||
expect(graph.entity(relation.id).members[0].role).to.eql('east');
|
||||
});
|
||||
|
||||
// For issue #3076
|
||||
it('reverses the direction of a forward facing stop sign on the way', function () {
|
||||
var node1 = iD.Node();
|
||||
var node2 = iD.Node();
|
||||
var node3 = iD.Node();
|
||||
// Attach a forward facing stop sign to node 2
|
||||
node2.tags = { 'direction': 'forward', 'highway': 'stop' };
|
||||
// Create our way
|
||||
var way = iD.Way({nodes: [node1.id, node2.id, node3.id]});
|
||||
// Act - reverse the way
|
||||
var graph = iD.actions.Reverse(way.id)(iD.Graph([node1, node2, node3, way]));
|
||||
// Assert - confirm that the stop sign on node 2 has changed direction
|
||||
var target = graph.entity(node2.id);
|
||||
expect(target.tags.direction).to.eql('backward');
|
||||
});
|
||||
|
||||
it('reverses the direction of a backward facing stop sign on the way', function () {
|
||||
var node1 = iD.Node();
|
||||
var node2 = iD.Node();
|
||||
var node3 = iD.Node();
|
||||
// Attach a backward facing stop sign to node 2
|
||||
node2.tags = { 'direction': 'backward', 'highway': 'stop' };
|
||||
// Create our way
|
||||
var way = iD.Way({nodes: [node1.id, node2.id, node3.id]});
|
||||
// Act - reverse the way
|
||||
var graph = iD.actions.Reverse(way.id)(iD.Graph([node1, node2, node3, way]));
|
||||
// Assert - confirm that the stop sign on node 2 has changed direction
|
||||
var target = graph.entity(node2.id);
|
||||
expect(target.tags.direction).to.eql('forward');
|
||||
});
|
||||
|
||||
it('reverses the direction of a left facing stop sign on the way', function () {
|
||||
var node1 = iD.Node();
|
||||
var node2 = iD.Node();
|
||||
var node3 = iD.Node();
|
||||
// Attach a left facing stop sign to node 2 (not sure this is a real situation,
|
||||
// but allows us to test)
|
||||
node2.tags = { 'direction': 'left', 'highway': 'stop' };
|
||||
// Create our way
|
||||
var way = iD.Way({nodes: [node1.id, node2.id, node3.id]});
|
||||
// Act - reverse the way
|
||||
var graph = iD.actions.Reverse(way.id)(iD.Graph([node1, node2, node3, way]));
|
||||
// Assert - confirm that the stop sign on node 2 has changed direction
|
||||
var target = graph.entity(node2.id);
|
||||
expect(target.tags.direction).to.eql('right');
|
||||
});
|
||||
|
||||
it('reverses the direction of a right facing stop sign on the way', function () {
|
||||
var node1 = iD.Node();
|
||||
var node2 = iD.Node();
|
||||
var node3 = iD.Node();
|
||||
// Attach a right facing stop sign to node 2 (not sure this is a real situation,
|
||||
// but allows us to test)
|
||||
node2.tags = { 'direction': 'right', 'highway': 'stop' };
|
||||
// Create our way
|
||||
var way = iD.Way({nodes: [node1.id, node2.id, node3.id]});
|
||||
// Act - reverse the way
|
||||
var graph = iD.actions.Reverse(way.id)(iD.Graph([node1, node2, node3, way]));
|
||||
// Assert - confirm that the stop sign on node 2 has changed direction
|
||||
var target = graph.entity(node2.id);
|
||||
expect(target.tags.direction).to.eql('left');
|
||||
});
|
||||
|
||||
it('does not assign a direction to a directionless stop sign on the way during a reverse', function () {
|
||||
var node1 = iD.Node();
|
||||
var node2 = iD.Node();
|
||||
var node3 = iD.Node();
|
||||
// Attach a stop sign to node 2 with no direction specified
|
||||
node2.tags = { 'highway': 'stop' };
|
||||
// Create our way
|
||||
var way = iD.Way({nodes: [node1.id, node2.id, node3.id]});
|
||||
// Act - reverse the way
|
||||
var graph = iD.actions.Reverse(way.id)(iD.Graph([node1, node2, node3, way]));
|
||||
// Assert - confirm that the stop sign on node 2 has not gained a direction tag
|
||||
var target = graph.entity(node2.id);
|
||||
expect(target.tags.direction).to.be.undefined;
|
||||
});
|
||||
|
||||
it('ignores directions other than forward or backward on attached stop sign during a reverse', function () {
|
||||
var node1 = iD.Node();
|
||||
var node2 = iD.Node();
|
||||
var node3 = iD.Node();
|
||||
// Attach a stop sign to node 2 with a non-standard direction
|
||||
node2.tags = { 'direction': 'empty', 'highway': 'stop' };
|
||||
// Create our way
|
||||
var way = iD.Way({nodes: [node1.id, node2.id, node3.id]});
|
||||
// Act - reverse the way
|
||||
var graph = iD.actions.Reverse(way.id)(iD.Graph([node1, node2, node3, way]));
|
||||
// Assert - confirm that the stop sign on node 2 has not had its direction tag altered
|
||||
var target = graph.entity(node2.id);
|
||||
expect(target.tags.direction).to.eql('empty');
|
||||
});
|
||||
|
||||
it('reverses the direction of a forward facing traffic sign on the way', function () {
|
||||
var node1 = iD.Node();
|
||||
var node2 = iD.Node();
|
||||
var node3 = iD.Node();
|
||||
// Attach a forward facing stop sign to node 2 using the traffic_sign approach
|
||||
node2.tags = { 'traffic_sign:forward': 'stop' };
|
||||
// Create our way
|
||||
var way = iD.Way({nodes: [node1.id, node2.id, node3.id]});
|
||||
// Act - reverse the way
|
||||
var graph = iD.actions.Reverse(way.id)(iD.Graph([node1, node2, node3, way]));
|
||||
// Assert - confirm that the stop sign on node 2 has changed direction
|
||||
var target = graph.entity(node2.id);
|
||||
expect(target.tags['traffic_sign:backward']).to.eql('stop');
|
||||
});
|
||||
|
||||
it('reverses the direction of a backward facing stop sign on the way', function () {
|
||||
var node1 = iD.Node();
|
||||
var node2 = iD.Node();
|
||||
var node3 = iD.Node();
|
||||
// Attach a backward facing stop sign to node 2 using the traffic_sign approach
|
||||
node2.tags = { 'traffic_sign:backward': 'stop' };
|
||||
// Create our way
|
||||
var way = iD.Way({nodes: [node1.id, node2.id, node3.id]});
|
||||
// Act - reverse the way
|
||||
var graph = iD.actions.Reverse(way.id)(iD.Graph([node1, node2, node3, way]));
|
||||
// Assert - confirm that the stop sign on node 2 has changed direction
|
||||
var target = graph.entity(node2.id);
|
||||
expect(target.tags['traffic_sign:forward']).to.eql('stop');
|
||||
});
|
||||
|
||||
it('reverses the direction of a left facing traffic sign on the way', function () {
|
||||
var node1 = iD.Node();
|
||||
var node2 = iD.Node();
|
||||
var node3 = iD.Node();
|
||||
// Attach a left facing stop sign to node 2 using the traffic_sign approach
|
||||
node2.tags = { 'traffic_sign:left': 'stop' };
|
||||
// Create our way
|
||||
var way = iD.Way({nodes: [node1.id, node2.id, node3.id]});
|
||||
// Act - reverse the way
|
||||
var graph = iD.actions.Reverse(way.id)(iD.Graph([node1, node2, node3, way]));
|
||||
// Assert - confirm that the stop sign on node 2 has changed direction
|
||||
var target = graph.entity(node2.id);
|
||||
expect(target.tags['traffic_sign:right']).to.eql('stop');
|
||||
});
|
||||
|
||||
it('reverses the direction of a right facing stop sign on the way', function () {
|
||||
var node1 = iD.Node();
|
||||
var node2 = iD.Node();
|
||||
var node3 = iD.Node();
|
||||
// Attach a right facing stop sign to node 2 using the traffic_sign approach
|
||||
node2.tags = { 'traffic_sign:right': 'stop' };
|
||||
// Create our way
|
||||
var way = iD.Way({nodes: [node1.id, node2.id, node3.id]});
|
||||
// Act - reverse the way
|
||||
var graph = iD.actions.Reverse(way.id)(iD.Graph([node1, node2, node3, way]));
|
||||
// Assert - confirm that the stop sign on node 2 has changed direction
|
||||
var target = graph.entity(node2.id);
|
||||
expect(target.tags['traffic_sign:left']).to.eql('stop');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user