From 3384598c608fb89be6c9c601594c0dbd8887b251 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Tue, 26 Mar 2013 17:46:32 -0400 Subject: [PATCH] Add ability to disconnect self-intersecting ways Fixes #1155 --- js/id/actions/disconnect.js | 27 ++++++++++++++++++++------- test/spec/actions/disconnect.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/js/id/actions/disconnect.js b/js/id/actions/disconnect.js index 415730e77..a666a0d3e 100644 --- a/js/id/actions/disconnect.js +++ b/js/id/actions/disconnect.js @@ -18,21 +18,34 @@ iD.actions.Disconnect = function(nodeId, newNodeId) { var node = graph.entity(nodeId); graph.parentWays(node).forEach(function(parent, i) { - if (i === 0) - return; - var index = parent.nodes.indexOf(nodeId), - newNode = iD.Node({id: newNodeId, loc: node.loc, tags: node.tags}); + var keep = i === 0; - graph = graph.replace(newNode); - graph = graph.replace(parent.updateNode(newNode.id, index)); + parent.nodes.forEach(function(waynode, index) { + if (waynode === nodeId) { + + if (!keep) { + var newNode = iD.Node({id: newNodeId, loc: node.loc, tags: node.tags}); + + graph = graph.replace(newNode); + graph = graph.replace(parent.updateNode(newNode.id, index)); + } + + // Only keep the first occurrence in first way + keep = false; + } + }); }); return graph; }; action.enabled = function(graph) { - return graph.parentWays(graph.entity(nodeId)).length >= 2; + var parentWays = graph.parentWays(graph.entity(nodeId)); + return parentWays.length >= 2 || + (parentWays.length == 1 && parentWays[0].nodes.filter(function(d) { + return d === nodeId; + }).length >= 2); }; return action; diff --git a/test/spec/actions/disconnect.js b/test/spec/actions/disconnect.js index 4ce298feb..0495e8e74 100644 --- a/test/spec/actions/disconnect.js +++ b/test/spec/actions/disconnect.js @@ -6,6 +6,20 @@ describe("iD.actions.Disconnect", function () { expect(iD.actions.Disconnect('a').enabled(graph)).to.equal(false); }); + it("returns true for a node appearing twice in the same way", function () { + // a ---- b + // | | + // d ---- c + var graph = iD.Graph({ + 'a': iD.Node({id: 'a'}), + 'b': iD.Node({id: 'b'}), + 'c': iD.Node({id: 'c'}), + 'd': iD.Node({id: 'd'}), + 'w': iD.Way({id: 'w', nodes: ['a', 'b', 'c', 'd', 'a']}) + }); + expect(iD.actions.Disconnect('a').enabled(graph)).to.equal(true); + }); + it("returns true for a node shared by two or more ways", function () { // a ---- b ---- c // | @@ -52,6 +66,25 @@ describe("iD.actions.Disconnect", function () { expect(graph.entity('|').nodes).to.eql(['d', 'e']); }); + it("replaces later occurrences in a self-intersecting way", function() { + // Situtation: + // a ---- b + // \_ | + // \__ c + // Split at a + // + // Expected result: + // a ---- b ---- c ---- d + var graph = iD.Graph({ + 'a': iD.Node({id: 'a'}), + 'b': iD.Node({id: 'b'}), + 'c': iD.Node({id: 'c'}), + 'w': iD.Way({id: 'w', nodes: ['a', 'b', 'c', 'a']}) + }); + graph = iD.actions.Disconnect('a', 'd')(graph); + expect(graph.entity('w').nodes).to.eql(['a', 'b', 'c', 'd']); + }); + it("copies location and tags to the new nodes", function () { var tags = {highway: 'traffic_signals'}, loc = [1, 2],