mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 01:02:58 +00:00
Better inferRestriction for no_u_turn
* where from.node === to.node * where from.way and to.way are oneways joined at a narrow angle
This commit is contained in:
@@ -11,14 +11,8 @@
|
||||
// `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`.
|
||||
// (The action does not check that these entities form a valid intersection.)
|
||||
//
|
||||
// If `restriction` is not provided, it is automatically determined by the
|
||||
// angle of the turn:
|
||||
//
|
||||
// 0-5 degrees: no_u_turn
|
||||
// 5-158 degrees: no_right_turn
|
||||
// 158-202 degrees: no_straight_on
|
||||
// 202-355 degrees: no_left_turn
|
||||
// 355-360 degrees: no_u_turn
|
||||
// If `restriction` is not provided, it is automatically determined by
|
||||
// iD.geo.inferRestriction.
|
||||
//
|
||||
// If necessary, the `from` and `to` ways are split. In these cases, `from.node`
|
||||
// and `to.node` are used to determine which portion of the split ways become
|
||||
@@ -74,9 +68,10 @@ iD.actions.RestrictTurn = function(turn, projection, restrictionId) {
|
||||
type: 'restriction',
|
||||
restriction: turn.restriction ||
|
||||
iD.geo.inferRestriction(
|
||||
graph.entity(turn.from.node),
|
||||
via,
|
||||
graph.entity(turn.to.node),
|
||||
graph,
|
||||
turn.from,
|
||||
turn.via,
|
||||
turn.to,
|
||||
projection)
|
||||
},
|
||||
members: [
|
||||
|
||||
@@ -118,23 +118,33 @@ iD.geo.Intersection = function(graph, vertexId) {
|
||||
return intersection;
|
||||
};
|
||||
|
||||
iD.geo.inferRestriction = function(from, via, to, projection) {
|
||||
var angle = iD.geo.angle(via, from, projection) -
|
||||
iD.geo.angle(via, to, projection);
|
||||
|
||||
iD.geo.inferRestriction = function(graph, from, via, to, projection) {
|
||||
var fromWay = graph.entity(from.way),
|
||||
fromNode = graph.entity(from.node),
|
||||
toWay = graph.entity(to.way),
|
||||
toNode = graph.entity(to.node),
|
||||
viaNode = graph.entity(via.node),
|
||||
fromOneWay = (fromWay.tags.oneway === 'yes' && fromWay.last() === via.node) ||
|
||||
(fromWay.tags.oneway === '-1' && fromWay.first() === via.node),
|
||||
toOneWay = (toWay.tags.oneway === 'yes' && toWay.first() === via.node) ||
|
||||
(toWay.tags.oneway === '-1' && toWay.last() === via.node),
|
||||
angle = iD.geo.angle(viaNode, fromNode, projection) -
|
||||
iD.geo.angle(viaNode, toNode, projection);
|
||||
|
||||
angle = angle * 180 / Math.PI;
|
||||
|
||||
while (angle < 0)
|
||||
angle += 360;
|
||||
|
||||
if (angle < 5)
|
||||
if (fromNode === toNode)
|
||||
return 'no_u_turn';
|
||||
if ((angle < 23 || angle > 336) && fromOneWay && toOneWay)
|
||||
return 'no_u_turn';
|
||||
if (angle < 158)
|
||||
return 'no_right_turn';
|
||||
if (angle < 202)
|
||||
return 'no_straight_on';
|
||||
if (angle < 355)
|
||||
if (angle > 202)
|
||||
return 'no_left_turn';
|
||||
|
||||
return 'no_u_turn';
|
||||
return 'no_straight_on';
|
||||
};
|
||||
|
||||
@@ -99,9 +99,10 @@ iD.ui.preset.restrictions = function(field, context) {
|
||||
} else {
|
||||
preset = presets.item('type/restriction/' +
|
||||
iD.geo.inferRestriction(
|
||||
graph.entity(datum.from.node),
|
||||
graph.entity(datum.via.node),
|
||||
graph.entity(datum.to.node),
|
||||
graph,
|
||||
datum.from,
|
||||
datum.via,
|
||||
datum.to,
|
||||
projection));
|
||||
}
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@ describe("iD.actions.RestrictTurn", function() {
|
||||
expect(_.pick(r.memberByRole('to'), 'id', 'type')).to.eql({id: '==', type: 'way'});
|
||||
});
|
||||
|
||||
it('guesses the restriction type based on the turn angle', function() {
|
||||
it('infers the restriction type based on the turn angle', function() {
|
||||
// u====*~~~~w
|
||||
// |
|
||||
// x
|
||||
@@ -306,4 +306,49 @@ describe("iD.actions.RestrictTurn", function() {
|
||||
}, projection, 'r')(graph);
|
||||
expect(u.entity('r').tags.restriction).to.equal('no_u_turn');
|
||||
});
|
||||
|
||||
it('infers no_u_turn from acute angle made by forward oneways', function() {
|
||||
// *
|
||||
// / \
|
||||
// w2/ \w1
|
||||
// / \
|
||||
// u x
|
||||
var graph = iD.Graph([
|
||||
iD.Node({id: 'u', loc: [-1, -20]}),
|
||||
iD.Node({id: '*', loc: [ 0, 0]}),
|
||||
iD.Node({id: 'x', loc: [ 1, -20]}),
|
||||
iD.Way({id: 'w1', nodes: ['x', '*'], tags: {oneway: 'yes'}}),
|
||||
iD.Way({id: 'w2', nodes: ['*', 'u'], tags: {oneway: 'yes'}})
|
||||
]);
|
||||
|
||||
var r = iD.actions.RestrictTurn({
|
||||
from: {node: 'x', way: 'w1'},
|
||||
via: {node: '*'},
|
||||
to: {node: 'u', way: 'w2'}
|
||||
}, projection, 'r')(graph);
|
||||
expect(r.entity('r').tags.restriction).to.equal('no_u_turn');
|
||||
});
|
||||
|
||||
it('infers no_u_turn from acute angle made by reverse oneways', function() {
|
||||
// *
|
||||
// / \
|
||||
// w2/ \w1
|
||||
// / \
|
||||
// u x
|
||||
var graph = iD.Graph([
|
||||
iD.Node({id: 'u', loc: [-1, -20]}),
|
||||
iD.Node({id: '*', loc: [ 0, 0]}),
|
||||
iD.Node({id: 'x', loc: [ 1, -20]}),
|
||||
iD.Way({id: 'w1', nodes: ['*', 'x'], tags: {oneway: '-1'}}),
|
||||
iD.Way({id: 'w2', nodes: ['u', '*'], tags: {oneway: '-1'}})
|
||||
]);
|
||||
|
||||
var r = iD.actions.RestrictTurn({
|
||||
from: {node: 'x', way: 'w1'},
|
||||
via: {node: '*'},
|
||||
to: {node: 'u', way: 'w2'}
|
||||
}, projection, 'r')(graph);
|
||||
expect(r.entity('r').tags.restriction).to.equal('no_u_turn');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user