Ticket #16998: 16998.patch

File 16998.patch, 4.7 KB (added by GerdP, 6 years ago)

roundabout: check number of connected highways

  • src/org/openstreetmap/josm/data/validation/tests/Highways.java

     
    3838    protected static final int SOURCE_MAXSPEED_CONTEXT_MISMATCH_VS_MAXSPEED = 2705;
    3939    protected static final int SOURCE_MAXSPEED_CONTEXT_MISMATCH_VS_HIGHWAY = 2706;
    4040    protected static final int SOURCE_WRONG_LINK = 2707;
     41    protected static final int ROUNDABOUT_CONNECTIONS_COUNT = 2708;
    4142
    4243    protected static final String SOURCE_MAXSPEED = "source:maxspeed";
    4344
     
    6869    private int pedestrianWays;
    6970    private int cyclistWays;
    7071    private int carsWays;
     72    private final Set<Node> connectionNodesComplained = new HashSet<>();
    7173
    7274    /**
    7375     * Constructs a new {@code Highways} test.
     
    7779    }
    7880
    7981    @Override
     82    public void initialize() throws Exception {
     83        super.initialize();
     84        connectionNodesComplained.clear();
     85    }
     86
     87    @Override
     88    public void endTest() {
     89        connectionNodesComplained.clear();
     90        super.endTest();
     91    }
     92
     93    @Override
    8094    public void visit(Node n) {
    8195        if (n.isUsable()) {
    8296            if (!n.hasTag("crossing", "no")
     
    96110    @Override
    97111    public void visit(Way w) {
    98112        if (w.isUsable()) {
    99             if (w.isClosed() && w.hasTag(HIGHWAY, CLASSIFIED_HIGHWAYS) && w.hasTag("junction", "circular", "roundabout")
    100                     && IN_DOWNLOADED_AREA_STRICT.test(w)) {
    101                 // TODO: find out how to handle splitted roundabouts (see #12841)
    102                 testWrongRoundabout(w);
     113            if (isRoundabout(w) && w.hasTag(HIGHWAY, CLASSIFIED_HIGHWAYS) && IN_DOWNLOADED_AREA_STRICT.test(w)) {
     114                if (w.isClosed()) {
     115                    // TODO: find out how to handle split roundabouts (see #12841)
     116                    testWrongRoundabout(w);
     117                }
     118                testRoundaboutConnections(w, connectionNodesComplained);
    103119            }
    104120            if (w.hasKey(SOURCE_MAXSPEED)) {
    105121                // Check maxspeed, including context against highway
     
    109125        }
    110126    }
    111127
     128    /**
     129     * Find nodes in roundabout with more than one connected highway
     130     * @param w
     131     * @param complained
     132     */
     133    private void testRoundaboutConnections(Way w, Set<Node> complained) {
     134        List<OsmPrimitive> primitives = new ArrayList<>();
     135        for (Node n : w.getNodes()) {
     136            if (complained.contains(n))
     137                continue;
     138            int countConnectedArcs = 0;
     139            primitives.clear();
     140            for (Way p : n.getParentWays()) {
     141                if (p == w || !p.isUsable() || isRoundabout(p) || !p.hasTag(HIGHWAY, CLASSIFIED_HIGHWAYS))
     142                    continue;
     143
     144                primitives.add(p);
     145                if (!p.isFirstLastNode(n)) {
     146                    errors.add(TestError.builder(this, Severity.WARNING, ROUNDABOUT_CONNECTIONS_COUNT)
     147                            .message(tr("Highway doesn't start or end at roundabout"))
     148                            .primitives(Arrays.asList(p,w,n))
     149                            .highlight(n)
     150                            .build());
     151                    complained.add(n);
     152                }
     153                countConnectedArcs++;
     154            }
     155            if (countConnectedArcs > 1) {
     156                primitives.add(w);
     157                primitives.add(n);
     158                errors.add(TestError.builder(this, Severity.WARNING, ROUNDABOUT_CONNECTIONS_COUNT)
     159                        .message(tr("Multiple highways connected in one node of a roundabout"))
     160                        .primitives(new ArrayList<>(primitives))
     161                        .highlight(n)
     162                        .build());
     163                complained.add(n);
     164            }
     165        }
     166    }
     167
     168    private static boolean isRoundabout(Way w) {
     169        return w.hasTag("junction", "circular", "roundabout");
     170    }
     171
    112172    private void testWrongRoundabout(Way w) {
    113173        Map<String, List<Way>> map = new HashMap<>();
    114174        // Count all highways (per type) connected to this roundabout, except correct links
     
    190250            // in roundabout designs that physically separate a specific turn from the main roundabout
    191251            // But if we have more than a single adjacent class, and one of them is a roundabout, that's an error
    192252            for (Way w : sameClass) {
    193                 if (w.hasTag("junction", "circular", "roundabout")) {
     253                if (isRoundabout(w)) {
    194254                    return false;
    195255                }
    196256            }