Skip to content

Commit 44280fc

Browse files
committed
also retrigger validation for connected ways of removed/disconnected ways
example: a way can become disconnected from the rest of the road network if the only way that connects it to the rest of the network is deleted. this also simplifies the logic in validator to be agnostic of the validation types this can affect and optimizes it slightly.
1 parent 240ebe9 commit 44280fc

File tree

3 files changed

+50
-42
lines changed

3 files changed

+50
-42
lines changed

modules/core/validator.js

+11-11
Original file line numberDiff line numberDiff line change
@@ -495,24 +495,24 @@ export function coreValidator(context) {
495495
_headCache.graph = currGraph; // take snapshot
496496
_completeDiff = context.history().difference().complete();
497497
const incrementalDiff = coreDifference(prevGraph, currGraph);
498-
let entityIDs = Object.keys(incrementalDiff.complete());
499-
entityIDs = _headCache.withAllRelatedEntities(entityIDs); // expand set
498+
const diff = Object.keys(incrementalDiff.complete());
499+
const entityIDs = _headCache.withAllRelatedEntities(diff); // expand set
500500

501501
if (!entityIDs.size) {
502502
dispatch.call('validated');
503503
return Promise.resolve();
504504
}
505505

506-
// Re-validate all issues that are disconnected_way or impossible_oneway
506+
// Re-validate also connected (or previously connected) entities to the current way
507507
// fix #8758
508-
let additionalEntityIDs = new Set();
509-
for (const IssueID in _headCache.issuesByIssueID) {
510-
const issue = _headCache.issuesByIssueID[IssueID];
511-
if (['disconnected_way', 'impossible_oneway'].includes(issue.type)) {
512-
issue.entityIds.forEach(additionalEntityIDs.add, additionalEntityIDs);
513-
}
514-
}
515-
entityIDs = new Set([...entityIDs, ...additionalEntityIDs]);
508+
const addConnectedWays = graph => diff
509+
.filter(entityID => graph.hasEntity(entityID))
510+
.map(entityID => graph.entity(entityID))
511+
.flatMap(entity => graph.childNodes(entity))
512+
.flatMap(vertex => graph.parentWays(vertex))
513+
.forEach(way => entityIDs.add(way.id));
514+
addConnectedWays(currGraph);
515+
addConnectedWays(prevGraph);
516516

517517
_headPromise = validateEntitiesAsync(entityIDs, _headCache)
518518
.then(() => updateResolvedIssues(entityIDs))

test/spec/core/validator.js

+39-4
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,9 @@ describe('iD.coreValidator', function() {
5959
);
6060
var validator = new iD.coreValidator(context);
6161
validator.init();
62-
var issues = validator.getIssues();
63-
expect(issues).to.have.lengthOf(0);
6462
validator.validate().then(function() {
6563
// Should produce disconnected way error
66-
issues = validator.getIssues();
64+
let issues = validator.getIssues();
6765
expect(issues).to.have.lengthOf(1);
6866

6967
// Add new node with entrance node to simulate connection with rest of map
@@ -84,8 +82,45 @@ describe('iD.coreValidator', function() {
8482
}).catch(function(err) {
8583
done(err);
8684
});
85+
});
86+
87+
it('add validation issue when highway becomes disconnected', function(done) {
88+
// Add a way which is connected to another way with an entrance node to simulate connection with rest of map
89+
var n1 = iD.osmNode({ id: 'n-1', loc: [4, 4] });
90+
var n2 = iD.osmNode({ id: 'n-2', loc: [4, 5] });
91+
var w = iD.osmWay({ id: 'w-1', nodes: ['n-1', 'n-2'], tags: { 'highway': 'unclassified' } });
92+
var n3 = iD.osmNode({ id: 'n-3', loc: [4, 6], tags: { 'entrance': 'yes' } });
93+
var w2 = iD.osmWay({ id: 'w-2', nodes: ['n-2', 'n-3'], tags: { 'highway': 'unclassified' } });
94+
context.perform(
95+
iD.actionAddEntity(n1),
96+
iD.actionAddEntity(n2),
97+
iD.actionAddEntity(w),
98+
iD.actionAddEntity(n3),
99+
iD.actionAddEntity(w2)
100+
);
101+
var validator = new iD.coreValidator(context);
102+
validator.init();
103+
validator.validate().then(function() {
104+
// Should be no errors
105+
let issues = validator.getIssues();
106+
expect(issues).to.have.lengthOf(0);
87107

88-
window.setTimeout(function() {}, 20); // async - to let the promise settle in phantomjs
108+
// delete second way -> first way becomes disconnected form the rest of the network
109+
context.perform(
110+
iD.actionDeleteWay(w2.id)
111+
);
112+
113+
validator.validate().then(function() {
114+
// Should produce disconnected way error
115+
issues = validator.getIssues();
116+
expect(issues).to.have.lengthOf(1);
117+
done();
118+
}).catch(function(err) {
119+
done(err);
120+
});
121+
}).catch(function(err) {
122+
done(err);
123+
});
89124
});
90125

91126
});

test/spec/validations/disconnected_way.js

-27
Original file line numberDiff line numberDiff line change
@@ -92,31 +92,4 @@ describe('iD.validations.disconnected_way', function() {
9292
var issues = validate();
9393
expect(issues).to.have.lengthOf(0);
9494
});
95-
96-
it('removes validation issue when highway is no longer disconnected', function() {
97-
// Add a way which is disconnected from the rest of the map
98-
var n1 = iD.osmNode({ id: 'n-1', loc: [4, 4] });
99-
var n2 = iD.osmNode({ id: 'n-2', loc: [4, 5] });
100-
var w = iD.osmWay({ id: 'w-1', nodes: ['n-1', 'n-2'], tags: { 'highway': 'unclassified' } });
101-
context.perform(
102-
iD.actionAddEntity(n1),
103-
iD.actionAddEntity(n2),
104-
iD.actionAddEntity(w)
105-
);
106-
var issues = validate();
107-
// Should produce disconnected way error
108-
expect(issues).to.have.lengthOf(1);
109-
110-
// Add new node with entrance node to simulate connection with rest of map
111-
var n3 = iD.osmNode({ id: 'n-3', loc: [4, 6], tags: { 'entrance': 'yes' } });
112-
var w2 = iD.osmWay({ id: 'w-2', nodes: ['n-2', 'n-3'], tags: { 'highway': 'unclassified' } });
113-
context.perform(
114-
iD.actionAddEntity(n3),
115-
iD.actionAddEntity(w2)
116-
);
117-
issues = validate();
118-
// Should be no errors
119-
expect(issues).to.have.lengthOf(0);
120-
});
121-
12295
});

0 commit comments

Comments
 (0)