Changeset 12312 in josm


Ignore:
Timestamp:
2017-06-04T18:39:14+02:00 (3 months ago)
Author:
Don-vip
Message:

fix #14891 - improve roundabout/links validator test

Location:
trunk
Files:
2 added
2 edited

Legend:

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

    r12031 r12312  
    1313import java.util.Map;
    1414import java.util.Set;
     15import java.util.stream.Collectors;
    1516
    1617import org.openstreetmap.josm.command.ChangePropertyCommand;
     
    108109    private void testWrongRoundabout(Way w) {
    109110        Map<String, List<Way>> map = new HashMap<>();
    110         // Count all highways (per type) connected to this roundabout, except links
     111        // Count all highways (per type) connected to this roundabout, except correct links
    111112        // As roundabouts are closed ways, take care of not processing the first/last node twice
    112113        for (Node n : new HashSet<>(w.getNodes())) {
    113114            for (Way h : Utils.filteredCollection(n.getReferrers(), Way.class)) {
    114115                String value = h.get(HIGHWAY);
    115                 if (h != w && value != null && !value.endsWith("_link")) {
    116                     List<Way> list = map.get(value);
    117                     if (list == null) {
    118                         list = new ArrayList<>();
    119                         map.put(value, list);
    120                     }
    121                     list.add(h);
     116                if (h != w && value != null) {
     117                    boolean link = value.endsWith("_link");
     118                    boolean linkOk = isHighwayLinkOkay(h);
     119                    if (link && !linkOk) {
     120                        // "Autofix" bad link value to avoid false positive in roundabout check
     121                        value = value.replaceAll("_link$", "");
     122                    }
     123                    if (!link || !linkOk) {
     124                        List<Way> list = map.get(value);
     125                        if (list == null) {
     126                            list = new ArrayList<>();
     127                            map.put(value, list);
     128                        }
     129                        list.add(h);
     130                    }
    122131                }
    123132            }
     
    146155    }
    147156
     157    /**
     158     * Determines if the given link road is correct, see https://wiki.openstreetmap.org/wiki/Highway_link.
     159     * @param way link road
     160     * @return {@code true} if the link road is correct or if the check cannot be performed due to missing data
     161     */
    148162    public static boolean isHighwayLinkOkay(final Way way) {
    149163        final String highway = way.get(HIGHWAY);
     
    165179        }
    166180
    167         return Utils.filteredCollection(referrers, Way.class).stream().anyMatch(
    168                 otherWay -> !way.equals(otherWay) && otherWay.hasTag(HIGHWAY, highway, highway.replaceAll("_link$", "")));
     181        // Find ways of same class (exact class of class_link)
     182        List<Way> sameClass = Utils.filteredCollection(referrers, Way.class).stream().filter(
     183                otherWay -> !way.equals(otherWay) && otherWay.hasTag(HIGHWAY, highway, highway.replaceAll("_link$", "")))
     184                .collect(Collectors.toList());
     185        if (sameClass.size() > 1) {
     186            // It is possible to have a class_link between 2 segments of same class
     187            // in roundabout designs that physically separate a specific turn from the main roundabout
     188            // But if we have more than a single adjacent class, and one of them is a roundabout, that's an error
     189            for (Way w : sameClass) {
     190                if (w.hasTag("junction", "roundabout")) {
     191                    return false;
     192                }
     193            }
     194        }
     195        // Link roads should always at least one adjacent segment of same class
     196        return !sameClass.isEmpty();
    169197    }
    170198
  • trunk/test/unit/org/openstreetmap/josm/data/validation/tests/HighwaysTest.java

    r11403 r12312  
    55import static org.junit.Assert.assertFalse;
    66import static org.junit.Assert.assertTrue;
     7import static org.junit.Assert.fail;
     8
     9import java.io.InputStream;
     10import java.util.Collection;
    711
    812import org.junit.Before;
    913import org.junit.Test;
    1014import org.openstreetmap.josm.JOSMFixture;
     15import org.openstreetmap.josm.TestUtils;
    1116import org.openstreetmap.josm.data.coor.LatLon;
    1217import org.openstreetmap.josm.data.osm.DataSet;
     
    1419import org.openstreetmap.josm.data.osm.Way;
    1520import org.openstreetmap.josm.data.validation.TestError;
     21import org.openstreetmap.josm.io.OsmReader;
    1622
    1723/**
     
    96102        assertEquals("GB:nsl_single", link.get("source:maxspeed"));
    97103    }
     104
     105    /**
     106     * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/14891">Bug #14891</a>.
     107     * @throws Exception if an error occurs
     108     */
     109    @Test
     110    public void testTicket14891() throws Exception {
     111        try (InputStream is = TestUtils.getRegressionDataStream(14891, "14891.osm.bz2")) {
     112            Collection<Way> ways = OsmReader.parseDataSet(is, null).getWays();
     113            Way roundabout = ways.stream().filter(w -> 10068083 == w.getId()).findFirst().get();
     114            Highways test = new Highways();
     115            test.visit(roundabout);
     116            if (!test.getErrors().isEmpty()) {
     117                fail(test.getErrors().get(0).getMessage());
     118            }
     119            Way w1 = ways.stream().filter(w -> 28508494 == w.getId()).findFirst().get();
     120            Way w2 = ways.stream().filter(w -> 28508493 == w.getId()).findFirst().get();
     121            test.visit(w1);
     122            test.visit(w2);
     123            assertEquals(2, test.getErrors().size());
     124        }
     125    }
    98126}
Note: See TracChangeset for help on using the changeset viewer.