Ignore:
Timestamp:
2013-10-06T20:27:55+02:00 (11 years ago)
Author:
Don-vip
Message:

fix #9141 - new validator test: detect nodes with missing highway=crossing

File:
1 edited

Legend:

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

    r6240 r6303  
    1414import org.openstreetmap.josm.command.Command;
    1515import org.openstreetmap.josm.data.osm.Node;
     16import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1617import org.openstreetmap.josm.data.osm.OsmUtils;
    1718import org.openstreetmap.josm.data.osm.Way;
     
    2829
    2930    protected static final int WRONG_ROUNDABOUT_HIGHWAY = 2701;
     31    protected static final int MISSING_PEDESTRIAN_CROSSING = 2702;
    3032   
    3133    protected static final List<String> CLASSIFIED_HIGHWAYS = Arrays.asList(
    3234            "motorway", "trunk", "primary", "secondary", "tertiary", "living_street", "residential", "unclassified");
    3335
     36    boolean leftByPedestrians = false;
     37    boolean leftByCyclists = false;
     38    boolean leftByCars = false;
     39    int pedestrianWays = 0;
     40    int cyclistWays = 0;
     41    int carsWays = 0;
     42   
    3443    /**
    3544     * Constructs a new {@code Highways} test.
     
    3847        super(tr("Highways"), tr("Performs semantic checks on highways."));
    3948    }
    40    
     49
    4150    protected class WrongRoundaboutHighway extends TestError {
    4251
     
    5261   
    5362    @Override
     63    public void visit(Node n) {
     64        if (n.isUsable() && !n.hasTag("highway", "crossing") && !n.hasTag("crossing", "no") && n.isReferredByWays(2)) {
     65            testMissingPedestrianCrossing(n);
     66        }
     67    }
     68
     69    @Override
    5470    public void visit(Way w) {
    5571        if (w.isUsable() && w.hasKey("highway") && w.hasKey("junction") && w.get("junction").equals("roundabout")) {
    56             Map<String, List<Way>> map = new HashMap<String, List<Way>>();
    57             // Count all highways (per type) connected to this roundabout
    58             // As roundabouts are closed ways, take care of not processing the first/last node twice
    59             for (Node n : new HashSet<Node>(w.getNodes())) {
    60                 for (Way h : Utils.filteredCollection(n.getReferrers(), Way.class)) {
    61                     if (h != w && h.hasKey("highway")) {
    62                         List<Way> list = map.get(h.get("highway"));
    63                         if (list == null) {
    64                             map.put(h.get("highway"), list = new ArrayList<Way>());
    65                         }
    66                         list.add(h);
     72            testWrongRoundabout(w);
     73        }
     74    }
     75
     76    private void testWrongRoundabout(Way w) {
     77        Map<String, List<Way>> map = new HashMap<String, List<Way>>();
     78        // Count all highways (per type) connected to this roundabout
     79        // As roundabouts are closed ways, take care of not processing the first/last node twice
     80        for (Node n : new HashSet<Node>(w.getNodes())) {
     81            for (Way h : Utils.filteredCollection(n.getReferrers(), Way.class)) {
     82                if (h != w && h.hasKey("highway")) {
     83                    List<Way> list = map.get(h.get("highway"));
     84                    if (list == null) {
     85                        map.put(h.get("highway"), list = new ArrayList<Way>());
    6786                    }
     87                    list.add(h);
    6888                }
    6989            }
    70             // The roundabout should carry the highway tag of its two biggest highways
    71             for (String s : CLASSIFIED_HIGHWAYS) {
    72                 List<Way> list = map.get(s);
    73                 if (list != null && list.size() >= 2) {
    74                     // Except when a single road is connected, but with two oneway segments
    75                     Boolean oneway1 = OsmUtils.getOsmBoolean(list.get(0).get("oneway"));
    76                     Boolean oneway2 = OsmUtils.getOsmBoolean(list.get(1).get("oneway"));
    77                     if (list.size() > 2 || oneway1 == null || oneway2 == null || !oneway1 || !oneway2) {
    78                         // Error when the highway tags do not match
    79                         if (!w.get("highway").equals(s)) {
    80                             errors.add(new TestError(this, Severity.WARNING,
    81                                     tr("Incorrect roundabout (highway: {0} instead of {1})", w.get("highway"), s),
    82                                     WRONG_ROUNDABOUT_HIGHWAY, w));
    83                         }
    84                         break;
     90        }
     91        // The roundabout should carry the highway tag of its two biggest highways
     92        for (String s : CLASSIFIED_HIGHWAYS) {
     93            List<Way> list = map.get(s);
     94            if (list != null && list.size() >= 2) {
     95                // Except when a single road is connected, but with two oneway segments
     96                Boolean oneway1 = OsmUtils.getOsmBoolean(list.get(0).get("oneway"));
     97                Boolean oneway2 = OsmUtils.getOsmBoolean(list.get(1).get("oneway"));
     98                if (list.size() > 2 || oneway1 == null || oneway2 == null || !oneway1 || !oneway2) {
     99                    // Error when the highway tags do not match
     100                    if (!w.get("highway").equals(s)) {
     101                        errors.add(new WrongRoundaboutHighway(w, tr("Incorrect roundabout (highway: {0} instead of {1})", w.get("highway"), s)));
    85102                    }
     103                    break;
    86104                }
    87105            }
     106        }
     107    }
     108   
     109    private void testMissingPedestrianCrossing(Node n) {
     110        leftByPedestrians = false;
     111        leftByCyclists = false;
     112        leftByCars = false;
     113        pedestrianWays = 0;
     114        cyclistWays = 0;
     115        carsWays = 0;
     116       
     117        for (Way w : OsmPrimitive.getFilteredList(n.getReferrers(), Way.class)) {
     118            String highway = w.get("highway");
     119            if (highway != null) {
     120                if (highway.equals("footway") || highway.equals("path")) {
     121                    handlePedestrianWay(n, w);
     122                    if (w.hasTag("bicycle", "yes", "designated")) {
     123                        handleCyclistWay(n, w);
     124                    }
     125                } else if (highway.equals("cycleway")) {
     126                    handleCyclistWay(n, w);
     127                    if (w.hasTag("foot", "yes", "designated")) {
     128                        handlePedestrianWay(n, w);
     129                    }
     130                } else if (CLASSIFIED_HIGHWAYS.contains(highway) || highway.equals("service") || highway.equals("road")) {
     131                    handleCarWay(n, w);
     132                }
     133                if ((leftByPedestrians || leftByCyclists) && leftByCars) {
     134                    errors.add(new TestError(this, Severity.WARNING, tr("Missing crossing information"), MISSING_PEDESTRIAN_CROSSING, n));
     135                    return;
     136                }
     137            }
     138        }
     139    }
     140
     141    private void handleCarWay(Node n, Way w) {
     142        carsWays++;
     143        if (!w.isFirstLastNode(n) || carsWays > 1) {
     144            leftByCars = true;
     145        }
     146    }
     147
     148    private void handleCyclistWay(Node n, Way w) {
     149        cyclistWays++;
     150        if (!w.isFirstLastNode(n) || cyclistWays > 1) {
     151            leftByCyclists = true;
     152        }
     153    }
     154
     155    private void handlePedestrianWay(Node n, Way w) {
     156        pedestrianWays++;
     157        if (!w.isFirstLastNode(n) || pedestrianWays > 1) {
     158            leftByPedestrians = true;
    88159        }
    89160    }
Note: See TracChangeset for help on using the changeset viewer.