Changeset 19029 in josm for trunk/src/org


Ignore:
Timestamp:
2024-04-04T15:19:33+02:00 (8 months ago)
Author:
GerdP
Message:

fix #9304: in validator, check for intersecting roads in different layers

  • initial implementation of the test
  • functional test with examples, also checks code coverage
File:
1 edited

Legend:

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

    r18801 r19029  
    1212import java.util.Locale;
    1313import java.util.Map;
     14import java.util.Map.Entry;
    1415import java.util.Set;
    1516import java.util.stream.Collectors;
     
    3940    protected static final int SOURCE_MAXSPEED_CONTEXT_MISMATCH_VS_HIGHWAY = 2706;
    4041    protected static final int SOURCE_WRONG_LINK = 2707;
     42    protected static final int DIFFERENT_LAYERS = 2708;
    4143
    4244    protected static final String SOURCE_MAXSPEED = "source:maxspeed";
     
    9092                // as maxspeed is not set on highways here but on signs, speed cameras, etc.
    9193                testSourceMaxspeed(n, false);
     94            }
     95            if (n.isReferredByWays(2)) {
     96                testDifferentLayers(n);
    9297            }
    9398        }
     
    299304        }
    300305    }
     306
     307    /**
     308     * See #9304: Find Highways connected to bridges or tunnels at the wrong place.
     309     * @param connection the connection node of two or more different ways
     310     */
     311    private void testDifferentLayers(Node connection) {
     312        List<Way> ways = connection.getParentWays();
     313        ways.removeIf(w -> !w.hasTag("highway") || w.hasTag("highway", "steps"));
     314        if (ways.size() < 2 || ways.stream().noneMatch(w -> w.hasKey("layer")))
     315            return;
     316        // check if connection has ways with different layers
     317        Map<String, List<Way>> layerCount = new HashMap<>();
     318        for (Way w : ways) {
     319            String layer = w.get("layer");
     320            if (layer == null)
     321                layer = "0";
     322            layerCount.computeIfAbsent(layer, k-> new ArrayList<>()).add(w);
     323        }
     324        if (layerCount.size() == 1)
     325            return; // all on the same layer
     326
     327        for (Entry<String, List<Way>> entry : layerCount.entrySet()) {
     328            if ("0".equals(entry.getKey()))
     329                continue;
     330            if (checkLayer(connection, entry.getValue())) {
     331                errors.add(TestError.builder(this, Severity.WARNING, DIFFERENT_LAYERS)
     332                        .message(tr("Node connects highways on different layers"))
     333                        .primitives(connection)
     334                        .build());
     335                return;
     336            }
     337        }
     338    }
     339
     340    /**
     341     * Check if there are at least two neighbouring nodes on the given ways.
     342     * If so, the connection node can be considered to be at a specific layer, else it marks the end of such a layer
     343     * @param connection the connection node
     344     * @param ways the ways with the same layer attribute connected to that node
     345     * @return true if the node can be considered to be at a specific layer
     346     */
     347    private static boolean checkLayer(Node connection, List<Way> ways) {
     348        int count = 0;
     349        for (Way w : ways) {
     350            if (!w.isFirstLastNode(connection))
     351                return true; // connection node has two neighbouring nodes
     352            count++;
     353        }
     354        return count > 1;
     355    }
    301356}
Note: See TracChangeset for help on using the changeset viewer.