Ticket #18127: 18112.10.patch

File 18112.10.patch, 13.0 KB (added by GerdP, 5 years ago)

remove debug code

  • src/org/openstreetmap/josm/data/validation/OsmValidator.java

     
    6161import org.openstreetmap.josm.data.validation.tests.RelationChecker;
    6262import org.openstreetmap.josm.data.validation.tests.RightAngleBuildingTest;
    6363import org.openstreetmap.josm.data.validation.tests.SelfIntersectingWay;
     64import org.openstreetmap.josm.data.validation.tests.SharpAngles;
    6465import org.openstreetmap.josm.data.validation.tests.SimilarNamedWays;
    6566import org.openstreetmap.josm.data.validation.tests.TagChecker;
    6667import org.openstreetmap.josm.data.validation.tests.TurnrestrictionTest;
     
    148149        LongSegment.class, // 3500 .. 3599
    149150        PublicTransportRouteTest.class, // 3600 .. 3699
    150151        RightAngleBuildingTest.class, // 3700 .. 3799
     152        SharpAngles.class, // 3800 .. 3899
    151153    };
    152154
    153155    /**
  • src/org/openstreetmap/josm/data/validation/tests/SharpAngles.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.validation.tests;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
     6import java.util.ArrayList;
     7import java.util.Arrays;
     8import java.util.Collection;
     9import java.util.LinkedHashMap;
     10import java.util.Map;
     11import java.util.Map.Entry;
     12import java.util.TreeSet;
     13
     14import org.openstreetmap.josm.data.coor.EastNorth;
     15import org.openstreetmap.josm.data.osm.Node;
     16import org.openstreetmap.josm.data.osm.OsmPrimitive;
     17import org.openstreetmap.josm.data.osm.Way;
     18import org.openstreetmap.josm.data.osm.WaySegment;
     19import org.openstreetmap.josm.data.validation.Severity;
     20import org.openstreetmap.josm.data.validation.Test;
     21import org.openstreetmap.josm.data.validation.TestError;
     22import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     23import org.openstreetmap.josm.tools.Geometry;
     24import org.openstreetmap.josm.tools.Logging;
     25
     26/**
     27 * Find highways that have sharp angles
     28 * @author Taylor Smock
     29 * @since xxx
     30 */
     31public class SharpAngles extends Test {
     32    private static final int SHARPANGLESCODE = 3800;
     33    /** The code for a sharp angle */
     34    private static final int SHARP_ANGLES = SHARPANGLESCODE + 0;
     35    /** The maximum angle for sharp angles */
     36    private double maxAngle = 45.0; // degrees
     37    /** The length that at least one way segment must be shorter than */
     38    private double maxLength = 10.0; // meters
     39    /** The stepping points for severity */
     40    private Map<Double, Severity> severityBreakPoints = new LinkedHashMap<>();
     41    /** Specific highway types to ignore */
     42    private Collection<String> ignoreHighways = new TreeSet<>(
     43            Arrays.asList("platform", "rest_area", "services", "via_ferrata"));
     44    ArrayList<Way> allWays;
     45
     46    /**
     47     * Construct a new {@code IntersectionIssues} object
     48     */
     49    public SharpAngles() {
     50        super(tr("Sharp angles"), tr("Check for sharp angles on roads"));
     51        setBreakPoints();
     52    }
     53
     54    @Override
     55    public void startTest(ProgressMonitor monitor) {
     56        super.startTest(monitor);
     57        allWays = new ArrayList<>();
     58    }
     59
     60    @Override
     61    public void endTest() {
     62        Way pWay = null;
     63        try {
     64            for (Way way : allWays) {
     65                pWay = way;
     66                checkWayForSharpAngles(way);
     67            }
     68        } catch (Exception e) {
     69            if (pWay != null) {
     70                Logging.debug("Way https://osm.org/way/{0} caused an error ({1})", pWay.getOsmId(), e);
     71            }
     72            Logging.warn(e);
     73        }
     74        allWays = null;
     75        super.endTest();
     76    }
     77
     78    @Override
     79    public void visit(Way way) {
     80        if (!way.isUsable()) return;
     81        if (way.hasKey("highway") && !way.hasTag("area", "yes") &&
     82                    !ignoreHighways.contains(way.get("highway"))) {
     83            allWays.add(way);
     84        }
     85    }
     86
     87    /**
     88     * Check nodes in a way for sharp angles
     89     * @param way A way to check for sharp angles
     90     */
     91    public void checkWayForSharpAngles(Way way) {
     92        Node node1 = null;
     93        Node node2 = null;
     94        Node node3 = null;
     95        int i = -2;
     96        for (Node node : way.getNodes()) {
     97            node1 = node2;
     98            node2 = node3;
     99            node3 = node;
     100            checkAngle(node1, node2, node3, i, way, false);
     101            i++;
     102        }
     103        if (way.isClosed() && way.getNodesCount() > 2) {
     104            node1 = node2;
     105            node2 = node3;
     106            // Get the second node, not the first node, since a closed way has first node == last node
     107            node3 = way.getNode(1);
     108            checkAngle(node1, node2, node3, i, way, true);
     109        }
     110    }
     111
     112    private void checkAngle(Node node1, Node node2, Node node3, int i, Way way, boolean last) {
     113        if (node1 == null || node2 == null || node3 == null) return;
     114        EastNorth n1 = node1.getEastNorth();
     115        EastNorth n2 = node2.getEastNorth();
     116        EastNorth n3 = node3.getEastNorth();
     117        double angle = Math.toDegrees(Math.abs(Geometry.getCornerAngle(n1, n2, n3)));
     118        if (angle < maxAngle) {
     119            processSharpAngleForErrorCreation(angle, i, way, last, node2);
     120        }
     121    }
     122
     123    private void processSharpAngleForErrorCreation(double angle, int i, Way way, boolean last, Node pointNode) {
     124        WaySegment ws1 = new WaySegment(way, i);
     125        WaySegment ws2 = new WaySegment(way, last ? 0 : i + 1);
     126        double shorterLen = Math.min(ws1.toWay().getLength(), ws2.toWay().getLength());
     127        if (shorterLen < maxLength) {
     128            createNearlyOverlappingError(angle, way, pointNode);
     129        }
     130    }
     131
     132    private void createNearlyOverlappingError(double angle, Way way, OsmPrimitive primitive) {
     133        TestError.Builder testError = TestError.builder(this, getSeverity(angle), SHARP_ANGLES)
     134                .primitives(way)
     135                .highlight(primitive)
     136                .message(tr("Sharp angle"));
     137        errors.add(testError.build());
     138    }
     139
     140    private Severity getSeverity(double angle) {
     141        Severity rSeverity = Severity.OTHER;
     142        for (Entry<Double, Severity> entry : severityBreakPoints.entrySet()) {
     143            if (angle < entry.getKey()) {
     144                rSeverity = entry.getValue();
     145            }
     146        }
     147        return rSeverity;
     148    }
     149
     150    /**
     151     * Set the maximum length for the shortest segment
     152     * @param length The max length in meters
     153     */
     154    public void setMaxLength(double length) {
     155        maxLength = length;
     156    }
     157
     158    /**
     159     * Add a highway to ignore
     160     * @param highway The highway type to ignore (e.g., if you want to ignore residential roads, use "residential")
     161     */
     162    public void addIgnoredHighway(String highway) {
     163        ignoreHighways.add(highway);
     164    }
     165
     166    /**
     167     * Set the maximum angle
     168     * @param angle The maximum angle in degrees.
     169     */
     170    public void setMaxAngle(double angle) {
     171        maxAngle = angle;
     172        setBreakPoints();
     173    }
     174
     175    /**
     176     * Set the breakpoints for the test
     177     */
     178    private void setBreakPoints() {
     179        severityBreakPoints.clear();
     180        severityBreakPoints.put(maxAngle, Severity.OTHER);
     181        severityBreakPoints.put(maxAngle * 2 / 3, Severity.WARNING);
     182        severityBreakPoints.put(maxAngle / 3, Severity.ERROR);
     183    }
     184}
  • test/unit/org/openstreetmap/josm/data/validation/tests/SharpAnglesTest.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.validation.tests;
     3
     4import org.junit.Assert;
     5import org.junit.Before;
     6import org.junit.Test;
     7import org.openstreetmap.josm.JOSMFixture;
     8import org.openstreetmap.josm.TestUtils;
     9import org.openstreetmap.josm.data.coor.LatLon;
     10import org.openstreetmap.josm.data.osm.Node;
     11import org.openstreetmap.josm.data.osm.Way;
     12
     13/**
     14 * JUnit Test of the Sharp Angles validation test.
     15 */
     16
     17public class SharpAnglesTest {
     18    private SharpAngles angles;
     19
     20    /**
     21     * Setup test.
     22     * @throws Exception if an error occurs
     23     */
     24    @Before
     25    public void setUp() throws Exception {
     26        JOSMFixture.createUnitTestFixture().init();
     27        angles = new SharpAngles();
     28        angles.initialize();
     29        angles.startTest(null);
     30    }
     31
     32    /**
     33     * Check a closed loop with no sharp angles
     34     */
     35    @Test
     36    public void closedLoopNoSharpAngles() {
     37        Way way = TestUtils.newWay("highway=residential",
     38                new Node(new LatLon(0, 0)), new Node(new LatLon(0.1, 0.1)),
     39                new Node(new LatLon(0.1, -0.2)), new Node(new LatLon(-0.1, -0.1)));
     40        way.addNode(way.firstNode());
     41        angles.visit(way);
     42        angles.endTest();
     43        Assert.assertEquals(0, angles.getErrors().size());
     44    }
     45
     46    /**
     47     * Check a closed loop with a sharp angle
     48     */
     49    @Test
     50    public void closedLoopSharpAngles() {
     51        Way way = TestUtils.newWay("highway=residential",
     52                new Node(new LatLon(0, 0)), new Node(new LatLon(0.1, 0.1)),
     53                new Node(new LatLon(0.1, -0.2)));
     54        way.addNode(way.firstNode());
     55        angles.setMaxLength(Double.MAX_VALUE);
     56        angles.visit(way);
     57        angles.endTest();
     58        Assert.assertEquals(1, angles.getErrors().size());
     59    }
     60
     61    /**
     62     * Check a way for multiple sharp angles
     63     */
     64    @Test
     65    public void testMultipleSharpAngles() {
     66        Way way = TestUtils.newWay("highway=residential",
     67                new Node(new LatLon(0.005069377713748322, -0.0014832642674429382)),
     68                new Node(new LatLon(0.005021097951663415, 0.0008636686205880686)),
     69                new Node(new LatLon(0.005085470967776624, -0.00013411313295197088)),
     70                new Node(new LatLon(0.005031826787678042, 0.0020116540789620915)));
     71        angles.setMaxLength(Double.MAX_VALUE);
     72        angles.visit(way);
     73        angles.endTest();
     74        Assert.assertEquals(2, angles.getErrors().size());
     75    }
     76
     77    /**
     78     * Check for no sharp angles
     79     */
     80    @Test
     81    public void testNoSharpAngles() {
     82        Way way = TestUtils.newWay("highway=residential",
     83                new Node(new LatLon(0, 0)), new Node(new LatLon(0.1, 0.1)),
     84                new Node(new LatLon(0.2, 0.3)), new Node(new LatLon(0.3, 0.1)));
     85        angles.visit(way);
     86        angles.endTest();
     87        Assert.assertEquals(0, angles.getErrors().size());
     88    }
     89
     90    /**
     91     * Ensure that we aren't accidentally using the same node twice.
     92     * This was found during initial testing. See way 10041221 (on 20190914)
     93     */
     94    @Test
     95    public void testCheckBadAnglesFromSameNodeTwice() {
     96        Way way = TestUtils.newWay("highway=service oneway=yes",
     97                new Node(new LatLon(52.8903308, 8.4302322)),
     98                new Node(new LatLon(52.8902468, 8.4302138)),
     99                new Node(new LatLon(52.8902191, 8.4302282)),
     100                new Node(new LatLon(52.8901155, 8.4304753)),
     101                new Node(new LatLon(52.8900669, 8.430763)),
     102                new Node(new LatLon(52.8901138, 8.4308262)),
     103                new Node(new LatLon(52.8902482, 8.4307568)));
     104        way.addNode(way.firstNode());
     105        angles.visit(way);
     106        angles.endTest();
     107        Assert.assertEquals(0, angles.getErrors().size());
     108    }
     109
     110    /**
     111     * Check that special cases are ignored
     112     */
     113    @Test
     114    public void testIgnoredCases() {
     115        Way way = TestUtils.newWay("highway=residential",
     116                new Node(new LatLon(0, 0)), new Node(new LatLon(0.1, 0.1)),
     117                new Node(new LatLon(0, 0.01)));
     118        angles.setMaxLength(Double.MAX_VALUE);
     119        angles.visit(way);
     120        angles.endTest();
     121        Assert.assertEquals(1, angles.getErrors().size());
     122
     123        way.put("highway", "rest_area");
     124        angles.startTest(null);
     125        angles.visit(way);
     126        angles.endTest();
     127        Assert.assertEquals(0, angles.getErrors().size());
     128
     129        way.put("highway", "residential");
     130        angles.startTest(null);
     131        angles.visit(way);
     132        angles.endTest();
     133        Assert.assertEquals(1, angles.getErrors().size());
     134        way.put("area", "yes");
     135        angles.startTest(null);
     136        angles.visit(way);
     137        angles.endTest();
     138        Assert.assertEquals(0, angles.getErrors().size());
     139        way.put("area", "no");
     140        angles.startTest(null);
     141        angles.visit(way);
     142        angles.endTest();
     143        Assert.assertEquals(1, angles.getErrors().size());
     144    }
     145}