mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 09:12:52 +00:00
Minor code cleanups, swap some math for existing functions
This commit is contained in:
@@ -1,11 +1,7 @@
|
||||
import { actionDeleteNode } from './delete_node';
|
||||
import _difference from 'lodash-es/difference';
|
||||
import _filter from 'lodash-es/filter';
|
||||
|
||||
import {
|
||||
geoVecInterp,
|
||||
geoVecLength
|
||||
} from '../geo';
|
||||
import { actionDeleteNode } from './delete_node';
|
||||
import { geoVecDot, geoVecInterp, geoVecLength } from '../geo';
|
||||
|
||||
|
||||
/*
|
||||
@@ -13,50 +9,49 @@ import {
|
||||
*/
|
||||
export function actionStraighten(selectedIDs, projection) {
|
||||
|
||||
function positionAlongWay(n, s, e) {
|
||||
return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1])) /
|
||||
(Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2));
|
||||
function positionAlongWay(a, o, b) {
|
||||
return geoVecDot(a, b, o) / geoVecDot(b, b, o);
|
||||
}
|
||||
|
||||
// Return all selected ways as a continuous, ordered array of nodes
|
||||
function allNodes(graph) {
|
||||
var nodes = [],
|
||||
startNodes = [],
|
||||
endNodes = [],
|
||||
remainingWays = [],
|
||||
selectedWays = selectedIDs.filter(function(w) {
|
||||
return graph.entity(w).type === 'way';
|
||||
}),
|
||||
selectedNodes = selectedIDs.filter(function(n) {
|
||||
return graph.entity(n).type === 'node';
|
||||
});
|
||||
var nodes = [];
|
||||
var startNodes = [];
|
||||
var endNodes = [];
|
||||
var remainingWays = [];
|
||||
var selectedWays = selectedIDs.filter(function(w) {
|
||||
return graph.entity(w).type === 'way';
|
||||
});
|
||||
var selectedNodes = selectedIDs.filter(function(n) {
|
||||
return graph.entity(n).type === 'node';
|
||||
});
|
||||
|
||||
for (var i = 0; i < selectedWays.length; i++) {
|
||||
var way = graph.entity(selectedWays[i]);
|
||||
nodes = way.nodes.slice(0);
|
||||
remainingWays.push(nodes);
|
||||
startNodes.push(nodes[0]);
|
||||
endNodes.push(nodes[nodes.length-1]);
|
||||
nodes = way.nodes.slice(0);
|
||||
remainingWays.push(nodes);
|
||||
startNodes.push(nodes[0]);
|
||||
endNodes.push(nodes[nodes.length-1]);
|
||||
}
|
||||
|
||||
// Remove duplicate end/startNodes (duplicate nodes cannot be at the line end,
|
||||
// and need to be removed so currNode _difference calculation below works)
|
||||
// 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) {
|
||||
startNodes = startNodes.filter(function(n) {
|
||||
return startNodes.indexOf(n) === startNodes.lastIndexOf(n);
|
||||
});
|
||||
endNodes = _filter(endNodes, function(n) {
|
||||
endNodes = endNodes.filter(function(n) {
|
||||
return endNodes.indexOf(n) === endNodes.lastIndexOf(n);
|
||||
});
|
||||
|
||||
// Choose the initial endpoint to start from
|
||||
var currNode = _difference(startNodes, endNodes).concat(_difference(endNodes, startNodes))[0],
|
||||
nextWay = [];
|
||||
nodes = [];
|
||||
var currNode = _difference(startNodes, endNodes).concat(_difference(endNodes, startNodes))[0];
|
||||
var nextWay = [];
|
||||
nodes = [];
|
||||
|
||||
// Create nested function outside of loop to avoid "function in loop" lint error
|
||||
var getNextWay = function(currNode, remainingWays) {
|
||||
return _filter(remainingWays, function(way) {
|
||||
return remainingWays.filter(function(way) {
|
||||
return way[0] === currNode || way[way.length-1] === currNode;
|
||||
})[0];
|
||||
};
|
||||
@@ -64,59 +59,51 @@ export function actionStraighten(selectedIDs, projection) {
|
||||
// Add nodes to end of nodes array, until all ways are added
|
||||
while (remainingWays.length) {
|
||||
nextWay = getNextWay(currNode, remainingWays);
|
||||
|
||||
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 === 2) {
|
||||
var startNodeIdx = nodes.indexOf(selectedNodes[0]),
|
||||
endNodeIdx = nodes.indexOf(selectedNodes[1]),
|
||||
sortedStartEnd = [startNodeIdx, endNodeIdx];
|
||||
var startNodeIdx = nodes.indexOf(selectedNodes[0]);
|
||||
var endNodeIdx = nodes.indexOf(selectedNodes[1]);
|
||||
var sortedStartEnd = [startNodeIdx, endNodeIdx];
|
||||
|
||||
sortedStartEnd.sort(function(a, b) {
|
||||
return a - b;
|
||||
});
|
||||
|
||||
sortedStartEnd.sort(function(a, b) { return a - b; });
|
||||
nodes = nodes.slice(sortedStartEnd[0], sortedStartEnd[1]+1);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
var nodes = allNodes(graph),
|
||||
points = nodes.map(function(n) { return projection(n.loc); }),
|
||||
startPoint = points[0],
|
||||
endPoint = points[points.length-1],
|
||||
toDelete = [],
|
||||
i;
|
||||
var nodes = allNodes(graph);
|
||||
var points = nodes.map(function(n) { return projection(n.loc); });
|
||||
var startPoint = points[0];
|
||||
var endPoint = points[points.length-1];
|
||||
var toDelete = [];
|
||||
var i;
|
||||
|
||||
for (i = 1; i < points.length-1; i++) {
|
||||
var node = nodes[i],
|
||||
point = points[i];
|
||||
var node = nodes[i];
|
||||
var point = points[i];
|
||||
|
||||
if (t < 1 || graph.parentWays(node).length > 1 ||
|
||||
graph.parentRelations(node).length ||
|
||||
node.hasInterestingTags()) {
|
||||
|
||||
var u = positionAlongWay(point, startPoint, endPoint),
|
||||
p = [
|
||||
startPoint[0] + u * (endPoint[0] - startPoint[0]),
|
||||
startPoint[1] + u * (endPoint[1] - startPoint[1])
|
||||
],
|
||||
loc2 = projection.invert(p);
|
||||
|
||||
node.hasInterestingTags()
|
||||
) {
|
||||
var u = positionAlongWay(point, startPoint, endPoint);
|
||||
var p = geoVecInterp(startPoint, endPoint, u);
|
||||
var loc2 = projection.invert(p);
|
||||
graph = graph.replace(node.move(geoVecInterp(node.loc, loc2, t)));
|
||||
|
||||
} else {
|
||||
@@ -137,23 +124,22 @@ export function actionStraighten(selectedIDs, projection) {
|
||||
|
||||
action.disabled = function(graph) {
|
||||
// check way isn't too bendy
|
||||
var nodes = allNodes(graph),
|
||||
points = nodes.map(function(n) { return projection(n.loc); }),
|
||||
startPoint = points[0],
|
||||
endPoint = points[points.length-1],
|
||||
threshold = 0.2 * geoVecLength(startPoint, endPoint),
|
||||
i;
|
||||
var nodes = allNodes(graph);
|
||||
var points = nodes.map(function(n) { return projection(n.loc); });
|
||||
var startPoint = points[0];
|
||||
var endPoint = points[points.length-1];
|
||||
var threshold = 0.2 * geoVecLength(startPoint, endPoint);
|
||||
var i;
|
||||
|
||||
if (threshold === 0) {
|
||||
return 'too_bendy';
|
||||
}
|
||||
|
||||
for (i = 1; i < points.length-1; i++) {
|
||||
var point = points[i],
|
||||
u = positionAlongWay(point, startPoint, endPoint),
|
||||
p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
|
||||
p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]),
|
||||
dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2));
|
||||
for (i = 1; i < points.length - 1; i++) {
|
||||
var point = points[i];
|
||||
var u = positionAlongWay(point, startPoint, endPoint);
|
||||
var p = geoVecInterp(startPoint, endPoint, u);
|
||||
var dist = geoVecLength(p, point);
|
||||
|
||||
// to bendy if point is off by 20% of total start/end distance in projected space
|
||||
if (isNaN(dist) || dist > threshold) {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import _uniq from 'lodash-es/uniq';
|
||||
import _difference from 'lodash-es/difference';
|
||||
import _includes from 'lodash-es/includes';
|
||||
import _filter from 'lodash-es/filter';
|
||||
|
||||
import { t } from '../util/locale';
|
||||
import { actionStraighten } from '../actions/index';
|
||||
@@ -18,24 +16,21 @@ export function operationStraighten(selectedIDs, context) {
|
||||
|
||||
|
||||
operation.available = function() {
|
||||
var nodes = [],
|
||||
startNodes = [],
|
||||
endNodes = [],
|
||||
selectedNodes = [];
|
||||
var nodes = [];
|
||||
var startNodes = [];
|
||||
var endNodes = [];
|
||||
var selectedNodes = [];
|
||||
|
||||
// collect nodes along selected ways
|
||||
for (var i = 0; i < selectedIDs.length; i++) {
|
||||
if (!context.hasEntity(selectedIDs[i])) return false;
|
||||
|
||||
var entity = context.entity(selectedIDs[i]);
|
||||
|
||||
if (entity.type === 'node') {
|
||||
selectedNodes.push(entity.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entity.type !== 'way' ||
|
||||
entity.isClosed()) {
|
||||
return false;
|
||||
} else if (entity.type !== 'way' || entity.isClosed()) {
|
||||
return false; // exit early, can't straighten these
|
||||
}
|
||||
|
||||
nodes = nodes.concat(entity.nodes);
|
||||
@@ -44,23 +39,26 @@ export function operationStraighten(selectedIDs, context) {
|
||||
}
|
||||
|
||||
// Remove duplicate end/startNodes (duplicate nodes cannot be at the line end)
|
||||
startNodes = _filter(startNodes, function(n) {
|
||||
startNodes = startNodes.filter(function(n) {
|
||||
return startNodes.indexOf(n) === startNodes.lastIndexOf(n);
|
||||
});
|
||||
endNodes = _filter(endNodes, function(n) {
|
||||
endNodes = endNodes.filter(function(n) {
|
||||
return 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;
|
||||
if (_uniq(nodes).length <= 2) return false;
|
||||
|
||||
// Return false unless exactly 0 or 2 specific start/end nodes are selected
|
||||
if (!(selectedNodes.length === 0 || selectedNodes.length === 2)) 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]) ||
|
||||
!_includes(nodes, selectedNodes[1]))) return false;
|
||||
// Ensure both start/end selected nodes lie on the selected path
|
||||
if (selectedNodes.length === 2 && (
|
||||
nodes.indexOf(selectedNodes[0]) === -1 || nodes.indexOf(selectedNodes[1]) === -1
|
||||
)) return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user