mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-20 15:34:49 +02:00
UnjoinNode action (fixes #442)
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
// Unjoin the ways at the given node.
|
||||
//
|
||||
// For testing convenience, accepts an ID to assign to the (first) new node.
|
||||
// Normally, this will be undefined and the way will automatically
|
||||
// be assigned a new ID.
|
||||
//
|
||||
// Reference:
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
|
||||
//
|
||||
iD.actions.UnjoinNode = function(nodeId, newNodeId) {
|
||||
var action = function(graph) {
|
||||
if (!action.permitted(graph))
|
||||
return graph;
|
||||
|
||||
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}),
|
||||
nodes = parent.nodes.slice();
|
||||
|
||||
nodes.splice(index, 1, newNode.id);
|
||||
|
||||
graph = graph.replace(newNode);
|
||||
graph = graph.replace(parent.update({nodes: nodes}));
|
||||
});
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
||||
action.permitted = function(graph) {
|
||||
return graph.parentWays(graph.entity(nodeId)).length >= 2;
|
||||
};
|
||||
|
||||
return action;
|
||||
};
|
||||
@@ -85,6 +85,11 @@ iD.modes.Select = function(entity, initial) {
|
||||
iD.actions.SplitWay(d.id),
|
||||
'split a way');
|
||||
|
||||
}).on('unjoin', function(d) {
|
||||
mode.history.perform(
|
||||
iD.actions.UnjoinNode(d.id),
|
||||
'unjoined ways');
|
||||
|
||||
}).on('remove', function() {
|
||||
remove();
|
||||
|
||||
|
||||
+10
-1
@@ -1,6 +1,6 @@
|
||||
iD.ui.inspector = function() {
|
||||
var event = d3.dispatch('changeTags', 'reverseWay',
|
||||
'update', 'remove', 'close', 'splitWay'),
|
||||
'update', 'remove', 'close', 'splitWay', 'unjoin'),
|
||||
taginfo = iD.taginfo(),
|
||||
initial = false,
|
||||
tagList;
|
||||
@@ -58,8 +58,10 @@ iD.ui.inspector = function() {
|
||||
|
||||
function drawButtons(selection) {
|
||||
var entity = selection.datum();
|
||||
|
||||
var inspectorButtonWrap = selection.append('div')
|
||||
.attr('class','button-wrap joined fl');
|
||||
|
||||
var inspectorButton1 = inspectorButtonWrap.append('button')
|
||||
.attr('class', 'apply col6 action')
|
||||
.on('click', apply);
|
||||
@@ -80,17 +82,24 @@ iD.ui.inspector = function() {
|
||||
.attr('href', 'http://www.openstreetmap.org/browse/' + entity.type + '/' + entity.osmId())
|
||||
.attr('target', '_blank')
|
||||
.text('View on OSM');
|
||||
|
||||
if (entity.type === 'way') {
|
||||
minorButtons.append('a')
|
||||
.attr('href', '#')
|
||||
.text('Reverse Direction')
|
||||
.on('click', function() { event.reverseWay(entity); });
|
||||
}
|
||||
|
||||
if (entity.geometry() === 'vertex') {
|
||||
minorButtons.append('a')
|
||||
.attr('href', '#')
|
||||
.text('Split Way')
|
||||
.on('click', function() { event.splitWay(entity); });
|
||||
|
||||
minorButtons.append('a')
|
||||
.attr('href', '#')
|
||||
.text('Unjoin')
|
||||
.on('click', function() { event.unjoin(entity); });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
<script src='../js/id/actions/remove_way_node.js'></script>
|
||||
<script src='../js/id/actions/reverse_way.js'></script>
|
||||
<script src='../js/id/actions/split_way.js'></script>
|
||||
<script src='../js/id/actions/unjoin_node.js'></script>
|
||||
<script src='../js/id/actions/update_relation_member.js'></script>
|
||||
|
||||
<script src='../js/id/behavior.js'></script>
|
||||
@@ -140,6 +141,7 @@
|
||||
<script src="spec/actions/remove_relation_member.js"></script>
|
||||
<script src="spec/actions/reverse_way.js"></script>
|
||||
<script src="spec/actions/split_way.js"></script>
|
||||
<script src='spec/actions/unjoin_node.js'></script>
|
||||
<script src="spec/actions/update_relation_member.js"></script>
|
||||
|
||||
<script src="spec/behavior/hover.js"></script>
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
<script src="spec/actions/remove_relation_member.js"></script>
|
||||
<script src="spec/actions/reverse_way.js"></script>
|
||||
<script src="spec/actions/split_way.js"></script>
|
||||
<script src='spec/actions/unjoin_node.js'></script>
|
||||
<script src="spec/actions/update_relation_member.js"></script>
|
||||
|
||||
<script src="spec/behavior/hover.js"></script>
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
describe("iD.actions.UnjoinNode", function () {
|
||||
describe("#permitted", function () {
|
||||
it("returns false for a node shared by less than two ways", function () {
|
||||
var graph = iD.Graph({'a': iD.Node()});
|
||||
|
||||
expect(iD.actions.UnjoinNode('a').permitted(graph)).to.equal(false);
|
||||
});
|
||||
|
||||
it("returns true for a node shared by two or more ways", function () {
|
||||
// a ---- b ---- 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: 'd'}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}),
|
||||
'|': iD.Way({id: '|', nodes: ['d', 'b']})
|
||||
});
|
||||
|
||||
expect(iD.actions.UnjoinNode('b').permitted(graph)).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
it("replaces the node with a new node in all but the first way", function () {
|
||||
// Situation:
|
||||
// a ---- b ---- c
|
||||
// |
|
||||
// d
|
||||
// Split at b.
|
||||
//
|
||||
// Expected result:
|
||||
// a ---- b ---- c
|
||||
//
|
||||
// e
|
||||
// |
|
||||
// d
|
||||
//
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'd': iD.Node({id: 'd'}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}),
|
||||
'|': iD.Way({id: '|', nodes: ['d', 'b']})
|
||||
});
|
||||
|
||||
graph = iD.actions.UnjoinNode('b', 'e')(graph);
|
||||
|
||||
expect(graph.entity('-').nodes).to.eql(['a', 'b', 'c']);
|
||||
expect(graph.entity('|').nodes).to.eql(['d', 'e']);
|
||||
});
|
||||
|
||||
it("copies location and tags to the new nodes", function () {
|
||||
var tags = {highway: 'traffic_signals'},
|
||||
loc = [1, 2],
|
||||
graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b', loc: loc, tags: tags}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'd': iD.Node({id: 'd'}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b', 'c']}),
|
||||
'|': iD.Way({id: '|', nodes: ['d', 'b']})
|
||||
});
|
||||
|
||||
graph = iD.actions.UnjoinNode('b', 'e')(graph);
|
||||
|
||||
// Immutable loc => should be shared by identity.
|
||||
expect(graph.entity('b').loc).to.equal(loc);
|
||||
expect(graph.entity('e').loc).to.equal(loc);
|
||||
|
||||
// Immutable tags => should be shared by identity.
|
||||
expect(graph.entity('b').tags).to.equal(tags);
|
||||
expect(graph.entity('e').tags).to.equal(tags);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user