Files
iD/js/id/actions/join.js
2013-05-07 12:34:04 -07:00

87 lines
2.6 KiB
JavaScript

// Join ways at the end node they share.
//
// This is the inverse of `iD.actions.Split`.
//
// Reference:
// https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
//
iD.actions.Join = function(ids) {
var idA = ids[0],
idB = ids[1];
function groupEntitiesByGeometry(graph) {
var entities = ids.map(function(id) { return graph.entity(id); });
return _.extend({line: []}, _.groupBy(entities, function(entity) { return entity.geometry(graph); }));
}
var action = function(graph) {
var a = graph.entity(idA),
b = graph.entity(idB),
nodes;
// Prefer to keep an existing way.
if (a.isNew() && !b.isNew()) {
var tmp = a;
a = b;
b = tmp;
idA = a.id;
idB = b.id;
}
if (a.first() === b.first()) {
// a <-- b ==> c
// Expected result:
// a <-- b <-- c
b = iD.actions.Reverse(idB)(graph).entity(idB);
nodes = b.nodes.slice().concat(a.nodes.slice(1));
} else if (a.first() === b.last()) {
// a <-- b <== c
// Expected result:
// a <-- b <-- c
nodes = b.nodes.concat(a.nodes.slice(1));
} else if (a.last() === b.first()) {
// a --> b ==> c
// Expected result:
// a --> b --> c
nodes = a.nodes.concat(b.nodes.slice(1));
} else if (a.last() === b.last()) {
// a --> b <== c
// Expected result:
// a --> b --> c
b = iD.actions.Reverse(idB)(graph).entity(idB);
nodes = a.nodes.concat(b.nodes.slice().slice(1));
}
graph.parentRelations(b).forEach(function(parent) {
graph = graph.replace(parent.replaceMember(b, a));
});
graph = graph.replace(a.mergeTags(b.tags).update({ nodes: nodes }));
graph = iD.actions.DeleteWay(idB)(graph);
return graph;
};
action.disabled = function(graph) {
var geometries = groupEntitiesByGeometry(graph);
if (ids.length !== 2 || ids.length !== geometries.line.length)
return 'not_eligible';
var a = graph.entity(idA),
b = graph.entity(idB);
if (a.first() !== b.first() &&
a.first() !== b.last() &&
a.last() !== b.first() &&
a.last() !== b.last())
return 'not_adjacent';
};
return action;
};