mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-15 21:48:20 +02:00
Update to work on ways going in opposite directions
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { actionDeleteNode } from './delete_node';
|
||||
import _difference from 'lodash-es/difference';
|
||||
import _filter from 'lodash-es/filter';
|
||||
|
||||
import {
|
||||
geoVecInterp,
|
||||
@@ -17,12 +18,12 @@ export function actionStraighten(selectedIDs, projection) {
|
||||
(Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2));
|
||||
}
|
||||
|
||||
// Return all ways as a continuous, ordered array of nodes
|
||||
var allNodes = function(graph) {
|
||||
// Return all selected ways as a continuous, ordered array of nodes
|
||||
function allNodes(graph) {
|
||||
var nodes = [],
|
||||
startNodes = [],
|
||||
endNodes = [],
|
||||
ways = {},
|
||||
remainingWays = [],
|
||||
selectedWays = selectedIDs.filter(function(w) {
|
||||
return graph.entity(w).type === 'way';
|
||||
}),
|
||||
@@ -32,27 +33,47 @@ export function actionStraighten(selectedIDs, projection) {
|
||||
|
||||
for (var i = 0; i < selectedWays.length; i++) {
|
||||
var way = graph.entity(selectedWays[i]);
|
||||
nodes = graph.childNodes(way);
|
||||
ways[nodes[0].id] = nodes;
|
||||
nodes = way.nodes.slice(0);
|
||||
remainingWays.push(nodes);
|
||||
startNodes.push(nodes[0]);
|
||||
endNodes.push(nodes[nodes.length-1]);
|
||||
}
|
||||
|
||||
var startNode = _difference(startNodes, endNodes)[0],
|
||||
endNode = _difference(endNodes, startNodes)[0];
|
||||
// Remove duplicate end/startNodes (duplicate nodes cannot be at the line end,
|
||||
// and need to be removed so currNode _difference calculation below works)
|
||||
// i.e. ["n-1", "n-1", "n-2"] => ["n-2"]
|
||||
startNodes = _filter(startNodes, function(n) {
|
||||
return startNodes.indexOf(n) == startNodes.lastIndexOf(n);
|
||||
});
|
||||
endNodes = _filter(endNodes, function(n) {
|
||||
return endNodes.indexOf(n) == endNodes.lastIndexOf(n);
|
||||
});
|
||||
|
||||
nodes = ways[startNode.id];
|
||||
// Choose the initial endpoint to start from
|
||||
var currNode = _difference(startNodes, endNodes).concat(_difference(endNodes, startNodes))[0],
|
||||
nextWay = [];
|
||||
nodes = [];
|
||||
|
||||
// Add nodes to end of array, until endNode matches end of array
|
||||
while (nodes[nodes.length-1] !== endNode) {
|
||||
var currEndNode = nodes[nodes.length-1];
|
||||
nodes = nodes.concat(ways[currEndNode.id]);
|
||||
// Add nodes to end of nodes array, until all ways are added
|
||||
while (remainingWays.length) {
|
||||
nextWay = _filter(remainingWays, function(way) {
|
||||
return way[0] == currNode || way[way.length-1] == currNode;
|
||||
})[0];
|
||||
|
||||
remainingWays = _difference(remainingWays, [nextWay]);
|
||||
|
||||
if (nextWay[0] != currNode) {
|
||||
nextWay.reverse();
|
||||
}
|
||||
nodes = nodes.concat(nextWay);
|
||||
|
||||
currNode = nodes[nodes.length-1];
|
||||
}
|
||||
|
||||
// If user selected 2 nodes to straighten between, then slice nodes array to those nodes
|
||||
if (selectedNodes.length) {
|
||||
var startNodeIdx = nodes.indexOf(graph.entity(selectedNodes[0])),
|
||||
endNodeIdx = nodes.indexOf(graph.entity(selectedNodes[1])),
|
||||
if (selectedNodes.length == 2) {
|
||||
var startNodeIdx = nodes.indexOf(selectedNodes[0]),
|
||||
endNodeIdx = nodes.indexOf(selectedNodes[1]),
|
||||
sortedStartEnd = [startNodeIdx, endNodeIdx];
|
||||
|
||||
sortedStartEnd.sort(function(a, b) {
|
||||
@@ -62,10 +83,9 @@ export function actionStraighten(selectedIDs, projection) {
|
||||
nodes = nodes.slice(sortedStartEnd[0], sortedStartEnd[1]+1);
|
||||
}
|
||||
|
||||
return nodes;
|
||||
return nodes.map(function(n) { return graph.entity(n); });
|
||||
};
|
||||
|
||||
|
||||
var action = function(graph, t) {
|
||||
if (t === null || !isFinite(t)) t = 1;
|
||||
t = Math.min(Math.max(+t, 0), 1);
|
||||
@@ -137,7 +157,6 @@ export function actionStraighten(selectedIDs, projection) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
action.transitionable = true;
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ export function operationStraighten(selectedIDs, context) {
|
||||
|
||||
|
||||
operation.available = function() {
|
||||
console.log("Running operation.available..");
|
||||
var nodes = [],
|
||||
startNodes = [],
|
||||
endNodes = [],
|
||||
@@ -42,11 +43,17 @@ export function operationStraighten(selectedIDs, context) {
|
||||
endNodes.push(entity.nodes[entity.nodes.length-1]);
|
||||
}
|
||||
|
||||
// Remove duplicate end/startNodes (duplicate nodes cannot be at the line end)
|
||||
// i.e. ["n-1", "n-1", "n-2"] => ["n-2"]
|
||||
startNodes = startNodes.filter(n => startNodes.indexOf(n) == startNodes.lastIndexOf(n));
|
||||
endNodes = endNodes.filter(n => endNodes.indexOf(n) == endNodes.lastIndexOf(n));
|
||||
|
||||
// Return false if line is only 2 nodes long
|
||||
// Return false unless exactly 0 or 2 specific nodes are selected
|
||||
if (_uniq(nodes).length <= 2 || !_includes([0,2], selectedNodes.length)) return false;
|
||||
|
||||
// Ensure all ways are connected (i.e. only one unique start point and one unique end point)
|
||||
if (_difference(startNodes, endNodes).length !== 1 ||
|
||||
_difference(endNodes, startNodes).length !== 1) return false;
|
||||
// Ensure all ways are connected (i.e. only 2 unique endpoints/startpoints)
|
||||
if (_difference(startNodes, endNodes).length + _difference(endNodes, startNodes).length !== 2) return false;
|
||||
|
||||
// Ensure both selected nodes lie on the selected path
|
||||
if (selectedNodes.length && (!_includes(nodes, selectedNodes[0]) ||
|
||||
@@ -57,6 +64,7 @@ export function operationStraighten(selectedIDs, context) {
|
||||
|
||||
|
||||
operation.disabled = function() {
|
||||
console.log("Running operation.disabled..");
|
||||
var reason;
|
||||
for (var i = 0; i < selectedIDs.length; i++) {
|
||||
if (context.hasHiddenConnections(selectedIDs[i])) {
|
||||
@@ -68,6 +76,7 @@ export function operationStraighten(selectedIDs, context) {
|
||||
|
||||
|
||||
operation.tooltip = function() {
|
||||
console.log("Running operation.tooltip");
|
||||
var disable = operation.disabled();
|
||||
return disable ?
|
||||
t('operations.straighten.' + disable) :
|
||||
|
||||
@@ -102,6 +102,28 @@ describe('iD.actionStraighten', function () {
|
||||
expect(graph.hasEntity('g')).to.eq(undefined);
|
||||
});
|
||||
|
||||
it('straightens multiple, connected ways going in different directions', function() {
|
||||
var graph = iD.Graph([
|
||||
iD.Node({id: 'a', loc: [0, 0]}),
|
||||
iD.Node({id: 'b', loc: [1, 0.01], tags: {foo: 'bar'}}),
|
||||
iD.Node({id: 'c', loc: [2, -0.01]}),
|
||||
iD.Node({id: 'd', loc: [3, 0]}),
|
||||
iD.Way({id: '-', nodes: ['a', 'b', 'c', 'd']}),
|
||||
|
||||
iD.Node({id: 'e', loc: [4, 0]}),
|
||||
iD.Node({id: 'f', loc: [5, 0.01], tags: {foo: 'bar'}}),
|
||||
iD.Node({id: 'g', loc: [6, -0.01]}),
|
||||
iD.Node({id: 'h', loc: [7, 0]}),
|
||||
iD.Way({id: '--', nodes: ['h', 'g', 'f', 'e', 'd']})
|
||||
]);
|
||||
|
||||
graph = iD.actionStraighten(['-', '--'], projection)(graph);
|
||||
expect(graph.entity('-').nodes).to.eql(['a', 'b', 'd']);
|
||||
expect(graph.entity('--').nodes).to.eql(['h', 'f', 'd']);
|
||||
expect(graph.entity('f').loc[0]).to.be.closeTo(5, 1e-6);
|
||||
expect(graph.entity('f').loc[1]).to.be.closeTo(0, 1e-6);
|
||||
expect(graph.hasEntity('g')).to.eq(undefined);
|
||||
});
|
||||
|
||||
describe('transitions', function () {
|
||||
it('is transitionable', function() {
|
||||
|
||||
@@ -29,9 +29,11 @@ describe('iD.operationStraighten', function () {
|
||||
iD.osmNode({ id: 'n10', type: 'node' }),
|
||||
iD.osmNode({ id: 'n11', type: 'node' }),
|
||||
iD.osmNode({ id: 'n12', type: 'node' }),
|
||||
iD.osmNode({ id: 'n13', type: 'node' }),
|
||||
iD.osmWay({ id: 'w1', nodes: ['n1', 'n2'] }),
|
||||
iD.osmWay({ id: 'w1-2', nodes: ['n2', 'n2-1'] }),
|
||||
iD.osmWay({ id: 'w2', nodes: ['n2', 'n3', 'n4'] }),
|
||||
iD.osmWay({ id: 'w2-2', nodes: ['n4', 'n13', 'n2'] }), // w-2 reversed
|
||||
iD.osmWay({ id: 'w3', nodes: ['n4', 'n5', 'n6'] }),
|
||||
iD.osmWay({ id: 'w4', nodes: ['n6', 'n7', 'n8'] }),
|
||||
iD.osmWay({ id: 'w5', nodes: ['n9', 'n10', 'n11', 'n12'] }),
|
||||
@@ -78,6 +80,11 @@ describe('iD.operationStraighten', function () {
|
||||
expect(result).to.be.ok;
|
||||
});
|
||||
|
||||
it('is available for selected, continuous ways with different way-directions', function () {
|
||||
var result = iD.operationStraighten(['w1', 'w3', 'w2-2'], fakeContext.graph()).available();
|
||||
expect(result).to.be.ok;
|
||||
});
|
||||
|
||||
it('is available for 2 selected nodes in the same way, more than one node apart', function () {
|
||||
var result = iD.operationStraighten(['w5', 'n9', 'n11'], fakeContext.graph()).available();
|
||||
expect(result).to.be.ok;
|
||||
@@ -93,6 +100,11 @@ describe('iD.operationStraighten', function () {
|
||||
expect(result).to.be.ok;
|
||||
});
|
||||
|
||||
it('is available for 2 selected nodes in non-adjacent, non-same-directional ways, providing inbetween ways are selected', function () {
|
||||
var result = iD.operationStraighten(['n2', 'n7', 'w4', 'w1', 'w3', 'w2-2'], fakeContext.graph()).available();
|
||||
expect(result).to.be.ok;
|
||||
});
|
||||
|
||||
it('is not available for nodes not on selected ways', function () {
|
||||
var result = iD.operationStraighten(['w5', 'n4', 'n11'], fakeContext.graph()).available();
|
||||
expect(result).to.be.not.ok;
|
||||
|
||||
Reference in New Issue
Block a user