// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.gui.dialogs.relation.sort; import static org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction.NONE; import static org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction.ROUNDABOUT_LEFT; import static org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction.ROUNDABOUT_RIGHT; import org.openstreetmap.josm.data.coor.EastNorth; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.RelationMember; import org.openstreetmap.josm.data.osm.Way; import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction; final class RelationSortUtils { private RelationSortUtils() { // Hide default constructor for utils classes } /** * determine, if the way i is a roundabout and if yes, what type of roundabout * @param member relation member * @return roundabout type */ static Direction roundaboutType(RelationMember member) { if (member == null || !member.isWay()) return NONE; return roundaboutType(member.getWay()); } static Direction roundaboutType(Way w) { if (w != null && w.hasTag("junction", "roundabout")) { int nodesCount = w.getNodesCount(); if (nodesCount > 2 && nodesCount < 200) { Node n1 = w.getNode(0); Node n2 = w.getNode(1); Node n3 = w.getNode(2); if (n1 != null && n2 != null && n3 != null && w.isClosed()) { /** do some simple determinant / cross product test on the first 3 nodes to see, if the roundabout goes clock wise or ccw */ EastNorth en1 = n1.getEastNorth(); EastNorth en2 = n2.getEastNorth(); EastNorth en3 = n3.getEastNorth(); if (en1 != null && en2 != null && en3 != null) { en1 = en2.subtract(en1); en2 = en3.subtract(en2); return en1.north() * en2.east() - en2.north() * en1.east() > 0 ? ROUNDABOUT_LEFT : ROUNDABOUT_RIGHT; } } } } return NONE; } static boolean isBackward(final RelationMember member) { return "backward".equals(member.getRole()); } static boolean isForward(final RelationMember member) { return "forward".equals(member.getRole()); } static boolean isOneway(final RelationMember member) { return isForward(member) || isBackward(member); } }