Fix connecting adjacent vertices

Can't unconditionally delete the node; it may be a member
of other ways.

I didn't preserve the behavior of dragging a midpoint to
an adjacent node being a no-op. In general we don't try to
eliminate compound operations whose net result is a no-op;
I don't think it's important to do so for this special case.

The degenerate case of connecting the endpoints of a two-vertex
line now results in a point. This is what naturally resulted
from the code, and seems ok.

Fixes #983.
This commit is contained in:
John Firebaugh
2013-03-12 16:21:12 -07:00
parent 3b3ee84a84
commit 4fa88acc85
3 changed files with 73 additions and 17 deletions

View File

@@ -17,10 +17,12 @@ iD.actions.Connect = function(nodeIds) {
var survivor = graph.entity(_.last(nodeIds));
for (var i = 0; i < nodeIds.length - 1; i++) {
var node = graph.entity(nodeIds[i]), index;
var node = graph.entity(nodeIds[i]);
graph.parentWays(node).forEach(function(parent) {
graph = graph.replace(parent.replaceNode(node.id, survivor.id));
if (!parent.areAdjacent(node.id, survivor.id)) {
graph = graph.replace(parent.replaceNode(node.id, survivor.id));
}
});
graph.parentRelations(node).forEach(function(parent) {

View File

@@ -102,12 +102,6 @@ iD.modes.DragNode = function(context) {
function end(entity) {
if (cancelled) return;
function adjacent(d) {
return _.any(context.graph().parentWays(entity).map(function(w) {
return w.areAdjacent(d.id, entity.id);
}));
}
var d = datum();
if (d.type === 'way') {
@@ -117,15 +111,6 @@ iD.modes.DragNode = function(context) {
iD.actions.AddVertex(d.id, entity.id, choice.index),
connectAnnotation(d));
} else if (d.type === 'node' && adjacent(d)) {
if (wasMidpoint) {
context.history().pop();
} else {
context.replace(
iD.actions.DeleteNode(entity.id),
t('operations.delete.annotation.vertex'));
}
} else if (d.type === 'node' && d.id !== entity.id) {
context.replace(
iD.actions.Connect([entity.id, d.id]),

View File

@@ -78,6 +78,75 @@ describe("iD.actions.Connect", function() {
expect(graph.entity('-').nodes).to.eql(['d', 'b', 'c', 'd']);
});
it("merges adjacent nodes", function() {
// a --- b --- c
//
// Connect [b, c]
//
// Expected result:
//
// a --- c
//
var graph = iD.Graph({
'a': iD.Node({id: 'a'}),
'b': iD.Node({id: 'b'}),
'c': iD.Node({id: 'c'}),
'-': iD.Way({id: '-', nodes: ['a', 'b', 'c']})
});
graph = iD.actions.Connect(['b', 'c'])(graph);
expect(graph.entity('-').nodes).to.eql(['a', 'c']);
expect(graph.entity('b')).to.be.undefined;
});
it("merges adjacent nodes with connections", function() {
// a --- b --- c
// |
// d
//
// Connect [b, c]
//
// Expected result:
//
// a --- c
// |
// d
//
var graph = iD.Graph({
'a': iD.Node({id: 'a'}),
'b': iD.Node({id: 'b'}),
'c': iD.Node({id: 'c'}),
'd': iD.Node({id: 'c'}),
'-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}),
'|': iD.Way({id: '|', nodes: ['b', 'd']})
});
graph = iD.actions.Connect(['b', 'c'])(graph);
expect(graph.entity('-').nodes).to.eql(['a', 'c']);
expect(graph.entity('|').nodes).to.eql(['c', 'd']);
expect(graph.entity('b')).to.be.undefined;
});
it("deletes a degenerate way", function() {
// a --- b
//
// Connect [a, b]
//
var graph = iD.Graph({
'a': iD.Node({id: 'a'}),
'b': iD.Node({id: 'b'}),
'-': iD.Way({id: '-', nodes: ['a', 'b']})
});
graph = iD.actions.Connect(['a', 'b'])(graph);
expect(graph.entity('a')).to.be.undefined;
expect(graph.entity('-')).to.be.undefined;
});
it("merges tags to the surviving node", function() {
var graph = iD.Graph({
'a': iD.Node({id: 'a', tags: {a: 'a'}}),