Render U-turns

This commit is contained in:
John Firebaugh
2014-05-17 08:42:47 -07:00
parent d4d80b2d6e
commit 573237e94e
6 changed files with 88 additions and 42 deletions
+4 -12
View File
@@ -947,17 +947,8 @@ text.point {
/* Turns */
g.turn path {
stroke: green;
stroke-width: 10px;
stroke-linecap: round;
}
g.turn.restricted path {
stroke: red;
}
g.turn rect {
g.turn rect,
g.turn circle {
fill: none;
pointer-events: all;
}
@@ -1109,7 +1100,8 @@ g.turn rect {
) 9 9, crosshair;
}
.turn rect {
.turn rect,
.turn circle {
cursor: pointer; /* Opera */
cursor: url(img/cursor-pointer.png) 6 1, pointer; /* FF */
cursor: -webkit-image-set(
+2 -2
View File
@@ -1941,7 +1941,7 @@
</g>
<g
id="g4190"
transform="matrix(0,1,-1,0,240.0095,-80.00893)">
transform="matrix(0,1,1,0,71.9905,-80.00893)">
<path
inkscape:connector-curvature="0"
id="path12001"
@@ -1961,7 +1961,7 @@
</g>
<g
id="g4206"
transform="matrix(0,1,-1,0,280,-115)">
transform="matrix(0,1,1,0,122,-115)">
<path
sodipodi:nodetypes="sssss"
inkscape:connector-curvature="0"

Before

Width:  |  Height:  |  Size: 169 KiB

After

Width:  |  Height:  |  Size: 169 KiB

+10
View File
@@ -93,6 +93,16 @@ iD.geo.Intersection = function(graph, vertexId) {
}
});
// U-turn
if (way.tags.oneway !== 'yes' && way.tags.oneway !== '-1') {
turns.push(withRestriction({
from: from,
via: via,
to: from,
u: true
}));
}
return turns;
};
+1 -1
View File
@@ -92,7 +92,7 @@ iD.svg.Defs = function(context) {
});
defs.selectAll()
.data([12, 18, 20, 45])
.data([12, 18, 20, 32, 45])
.enter().append('clipPath')
.attr('id', function (d) {
return 'clip-square-' + d;
+29 -11
View File
@@ -1,25 +1,38 @@
iD.svg.Turns = function(projection) {
return function(surface, graph, turns) {
var groups = surface.select('.layer-hit').selectAll('g.turn')
.data(turns);
var layer = surface.select('.layer-hit'),
nTurns = turns.filter(function (d) { return !d.u; }),
uTurns = turns.filter(function (d) { return d.u; });
var nGroups = layer.selectAll('g.turn.turn-n')
.data(nTurns);
var uGroups = layer.selectAll('g.turn.turn-u')
.data(uTurns);
// Enter
var enter = groups.enter().append('g')
.attr('class', 'turn');
var nEnter = nGroups.enter().append('g')
.attr('class', 'turn turn-n');
var uEnter = uGroups.enter().append('g')
.attr('class', 'turn turn-u');
enter.append('rect')
nEnter.append('rect')
.attr('transform', 'translate(-12, -12)')
.attr('width', '45')
.attr('height', '25');
uEnter.append('circle')
.attr('r', '16');
enter.append('use')
nEnter.append('use')
.attr('transform', 'translate(-12, -12)')
.attr('clip-path', 'url(#clip-square-45)');
uEnter.append('use')
.attr('transform', 'translate(-16, -16)')
.attr('clip-path', 'url(#clip-square-32)');
// Update
groups
layer.selectAll('g.turn')
.classed('restricted', function(turn) {
return turn.restriction;
})
@@ -28,20 +41,25 @@ iD.svg.Turns = function(projection) {
t = graph.entity(turn.to.node),
a = iD.geo.angle(v, t, projection),
p = projection(v.loc),
r = 60;
r = turn.u ? 0 : 60;
return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ')' +
'rotate(' + a * 180 / Math.PI + ')';
});
groups.select('use')
nGroups.select('use')
.attr('xlink:href', function(turn) { return '#icon-restriction-' + (turn.restriction ? 'no' : 'yes'); });
uGroups.select('use')
.attr('xlink:href', function(turn) { return '#icon-restriction-' + (turn.restriction ? 'no' : 'yes') + '-u'; });
groups.select('rect');
nGroups.select('rect');
uGroups.select('circle');
// Exit
groups.exit()
nGroups.exit()
.remove();
uGroups.exit()
.remove();
return this;
+42 -16
View File
@@ -65,11 +65,12 @@ describe("iD.geo.Intersection", function() {
]),
turns = iD.geo.Intersection(graph, '*').turns('=');
expect(turns).to.eql([{
expect(turns.length).to.eql(2);
expect(turns[0]).to.eql({
from: {node: 'u', way: '='},
via: {node: '*'},
to: {node: 'w', way: '-'}
}]);
});
});
it("permits turns onto a way backward", function() {
@@ -83,11 +84,12 @@ describe("iD.geo.Intersection", function() {
]),
turns = iD.geo.Intersection(graph, '*').turns('=');
expect(turns).to.eql([{
expect(turns.length).to.eql(2);
expect(turns[0]).to.eql({
from: {node: 'u', way: '='},
via: {node: '*'},
to: {node: 'w', way: '-'}
}]);
});
});
it("permits turns onto a way in both directions", function() {
@@ -106,15 +108,17 @@ describe("iD.geo.Intersection", function() {
]),
turns = iD.geo.Intersection(graph, '*').turns('=');
expect(turns).to.eql([{
expect(turns.length).to.eql(3);
expect(turns[0]).to.eql({
from: {node: 'u', way: '='},
via: {node: '*'},
to: {node: 'w', way: '-'}
}, {
});
expect(turns[1]).to.eql({
from: {node: 'u', way: '='},
via: {node: '*'},
to: {node: 'x', way: '-'}
}]);
});
});
it("permits turns from a oneway forward", function() {
@@ -188,11 +192,12 @@ describe("iD.geo.Intersection", function() {
]),
turns = iD.geo.Intersection(graph, '*').turns('=');
expect(turns).to.eql([{
expect(turns.length).to.eql(2);
expect(turns[0]).to.eql({
from: {node: 'u', way: '='},
via: {node: '*'},
to: {node: 'w', way: '-'}
}]);
});
});
it("permits turns onto a reverse oneway backward", function() {
@@ -206,11 +211,12 @@ describe("iD.geo.Intersection", function() {
]),
turns = iD.geo.Intersection(graph, '*').turns('=');
expect(turns).to.eql([{
expect(turns.length).to.eql(2);
expect(turns[0]).to.eql({
from: {node: 'u', way: '='},
via: {node: '*'},
to: {node: 'w', way: '-'}
}]);
});
});
it("omits turns onto a oneway backward", function() {
@@ -222,7 +228,7 @@ describe("iD.geo.Intersection", function() {
iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}),
iD.Way({id: '-', nodes: ['w', '*'], tags: {highway: 'residential', oneway: 'yes'}})
]);
expect(iD.geo.Intersection(graph, '*').turns('=')).to.eql([]);
expect(iD.geo.Intersection(graph, '*').turns('=').length).to.eql(1);
});
it("omits turns onto a reverse oneway forward", function() {
@@ -234,7 +240,27 @@ describe("iD.geo.Intersection", function() {
iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}),
iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential', oneway: '-1'}})
]);
expect(iD.geo.Intersection(graph, '*').turns('=')).to.eql([]);
expect(iD.geo.Intersection(graph, '*').turns('=').length).to.eql(1);
});
it("includes U-turns", function() {
// u====*--->w
var graph = iD.Graph([
iD.Node({id: 'u'}),
iD.Node({id: '*'}),
iD.Node({id: 'w'}),
iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}),
iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}})
]),
turns = iD.geo.Intersection(graph, '*').turns('=');
expect(turns.length).to.eql(2);
expect(turns[1]).to.eql({
from: {node: 'u', way: '='},
via: {node: '*'},
to: {node: 'u', way: '='},
u: true
});
});
it("restricts turns with a restriction relation", function() {
@@ -253,17 +279,17 @@ describe("iD.geo.Intersection", function() {
]),
turns = iD.geo.Intersection(graph, '*').turns('=');
expect(turns).to.eql([{
expect(turns.length).to.eql(2);
expect(turns[0]).to.eql({
from: {node: 'u', way: '='},
via: {node: '*'},
to: {node: 'w', way: '-'},
restriction: 'r'
}]);
});
});
});
// 'no' vs 'only'
// U-turns
// Self-intersections
// Incomplete relations
});