Ticket #9304: 9304.patch

File 9304.patch, 3.2 KB (added by GerdP, 3 months ago)

first implementation which checks only highways and ignores ways with highway=steps, creates a warning for the connection node with the text tr("Node connects highways on different layers")

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

     
    1111import java.util.List;
    1212import java.util.Locale;
    1313import java.util.Map;
     14import java.util.Map.Entry;
    1415import java.util.Set;
    1516import java.util.stream.Collectors;
    1617
     
    3839    protected static final int SOURCE_MAXSPEED_CONTEXT_MISMATCH_VS_MAXSPEED = 2705;
    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";
    4345
     
    9092                // as maxspeed is not set on highways here but on signs, speed cameras, etc.
    9193                testSourceMaxspeed(n, false);
    9294            }
     95            if (n.isReferredByWays(2)) {
     96                testDifferentLayers(n);
     97            }
    9398        }
    9499    }
    95100
     
    298303            }
    299304        }
    300305    }
     306
     307    private void testDifferentLayers(Node connection) {
     308        List<Way> ways = connection.getParentWays();
     309        ways.removeIf(w -> !w.hasTag("highway") || w.hasTag("highway", "steps"));
     310        if (ways.size() < 2 || ways.stream().noneMatch(w -> w.hasKey("layer")))
     311            return;
     312        // check if connection has ways with different layers
     313        Map<String, List<Way>> layerCount = new HashMap<>();
     314        for (Way w : ways) {
     315            String layer = w.get("layer");
     316            if (layer == null)
     317                layer = "0";
     318            layerCount.computeIfAbsent(layer, k-> new ArrayList<>()).add(w);
     319        }
     320        if (layerCount.size() == 1)
     321            return; // all on the same layer
     322
     323        int confirmedLayers = 0;
     324        for (Entry<String, List<Way>> entry : layerCount.entrySet()) {
     325            if (checkLayer(connection, entry.getValue()))
     326                confirmedLayers++;
     327            if (confirmedLayers > 1) {
     328                errors.add(TestError.builder(this, Severity.WARNING, DIFFERENT_LAYERS)
     329                        .message(tr("Node connects highways on different layers"))
     330                        .primitives(connection)
     331                        .build());
     332                break;
     333            }
     334        }
     335    }
     336
     337    /**
     338     * Check if there are at least two neighbouring nodes on the given ways.
     339     * If so, the connection node can be considered to be at a specific layer, else it marks the end of such a layer
     340     * @param connection the connection node
     341     * @param ways the ways with the same layer attribute connected to that node
     342     * @return true if the node can be considered to be at a specific layer
     343     */
     344    private static boolean checkLayer(Node connection, List<Way> ways) {
     345        int count = 0;
     346        for (Way w : ways) {
     347            if (!w.isFirstLastNode(connection))
     348                return true; // connection node has two neighbouring nodes
     349            count++;
     350        }
     351        return count > 1;
     352    }
    301353}