Ignore:
Timestamp:
2017-05-02T01:29:35+02:00 (7 years ago)
Author:
michael2402
Message:

See #14708: For long segment test, notify the user about the exact segment. Do not check segments that have not been touched.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/validation/tests/LongSegment.java

    r12032 r12037  
    55import static org.openstreetmap.josm.tools.I18n.tr;
    66
     7import java.util.Collections;
    78import java.util.HashSet;
    89import java.util.Set;
    910
    1011import org.openstreetmap.josm.Main;
     12import org.openstreetmap.josm.data.coor.LatLon;
    1113import org.openstreetmap.josm.data.osm.Node;
    1214import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1315import org.openstreetmap.josm.data.osm.Way;
     16import org.openstreetmap.josm.data.osm.WaySegment;
    1417import org.openstreetmap.josm.data.validation.Severity;
    1518import org.openstreetmap.josm.data.validation.Test;
     
    2831    /** Maximum segment length for this test */
    2932    protected int maxlength;
    30     /** set of visited ways */
    31     private final Set<Way> visitedWays = new HashSet<>();
     33    /** set of visited ways. Tracking this increases performance when checking single nodes. */
     34    private Set<Way> visitedWays;
     35
     36    /** set of way segments that have been reported */
     37    protected Set<WaySegment> reported;
    3238
    3339    /**
     
    4147    @Override
    4248    public void visit(Node n) {
    43         for (Way w : n.getParentWays()) {
    44             if (isPrimitiveUsable(w)) {
    45                 testWay(w);
     49        // Test all way segments around this node.
     50        // If there is an error in the unchanged part of the way, we do not need to warn the user about it.
     51        for (Way way : n.getParentWays()) {
     52                if (ignoreWay(way)) {
     53                    continue;
     54                }
     55                // Do not simply use index of - a node may be in a way multiple times
     56                for (int i = 0; i < way.getNodesCount(); i++) {
     57                    if (n == way.getNode(i)) {
     58                        if (i > 0) {
     59                            visitWaySegment(way, i - 1);
     60                        }
     61                        if (i < way.getNodesCount() - 1) {
     62                            visitWaySegment(way, i);
     63                        }
     64                    }
     65                }
     66            }
     67    }
     68
     69    @Override
     70    public void visit(Way w) {
     71        if (ignoreWay(w)) {
     72            return;
     73        }
     74        visitedWays.add(w);
     75
     76        testWay(w);
     77    }
     78
     79    private void testWay(Way w) {
     80        for (int i = 0; i < w.getNodesCount() - 1; i++) {
     81            visitWaySegment(w, i);
     82        }
     83    }
     84
     85    private boolean ignoreWay(Way w) {
     86        return visitedWays.contains(w) || w.hasTag("route", "ferry");
     87    }
     88
     89    private void visitWaySegment(Way w, int i) {
     90        LatLon coor1 = w.getNode(i).getCoor();
     91        LatLon coor2 = w.getNode(i + 1).getCoor();
     92
     93        if (coor1 != null && coor2 != null) {
     94            Double length = coor1.greatCircleDistance(coor2);
     95            if (length > maxlength) {
     96                addErrorForSegment(new WaySegment(w, i), length / 1000.0);
    4697            }
    4798        }
    4899    }
    49100
    50     @Override
    51     public void visit(Way w) {
    52         testWay(w);
    53     }
    54 
    55     private void testWay(Way w) {
    56         if (visitedWays.contains(w) || w.hasTag("route", "ferry")) {
    57             return;
    58         }
    59         visitedWays.add(w);
    60         Double length = w.getLongestSegmentLength();
    61         if (length > maxlength) {
    62             length /= 1000.0;
     101    private void addErrorForSegment(WaySegment waySegment, Double length) {
     102        if (reported.add(waySegment)) {
    63103            errors.add(TestError.builder(this, Severity.WARNING, LONG_SEGMENT)
    64104                    .message(tr("Long segments"), marktr("Very long segment of {0} kilometers"), length.intValue())
    65                     .primitives(w)
     105                    .primitives(waySegment.way)
     106                    .highlightWaySegments(Collections.singleton(waySegment))
    66107                    .build());
    67108        }
     
    72113        super.startTest(monitor);
    73114        maxlength = Main.pref.getInteger("validator.maximum.segment.length", 15_000);
    74         visitedWays.clear();
     115        reported = new HashSet<>();
     116        visitedWays = new HashSet<>();
    75117    }
    76118
    77119    @Override
    78120    public void endTest() {
    79         visitedWays.clear();
    80121        super.endTest();
     122        // free memory
     123        visitedWays = null;
     124        reported = null;
    81125    }
    82126
    83127    @Override
    84128    public boolean isPrimitiveUsable(OsmPrimitive p) {
    85         // test only nodes and Ways with at least 2 nodes
    86         return p.isUsable() && ((p instanceof Node && p.isDrawable()) || (p instanceof Way && ((Way) p).getNodesCount() > 1));
     129        if (!p.isUsable()) {
     130            return false;
     131        } else if (p instanceof Way && ((Way) p).getNodesCount() > 1) {
     132            // test only Ways with at least 2 nodes
     133            return true;
     134        } else if (p instanceof Node && p.isDrawable()) {
     135            // test all nodes - ways referred by them may not be checked automatically.
     136            return true;
     137        } else {
     138            return false;
     139        }
    87140    }
    88141}
Note: See TracChangeset for help on using the changeset viewer.