fix destination_sign relations not updated when splitting a way (#10646)

This commit is contained in:
Kyℓe Hensel
2025-02-17 21:46:42 +11:00
committed by GitHub
parent 8f9d7e01bf
commit ef88e1c7ca
4 changed files with 64 additions and 27 deletions

View File

@@ -172,7 +172,10 @@ export function actionSplit(nodeIds, newWayIds) {
// 2. Splitting a VIA way - `wayB` remains in relation as a VIA way
if (relation.hasFromViaTo()) {
var f = relation.memberByRole('from');
var v = relation.membersByRole('via');
var v = [
...relation.membersByRole('via'),
...relation.membersByRole('intersection'),
];
var t = relation.memberByRole('to');
var i;
@@ -461,7 +464,10 @@ export function actionSplit(nodeIds, newWayIds) {
for (const parentRelation of parentRelations) {
if (parentRelation.hasFromViaTo()) {
// turn restrictions: via members must be loaded
const vias = parentRelation.membersByRole('via');
const vias = [
...parentRelation.membersByRole('via'),
...parentRelation.membersByRole('intersection'),
];
if (!vias.every(via => graph.hasEntity(via.id))) {
return 'parent_incomplete';
}

View File

@@ -262,7 +262,10 @@ const prototype = {
hasFromViaTo: function() {
return (
this.members.some(function(m) { return m.role === 'from'; }) &&
this.members.some(function(m) { return m.role === 'via'; }) &&
this.members.some((m) =>
m.role === 'via' ||
(m.role === 'intersection' && this.tags.type === 'destination_sign')
) &&
this.members.some(function(m) { return m.role === 'to'; })
);
},

View File

@@ -1673,7 +1673,9 @@ describe('iD.actionSplit', function () {
});
['restriction', 'restriction:bus', 'manoeuvre'].forEach(function (type) {
['restriction', 'restriction:bus', 'manoeuvre', 'destination_sign'].forEach(function (type) {
const viaRole = type === 'destination_sign' ? 'intersection' : 'via';
describe('type = ' + type, function () {
var a = iD.osmNode({id: 'a', loc: [0, 0]});
var b = iD.osmNode({id: 'b', loc: [1, 0]});
@@ -1694,7 +1696,7 @@ describe('iD.actionSplit', function () {
iD.osmRelation({id: 'r', tags: {type: type}, members: [
{id: '-', role: 'from', type: 'way'},
{id: '~', role: 'to', type: 'way'},
{id: 'd', role: 'via', type: 'node'}
{id: 'd', role: viaRole, type: 'node'}
]})
]);
@@ -1710,7 +1712,7 @@ describe('iD.actionSplit', function () {
iD.osmRelation({id: 'r', tags: {type: type}, members: [
{id: '~', role: 'from', type: 'way'},
{id: '-', role: 'to', type: 'way'},
{id: 'd', role: 'via', type: 'node'}
{id: 'd', role: viaRole, type: 'node'}
]})
]);
@@ -1726,7 +1728,7 @@ describe('iD.actionSplit', function () {
iD.osmRelation({id: 'r', tags: {type: type}, members: [
{id: '-', role: 'from', type: 'way'},
{id: '-', role: 'to', type: 'way'},
{id: 'd', role: 'via', type: 'node'}
{id: 'd', role: viaRole, type: 'node'}
]})
]);
@@ -1747,7 +1749,7 @@ describe('iD.actionSplit', function () {
iD.osmRelation({id: 'r', tags: {type: type}, members: [
{id: '-', role: 'from', type: 'way'},
{id: '~', role: 'to', type: 'way'},
{id: '|', role: 'via', type: 'way'}
{id: '|', role: viaRole, type: 'way'}
]})
]);
@@ -1768,7 +1770,7 @@ describe('iD.actionSplit', function () {
iD.osmRelation({id: 'r', tags: {type: type}, members: [
{id: '~', role: 'from', type: 'way'},
{id: '-', role: 'to', type: 'way'},
{id: '|', role: 'via', type: 'way'}
{id: '|', role: viaRole, type: 'way'}
]})
]);
@@ -1788,7 +1790,7 @@ describe('iD.actionSplit', function () {
iD.osmWay({id: '‖', nodes: ['f', 'd']}),
iD.osmRelation({id: 'r', tags: {type: type}, members: [
{id: '|', role: 'from', type: 'way'},
{id: '-', role: 'via', type: 'way'},
{id: '-', role: viaRole, type: 'way'},
{id: '‖', role: 'to', type: 'way'}
]})
]);
@@ -1805,7 +1807,7 @@ describe('iD.actionSplit', function () {
iD.osmRelation({id: 'r', tags: {type: type}, members: [
{id: '-', role: 'from', type: 'way'},
{id: '~', role: 'to', type: 'way'},
{id: 'd', role: 'via', type: 'node'}
{id: 'd', role: viaRole, type: 'node'}
]})
]);
@@ -1821,7 +1823,7 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '=', role: 'from', type: 'way'},
{id: '~', role: 'to', type: 'way'},
{id: 'd', role: 'via', type: 'node'}
{id: 'd', role: viaRole, type: 'node'}
]);
});
@@ -1837,7 +1839,7 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '-', role: 'from', type: 'way'},
{id: '~', role: 'to', type: 'way'},
{id: 'd', role: 'via', type: 'node'}
{id: 'd', role: viaRole, type: 'node'}
]);
});
@@ -1853,7 +1855,7 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '~', role: 'from', type: 'way'},
{id: '=', role: 'to', type: 'way'},
{id: 'd', role: 'via', type: 'node'}
{id: 'd', role: viaRole, type: 'node'}
]);
});
@@ -1869,7 +1871,7 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '~', role: 'from', type: 'way'},
{id: '-', role: 'to', type: 'way'},
{id: 'd', role: 'via', type: 'node'}
{id: 'd', role: viaRole, type: 'node'}
]);
});
@@ -1885,7 +1887,7 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '=', role: 'from', type: 'way'},
{id: '=', role: 'to', type: 'way'},
{id: 'd', role: 'via', type: 'node'}
{id: 'd', role: viaRole, type: 'node'}
]);
});
@@ -1901,7 +1903,7 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '-', role: 'from', type: 'way'},
{id: '-', role: 'to', type: 'way'},
{id: 'd', role: 'via', type: 'node'}
{id: 'd', role: viaRole, type: 'node'}
]);
});
@@ -1921,7 +1923,7 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '=', role: 'from', type: 'way'},
{id: '~', role: 'to', type: 'way'},
{id: '|', role: 'via', type: 'way'}
{id: '|', role: viaRole, type: 'way'}
]);
});
@@ -1941,7 +1943,7 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '-', role: 'from', type: 'way'},
{id: '~', role: 'to', type: 'way'},
{id: '|', role: 'via', type: 'way'}
{id: '|', role: viaRole, type: 'way'}
]);
});
@@ -1961,7 +1963,7 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '~', role: 'from', type: 'way'},
{id: '=', role: 'to', type: 'way'},
{id: '|', role: 'via', type: 'way'}
{id: '|', role: viaRole, type: 'way'}
]);
});
@@ -1981,7 +1983,7 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '~', role: 'from', type: 'way'},
{id: '-', role: 'to', type: 'way'},
{id: '|', role: 'via', type: 'way'}
{id: '|', role: viaRole, type: 'way'}
]);
});
@@ -2000,8 +2002,8 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '|', role: 'from', type: 'way'},
{id: '-', role: 'via', type: 'way'},
{id: '=', role: 'via', type: 'way'},
{id: '-', role: viaRole, type: 'way'},
{id: '=', role: viaRole, type: 'way'},
{id: '‖', role: 'to', type: 'way'}
]);
});
@@ -2021,8 +2023,8 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '|', role: 'from', type: 'way'},
{id: '-', role: 'via', type: 'way'},
{id: '=', role: 'via', type: 'way'},
{id: '-', role: viaRole, type: 'way'},
{id: '=', role: viaRole, type: 'way'},
{id: '‖', role: 'to', type: 'way'}
]);
});
@@ -2039,7 +2041,7 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '-', role: 'from', type: 'way'},
{id: '~', role: 'to', type: 'way'},
{id: 'd', role: 'via', type: 'node'}
{id: 'd', role: viaRole, type: 'node'}
]);
});
@@ -2055,7 +2057,7 @@ describe('iD.actionSplit', function () {
expect(graph.entity('r').members).to.eql([
{id: '=', role: 'from', type: 'way'},
{id: '~', role: 'to', type: 'way'},
{id: 'd', role: 'via', type: 'node'}
{id: 'd', role: viaRole, type: 'node'}
]);
});
});

View File

@@ -262,6 +262,32 @@ describe('iD.osmRelation', function () {
});
expect(r.hasFromViaTo()).to.be.false;
});
it('returns true if the `intersection` role is used instead of `via` for destination signs', () => {
const r = iD.osmRelation({
id: 'r',
tags: { type: 'destination_sign' },
members: [
{ role: 'from', id: 'f', type: 'way' },
{ role: 'intersection', id: 'v', type: 'node' },
{ role: 'to', id: 't', type: 'way' },
]
});
expect(r.hasFromViaTo()).to.be.true;
});
it('returns false if the `intersection` role is used on anything other than a destination sign', () => {
const r = iD.osmRelation({
id: 'r',
tags: { type: 'restriction' },
members: [
{ role: 'from', id: 'f', type: 'way' },
{ role: 'intersection', id: 'v', type: 'node' },
{ role: 'to', id: 't', type: 'way' },
]
});
expect(r.hasFromViaTo()).to.be.false;
});
});
describe('#isRestriction', function () {