From 8b6ce214a2c0cb389db6e5f68f1a50f05be53ba8 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 19 May 2014 15:53:46 -0700 Subject: [PATCH] Initial support for only_* restrictions --- data/operations-sprite.json | 6 ++-- dist/img/sprite.svg | 52 +++++++++++++++++++++++++---------- js/id/geo/intersection.js | 6 ++++ js/id/svg/turns.js | 47 +++++++++++++++---------------- test/spec/geo/intersection.js | 48 +++++++++++++++++++++++++++++--- 5 files changed, 115 insertions(+), 44 deletions(-) diff --git a/data/operations-sprite.json b/data/operations-sprite.json index 9eab70d5c..f9ae5a12c 100644 --- a/data/operations-sprite.json +++ b/data/operations-sprite.json @@ -27,6 +27,8 @@ "icon-restriction-yes": [50, 80], "icon-restriction-no": [95, 80], - "icon-restriction-yes-u": [140, 80], - "icon-restriction-no-u": [185, 80] + "icon-restriction-only": [140, 80], + "icon-restriction-yes-u": [185, 80], + "icon-restriction-no-u": [230, 80], + "icon-restriction-only-u": [275, 80] } \ No newline at end of file diff --git a/dist/img/sprite.svg b/dist/img/sprite.svg index d27db5d95..e6c15a29b 100644 --- a/dist/img/sprite.svg +++ b/dist/img/sprite.svg @@ -13,7 +13,7 @@ width="800" height="560" id="svg12393" - inkscape:version="0.48.2 r9819" + inkscape:version="0.48.4 r" sodipodi:docname="sprite.svg"> image/svg+xml - + @@ -1941,14 +1941,15 @@ + transform="matrix(0,1,1,0,116.9905,-80.00893)"> + transform="matrix(0,1,1,0,80.00893,-71.9905)" + inkscape:connector-curvature="0" /> @@ -1961,7 +1962,7 @@ + transform="matrix(0,1,1,0,167,-115)"> ONLY + + + + + diff --git a/js/id/geo/intersection.js b/js/id/geo/intersection.js index e2dace3d6..1697cc7d4 100644 --- a/js/id/geo/intersection.js +++ b/js/id/geo/intersection.js @@ -58,6 +58,12 @@ iD.geo.Intersection = function(graph, vertexId) { v && v.id === turn.via.node && t && t.id === turn.to.way) { turn.restriction = relation.id; + } else if (/^only_/.test(relation.tags.restriction) && + f && f.id === turn.from.way && + v && v.id === turn.via.node && + t && t.id !== turn.to.way) { + turn.restriction = relation.id; + turn.indirect_restriction = true; } }); diff --git a/js/id/svg/turns.js b/js/id/svg/turns.js index 45f09fc7b..555b75eef 100644 --- a/js/id/svg/turns.js +++ b/js/id/svg/turns.js @@ -1,22 +1,21 @@ iD.svg.Turns = function(projection) { return function(surface, graph, turns) { - function key(turn) { - return iD.Entity.key(graph.entity(turn.from.node)) + ',' + - iD.Entity.key(graph.entity(turn.via.node)) + ',' + - iD.Entity.key(graph.entity(turn.to.node)) + ',' + - turn.restriction; + function icon(turn) { + if (!turn.restriction) + return '#icon-restriction-yes'; + var restriction = graph.entity(turn.restriction).tags.restriction; + return '#icon-restriction-' + + (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + + (turn.u ? '-u' : ''); } var groups = surface.select('.layer-hit').selectAll('g.turn') - .data(turns, key); + .data(turns); // Enter var enter = groups.enter().append('g') - .attr('class', 'turn') - .classed('restricted', function (turn) { - return turn.restriction; - }); + .attr('class', 'turn'); var nEnter = enter.filter(function (turn) { return !turn.u; }); @@ -27,8 +26,7 @@ iD.svg.Turns = function(projection) { nEnter.append('use') .attr('transform', 'translate(-12, -12)') - .attr('clip-path', 'url(#clip-square-45)') - .attr('xlink:href', function(turn) { return '#icon-restriction-' + (turn.restriction ? 'no' : 'yes'); }); + .attr('clip-path', 'url(#clip-square-45)'); var uEnter = enter.filter(function (turn) { return turn.u; }); @@ -37,21 +35,24 @@ iD.svg.Turns = function(projection) { uEnter.append('use') .attr('transform', 'translate(-16, -16)') - .attr('clip-path', 'url(#clip-square-32)') - .attr('xlink:href', function(turn) { return '#icon-restriction-' + (turn.restriction ? 'no' : 'yes') + '-u'; }); + .attr('clip-path', 'url(#clip-square-32)'); // Update - groups.attr('transform', function (turn) { - var v = graph.entity(turn.via.node), - t = graph.entity(turn.to.node), - a = iD.geo.angle(v, t, projection), - p = projection(v.loc), - r = turn.u ? 0 : 60; + groups + .attr('transform', function (turn) { + var v = graph.entity(turn.via.node), + t = graph.entity(turn.to.node), + a = iD.geo.angle(v, t, projection), + p = projection(v.loc), + r = turn.u ? 0 : 60; - return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ')' + - 'rotate(' + a * 180 / Math.PI + ')'; - }); + return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ')' + + 'rotate(' + a * 180 / Math.PI + ')'; + }); + + groups.select('use') + .attr('xlink:href', icon); groups.select('rect'); groups.select('circle'); diff --git a/test/spec/geo/intersection.js b/test/spec/geo/intersection.js index 62170e601..bcf083542 100644 --- a/test/spec/geo/intersection.js +++ b/test/spec/geo/intersection.js @@ -328,9 +328,49 @@ describe("iD.geo.Intersection", function() { restriction: 'r' }); }); - }); - // 'no' vs 'only' - // Self-intersections - // Incomplete relations + it("restricts turns affected by an only_* restriction relation", function() { + // u====*~~~~v + // | + // w + var graph = iD.Graph([ + iD.Node({id: 'u'}), + iD.Node({id: 'v'}), + iD.Node({id: 'w'}), + iD.Node({id: '*'}), + iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '~', nodes: ['v', '*'], tags: {highway: 'residential'}}), + iD.Way({id: '-', nodes: ['w', '*'], tags: {highway: 'residential'}}), + iD.Relation({id: 'r', tags: {type: 'restriction', restriction: 'only_right_turn'}, members: [ + {id: '=', role: 'from', type: 'way'}, + {id: '-', role: 'to', type: 'way'}, + {id: '*', role: 'via', type: 'node'} + ]}) + ]), + turns = iD.geo.Intersection(graph, '*').turns('u'); + + expect(turns.length).to.eql(3); + expect(turns[0]).to.eql({ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'v', way: '~'}, + restriction: 'r', + indirect_restriction: true + }); + expect(turns[1]).to.eql({ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'w', way: '-'}, + restriction: 'r' + }); + expect(turns[2]).to.eql({ + from: {node: 'u', way: '='}, + via: {node: '*'}, + to: {node: 'u', way: '='}, + restriction: 'r', + indirect_restriction: true, + u: true + }); + }); + }); });