Ticket #20019: 20019.2.patch

File 20019.2.patch, 4.6 KB (added by GerdP, 4 months ago)
  • src/org/openstreetmap/josm/data/validation/OsmValidator.java

     
    4444import org.openstreetmap.josm.data.validation.tests.ConditionalKeys;
    4545import org.openstreetmap.josm.data.validation.tests.ConnectivityRelations;
    4646import org.openstreetmap.josm.data.validation.tests.CrossingWays;
     47import org.openstreetmap.josm.data.validation.tests.DirectionNodes;
    4748import org.openstreetmap.josm.data.validation.tests.DuplicateNode;
    4849import org.openstreetmap.josm.data.validation.tests.DuplicateRelation;
    4950import org.openstreetmap.josm.data.validation.tests.DuplicateWay;
     
    151152        RightAngleBuildingTest.class, // 3700 .. 3799
    152153        SharpAngles.class, // 3800 .. 3899
    153154        ConnectivityRelations.class, // 3900 .. 3999
     155        DirectionNodes.class, // 4000-4099
    154156    };
    155157
    156158    /**
  • src/org/openstreetmap/josm/data/validation/tests/DirectionNodes.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.List;
     8import java.util.Map.Entry;
     9import java.util.regex.Pattern;
     10
     11import org.openstreetmap.josm.data.osm.Node;
     12import org.openstreetmap.josm.data.osm.OsmPrimitive;
     13import org.openstreetmap.josm.data.osm.Way;
     14import org.openstreetmap.josm.data.validation.Severity;
     15import org.openstreetmap.josm.data.validation.Test;
     16import org.openstreetmap.josm.data.validation.TestError;
     17
     18/**
     19 * Find nodes with direction tag and invalid number of parent ways or position in way. See #20019.
     20 * @author Gerd Petermann
     21 * @since xxx
     22 */
     23public class DirectionNodes extends Test {
     24    private static final int MULLTIPLE_WAYS_CODE = 4000;
     25    private static final int END_NODE_CODE = 4001;
     26    private static final int NO_WAY_CODE = 4002;
     27
     28    private static final Pattern KEY_PATTERN = Pattern.compile(".*[:]?direction");
     29
     30    /**
     31     * Construct a new {@code DirectionNodes} object
     32     */
     33    public DirectionNodes() {
     34        super(tr("Direction nodes"), tr("Check for nodes which have a direction"));
     35    }
     36
     37    @Override
     38    public void visit(Node n) {
     39        if (!n.isUsable() || !n.isTagged())
     40            return;
     41        for (Entry<String, String> tag : n.getKeys().entrySet()) {
     42            if (("forward".equals(tag.getValue()) || "backward".equals(tag.getValue()))
     43                    && KEY_PATTERN.matcher(tag.getKey()).matches()) {
     44                checkParents(n, tag.toString());
     45            }
     46        }
     47    }
     48
     49    private static boolean isSuitableParentWay(Way w) {
     50        return w.hasKey("highway", "railway", "waterway") || w.hasTag("man_made", "pipeline");
     51    }
     52
     53    private void checkParents(Node n, String tag) {
     54        final List<Way> ways = new ArrayList<>();
     55        for (Way w : n.getParentWays()) {
     56            if (isSuitableParentWay(w)) {
     57                ways.add(w);
     58            }
     59        }
     60        boolean needsParentWays = n.isNew() || (!n.isOutsideDownloadArea() && n.getDataSet().getDataSourceArea() != null);
     61
     62        if (ways.isEmpty() && needsParentWays) {
     63            errors.add(TestError.builder(this, Severity.WARNING, NO_WAY_CODE)
     64                    .primitives(n)
     65                    .message(tr("Unconnected node with {0}", tag)).build());
     66        } else if (ways.size() == 1) {
     67            Way w = ways.get(0);
     68            if (w.firstNode() == n || w.lastNode() == n) {
     69                errors.add(TestError.builder(this, Severity.WARNING, END_NODE_CODE)
     70                        .primitives(n, w)
     71                        .highlight(n)
     72                        .message(tr("Node with {0} on end of way", tag)).build());
     73            }
     74        } else if (ways.size() > 1) {
     75            List<OsmPrimitive> primitives = new ArrayList<>();
     76            primitives.add(n);
     77            primitives.addAll(ways);
     78            errors.add(TestError.builder(this, Severity.WARNING, MULLTIPLE_WAYS_CODE)
     79                    .primitives(primitives)
     80                    .highlight(n)
     81                    .message(tr("Node with {0} on a connection of multiple ways", tag)).build());
     82        }
     83    }
     84}