Ticket #24851: 24851-powerlines-v2.patch

File 24851-powerlines-v2.patch, 5.3 KB (added by GerdP, 4 days ago)

improved patch

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

     
    1111import java.util.EnumSet;
    1212import java.util.HashMap;
    1313import java.util.HashSet;
     14import java.util.LinkedHashSet;
    1415import java.util.List;
    1516import java.util.Map;
     17import java.util.Map.Entry;
    1618import java.util.Set;
     19import java.util.stream.Collectors;
    1720
    1821import org.openstreetmap.josm.data.coor.ILatLon;
    1922import org.openstreetmap.josm.data.osm.Node;
     
    7578
    7679    private double hillyCompensation;
    7780    private double hillyThreshold;
    78     private final Set<Node> badConnections = new HashSet<>();
    79     private final Set<Node> missingTags = new HashSet<>();
     81    private final Map<Node, Set<OsmPrimitive>> badConnections = new HashMap<>();
     82    private final Map<Node, Set<OsmPrimitive>> missingTags = new HashMap<>();
    8083    private final Set<Way> wrongLineType = new HashSet<>();
    8184    private final Set<WaySegment> missingNodes = new HashSet<>();
    8285    private final Set<OsmPrimitive> refDiscontinuities = new HashSet<>();
     
    98101
    99102    @Override
    100103    public void visit(Node n) {
    101         boolean nodeInLineOrCable = false;
    102         boolean connectedToUnrelated = false;
    103         for (Way parent : n.getParentWays()) {
    104             if (parent.hasTag(POWER, "line", MINOR_LINE, "cable"))
    105                 nodeInLineOrCable = true;
    106             else if (!isRelatedToPower(parent))
    107                 connectedToUnrelated = true;
     104        if (!n.isConnectionNode() || n.referrers(Way.class).noneMatch(w -> isPowerLineOrCable(w)))
     105            return;
     106
     107        List<Way> unrelatedParents = n.referrers(Way.class).filter(w -> !isPowerLineOrCable(w) && !isRelatedToPower(w))
     108                .collect(Collectors.toList());
     109        if (!unrelatedParents.isEmpty()) {
     110            Set<OsmPrimitive> set = badConnections.computeIfAbsent(n, k -> new HashSet<>());
     111            set.addAll(unrelatedParents);
    108112        }
    109         if (nodeInLineOrCable && connectedToUnrelated)
    110             badConnections.add(n);
    111113    }
    112114
    113115    @Override
     
    162164            powerlineChecks(w);
    163165        }
    164166        // Then return the errors
    165         for (Node n : missingTags) {
     167        for (Entry<Node, Set<OsmPrimitive>> entry : missingTags.entrySet()) {
     168            Node n = entry.getKey();
    166169            if (!isInPowerStation(n)) {
    167170                errors.add(TestError.builder(this, Severity.WARNING, POWER_SUPPORT)
    168171                        // the "missing tag" grouping can become broken if the MapCSS message get reworded
    169172                        .message(tr("missing tag"), tr("node without power=*"))
    170                         .primitives(n)
     173                        .primitives(getAllPrimitives(entry))
     174                        .highlight(n)
    171175                        .build());
    172176            }
    173177        }
    174178
    175         for (Node n : badConnections) {
     179        for (Entry<Node, Set<OsmPrimitive>> entry : badConnections.entrySet()) {
    176180            errors.add(TestError.builder(this, Severity.WARNING, POWER_CONNECTION)
    177181                    .message(tr("Node connects a power line or cable with an object "
    178182                            + "which is not related to the power infrastructure"))
    179                     .primitives(n)
     183                    .primitives(getAllPrimitives(entry))
     184                    .highlight(entry.getKey())
    180185                    .build());
    181186        }
    182187
     
    224229    }
    225230
    226231    /**
     232     * Combine the node and the related objects.
     233     * @param entry a map entry with a node and related objects
     234     * @return set containing the node and the related objects
     235     */
     236    private Collection<? extends OsmPrimitive> getAllPrimitives(Entry<Node, Set<OsmPrimitive>> entry) {
     237        Set<OsmPrimitive> primitives = new LinkedHashSet<>();
     238        primitives.add(entry.getKey());
     239        primitives.addAll(entry.getValue());
     240        return primitives;
     241    }
     242
     243    /**
    227244     * The base powerline checks
    228245     * @param w The powerline to check
    229246     */
     
    253270
    254271            /// handle missing power line support tags (e.g. tower)
    255272            if (!isPowerTower(n) && !isPowerInfrastructure(n) && IN_DOWNLOADED_AREA.test(n)
    256                     && (!w.isFirstLastNode(n) || !isPowerStation(n)))
    257                 missingTags.add(n);
     273                    && (!w.isFirstLastNode(n) || !isPowerStation(n))) {
     274                Set<OsmPrimitive> set = missingTags.computeIfAbsent(n, k -> new HashSet<>());
     275                set.add(w);
     276            }
    258277
    259278            /// handle missing nodes
    260279            double segmentLen = n.greatCircleDistance(prevNode);
     
    669688    }
    670689
    671690    /**
     691     * Determines if the specified way denotes a power line or cable.
     692     * @param w The way to be tested
     693     * @return {@code true} if power key is set and equal to line,minor_line or cable
     694     */
     695    protected static boolean isPowerLineOrCable(Way w) {
     696        return isPowerIn(w, Arrays.asList("line", MINOR_LINE, "cable"));
     697    }
     698
     699    /**
    672700     * Determines if the specified primitive denotes a power station.
    673701     * @param p The primitive to be tested
    674702     * @return {@code true} if power key is set and equal to generator/substation/plant