Don't allow autofixing unsquare buildings unless they are already very close to square

Allow autofixing buildings with tags
This commit is contained in:
Quincy Morgan
2019-05-13 16:28:08 -04:00
parent bb4aa84a3b
commit 4eedfa8b25
3 changed files with 35 additions and 4 deletions
+1
View File
@@ -45,4 +45,5 @@ export { geoVecScale } from './vector.js';
export { geoOrthoNormalizedDotProduct } from './ortho.js';
export { geoOrthoCalcScore } from './ortho.js';
export { geoOrthoMaxOffsetAngle } from './ortho.js';
export { geoOrthoCanOrthogonalize } from './ortho.js';
+27
View File
@@ -45,6 +45,33 @@ export function geoOrthoCalcScore(points, isClosed, epsilon, threshold) {
return score;
}
// returns the maximum angle less than `lessThan` between the actual corner and a 0° or 90° corner
export function geoOrthoMaxOffsetAngle(coords, isClosed, lessThan) {
var max = -Infinity;
var first = isClosed ? 0 : 1;
var last = isClosed ? coords.length : coords.length - 1;
for (var i = first; i < last; i++) {
var a = coords[(i - 1 + coords.length) % coords.length];
var origin = coords[i];
var b = coords[(i + 1) % coords.length];
var normalizedDotP = geoOrthoNormalizedDotProduct(a, b, origin);
var angle = Math.acos(Math.abs(normalizedDotP)) * 180 / Math.PI;
if (angle > 45) angle = 90 - angle;
if (angle >= lessThan) continue;
if (angle > max) max = angle;
}
if (max === -Infinity) return null;
return max;
}
// similar to geoOrthoCalcScore, but returns quickly if there is something to do
export function geoOrthoCanOrthogonalize(coords, isClosed, epsilon, threshold, allowStraightAngles) {
+7 -4
View File
@@ -1,7 +1,7 @@
import { t } from '../util/locale';
import { actionChangeTags } from '../actions/change_tags';
import { actionOrthogonalize } from '../actions/orthogonalize';
import { geoOrthoCanOrthogonalize } from '../geo';
import { geoOrthoCanOrthogonalize, geoOrthoMaxOffsetAngle } from '../geo/ortho';
import { utilDisplayLabel } from '../util';
import { validationIssue, validationIssueFix } from '../core/validation';
@@ -9,9 +9,10 @@ import { validationIssue, validationIssueFix } from '../core/validation';
export function validationUnsquareWay() {
var type = 'unsquare_way';
// use looser epsilon for detection to reduce false positives if nearly orthogonal
// 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;
function isBuilding(entity, graph) {
@@ -57,9 +58,10 @@ export function validationUnsquareWay() {
var points = nodes.map(function(node) { return context.projection(node.loc); });
if (!geoOrthoCanOrthogonalize(points, isClosed, epsilon, degreeThreshold, true)) return [];
// only allow autofix if there are no extra tags on the building (e.g. source) - #6288
var autoArgs;
if (Object.keys(entity.tags).length === 1) {
// only allow autofixing features that are very close to square already
var maxOffsetAngle = geoOrthoMaxOffsetAngle(points, isClosed, degreeThreshold);
if (maxOffsetAngle && maxOffsetAngle < autofixDegreeThreshold) {
// note: use default params for actionOrthogonalize, not relaxed epsilon
var autoAction = actionOrthogonalize(entity.id, context.projection);
autoAction.transitionable = false; // when autofixing, do it instantly
@@ -75,6 +77,7 @@ export function validationUnsquareWay() {
},
reference: showReference,
entityIds: [entity.id],
hash: JSON.stringify(autoArgs !== undefined),
fixes: [
new validationIssueFix({
icon: 'iD-operation-orthogonalize',