001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs.relation.sort;
003
004import static org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction.NONE;
005import static org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction.ROUNDABOUT_LEFT;
006import static org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction.ROUNDABOUT_RIGHT;
007
008import org.openstreetmap.josm.data.coor.EastNorth;
009import org.openstreetmap.josm.data.osm.RelationMember;
010import org.openstreetmap.josm.data.osm.Way;
011import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction;
012
013final class RelationSortUtils {
014
015    private RelationSortUtils() {
016        // Hide default constructor for utils classes
017    }
018    
019    /**
020     * determine, if the way i is a roundabout and if yes, what type of roundabout
021     */
022    static Direction roundaboutType(RelationMember member) {
023        if (member == null || !member.isWay()) return NONE;
024        Way w = member.getWay();
025        return roundaboutType(w);
026    }
027
028    static Direction roundaboutType(Way w) {
029        if (w != null &&
030                "roundabout".equals(w.get("junction")) &&
031                w.getNodesCount() < 200 &&
032                w.getNodesCount() > 2 &&
033                w.getNode(0) != null &&
034                w.getNode(1) != null &&
035                w.getNode(2) != null &&
036                w.firstNode() == w.lastNode()) {
037            /** do some simple determinant / cross pruduct test on the first 3 nodes
038                to see, if the roundabout goes clock wise or ccw */
039            EastNorth en1 = w.getNode(0).getEastNorth();
040            EastNorth en2 = w.getNode(1).getEastNorth();
041            EastNorth en3 = w.getNode(2).getEastNorth();
042            if (en1 != null && en2 != null && en3 != null) {
043                en1 = en1.sub(en2);
044                en2 = en2.sub(en3);
045                return en1.north() * en2.east() - en2.north() * en1.east() > 0 ? ROUNDABOUT_LEFT : ROUNDABOUT_RIGHT;
046            }
047        }
048        return NONE;
049    }
050
051    static boolean isBackward(final RelationMember member){
052        return "backward".equals(member.getRole());
053    }
054
055    static boolean isForward(final RelationMember member){
056        return "forward".equals(member.getRole());
057    }
058
059    static boolean isOneway(final RelationMember member){
060        return isForward(member) || isBackward(member);
061    }
062}