mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-25 01:24:05 +02:00
Reduce very close nodes validation threshold (close #6292)
Use spherical distances for very close nodes validation Don't flag very close nodes from different ways Don't flag very close nodes if both have interesting tags Update very close nodes validation reference string
This commit is contained in:
@@ -284,9 +284,12 @@ export function coreValidator(context) {
|
||||
|
||||
var entityIDsToCheck = entityIDs.reduce(function(acc, entityID) {
|
||||
if (acc.has(entityID)) return acc;
|
||||
|
||||
var entity = graph.hasEntity(entityID);
|
||||
if (!entity) return acc;
|
||||
|
||||
acc.add(entityID);
|
||||
|
||||
var entity = graph.entity(entityID);
|
||||
var checkParentRels = [entity];
|
||||
|
||||
if (entity.type === 'node') { // include parent ways
|
||||
|
||||
@@ -3,86 +3,75 @@ import { utilDisplayLabel } from '../util';
|
||||
import { t } from '../util/locale';
|
||||
import { validationIssue, validationIssueFix } from '../core/validation';
|
||||
import { osmRoutableHighwayTagValues } from '../osm/tags';
|
||||
import { geoExtent } from '../geo';
|
||||
import { geoExtent, geoSphericalDistance } from '../geo';
|
||||
|
||||
|
||||
export function validationCloseNodes() {
|
||||
var type = 'close_nodes';
|
||||
|
||||
var thresholdMeters = 0.2;
|
||||
|
||||
function getVeryCloseNodeIssues(node, context) {
|
||||
|
||||
var issues = [];
|
||||
|
||||
function checkForCloseness(node1, node2, way) {
|
||||
if (node1.id !== node2.id &&
|
||||
!(node1.hasInterestingTags() && node2.hasInterestingTags()) &&
|
||||
geoSphericalDistance(node1.loc, node2.loc) < thresholdMeters) {
|
||||
|
||||
issues.push(makeIssue(node1, node2, way, context));
|
||||
}
|
||||
}
|
||||
|
||||
function isNodeOnRoad(node, context) {
|
||||
var parentWays = context.graph().parentWays(node);
|
||||
|
||||
for (var i = 0; i < parentWays.length; i++) {
|
||||
var parentWay = parentWays[i];
|
||||
if (osmRoutableHighwayTagValues[parentWay.tags.highway]) {
|
||||
return parentWay;
|
||||
|
||||
if (!parentWay.tags.highway || !osmRoutableHighwayTagValues[parentWay.tags.highway]) continue;
|
||||
|
||||
var lastIndex = parentWay.nodes.length - 1;
|
||||
for (var j in parentWay.nodes) {
|
||||
if (j !== 0) {
|
||||
if (parentWay.nodes[j-1] === node.id) {
|
||||
checkForCloseness(node, context.entity(parentWay.nodes[j]), parentWay);
|
||||
}
|
||||
}
|
||||
if (j !== lastIndex) {
|
||||
if (parentWay.nodes[j+1] === node.id) {
|
||||
checkForCloseness(context.entity(parentWay.nodes[j]), node, parentWay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
function findDupeNode(node, context) {
|
||||
var epsilon = 2e-5,
|
||||
extent = geoExtent([
|
||||
[node.loc[0] - epsilon, node.loc[1] - epsilon],
|
||||
[node.loc[0] + epsilon, node.loc[1] + epsilon]
|
||||
]);
|
||||
var filteredEnts = context.intersects(extent);
|
||||
for (var i = 0; i < filteredEnts.length; i++) {
|
||||
var entity = filteredEnts[i];
|
||||
if (entity.type === 'node' && entity.id !== node.id &&
|
||||
Math.abs(node.loc[0] - entity.loc[0]) < epsilon &&
|
||||
Math.abs(node.loc[1] - entity.loc[1]) < epsilon &&
|
||||
isNodeOnRoad(entity, context) ) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function makeIssue(node1, node2, way, context) {
|
||||
|
||||
|
||||
var validation = function(entity, context) {
|
||||
|
||||
if (entity.type !== 'node') return [];
|
||||
|
||||
var road = isNodeOnRoad(entity, context);
|
||||
if (!road) return [];
|
||||
|
||||
var dupe = findDupeNode(entity, context);
|
||||
if (dupe === null) return [];
|
||||
|
||||
var mergable = !operationMerge([entity.id, dupe.id], context).disabled();
|
||||
var fixes = [];
|
||||
if (mergable) {
|
||||
fixes.push(
|
||||
return new validationIssue({
|
||||
type: type,
|
||||
severity: 'warning',
|
||||
message: t('issues.close_nodes.message', { way: utilDisplayLabel(way, context) }),
|
||||
reference: showReference,
|
||||
entityIds: [node1.id, node2.id],
|
||||
fixes: [
|
||||
new validationIssueFix({
|
||||
icon: 'iD-icon-plus',
|
||||
title: t('issues.fix.merge_points.title'),
|
||||
onClick: function() {
|
||||
var entityIds = this.issue.entityIds,
|
||||
operation = operationMerge([entityIds[0], entityIds[1]], context);
|
||||
if (!operation.disabled()) {
|
||||
operation();
|
||||
}
|
||||
operation();
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return [new validationIssue({
|
||||
type: type,
|
||||
severity: 'warning',
|
||||
message: t('issues.close_nodes.message', { way: utilDisplayLabel(road, context) }),
|
||||
reference: showReference,
|
||||
entityIds: [entity.id, dupe.id],
|
||||
fixes: fixes
|
||||
})];
|
||||
|
||||
]
|
||||
});
|
||||
|
||||
function showReference(selection) {
|
||||
var referenceText = mergable
|
||||
? t('issues.close_nodes.ref_merge')
|
||||
: t('issues.close_nodes.ref_move_away');
|
||||
var referenceText = t('issues.close_nodes.reference');
|
||||
selection.selectAll('.issue-reference')
|
||||
.data([0])
|
||||
.enter()
|
||||
@@ -90,6 +79,14 @@ export function validationCloseNodes() {
|
||||
.attr('class', 'issue-reference')
|
||||
.text(referenceText);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var validation = function(entity, context) {
|
||||
|
||||
if (entity.type !== 'node') return [];
|
||||
|
||||
return getVeryCloseNodeIssues(entity, context);
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user