import { actionSplit } from './split'; import { osmInferRestriction, osmRelation, osmWay } from '../osm/index'; // Create a restriction relation for `turn`, which must have the following structure: // // { // from: { node: , way: }, // via: { node: }, // to: { node: , way: }, // restriction: <'no_right_turn', 'no_left_turn', etc.> // } // // This specifies a restriction of type `restriction` when traveling from // `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 // osmInferRestriction. // // 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 // members of the restriction. // // For testing convenience, accepts an ID to assign to the new relation. // Normally, this will be undefined and the relation will automatically // be assigned a new ID. // export function actionRestrictTurn(turn, projection, restrictionId) { return function(graph) { var from = graph.entity(turn.from.way), via = graph.entity(turn.via.node), to = graph.entity(turn.to.way); function isClosingNode(way, nodeId) { return nodeId === way.first() && nodeId === way.last(); } function split(toOrFrom) { var newID = toOrFrom.newID || osmWay().id; graph = actionSplit(via.id, [newID]) .limitWays([toOrFrom.way])(graph); var a = graph.entity(newID), b = graph.entity(toOrFrom.way); if (a.nodes.indexOf(toOrFrom.node) !== -1) { return [a, b]; } else { return [b, a]; } } if (!from.affix(via.id) || isClosingNode(from, via.id)) { if (turn.from.node === turn.to.node) { // U-turn from = to = split(turn.from)[0]; } else if (turn.from.way === turn.to.way) { // Straight-on or circular var s = split(turn.from); from = s[0]; to = s[1]; } else { // Other from = split(turn.from)[0]; } } if (!to.affix(via.id) || isClosingNode(to, via.id)) { to = split(turn.to)[0]; } return graph.replace(osmRelation({ id: restrictionId, tags: { type: 'restriction', restriction: turn.restriction || osmInferRestriction( graph, turn.from, turn.via, turn.to, projection) }, members: [ {id: from.id, type: 'way', role: 'from'}, {id: via.id, type: 'node', role: 'via'}, {id: to.id, type: 'way', role: 'to'} ] })); }; }