mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-23 00:29:50 +02:00
Render U-turns
This commit is contained in:
+4
-12
@@ -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(
|
||||
|
||||
Vendored
+2
-2
@@ -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 |
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user