Ticket #9304: 9304-v2.patch

File 9304-v2.patch, 3.1 KB (added by GerdP, 2 years ago)

improved patch

  • 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        for (Entry<String, List<Way>> entry : layerCount.entrySet()) {
     324            if ("0".equals(entry.getKey()))
     325                continue;
     326            if (checkLayer(connection, entry.getValue())) {
     327                errors.add(TestError.builder(this, Severity.WARNING, DIFFERENT_LAYERS)
     328                        .message(tr("Node connects highways on different layers"))
     329                        .primitives(connection)
     330                        .build());
     331                return;
     332            }
     333        }
     334    }
     335
     336    /**
     337     * Check if there are at least two neighbouring nodes on the given ways.
     338     * If so, the connection node can be considered to be at a specific layer, else it marks the end of such a layer
     339     * @param connection the connection node
     340     * @param ways the ways with the same layer attribute connected to that node
     341     * @return true if the node can be considered to be at a specific layer
     342     */
     343    private static boolean checkLayer(Node connection, List<Way> ways) {
     344        int count = 0;
     345        for (Way w : ways) {
     346            if (!w.isFirstLastNode(connection))
     347                return true; // connection node has two neighbouring nodes
     348            count++;
     349        }
     350        return count > 1;
     351    }
    301352}