Add support for connectivity relations

This commit is contained in:
John Firebaugh
2021-09-08 20:30:38 -07:00
parent a14cf49710
commit 1457759994
6 changed files with 108 additions and 103 deletions
+1 -1
View File
@@ -312,7 +312,7 @@ en:
other: "Merged {n} features."
not_eligible: These features can't be merged.
not_adjacent: These features can't be merged because their endpoints aren't connected.
restriction: "These features can't be merged because it would damage a \"{relation}\" relation."
damage_relation: "These features can't be merged because it would damage a \"{relation}\" relation."
relation: These features can't be merged because they have conflicting relation roles.
incomplete_relation: These features can't be merged because at least one hasn't been fully downloaded.
conflicting_tags: These features can't be merged because some of their tags have conflicting values.
+1 -1
View File
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -136,7 +136,7 @@ export function actionJoin(ids) {
// this prohibits, and prohibits some cases this allows.
var sortedParentRelations = function (id) {
return graph.parentRelations(graph.entity(id))
.filter((rel) => !rel.isRestriction())
.filter((rel) => !rel.isRestriction() && !rel.isConnectivity())
.sort((a, b) => a.id - b.id);
};
var relsA = sortedParentRelations(ids[0]);
@@ -177,7 +177,7 @@ export function actionJoin(ids) {
joined[0].forEach(function(way) {
var parents = graph.parentRelations(way);
parents.forEach(function(parent) {
if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; })) {
if ((parent.isRestriction() || parent.isConnectivity()) && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; })) {
relation = parent;
}
});
@@ -192,7 +192,7 @@ export function actionJoin(ids) {
});
if (relation) {
return 'restriction';
return relation.isRestriction() ? 'restriction' : 'connectivity';
}
if (conflicting) {
+3 -3
View File
@@ -77,9 +77,9 @@ export function operationMerge(context, selectedIDs) {
if (disabled === 'conflicting_relations') {
return t('operations.merge.conflicting_relations');
}
if (disabled === 'restriction') {
return t('operations.merge.restriction',
{ relation: presetManager.item('type/restriction').name() });
if (disabled === 'restriction' || disabled === 'connectivity') {
return t('operations.merge.damage_relation',
{ relation: presetManager.item('type/' + disabled).name() });
}
return t('operations.merge.' + disabled);
}
+3
View File
@@ -289,6 +289,9 @@ Object.assign(osmRelation.prototype, {
return true;
},
isConnectivity: function() {
return !!(this.tags.type && this.tags.type.match(/^connectivity:?/));
},
// Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
// where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
+97 -95
View File
@@ -96,50 +96,106 @@ describe('iD.actionJoin', function () {
expect(iD.actionJoin(['-', '=']).disabled(graph)).to.equal('not_adjacent');
});
it('returns \'restriction\' in situations where a turn restriction would be damaged (a)', function () {
// a --> b ==> c
// from: -
// to: =
// via: b
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [0,0]}),
iD.osmNode({id: 'b', loc: [2,0]}),
iD.osmNode({id: 'c', loc: [4,0]}),
iD.osmWay({id: '-', nodes: ['a', 'b']}),
iD.osmWay({id: '=', nodes: ['b', 'c']}),
iD.osmRelation({id: 'r', tags: {type: 'restriction'}, members: [
{type: 'way', id: '-', role: 'from'},
{type: 'way', id: '=', role: 'to'},
{type: 'node', id: 'b', role: 'via'}
]})
]);
['restriction', 'connectivity'].forEach(function (type) {
it(`returns '${type}' in situations where a ${type} relation would be damaged (a)`, function () {
// a --> b ==> c
// from: -
// to: =
// via: b
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [0,0]}),
iD.osmNode({id: 'b', loc: [2,0]}),
iD.osmNode({id: 'c', loc: [4,0]}),
iD.osmWay({id: '-', nodes: ['a', 'b']}),
iD.osmWay({id: '=', nodes: ['b', 'c']}),
iD.osmRelation({id: 'r', tags: {type}, members: [
{type: 'way', id: '-', role: 'from'},
{type: 'way', id: '=', role: 'to'},
{type: 'node', id: 'b', role: 'via'}
]})
]);
expect(iD.actionJoin(['-', '=']).disabled(graph)).to.equal('restriction');
});
expect(iD.actionJoin(['-', '=']).disabled(graph)).to.equal(type);
});
it('returns \'restriction\' in situations where a turn restriction would be damaged (b)', function () {
// a --> b ==> c
// |
// d
// from: -
// to: |
// via: b
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [0,0]}),
iD.osmNode({id: 'b', loc: [2,0]}),
iD.osmNode({id: 'c', loc: [4,0]}),
iD.osmNode({id: 'd', loc: [2,2]}),
iD.osmWay({id: '-', nodes: ['a', 'b']}),
iD.osmWay({id: '=', nodes: ['b', 'c']}),
iD.osmWay({id: '|', nodes: ['b', 'd']}),
iD.osmRelation({id: 'r', tags: {type: 'restriction'}, members: [
{type: 'way', id: '-', role: 'from'},
{type: 'way', id: '|', role: 'to'},
{type: 'node', id: 'b', role: 'via'}
]})
]);
it(`returns '${type}' in situations where a ${type} relation would be damaged (b)`, function () {
// a --> b ==> c
// |
// d
// from: -
// to: |
// via: b
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [0,0]}),
iD.osmNode({id: 'b', loc: [2,0]}),
iD.osmNode({id: 'c', loc: [4,0]}),
iD.osmNode({id: 'd', loc: [2,2]}),
iD.osmWay({id: '-', nodes: ['a', 'b']}),
iD.osmWay({id: '=', nodes: ['b', 'c']}),
iD.osmWay({id: '|', nodes: ['b', 'd']}),
iD.osmRelation({id: 'r', tags: {type}, members: [
{type: 'way', id: '-', role: 'from'},
{type: 'way', id: '|', role: 'to'},
{type: 'node', id: 'b', role: 'via'}
]})
]);
expect(iD.actionJoin(['-', '=']).disabled(graph)).to.equal('restriction');
expect(iD.actionJoin(['-', '=']).disabled(graph)).to.equal(type);
});
it(`returns falsy in situations where a ${type} relation wouldn't be damaged (a)`, function () {
// a --> b ==> c
// |
// d
// from: -
// to: |
// via: a
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [0,0]}),
iD.osmNode({id: 'b', loc: [2,0]}),
iD.osmNode({id: 'c', loc: [4,0]}),
iD.osmNode({id: 'd', loc: [0,2]}),
iD.osmWay({id: '-', nodes: ['a', 'b']}),
iD.osmWay({id: '=', nodes: ['b', 'c']}),
iD.osmWay({id: '|', nodes: ['a', 'd']}),
iD.osmRelation({id: 'r', tags: {type}, members: [
{type: 'way', id: '-', role: 'from'},
{type: 'way', id: '|', role: 'to'},
{type: 'node', id: 'a', role: 'via'}
]})
]);
expect(iD.actionJoin(['-', '=']).disabled(graph)).not.to.be.ok;
});
it(`returns falsy in situations where a ${type} restriction wouldn't be damaged (b)`, function () {
// d
// |
// a --> b ==> c
// \
// e
// from: |
// to: \
// via: b
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [0,0]}),
iD.osmNode({id: 'b', loc: [2,0]}),
iD.osmNode({id: 'c', loc: [4,0]}),
iD.osmNode({id: 'd', loc: [2,-2]}),
iD.osmNode({id: 'e', loc: [3,2]}),
iD.osmWay({id: '-', nodes: ['a', 'b']}),
iD.osmWay({id: '=', nodes: ['b', 'c']}),
iD.osmWay({id: '|', nodes: ['d', 'b']}),
iD.osmWay({id: '\\', nodes: ['b', 'e']}),
iD.osmRelation({id: 'r', tags: {type}, members: [
{type: 'way', id: '|', role: 'from'},
{type: 'way', id: '\\', role: 'to'},
{type: 'node', id: 'b', role: 'via'}
]})
]);
expect(iD.actionJoin(['-', '=']).disabled(graph)).not.to.be.ok;
});
});
it('returns \'conflicting_relations\' when a relation would be extended', function () {
@@ -202,60 +258,6 @@ describe('iD.actionJoin', function () {
expect(iD.actionJoin(['-', '=']).disabled(graph)).to.equal('paths_intersect');
});
it('returns falsy in situations where a turn restriction wouldn\'t be damaged (a)', function () {
// a --> b ==> c
// |
// d
// from: -
// to: |
// via: a
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [0,0]}),
iD.osmNode({id: 'b', loc: [2,0]}),
iD.osmNode({id: 'c', loc: [4,0]}),
iD.osmNode({id: 'd', loc: [0,2]}),
iD.osmWay({id: '-', nodes: ['a', 'b']}),
iD.osmWay({id: '=', nodes: ['b', 'c']}),
iD.osmWay({id: '|', nodes: ['a', 'd']}),
iD.osmRelation({id: 'r', tags: {type: 'restriction'}, members: [
{type: 'way', id: '-', role: 'from'},
{type: 'way', id: '|', role: 'to'},
{type: 'node', id: 'a', role: 'via'}
]})
]);
expect(iD.actionJoin(['-', '=']).disabled(graph)).not.to.be.ok;
});
it('returns falsy in situations where a turn restriction wouldn\'t be damaged (b)', function () {
// d
// |
// a --> b ==> c
// \
// e
// from: |
// to: \
// via: b
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [0,0]}),
iD.osmNode({id: 'b', loc: [2,0]}),
iD.osmNode({id: 'c', loc: [4,0]}),
iD.osmNode({id: 'd', loc: [2,-2]}),
iD.osmNode({id: 'e', loc: [3,2]}),
iD.osmWay({id: '-', nodes: ['a', 'b']}),
iD.osmWay({id: '=', nodes: ['b', 'c']}),
iD.osmWay({id: '|', nodes: ['d', 'b']}),
iD.osmWay({id: '\\', nodes: ['b', 'e']}),
iD.osmRelation({id: 'r', tags: {type: 'restriction'}, members: [
{type: 'way', id: '|', role: 'from'},
{type: 'way', id: '\\', role: 'to'},
{type: 'node', id: 'b', role: 'via'}
]})
]);
expect(iD.actionJoin(['-', '=']).disabled(graph)).not.to.be.ok;
});
it('returns \'conflicting_tags\' for two entities that have conflicting tags', function () {
var graph = iD.coreGraph([
iD.osmNode({id: 'a', loc: [0,0]}),