Use existing nodes where possible in almost junction connection fix

This commit is contained in:
Quincy Morgan
2019-02-06 12:47:12 -05:00
parent 8545ebde8e
commit b25d75a6cc
4 changed files with 57 additions and 19 deletions
+8 -3
View File
@@ -7,7 +7,7 @@ import { geoVecAdd, geoVecScale } from '../geo';
// 1. move all the nodes to a common location
// 2. `actionConnect` them
export function actionMergeNodes(nodeIDs) {
export function actionMergeNodes(nodeIDs, loc) {
// If there is a single "interesting" node, use that as the location.
// Otherwise return the average location of all the nodes.
@@ -31,11 +31,16 @@ export function actionMergeNodes(nodeIDs) {
var action = function(graph) {
if (nodeIDs.length < 2) return graph;
var toLoc = chooseLoc(graph);
var toLoc = loc;
if (!toLoc) {
toLoc = chooseLoc(graph);
}
for (var i = 0; i < nodeIDs.length; i++) {
var node = graph.entity(nodeIDs[i]);
graph = graph.replace(node.move(toLoc));
if (node.loc !== toLoc) {
graph = graph.replace(node.move(toLoc));
}
}
return actionConnect(nodeIDs)(graph);
+20
View File
@@ -66,3 +66,23 @@ export function geoZoomToScale(z, tileSize) {
return tileSize * Math.pow(2, z) / TAU;
}
// returns info about the node from `nodes` closest to the given `point`
export function geoSphericalClosestNode(nodes, point) {
var minDistance = Infinity, distance;
var indexOfMin;
for (var i in nodes) {
distance = geoSphericalDistance(nodes[i].loc, point);
if (distance < minDistance) {
minDistance = distance;
indexOfMin = i;
}
}
if (indexOfMin !== undefined) {
return { index: indexOfMin, distance: minDistance, node: nodes[indexOfMin] };
} else {
return null;
}
}
+1
View File
@@ -7,6 +7,7 @@ export { geoMetersToLon } from './geo.js';
export { geoMetersToOffset } from './geo.js';
export { geoOffsetToMeters } from './geo.js';
export { geoScaleToZoom } from './geo.js';
export { geoSphericalClosestNode } from './geo.js';
export { geoSphericalDistance } from './geo.js';
export { geoZoomToScale } from './geo.js';
+28 -16
View File
@@ -6,14 +6,16 @@ import {
geoMetersToLon,
geoSphericalDistance,
geoVecInterp,
geoHasSelfIntersections
geoHasSelfIntersections,
geoSphericalClosestNode
} from '../geo';
import {
utilDisplayLabel
} from '../util';
import {
actionAddMidpoint,
actionChangeTags
actionChangeTags,
actionMergeNodes
} from '../actions';
import { t } from '../util/locale';
import {
@@ -135,20 +137,30 @@ export function validationAlmostJunction() {
extendableNodeInfos.forEach(function(extendableNodeInfo) {
var node = extendableNodeInfo.node;
var edgeHighway = graph.entity(extendableNodeInfo.wid);
var fixes = [
new validationIssueFix({
title: t('issues.fix.connect_almost_junction.title'),
onClick: function() {
var endNode = this.issue.entities[1],
targetEdge = this.issue.info.edge,
crossLoc = this.issue.info.cross_loc;
context.perform(
actionAddMidpoint({loc: crossLoc, edge: targetEdge}, endNode),
t('issues.fix.connect_almost_junction.undo_redo')
);
}
})
];
var fixes = [new validationIssueFix({
title: t('issues.fix.connect_almost_junction.title'),
onClick: function() {
var endNode = this.issue.entities[1],
edgeWay = this.issue.entities[2],
crossLoc = this.issue.info.cross_loc;
var edgeWayNodes = context.graph().childNodes(edgeWay);
var closestNodeInfo = geoSphericalClosestNode(edgeWayNodes, crossLoc);
// if there is already a point nearby, just connect to that
if (closestNodeInfo.distance < 0.8) {
context.perform(
actionMergeNodes([closestNodeInfo.node.id, endNode.id], closestNodeInfo.node.loc),
t('issues.fix.connect_almost_junction.undo_redo')
);
// else add the end node to the edge way
} else {
var targetEdge = this.issue.info.edge;
context.perform(
actionAddMidpoint({loc: crossLoc, edge: targetEdge}, endNode),
t('issues.fix.connect_almost_junction.undo_redo')
);
}
}
})];
if (Object.keys(node.tags).length === 0) {
// node has no tags, suggest noexit fix
fixes.push(new validationIssueFix({