001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.validation.tests;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.util.HashSet;
007import java.util.Set;
008
009import org.openstreetmap.josm.data.osm.Node;
010import org.openstreetmap.josm.data.osm.Way;
011import org.openstreetmap.josm.data.validation.Severity;
012import org.openstreetmap.josm.data.validation.Test;
013import org.openstreetmap.josm.data.validation.TestError;
014
015/**
016 * Checks for self-intersecting ways.
017 */
018public class SelfIntersectingWay extends Test {
019
020    protected static final int SELF_INTERSECT = 401;
021
022    /**
023     * Constructs a new {@code SelfIntersectingWay} test.
024     */
025    public SelfIntersectingWay() {
026        super(tr("Self-intersecting ways"),
027                tr("This test checks for ways " +
028                        "that contain some of their nodes more than once."));
029    }
030
031    @Override
032    public void visit(Way w) {
033        Set<Node> nodes = new HashSet<>();
034        for (int i = 1; i < w.getNodesCount() - 1; i++) {
035            Node n = w.getNode(i);
036            if (nodes.contains(n)) {
037                errors.add(TestError.builder(this, Severity.WARNING, SELF_INTERSECT)
038                        .message(tr("Self-intersecting ways"))
039                        .primitives(w)
040                        .highlight(n)
041                        .build());
042                break;
043            } else {
044                nodes.add(n);
045            }
046        }
047    }
048}