Allow user to adjust the threshold for the unsquare building warning

This commit is contained in:
Bryan Housel
2019-05-18 15:44:29 -04:00
parent 03dd95e00f
commit 511f8ecc82
5 changed files with 136 additions and 13 deletions
+8
View File
@@ -3397,6 +3397,14 @@ button.autofix.action.active {
color: #05ac10;
}
input.square-degrees-input {
padding: 2px;
height: unset;
text-align: center;
background: rgba(0,0,0,0);
color: currentColor;
}
/* Entity Issues List */
.entity-issues .issue-container .issue {
+53 -2
View File
@@ -1,6 +1,7 @@
import { dispatch as d3_dispatch } from 'd3-dispatch';
import { coreDifference } from './difference';
import { geoExtent } from '../geo/extent';
import { modeSelect } from '../modes/select';
import { utilArrayGroupBy, utilRebind } from '../util';
import { t } from '../util/locale';
@@ -69,6 +70,56 @@ export function coreValidator(context) {
dispatch.call('validated');
};
// when the user changes the squaring thereshold, rerun this on all buildings
validator.changeSquareThreshold = function() {
var checkUnsquareWay = _rules.unsquare_way;
if (typeof checkUnsquareWay !== 'function') return;
// uncache existing
Object.values(_issuesByIssueID)
.filter(function(issue) { return issue.type === 'unsquare_way'; })
.forEach(function(issue) {
var entityId = issue.entityIds[0]; // always 1 entity for unsquare way
if (_issuesByEntityID[entityId]) {
_issuesByEntityID[entityId].delete(issue.id);
}
delete _issuesByIssueID[issue.id];
});
var buildings = context.intersects(geoExtent([-180,-90],[180, 90])) // everywhere
.filter(function(entity) {
return entity.type === 'way' && entity.tags.building && entity.tags.building !== 'no';
});
// rerun for all buildings
buildings.forEach(function(entity) {
var detected = checkUnsquareWay(entity, context);
if (detected.length !== 1) return;
var issue = detected[0];
var ignoreFix = new validationIssueFix({
title: t('issues.fix.ignore_issue.title'),
icon: 'iD-icon-close',
onClick: function() {
ignoreIssue(this.issue.id);
}
});
ignoreFix.type = 'ignore';
ignoreFix.issue = issue;
issue.fixes.push(ignoreFix);
if (!_issuesByEntityID[entity.id]) {
_issuesByEntityID[entity.id] = new Set();
}
_issuesByEntityID[entity.id].add(issue.id);
_issuesByIssueID[issue.id] = issue;
});
dispatch.call('validated');
};
// options = {
// what: 'all', // 'all' or 'edited'
// where: 'all', // 'all' or 'visible'
@@ -89,13 +140,13 @@ export function coreValidator(context) {
if (!opts.includeIgnored && _ignoredIssueIDs[issue.id]) return false;
// Sanity check: This issue may be for an entity that not longer exists.
// If we detect this, uncache and return false so it is not incluced..
// If we detect this, uncache and return false so it is not included..
var entityIds = issue.entityIds || [];
for (var i = 0; i < entityIds.length; i++) {
var entityId = entityIds[i];
if (!context.hasEntity(entityId)) {
delete _issuesByEntityID[entityId];
delete _issuesByIssueID[entityId];
delete _issuesByIssueID[issue.id];
return false;
}
}
+63 -7
View File
@@ -10,11 +10,16 @@ import { geoSphericalDistance } from '../geo';
import { svgIcon } from '../svg/icon';
import { uiDisclosure } from './disclosure';
import { uiTooltipHtml } from './tooltipHtml';
import { utilHighlightEntities } from '../util';
import { utilGetSetValue, utilHighlightEntities, utilNoAuto } from '../util';
export function uiIssues(context) {
var key = t('issues.key');
var MINSQUARE = 0;
var MAXSQUARE = 20;
var DEFAULTSQUARE = 6.5; // see also unsquare_way.js
var _errorsSelection = d3_select(null);
var _warningsSelection = d3_select(null);
var _rulesList = d3_select(null);
@@ -564,10 +569,10 @@ export function uiIssues(context) {
label
.append('span')
.text(function(d) {
.html(function(d) {
var params = {};
if (d === 'unsquare_way') {
params.val = 6.5;
params.val = '<span class="square-degrees"></span>';
}
return t('issues.' + d + '.title', params);
});
@@ -581,19 +586,70 @@ export function uiIssues(context) {
.selectAll('input')
.property('checked', active)
.property('indeterminate', false);
// user-configurable square threshold
var degStr = context.storage('validate-square-degrees');
if (degStr === null) {
degStr = '' + DEFAULTSQUARE;
}
var span = items.selectAll('.square-degrees');
var input = span.selectAll('.square-degrees-input')
.data([0]);
// enter / update
input.enter()
.append('input')
.attr('type', 'number')
.attr('min', '' + MINSQUARE)
.attr('max', '' + MAXSQUARE)
.attr('step', '0.5')
.attr('class', 'square-degrees-input')
.call(utilNoAuto)
.on('input', function() {
this.style.width = (this.value.length + 1) + 'ch'; // resize
})
.on('blur', changeSquare)
.merge(input)
.property('value', degStr)
.style('width', (degStr.length + 1) + 'ch'); // resize
}
function changeSquare() {
var input = d3_select(this);
var degStr = utilGetSetValue(input).trim();
var degNum = parseFloat(degStr, 10);
if (!isFinite(degNum) || degNum > MAXSQUARE || degNum < MINSQUARE) {
degNum = DEFAULTSQUARE;
}
degNum = Math.round(degNum * 10 ) / 10; // round to 1 decimal
degStr = '' + degNum;
input
.property('value', degStr)
.style('width', (degStr.length + 1) + 'ch'); // resize
context.storage('validate-square-degrees', degStr);
context.validator().changeSquareThreshold(degNum);
}
function hidePane() {
context.ui().togglePanes();
}
var paneTooltip = tooltip()
.placement((textDirection === 'rtl') ? 'right' : 'left')
.html(true)
.title(uiTooltipHtml(t('issues.title'), key));
function hidePane() {
context.ui().togglePanes();
}
uiIssues.togglePane = function() {
if (d3_event) d3_event.preventDefault();
+11 -3
View File
@@ -8,16 +8,17 @@ import { validationIssue, validationIssueFix } from '../core/validation';
export function validationUnsquareWay() {
var type = 'unsquare_way';
var DEFAULTSQUARE = 6.5; // see also issues.js
// use looser epsilon for detection to reduce warnings of buildings that are essentially square already
var epsilon = 0.05;
var degreeThreshold = 13;
var autofixDegreeThreshold = 6.5;
var nodeThreshold = 10;
// var degreeThreshold = 13;
// var autofixDegreeThreshold = 6.5;
function isBuilding(entity, graph) {
if (entity.type !== 'way' || entity.geometry(graph) !== 'area') return false;
return entity.tags.building && entity.tags.building !== 'no';
}
@@ -55,6 +56,13 @@ export function validationUnsquareWay() {
if (hasConnectedSquarableWays) return [];
// testing: user-configurable square threshold
var degreeThreshold = context.storage('validate-square-degrees');
if (degreeThreshold === null) {
degreeThreshold = '' + DEFAULTSQUARE;
}
var autofixDegreeThreshold = degreeThreshold;
var points = nodes.map(function(node) { return context.projection(node.loc); });
if (!geoOrthoCanOrthogonalize(points, isClosed, epsilon, degreeThreshold, true)) return [];
+1 -1
View File
@@ -1,4 +1,4 @@
describe('iD.validations.validator', function () {
describe('iD.coreValidator', function () {
var context;
beforeEach(function() {