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     * @param member relation member
022     * @return roundabout type
023     */
024    static Direction roundaboutType(RelationMember member) {
025        if (member == null || !member.isWay()) return NONE;
026        return roundaboutType(member.getWay());
027    }
028
029    static Direction roundaboutType(Way w) {
030        if (w != null &&
031                "roundabout".equals(w.get("junction")) &&
032                w.getNodesCount() < 200 &&
033                w.getNodesCount() > 2 &&
034                w.getNode(0) != null &&
035                w.getNode(1) != null &&
036                w.getNode(2) != null &&
037                w.isClosed()) {
038            /** do some simple determinant / cross pruduct test on the first 3 nodes
039                to see, if the roundabout goes clock wise or ccw */
040            EastNorth en1 = w.getNode(0).getEastNorth();
041            EastNorth en2 = w.getNode(1).getEastNorth();
042            EastNorth en3 = w.getNode(2).getEastNorth();
043            if (en1 != null && en2 != null && en3 != null) {
044                en1 = en2.subtract(en1);
045                en2 = en3.subtract(en2);
046                return en1.north() * en2.east() - en2.north() * en1.east() > 0 ? ROUNDABOUT_LEFT : ROUNDABOUT_RIGHT;
047            }
048        }
049        return NONE;
050    }
051
052    static boolean isBackward(final RelationMember member) {
053        return "backward".equals(member.getRole());
054    }
055
056    static boolean isForward(final RelationMember member) {
057        return "forward".equals(member.getRole());
058    }
059
060    static boolean isOneway(final RelationMember member) {
061        return isForward(member) || isBackward(member);
062    }
063}