001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.validation.tests; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.util.List; 007 008import org.openstreetmap.josm.data.osm.Node; 009import org.openstreetmap.josm.data.osm.Way; 010import org.openstreetmap.josm.data.validation.Severity; 011import org.openstreetmap.josm.data.validation.Test; 012import org.openstreetmap.josm.data.validation.TestError; 013import org.openstreetmap.josm.gui.progress.ProgressMonitor; 014import org.openstreetmap.josm.spi.preferences.Config; 015import org.openstreetmap.josm.tools.Pair; 016 017/** 018 * Checks for buildings with angles close to right angle. 019 * 020 * @author marxin 021 * @since 13670 022 */ 023public class RightAngleBuildingTest extends Test { 024 025 /** Maximum angle difference from right angle that is considered as invalid. */ 026 protected double maxAngleDelta; 027 028 /** Minimum angle difference from right angle that is considered as invalid. */ 029 protected double minAngleDelta; 030 031 /** 032 * Constructs a new {@code RightAngleBuildingTest} test. 033 */ 034 public RightAngleBuildingTest() { 035 super(tr("Almost right angle buildings"), 036 tr("Checks for buildings that have angles close to right angle and are not orthogonalized.")); 037 } 038 039 @Override 040 public void visit(Way w) { 041 if (!w.isUsable() || !w.isClosed() || !isBuilding(w) || !IN_DOWNLOADED_AREA_STRICT.test(w)) return; 042 043 List<Pair<Double, Node>> angles = w.getAngles(); 044 for (Pair<Double, Node> pair: angles) { 045 if (checkAngle(pair.a)) { 046 TestError.Builder builder = TestError.builder(this, Severity.OTHER, 3701) 047 .message(tr("Building with an almost square angle")) 048 .primitives(w) 049 .highlight(pair.b); 050 errors.add(builder.build()); 051 return; 052 } 053 } 054 } 055 056 @Override 057 public void startTest(ProgressMonitor monitor) { 058 super.startTest(monitor); 059 maxAngleDelta = Config.getPref().getDouble("validator.RightAngleBuilding.maximumDelta", 10.0); 060 minAngleDelta = Config.getPref().getDouble("validator.RightAngleBuilding.minimumDelta", 1.0); 061 } 062 063 private boolean checkAngle(double angle) { 064 double difference = Math.abs(angle - 90); 065 return difference > minAngleDelta && difference < maxAngleDelta; 066 } 067}