From aa5f1aec5bb2dda7f4227b0d7824257f122b80bd Mon Sep 17 00:00:00 2001 From: Xiaoming Gao Date: Wed, 16 Jan 2019 20:02:25 -0500 Subject: [PATCH] add auto-fix for almost junction by creating connection nodes --- data/core.yaml | 3 + dist/locales/en.json | 4 ++ .../validations/highway_almost_junction.js | 63 ++++++++++++++----- .../validations/highway_almost_junction.js | 42 ++++++++++--- 4 files changed, 88 insertions(+), 24 deletions(-) diff --git a/data/core.yaml b/data/core.yaml index 249312621..3144ac9f8 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -1210,6 +1210,9 @@ en: tag_as_disconnected: title: Tag as disconnected undo_redo: Tagged nearby features as disconnected. + connect_almost_junction: + title: Connect the features + undo_redo: Connected two features that were really close. intro: done: done ok: OK diff --git a/dist/locales/en.json b/dist/locales/en.json index 2f5f4dca2..6c6f4082f 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -1476,6 +1476,10 @@ "tag_as_disconnected": { "title": "Tag as disconnected", "undo_redo": "Tagged nearby features as disconnected." + }, + "connect_almost_junction": { + "title": "Connect the features", + "undo_redo": "Connected two features that were really close." } } }, diff --git a/modules/validations/highway_almost_junction.js b/modules/validations/highway_almost_junction.js index 6e8836d05..d32a91907 100644 --- a/modules/validations/highway_almost_junction.js +++ b/modules/validations/highway_almost_junction.js @@ -9,7 +9,10 @@ import { import { utilDisplayLabel } from '../util'; -import { actionChangeTags } from '../actions'; +import { + actionAddMidpoint, + actionChangeTags +} from '../actions'; import { t } from '../util/locale'; import { ValidationIssueType, @@ -40,21 +43,25 @@ export function validationHighwayAlmostJunction(context) { if (nidFirst === nidLast) return results; if (!isNoexit(nodeFirst) && graph.parentWays(nodeFirst).length === 1) { - var widNearFirst = canConnectByExtend(way, 0, graph, tree); - if (widNearFirst !== null) { - results.push({ - node: nodeFirst, - wid: widNearFirst, - }); + var connNearFirst = canConnectByExtend(way, 0, graph, tree); + if (connNearFirst !== null) { + results.push({ + node: nodeFirst, + wid: connNearFirst.wid, + edge: connNearFirst.edge, + cross_loc: connNearFirst.cross_loc + }); } } if (!isNoexit(nodeLast) && graph.parentWays(nodeLast).length === 1) { - var widNearLast = canConnectByExtend(way, way.nodes.length - 1, graph, tree); - if (widNearLast !== null) { - results.push({ - node: nodeLast, - wid: widNearLast, - }); + var connNearLast = canConnectByExtend(way, way.nodes.length - 1, graph, tree); + if (connNearLast !== null) { + results.push({ + node: nodeLast, + wid: connNearLast.wid, + edge: connNearLast.edge, + cross_loc: connNearLast.cross_loc + }); } } return results; @@ -87,9 +94,14 @@ export function validationHighwayAlmostJunction(context) { var way2 = intersected[i]; for (var j = 0; j < way2.nodes.length - 1; j++) { var nA = graph.entity(way2.nodes[j]), - nB = graph.entity(way2.nodes[j + 1]); - if (geoLineIntersection([tipNode.loc, extTipLoc], [nA.loc, nB.loc])) { - return way2.id; + nB = graph.entity(way2.nodes[j + 1]), + crossLoc = geoLineIntersection([tipNode.loc, extTipLoc], [nA.loc, nB.loc]); + if (crossLoc !== null) { + return { + wid: way2.id, + edge: [nA.id, nB.id], + cross_loc: crossLoc + }; } } } @@ -107,7 +119,20 @@ export function validationHighwayAlmostJunction(context) { var node = extendableNodes[j].node; var edgeHighway = graph.entity(extendableNodes[j].wid); - var fixes = []; + var fixes = [ + new validationIssueFix({ + title: t('issues.fix.connect_almost_junction.title'), + action: function() { + var endNode = this.issue.entities[1], + targetEdge = this.issue.info.edge, + crossLoc = this.issue.info.cross_loc; + context.perform( + actionAddMidpoint({loc: crossLoc, edge: targetEdge}, endNode), + t('issues.fix.connect_almost_junction.undo_redo') + ); + } + }) + ]; if (Object.keys(node.tags).length === 0) { // node has no tags, suggest noexit fix fixes.push(new validationIssueFix({ @@ -131,6 +156,10 @@ export function validationHighwayAlmostJunction(context) { tooltip: t('issues.highway_almost_junction.tooltip'), entities: [endHighway, node, edgeHighway], coordinates: extendableNodes[j].node.loc, + info: { + edge: extendableNodes[j].edge, + cross_loc: extendableNodes[j].cross_loc + }, fixes: fixes })); } diff --git a/test/spec/validations/highway_almost_junction.js b/test/spec/validations/highway_almost_junction.js index 7318541c1..06ebe3cf8 100644 --- a/test/spec/validations/highway_almost_junction.js +++ b/test/spec/validations/highway_almost_junction.js @@ -127,7 +127,7 @@ describe('iD.validations.highway_almost_junction', function () { } function validate() { - var validator = iD.validationHighwayAlmostJunction(); + var validator = iD.validationHighwayAlmostJunction(context); var changes = context.history().changes(); return validator(changes, context.graph(), context.history().tree()); } @@ -143,13 +143,27 @@ describe('iD.validations.highway_almost_junction', function () { expect(issues).to.have.lengthOf(1); var issue = issues[0]; expect(issue.type).to.eql(iD.ValidationIssueType.highway_almost_junction); - expect(issue.entities).to.have.lengthOf(2); - expect(issue.entities[0].id).to.eql('n-1'); - expect(issue.entities[1].id).to.eql('w-2'); + expect(issue.entities).to.have.lengthOf(3); + expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entities[1].id).to.eql('n-1'); + expect(issue.entities[2].id).to.eql('w-2'); expect(issue.coordinates).to.have.lengthOf(2); expect(issue.coordinates[0]).to.eql(22.42357); expect(issue.coordinates[1]).to.eql(0); + + expect(issue.info.edge).to.have.lengthOf(2); + expect(issue.info.edge[0]).to.eql('n-3'); + expect(issue.info.edge[1]).to.eql('n-4'); + + expect(issue.info.cross_loc).to.have.lengthOf(2); + expect(issue.info.cross_loc[0]).to.eql(22.42356); + expect(issue.info.cross_loc[1]).to.eql(0); + + expect(issue.fixes).to.have.lengthOf(2); + issue.fixes[0].action(); + issues = validate(); + expect(issues).to.have.lengthOf(0); }); it('horizontal and tilted road, closer than threshold', function() { @@ -158,13 +172,27 @@ describe('iD.validations.highway_almost_junction', function () { expect(issues).to.have.lengthOf(1); var issue = issues[0]; expect(issue.type).to.eql(iD.ValidationIssueType.highway_almost_junction); - expect(issue.entities).to.have.lengthOf(2); - expect(issue.entities[0].id).to.eql('n-1'); - expect(issue.entities[1].id).to.eql('w-2'); + expect(issue.entities).to.have.lengthOf(3); + expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entities[1].id).to.eql('n-1'); + expect(issue.entities[2].id).to.eql('w-2'); expect(issue.coordinates).to.have.lengthOf(2); expect(issue.coordinates[0]).to.eql(22.42357); expect(issue.coordinates[1]).to.eql(0); + + expect(issue.info.edge).to.have.lengthOf(2); + expect(issue.info.edge[0]).to.eql('n-3'); + expect(issue.info.edge[1]).to.eql('n-4'); + + expect(issue.info.cross_loc).to.have.lengthOf(2); + expect(issue.info.cross_loc[0]).to.eql(22.42356); + expect(issue.info.cross_loc[1]).to.eql(0); + + expect(issue.fixes).to.have.lengthOf(2); + issue.fixes[1].action(); + issues = validate(); + expect(issues).to.have.lengthOf(0); }); it('horizontal and vertical road, further than threshold', function() {