Merge pull request #6267 from gaoxm/dupeNodeValidation

add validation for very close node on road
This commit is contained in:
Bryan Housel
2019-04-29 23:52:49 -04:00
committed by GitHub
5 changed files with 112 additions and 15 deletions
+7
View File
@@ -1403,6 +1403,11 @@ en:
unknown_road:
message: "{feature} has no classification"
reference: "Roads without a specific type may not appear in maps or routing."
dupe_node_on_road:
title: Very close nodes on road
message: "Very close nodes on road"
ref_merge: "Nodes are less than 2 meters away; you may want to merge them."
ref_move_away: "Nodes are less than 2 meters away but not mergable; you may want to move them further apart."
impossible_oneway:
title: Impossible One-Ways
tip: "Find route issues with one-way features"
@@ -1491,6 +1496,8 @@ en:
title: Use different levels
use_tunnel:
title: Use a tunnel
merge_nodes:
title: Merge these nodes
intro:
done: done
ok: OK
+9 -14
View File
@@ -1737,6 +1737,12 @@
"message": "{feature} has no classification",
"reference": "Roads without a specific type may not appear in maps or routing."
},
"dupe_node_on_road": {
"title": "Very close nodes on road",
"message": "Very close nodes on road",
"ref_merge": "Nodes are less than 2 meters away; you may want to merge them.",
"ref_move_away": "Nodes are less than 2 meters away but not mergable; you may want to move them further apart."
},
"impossible_oneway": {
"title": "Impossible One-Ways",
"tip": "Find route issues with one-way features",
@@ -1863,6 +1869,9 @@
},
"use_tunnel": {
"title": "Use a tunnel"
},
"merge_nodes": {
"title": "Merge these nodes"
}
}
},
@@ -9092,20 +9101,6 @@
"description": "Japan GSI ortho Imagery. Usually better than bing, but a bit older.",
"name": "Japan GSI ortho Imagery"
},
"gsi.go.jp_airphoto": {
"attribution": {
"text": "GSI Japan"
},
"description": "Japan GSI airphoto Imagery. Not fully orthorectified, but a bit newer and/or differently covered than GSI ortho Imagery.",
"name": "Japan GSI airphoto Imagery"
},
"gsi.go.jp_seamlessphoto": {
"attribution": {
"text": "GSI Japan seamless photo"
},
"description": "Japan GSI seamlessphoto Imagery. The collection of latest imageries of GSI ortho, airphoto, post disaster and others.",
"name": "Japan GSI seamlessphoto Imagery"
},
"gsi.go.jp_std_map": {
"attribution": {
"text": "GSI Japan"
+3 -1
View File
@@ -52,8 +52,10 @@ export function uiInspector(context) {
var hasNonGeometryTags = entity.hasNonGeometryTags();
var isTaglessOrIntersectionVertex = entity.geometry(context.graph()) === 'vertex' &&
(!hasNonGeometryTags && !entity.isHighwayIntersection(context.graph()));
var issues = context.validator().getEntityIssues(_entityID);
// start with the preset list if the feature is new and untagged or is an uninteresting vertex
var showPresetList = (newFeature && !hasNonGeometryTags) || isTaglessOrIntersectionVertex;
var showPresetList = issues.length === 0 &&
((newFeature && !hasNonGeometryTags) || isTaglessOrIntersectionVertex);
if (showPresetList) {
wrap.style('right', '-100%');
+92
View File
@@ -0,0 +1,92 @@
import { operationMerge } from '../operations/index';
import { t } from '../util/locale';
import { validationIssue, validationIssueFix } from '../core/validation';
import { geoExtent } from '../geo';
export function validationDupeNodeOnRoad() {
var type = 'dupe_node_on_road';
function isNodeOnRoad(node, context) {
var parentWays = context.graph().parentWays(node);
for (var i = 0; i < parentWays.length; i++) {
if (parentWays[i].tags.highway) {
return true;
}
}
return false;
}
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;
}
var validation = function(entity, context) {
if (entity.type !== 'node' || !isNodeOnRoad(entity, context)) 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(
new validationIssueFix({
icon: 'iD-icon-plus',
title: t('issues.fix.merge_nodes.title'),
onClick: function() {
var entities = this.issue.entities,
operation = operationMerge([entities[0].id, entities[1].id], context);
if (!operation.disabled()) {
operation();
}
}
})
);
}
return [new validationIssue({
type: type,
severity: 'warning',
message: t('issues.dupe_node_on_road.message'),
reference: showReference,
entities: [entity, dupe],
fixes: fixes
})];
function showReference(selection) {
var referenceText = mergable
? t('issues.dupe_node_on_road.ref_merge')
: t('issues.dupe_node_on_road.ref_move_away');
selection.selectAll('.issue-reference')
.data([0])
.enter()
.append('div')
.attr('class', 'issue-reference')
.text(referenceText);
}
};
validation.type = type;
return validation;
}
+1
View File
@@ -1,6 +1,7 @@
export { validationAlmostJunction } from './almost_junction';
export { validationCrossingWays } from './crossing_ways';
export { validationDisconnectedWay } from './disconnected_way';
export { validationDupeNodeOnRoad } from './dupe_node_on_road';
export { validationFixmeTag } from './fixme_tag';
export { validationGenericName } from './generic_name';
export { validationImpossibleOneway } from './impossible_oneway';