Ticket #5861: 5861.patch

File 5861.patch, 8.9 KB (added by simon04, 10 years ago)
  • src/org/openstreetmap/josm/data/validation/tests/TurnrestrictionTest.java

     
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    66import java.util.ArrayList;
     7import java.util.Arrays;
    78import java.util.Collections;
     9import java.util.List;
    810
    911import org.openstreetmap.josm.data.osm.Node;
    1012import org.openstreetmap.josm.data.osm.OsmPrimitive;
     
    3032    protected static final int TO_VIA_NODE = 1810;
    3133    protected static final int FROM_VIA_WAY = 1811;
    3234    protected static final int TO_VIA_WAY = 1812;
     35    protected static final int MIX_VIA = 1813;
     36    protected static final int UNCONNECTED_VIA = 1814;
    3337
    3438    public TurnrestrictionTest() {
    3539        super(tr("Turnrestriction"), tr("This test checks if turnrestrictions are valid"));
     
    4246
    4347        Way fromWay = null;
    4448        Way toWay = null;
    45         OsmPrimitive via = null;
     49        List<OsmPrimitive> via = new ArrayList<OsmPrimitive>();
    4650
    4751        boolean morefrom = false;
    4852        boolean moreto = false;
    4953        boolean morevia = false;
     54        boolean mixvia = false;
    5055
    5156        /* find the "from", "via" and "to" elements */
    5257        for (RelationMember m : r.getMembers()) {
     
    7580                        toWay = w;
    7681                    }
    7782                } else if ("via".equals(m.getRole())) {
    78                     if (via != null) {
    79                         morevia = true;
     83                    if (!via.isEmpty() && via.get(0) instanceof Node) {
     84                        mixvia = true;
    8085                    } else {
    81                         via = w;
     86                        via.add(w);
    8287                    }
    8388                } else {
    8489                    errors.add(new TestError(this, Severity.WARNING, tr("Unknown role"), UNKNOWN_ROLE,
     
    8792            } else if (m.isNode()) {
    8893                Node n = m.getNode();
    8994                if ("via".equals(m.getRole())) {
    90                     if (via != null) {
    91                         morevia = true;
     95                    if (!via.isEmpty()) {
     96                        if (via.get(0) instanceof Node) {
     97                            morevia = true;
     98                        } else {
     99                            mixvia = true;
     100                        }
    92101                    } else {
    93                         via = n;
     102                        via.add(n);
    94103                    }
    95104                } else {
    96105                    errors.add(new TestError(this, Severity.WARNING, tr("Unknown role"), UNKNOWN_ROLE,
     
    108117            errors.add(new TestError(this, Severity.ERROR, tr("More than one \"to\" way found"), MORE_TO, r));
    109118        }
    110119        if (morevia) {
    111             errors.add(new TestError(this, Severity.ERROR, tr("More than one \"via\" way found"), MORE_VIA, r));
     120            errors.add(new TestError(this, Severity.ERROR, tr("More than one \"via\" node found"), MORE_VIA, r));
    112121        }
     122        if (mixvia) {
     123            errors.add(new TestError(this, Severity.ERROR, tr("Cannot mix node and way for role \"via\""), MIX_VIA, r));
     124        }
    113125
    114126        if (fromWay == null) {
    115127            errors.add(new TestError(this, Severity.ERROR, tr("No \"from\" way found"), NO_FROM, r));
     
    119131            errors.add(new TestError(this, Severity.ERROR, tr("No \"to\" way found"), NO_TO, r));
    120132            return;
    121133        }
    122         if (via == null) {
     134        if (via.isEmpty()) {
    123135            errors.add(new TestError(this, Severity.ERROR, tr("No \"via\" node or way found"), NO_VIA, r));
    124136            return;
    125137        }
    126138
    127139        Node viaNode;
    128         if (via instanceof Node) {
    129             viaNode = (Node) via;
     140        if (via.get(0) instanceof Node) {
     141            viaNode = (Node) via.get(0);
    130142            if (!fromWay.isFirstLastNode(viaNode)) {
    131143                errors.add(new TestError(this, Severity.ERROR,
    132144                        tr("The \"from\" way does not start or end at a \"via\" node"), FROM_VIA_NODE, r));
     
    138150                return;
    139151            }
    140152        } else {
    141             Way viaWay = (Way) via;
    142             Node firstNode = viaWay.firstNode();
    143             Node lastNode = viaWay.lastNode();
    144             Boolean onewayvia = false;
    145 
    146             String onewayviastr = viaWay.get("oneway");
    147             if (onewayviastr != null) {
    148                 if ("-1".equals(onewayviastr)) {
    149                     onewayvia = true;
    150                     Node tmp = firstNode;
    151                     firstNode = lastNode;
    152                     lastNode = tmp;
    153                 } else {
    154                     onewayvia = OsmUtils.getOsmBoolean(onewayviastr);
    155                     if (onewayvia == null) {
    156                         onewayvia = false;
    157                     }
     153            // check if consecutive ways are connected: from/via[0], via[i-1]/via[i], via[last]/to
     154            checkIfConnected(fromWay, (Way) via.get(0),
     155                    tr("The \"from\" and the first \"via\" way are not connected."), FROM_VIA_WAY);
     156            if (via.size() > 1) {
     157                for (int i = 1; i < via.size(); i++) {
     158                    Way previous = (Way) via.get(i - 1);
     159                    Way current = (Way) via.get(i);
     160                    checkIfConnected(previous, current,
     161                            tr("The \"via\" ways are not connected."), UNCONNECTED_VIA);
    158162                }
    159163            }
     164            checkIfConnected((Way) via.get(via.size() - 1), toWay,
     165                    tr("The last \"via\" and the \"to\" way are not connected."), TO_VIA_WAY);
    160166
    161             if (fromWay.isFirstLastNode(firstNode)) {
    162                 viaNode = firstNode;
    163             } else if (!onewayvia && fromWay.isFirstLastNode(lastNode)) {
    164                 viaNode = lastNode;
     167        }
     168    }
     169
     170    private void checkIfConnected(Way previous, Way current, String msg, int code) {
     171        int onewayPrevious = isOneway(previous);
     172        int onewayCurrent = isOneway(current);
     173        Node endPrevious = onewayPrevious != -1 ? previous.lastNode() : previous.firstNode();
     174        Node startCurrent = onewayCurrent != -1 ? current.firstNode() : current.lastNode();
     175        //System.out.println(previous.getUniqueId() + " -- " + current.getUniqueId() + ": " + onewayPrevious + "/" + onewayCurrent + " " + endPrevious.getUniqueId() + "/" + startCurrent.getUniqueId());
     176        boolean c;
     177        if (onewayPrevious != 0 && onewayCurrent != 0) {
     178            // both oneways: end/start node must be equal
     179            c = endPrevious.equals(startCurrent);
     180        } else if (onewayPrevious != 0) {
     181            // previous way is oneway: end of previous must be start/end of current
     182            c = current.isFirstLastNode(endPrevious);
     183        } else if (onewayCurrent != 0) {
     184            // current way is oneway: start of current must be start/end of previous
     185            c = previous.isFirstLastNode(startCurrent);
     186        } else {
     187            // otherwise: start/end of previous must be start/end of current
     188            c = current.isFirstLastNode(previous.firstNode()) || current.isFirstLastNode(previous.lastNode());
     189        }
     190        if (!c) {
     191            errors.add(new TestError(this, Severity.ERROR, msg, code, Arrays.asList(previous, current)));
     192        }
     193    }
     194
     195    private static int isOneway(Way w) {
     196        String onewayviastr = w.get("oneway");
     197        if (onewayviastr != null) {
     198            if ("-1".equals(onewayviastr)) {
     199                return -1;
    165200            } else {
    166                 errors.add(new TestError(this, Severity.ERROR,
    167                         tr("The \"from\" way does not start or end at a \"via\" way."), FROM_VIA_WAY, r));
    168                 return;
     201                Boolean onewayvia = OsmUtils.getOsmBoolean(onewayviastr);
     202                if (onewayvia != null && onewayvia) {
     203                    return 1;
     204                }
    169205            }
    170             if (!toWay.isFirstLastNode(viaNode == firstNode ? lastNode : firstNode)) {
    171                 errors.add(new TestError(this, Severity.ERROR,
    172                         tr("The \"to\" way does not start or end at a \"via\" way."), TO_VIA_WAY, r));
    173             }
    174206        }
     207        return 0;
    175208    }
    176209}
  • data/defaultpresets.xml

     
    41384138            </optional>
    41394139            <roles>
    41404140                <role key="from" text="from way" requisite="required" count="1" type="way" />
    4141                 <role key="via" text="via node or way" requisite="required" count="1" type="way,node" />
     4141                <role key="via" text="via node or ways" requisite="required" type="way,node" />
    41424142                <role key="to" text="to way" requisite="required" count="1" type="way" />
    41434143            </roles>
    41444144        </item>