Ticket #5109: forward_backward.2.patch
| File forward_backward.2.patch, 32.6 KB (added by , 15 years ago) |
|---|
-
src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableLinkedCellRenderer.java
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableLinkedCellRenderer.java b/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableLinkedCellRenderer.java index 5344a6e..6a25ec7 100644
a b 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.gui.dialogs.relation; 3 3 4 import java.awt.BasicStroke;5 4 import java.awt.Color; 6 5 import java.awt.Component; 7 6 import java.awt.Graphics; 8 import java.awt.Graphics2D;9 7 import java.awt.Image; 10 8 11 9 import javax.swing.JTable; … … public class MemberTableLinkedCellRenderer extends MemberTableCellRenderer { 41 39 return; 42 40 43 41 int ymax=this.getSize().height - 1; 44 int xloop = 10; 45 int xowloop = 0; 46 if(value.isOnewayLoopForwardPart) xowloop = -3; 47 if(value.isOnewayLoopBackwardPart) xowloop = 3; 48 42 int xloop = 8; 49 43 int xoff = this.getSize().width / 2; 50 44 if (value.isLoop) { 51 45 xoff -= xloop / 2 - 1; … … public class MemberTableLinkedCellRenderer extends MemberTableCellRenderer { 57 51 58 52 if (value.linkPrev) { 59 53 g.setColor(Color.black); 60 if(value.isOnewayHead) 61 g.fillRect(xoff - 1, 0, 3, 1); 62 else 63 g.fillRect(xoff - 1 + xowloop, 0, 3, 1); 54 g.fillRect(xoff - 1, 0, 3, 1); 64 55 y1 = 0; 65 56 } else { 66 57 if (value.isLoop) { … … public class MemberTableLinkedCellRenderer extends MemberTableCellRenderer { 72 63 } 73 64 else { 74 65 g.setColor(Color.red); 75 if(value.isOnewayHead) 76 g.drawRect(xoff-1, p - 3 - w, w, w); 77 else 78 g.drawRect(xoff-1 + xowloop, p - 1 - w, w, w); 66 g.drawRect(xoff-1, p - 1 - w, w, w); 79 67 y1 = p; 80 68 } 81 69 } 82 70 83 71 if (value.linkNext) { 84 72 g.setColor(Color.black); 85 if(value.isOnewayTail) 86 g.fillRect(xoff - 1, ymax, 3, 1); 87 else 88 g.fillRect(xoff - 1 + xowloop, ymax, 3, 1); 73 g.fillRect(xoff - 1, ymax, 3, 1); 89 74 y2 = ymax; 90 75 } else { 91 76 if (value.isLoop) { … … public class MemberTableLinkedCellRenderer extends MemberTableCellRenderer { 98 83 } 99 84 else { 100 85 g.setColor(Color.red); 101 if(value.isOnewayTail) 102 g.drawRect(xoff-1, ymax - p + 3, w, w); 103 else 104 g.drawRect(xoff-1 + xowloop, ymax - p + 1, w, w); 105 // g.drawRect(xoff-1, ymax - p + 1, ssw, w); 86 g.drawRect(xoff-1, ymax - p + 1, w, w); 106 87 y2 = ymax - p; 107 88 } 108 89 } 109 90 110 91 /* vertical lines */ 111 92 g.setColor(Color.black); 93 g.drawLine(xoff, y1, xoff, y2); 112 94 if (value.isLoop) { 113 95 g.drawLine(xoff+xloop, y1, xoff+xloop, y2); 114 96 } 115 97 116 if (value.isOnewayHead) {117 setDotted(g);118 y1 = 7;119 120 int xValues [] = {xoff - xowloop + 1, xoff - xowloop + 1, xoff};121 int yValues [] = {ymax, y1+1, 1};122 g.drawPolyline(xValues, yValues, 3);123 unsetDotted(g);124 g.drawLine(xoff + xowloop, y1+1, xoff, 1);125 }126 127 if(value.isOnewayTail){128 setDotted(g);129 y2 = ymax - 7;130 131 int xValues [] = {xoff+1, xoff - xowloop + 1, xoff - xowloop + 1};132 int yValues [] = {ymax-1, y2, y1};133 g.drawPolyline(xValues, yValues, 3);134 unsetDotted(g);135 g.drawLine(xoff + xowloop, y2, xoff, ymax-1);136 }137 138 if ((value.isOnewayLoopForwardPart || value.isOnewayLoopBackwardPart) && !value.isOnewayTail && !value.isOnewayHead) {139 setDotted(g);140 g.drawLine(xoff - xowloop+1, y1, xoff - xowloop+1, y2 + 1);141 unsetDotted(g);142 }143 144 if (!value.isOnewayLoopForwardPart && !value.isOnewayLoopBackwardPart){145 g.drawLine(xoff, y1, xoff, y2);146 }147 148 g.drawLine(xoff+xowloop, y1, xoff+xowloop, y2);149 150 98 /* special icons */ 151 99 Image arrow = null; 152 100 switch (value.direction) { … … public class MemberTableLinkedCellRenderer extends MemberTableCellRenderer { 157 105 arrow = arrowUp; 158 106 break; 159 107 } 160 if (value.direction == Direction.ROUNDABOUT_LEFT) { 108 if ((arrow != null) && (value.linkPrev || value.linkNext)) { 109 g.drawImage(arrow, xoff-3, (y1 + y2) / 2 - 2, null); 110 } 111 else if (value.direction == Direction.ROUNDABOUT_LEFT) { 161 112 g.drawImage(roundabout_left, xoff-6, 1, null); 162 113 } else if (value.direction == Direction.ROUNDABOUT_RIGHT) { 163 114 g.drawImage(roundabout_right, xoff-6, 1, null); 164 115 } 165 166 if (!value.isOnewayLoopForwardPart && !value.isOnewayLoopBackwardPart &&167 (arrow != null)) {168 g.drawImage(arrow, xoff-3, (y1 + y2) / 2 - 2, null);169 }170 171 if (value.isOnewayLoopBackwardPart) {172 if(value.isOnewayLoopForwardPart) {173 if(arrow == arrowDown)174 arrow = arrowUp;175 else if (arrow == arrowUp)176 arrow = arrowDown;177 }178 }179 180 if ((arrow != null)) {181 g.drawImage(arrow, xoff+xowloop-3, (y1 + y2) / 2 - 2, null);182 }183 }184 185 private void setDotted(Graphics g) {186 ((Graphics2D)g).setStroke(new BasicStroke(187 1f,188 BasicStroke.CAP_BUTT,189 BasicStroke.CAP_BUTT,190 5f,191 new float[] {1f, 2f},192 0f));193 }194 195 private void unsetDotted(Graphics g) {196 ((Graphics2D)g).setStroke(new BasicStroke());197 116 } 198 117 } -
src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java b/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java index b254ef3..beb01aa 100644
a b public class MemberTableModel extends AbstractTableModel implements TableModelLi 57 57 private CopyOnWriteArrayList<IMemberModelListener> listeners; 58 58 private OsmDataLayer layer; 59 59 60 private final int UNCONNECTED = Integer.MIN_VALUE;61 62 60 /** 63 61 * constructor 64 62 */ … … public class MemberTableModel extends AbstractTableModel implements TableModelLi 788 786 setSelectedMembers(sortedMembers); 789 787 } 790 788 791 private Direction determineDirection(int ref_i, Direction ref_direction, int k) {792 return determineDirection(ref_i, ref_direction, k, false);793 }794 789 /** 795 790 * Determines the direction of way k with respect to the way ref_i. 796 791 * The way ref_i is assumed to have the direction ref_direction and … … public class MemberTableModel extends AbstractTableModel implements TableModelLi 800 795 * 801 796 * Else the direction is given as follows: 802 797 * Let the relation be a route of oneway streets, and someone travels them in the given order. 803 * Direction is FORWARD if it is leg al and BACKWARD if it is illegal to do so for the given way.798 * Direction is FORWARD if it is legel and BACKWARD if it is illegal to do so for the given way. 804 799 * 805 800 **/ 806 private Direction determineDirection(int ref_i, Direction ref_direction, int k, boolean reversed) {801 private Direction determineDirection(int ref_i,Direction ref_direction, int k) { 807 802 if (ref_i < 0 || k < 0 || ref_i >= members.size() || k >= members.size()) 808 803 return NONE; 809 804 if (ref_direction == NONE) … … public class MemberTableModel extends AbstractTableModel implements TableModelLi 829 824 830 825 switch (ref_direction) { 831 826 case FORWARD: 832 refNodes.add(way_ref.lastNode());827 refNodes.add(way_ref.lastNode()); 833 828 break; 834 829 case BACKWARD: 835 refNodes.add(way_ref.firstNode());830 refNodes.add(way_ref.firstNode()); 836 831 break; 837 832 case ROUNDABOUT_LEFT: 838 833 case ROUNDABOUT_RIGHT: … … public class MemberTableModel extends AbstractTableModel implements TableModelLi 852 847 if (n == nn) 853 848 return roundaboutType(k); 854 849 } 855 } else if(isOneway(m)) {856 if (n == RelationNodeMap.firstOnewayNode(m) && !reversed) {857 if(m.getRole().equals("backward"))858 return BACKWARD;859 else860 return FORWARD;861 }862 if (n == RelationNodeMap.lastOnewayNode(m) && reversed) {863 if(m.getRole().equals("backward"))864 return FORWARD;865 else866 return BACKWARD;867 }868 850 } else { 869 851 if (n == way.firstNode()) 870 852 return FORWARD; … … public class MemberTableModel extends AbstractTableModel implements TableModelLi 949 931 */ 950 932 public void updateLinks() { 951 933 connectionType = null; 952 List<WayConnectionType> con = new ArrayList<WayConnectionType>();934 ArrayList<WayConnectionType> con = new ArrayList<WayConnectionType>(); 953 935 954 936 for (int i=0; i<members.size(); ++i) { 955 937 con.add(null); … … public class MemberTableModel extends AbstractTableModel implements TableModelLi 958 940 int firstGroupIdx=0; 959 941 boolean resetFirstGoupIdx=false; 960 942 961 int lastForwardWay = UNCONNECTED;962 int lastBackwardWay = UNCONNECTED;963 boolean onewayBeginning = false;964 965 943 for (int i=0; i<members.size(); ++i) { 966 944 if (resetFirstGoupIdx) { 967 945 firstGroupIdx = i; … … public class MemberTableModel extends AbstractTableModel implements TableModelLi 983 961 } 984 962 985 963 boolean linkPrev = (i != firstGroupIdx); 986 boolean linkNext = false; 987 988 con.set(i, new WayConnectionType(false)); 989 990 if(isOneway(m) || roundaboutType(i) != NONE){ 991 if(i>0 && con.get(i-1).isOnewayTail) 992 con.get(i).isOnewayHead = true; 993 if(lastBackwardWay == UNCONNECTED && lastForwardWay == UNCONNECTED){ //Beginning of new oneway 994 con.get(i).isOnewayHead = true; 995 lastForwardWay = i-1; 996 lastBackwardWay = i; 997 onewayBeginning = true; 998 } 964 boolean linkNext; 965 Direction dir; 966 if (linkPrev) { 967 dir = determineDirection(i-1, con.get(i-1).direction, i); 968 linkNext = (determineDirection(i, dir, i+1) != NONE); 999 969 } 1000 1001 Direction dir = NONE; 1002 if (linkPrev) { 1003 if(lastBackwardWay != UNCONNECTED && lastForwardWay != UNCONNECTED) { 1004 Direction dirFW = determineDirection(lastForwardWay, con.get(lastForwardWay).direction, i); 1005 Direction dirBW = NONE; 1006 if(onewayBeginning) { 1007 if(lastBackwardWay != i) 1008 dirBW = determineDirection(lastBackwardWay, reverse(con.get(lastBackwardWay).direction), i, true); 1009 if(dirBW != NONE) 1010 onewayBeginning = false; 1011 } else 1012 dirBW = determineDirection(lastBackwardWay, con.get(lastBackwardWay).direction, i, true); 1013 1014 if(isOneway(m) || roundaboutType(i) != NONE) { 1015 if(dirBW != NONE){ 1016 dir = dirBW; 1017 lastBackwardWay = i; 1018 con.get(i).isOnewayLoopBackwardPart = true; 1019 } 1020 if(dirFW != NONE){ 1021 dir = dirFW; 1022 lastForwardWay = i; 1023 con.get(i).isOnewayLoopForwardPart = true; 1024 } 1025 if(dirFW == NONE && dirBW == NONE) { 1026 // unconnectPreviousLink(con, i, true); 1027 // unconnectPreviousLink(con, i, false); 1028 if(i>0) con.get(i-1).linkNext = false; 1029 if(isOneway(m)){ 1030 lastForwardWay = i-1; 1031 lastBackwardWay = i; 1032 } else { 1033 lastForwardWay = UNCONNECTED; 1034 lastBackwardWay = UNCONNECTED; 1035 } 1036 firstGroupIdx = i; 1037 linkPrev = false; 1038 } 1039 1040 if(dirFW != NONE && dirBW != NONE) { 1041 if(i+1<members.size() && determineDirection(i, dirFW, i+1) != NONE) { 1042 con.get(i).isOnewayLoopBackwardPart = false; 1043 dirBW = NONE; 1044 dir = dirFW; 1045 } else { 1046 con.get(i).isOnewayLoopForwardPart = false; 1047 dirFW = NONE; 1048 dir = dirBW; 1049 } 1050 1051 con.get(i).isOnewayTail = true; 1052 } 1053 1054 linkNext = (i+1!=members.size()); 1055 } else { 1056 lastForwardWay = UNCONNECTED; 1057 lastBackwardWay = UNCONNECTED; 1058 if(dirFW == NONE | dirBW == NONE) { 1059 linkPrev = false; 1060 } 1061 } 1062 } 1063 1064 if(!isOneway(m)) { 1065 dir = determineDirection(i-1, con.get(i-1).direction, i); 1066 linkNext = (determineDirection(i, dir, i+1) != NONE); 1067 } 1068 } 1069 1070 if (!linkPrev) { 1071 if (isOneway(m)){ 1072 if(m.getRole().equals("backward")) dir = BACKWARD; 1073 else dir = FORWARD; 1074 con.get(i).isOnewayLoopForwardPart = true; 1075 lastForwardWay = i; 1076 } else 970 else { 1077 971 if (roundaboutType(i) != NONE) { 1078 972 dir = determineDirection(i, roundaboutType(i), i+1) != NONE ? roundaboutType(i) : NONE; 1079 973 } else { /** guess the direction and see if it fits with the next member */ … … public class MemberTableModel extends AbstractTableModel implements TableModelLi 1091 985 1092 986 } 1093 987 1094 con.get(i).direction = dir; 1095 con.get(i).linkNext = linkNext; 1096 con.get(i).linkPrev = linkPrev; 988 con.set(i, new WayConnectionType(linkPrev, linkNext, dir)); 1097 989 1098 990 if (! linkNext) { 1099 991 boolean loop; 1100 int lastGroupIdx = i; 1101 if (lastGroupIdx == firstGroupIdx) { //is primitive loop 1102 loop = determineDirection(lastGroupIdx, FORWARD, lastGroupIdx) == FORWARD; 1103 } else { 1104 loop = determineDirection(lastGroupIdx, con.get(lastGroupIdx).direction, firstGroupIdx) == con.get(firstGroupIdx).direction; 992 if (i == firstGroupIdx) { 993 loop = determineDirection(i, FORWARD, i) == FORWARD; 994 } else { 995 loop = determineDirection(i, dir, firstGroupIdx) == con.get(firstGroupIdx).direction; 1105 996 } 1106 997 if (loop) { 1107 998 for (int j=firstGroupIdx; j <= i; ++j) { … … public class MemberTableModel extends AbstractTableModel implements TableModelLi 1111 1002 resetFirstGoupIdx = true; 1112 1003 } 1113 1004 } 1114 1115 1005 connectionType = con; 1116 1006 // for (int i=0; i<con.size(); ++i) { 1117 1007 // System.err.println(con.get(i)); 1118 1008 // } 1119 1009 } 1120 1121 // private static void unconnectPreviousLink(List<WayConnectionType> con, int beg, boolean backward){1122 // int i = beg;1123 // while(true){1124 // WayConnectionType t = con.get(i--);1125 // t.isOnewayOppositeConnected = false;1126 // if(backward && t.isOnewayLoopBackwardPart) break;1127 // if(!backward && t.isOnewayLoopForwardPart) break;1128 // }1129 // }1130 1131 private static Direction reverse(Direction dir){1132 if(dir == FORWARD) return BACKWARD;1133 if(dir == BACKWARD) return FORWARD;1134 return dir;1135 }1136 1137 public static boolean isOneway(RelationMember m){1138 return m.getRole().equals("forward") || m.getRole().equals("backward");1139 }1140 1010 } -
src/org/openstreetmap/josm/gui/dialogs/relation/RelationNodeMap.java
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/RelationNodeMap.java b/src/org/openstreetmap/josm/gui/dialogs/relation/RelationNodeMap.java index 1f4b388..d6e1d8d 100644
a b package org.openstreetmap.josm.gui.dialogs.relation; 4 4 import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.NONE; 5 5 6 6 import java.util.ArrayList; 7 import java.util.Iterator; 7 8 import java.util.List; 8 9 import java.util.Map; 9 import java.util.Set;10 10 import java.util.TreeMap; 11 11 import java.util.TreeSet; 12 12 … … import org.openstreetmap.josm.data.osm.Way; 29 29 * 30 30 */ 31 31 public class RelationNodeMap { 32 private class NodesWays{33 public Map<Node, Set<Integer>> nodes = new TreeMap<Node, Set<Integer>>();34 public Map<Integer, Set<Node>> ways = new TreeMap<Integer, Set<Node>>();35 public boolean oneWay;36 public NodesWays(boolean oneWay){37 this.oneWay = oneWay;38 }39 }40 41 32 /* 42 33 * the maps. (Need TreeMap for efficiency.) 43 34 */ 44 private NodesWays map = new NodesWays(false); 45 /* 46 * Maps for oneways (forward/backward roles) 47 */ 48 49 private NodesWays onewayMap = new NodesWays(true); 50 private NodesWays onewayReverseMap = new NodesWays(true); 35 private TreeMap<Node, TreeSet<Integer>> nodesMap; 36 private TreeMap<Integer, TreeSet<Node>> waysMap; 51 37 /* 52 38 * Used to keep track of what members are done. 53 39 */ 54 private Set<Integer> remaining; 55 private Map<Integer, Set<Node>> remainingOneway = new TreeMap<Integer, Set<Node>>();; 40 private TreeSet<Integer> remaining; 56 41 57 42 /** 58 43 * All members that are incomplete or not a way 59 44 */ 60 45 private List<Integer> notSortable = new ArrayList<Integer>(); 61 46 62 public static Node firstOnewayNode(RelationMember m){63 if(!m.isWay()) return null;64 if(m.getRole().equals("backward")) return m.getWay().lastNode();65 return m.getWay().firstNode();66 }67 68 public static Node lastOnewayNode(RelationMember m){69 if(!m.isWay()) return null;70 if(m.getRole().equals("backward")) return m.getWay().firstNode();71 return m.getWay().lastNode();72 }73 74 47 RelationNodeMap(List<RelationMember> members) { 75 map.nodes = new TreeMap<Node,Set<Integer>>();76 map.ways = new TreeMap<Integer,Set<Node>>();48 nodesMap = new TreeMap<Node, TreeSet<Integer>>(); 49 waysMap = new TreeMap<Integer, TreeSet<Node>>(); 77 50 78 51 for (int i = 0; i < members.size(); ++i) { 79 52 RelationMember m = members.get(i); 80 if (m.getMember().isIncomplete() || !m.isWay()) { 53 if (m.getMember().isIncomplete() || !m.isWay()) 54 { 81 55 notSortable.add(i); 82 continue;83 56 } 84 85 Way w = m.getWay(); 86 if ((MemberTableModel.roundaboutType(w) != NONE)) { 87 for (Node nd : w.getNodes()) { 88 addPair(nd, i); 57 else { 58 Way w = m.getWay(); 59 if (MemberTableModel.roundaboutType(w) != NONE) { 60 for (Node nd : w.getNodes()) { 61 addPair(nd, i); 62 } 63 } else { 64 addPair(w.firstNode(), i); 65 addPair(w.lastNode(), i); 89 66 } 90 } else if(MemberTableModel.isOneway(m)) {91 addNodeWayMap(firstOnewayNode(m), i);92 addWayNodeMap(lastOnewayNode(m), i);93 addNodeWayMapReverse(lastOnewayNode(m), i);94 addWayNodeMapReverse(firstOnewayNode(m), i);95 addRemainingForward(firstOnewayNode(m), i);96 addRemainingForward(lastOnewayNode(m), i);97 } else {98 addPair(w.firstNode(), i);99 addPair(w.lastNode(), i);100 67 } 101 68 } 102 69 103 70 remaining = new TreeSet<Integer>(); 104 remaining.addAll(map.ways.keySet()); 71 for (Integer k : waysMap.keySet()) { 72 remaining.add(k); 73 } 105 74 106 75 /* 107 76 * Clean up the maps, i.e. remove nodes from roundabouts and dead ends that 108 77 * cannot be used in future. (only for performance) 109 78 */ 110 // Iterator<Map.Entry<Node,TreeSet<Integer>>> it = map.nodes.entrySet().iterator(); 111 // while (it.hasNext()) { 112 // Map.Entry<Node,TreeSet<Integer>> nodeLinks = it.next(); 113 // 114 // if (nodeLinks.getValue().size() < 2) { 115 // if (nodeLinks.getValue().size() != 1) throw new AssertionError(); 116 // 117 // Integer d_way = nodeLinks.getValue().iterator().next(); 118 // TreeSet<Node> d_way_nodes = map.ways.get(d_way); 119 // d_way_nodes.remove(nodeLinks.getKey()); 120 // 121 // it.remove(); 122 // continue; 123 // } 124 // } 125 } 79 Iterator<Map.Entry<Node,TreeSet<Integer>>> it = nodesMap.entrySet().iterator(); 80 while (it.hasNext()) { 81 Map.Entry<Node,TreeSet<Integer>> nodeLinks = it.next(); 126 82 127 private void addPair(Node n, int i) { 128 Set<Integer> ts = map.nodes.get(n); 129 if (ts == null) { 130 ts = new TreeSet<Integer>(); 131 map.nodes.put(n, ts); 132 } 133 ts.add(i); 83 if (nodeLinks.getValue().size() < 2) { 84 if (nodeLinks.getValue().size() != 1) throw new AssertionError(); 134 85 135 Set<Node> ts2 = map.ways.get(i); 136 if (ts2 == null) { 137 ts2 = new TreeSet<Node>(); 138 map.ways.put(i, ts2); 139 } 140 ts2.add(n); 141 } 86 Integer d_way = nodeLinks.getValue().iterator().next(); 87 TreeSet<Node> d_way_nodes = waysMap.get(d_way); 88 d_way_nodes.remove(nodeLinks.getKey()); 142 89 143 private void addNodeWayMap(Node n, int i) { 144 Set<Integer> ts = onewayMap.nodes.get(n); 145 if (ts == null) { 146 ts = new TreeSet<Integer>(); 147 onewayMap.nodes.put(n, ts); 148 } 149 ts.add(i); 150 } 151 152 private void addWayNodeMap(Node n, int i) { 153 Set<Node> ts2 = onewayMap.ways.get(i); 154 if (ts2 == null) { 155 ts2 = new TreeSet<Node>(); 156 onewayMap.ways.put(i, ts2); 90 it.remove(); 91 continue; 92 } 157 93 } 158 ts2.add(n);159 94 } 160 95 161 private void add NodeWayMapReverse(Node n, int i) {162 Set<Integer> ts = onewayReverseMap.nodes.get(n);96 private void addPair(Node n, int i) { 97 TreeSet<Integer> ts = nodesMap.get(n); 163 98 if (ts == null) { 164 99 ts = new TreeSet<Integer>(); 165 onewayReverseMap.nodes.put(n, ts);100 nodesMap.put(n, ts); 166 101 } 167 102 ts.add(i); 168 }169 103 170 private void addWayNodeMapReverse(Node n, int i) { 171 Set<Node> ts2 = onewayReverseMap.ways.get(i); 104 TreeSet<Node> ts2 = waysMap.get(i); 172 105 if (ts2 == null) { 173 106 ts2 = new TreeSet<Node>(); 174 onewayReverseMap.ways.put(i, ts2);107 waysMap.put(i, ts2); 175 108 } 176 109 ts2.add(n); 177 110 } 178 111 179 private void addRemainingForward(Node n, int i) {180 Set<Node> ts2 = remainingOneway.get(i);181 if (ts2 == null) {182 ts2 = new TreeSet<Node>();183 remainingOneway.put(i, ts2);184 }185 ts2.add(n);186 }187 188 Integer firstOneway = null;189 Node lastOnewayNode = null;190 Node firstCircular = null;191 192 112 /** 193 113 * Return a relation member that is linked to the 194 * member 'i', but has not been popped yet.114 * member 'i', but has not been popped jet. 195 115 * Return null if there is no such member left. 196 116 */ 197 public Integer popAdjacent(Integer way) { 198 if (lastOnewayNode != null) return popBackwardOnewayPart(way); 199 if (firstOneway != null) return popForwardOnewayPart(way); 200 201 if (map.ways.containsKey(way)){ 202 for (Node n : map.ways.get(way)) { 203 Integer i = deleteAndGetAdjacentNode(map, n); 204 if(i != null) return i; 205 206 Integer j = deleteAndGetAdjacentNode(onewayMap, n); 207 if(j != null) { 208 firstOneway = j; 209 return j; 210 } 211 } 212 } 213 214 firstOneway = way; 215 return popForwardOnewayPart(way); 216 } 217 218 private Integer popForwardOnewayPart(Integer way) { 219 if(onewayMap.ways.containsKey(way)) { 220 for (Node n : onewayMap.ways.get(way)) { 221 Integer i = findAdjacentWay(onewayMap, n); 222 if(i == null) continue; 223 224 lastOnewayNode = processBackwardIfEndOfLoopReached(i); 225 if(lastOnewayNode != null){ 226 return popBackwardOnewayPart(firstOneway); 227 } 228 229 deleteWayNode(onewayMap, i, n); 230 return i; 231 } 232 } 233 234 firstOneway = null; 235 return null; 236 } 237 238 private Node processBackwardIfEndOfLoopReached(Integer way) { //find if we didn't reach end of the loop (and process backward part) 239 if (onewayReverseMap.ways.containsKey(way)) { 240 for (Node n : onewayReverseMap.ways.get(way)) { 241 if((map.nodes.containsKey(n)) 242 || (onewayMap.nodes.containsKey(n) && onewayMap.nodes.get(n).size() > 1)) { 243 return n; 244 } 245 if(firstCircular != null && firstCircular == n) { 246 return firstCircular; 247 } 248 } 249 } 250 return null; 251 } 252 253 private Integer popBackwardOnewayPart(int way){ 254 if (lastOnewayNode != null) { 255 TreeSet<Node> nodes = new TreeSet<Node>(); 256 if (onewayReverseMap.ways.containsKey(way)) nodes.addAll(onewayReverseMap.ways.get(way)); 257 if (map.ways.containsKey(way)) nodes.addAll(map.ways.get(way)); 258 for (Node n : nodes) { 259 if(n == lastOnewayNode) { //if oneway part ends 260 firstOneway = null; 261 lastOnewayNode = null; 262 Integer j = deleteAndGetAdjacentNode(map, n); 263 if(j != null) return j; 264 265 Integer k = deleteAndGetAdjacentNode(onewayMap, n); 266 if(k != null) { 267 firstOneway = k; 268 return k; 269 } 270 } 271 272 Integer j = deleteAndGetAdjacentNode(onewayReverseMap, n); 273 if(j != null) return j; 117 public Integer popAdjacent(Integer i) { 118 TreeSet<Node> nodes = waysMap.get(i); 119 for (Node n : nodes) { 120 TreeSet<Integer> adj = nodesMap.get(n); 121 if (!adj.isEmpty()) { 122 Integer j = adj.iterator().next(); 123 done(j); 124 waysMap.get(j).remove(n); 125 return j; 274 126 } 275 127 } 276 277 firstOneway = null;278 lastOnewayNode = null;279 280 128 return null; 281 129 } 282 130 283 131 /** 284 * find next node in nw NodeWays structure, if the node is found delete and return it285 * @param nw286 * @param n287 * @return node next to n288 */289 private Integer deleteAndGetAdjacentNode(NodesWays nw, Node n){290 Integer j = findAdjacentWay(nw, n);291 if(j == null) return null;292 deleteWayNode(nw, j, n);293 return j;294 }295 296 private Integer findAdjacentWay(NodesWays nw, Node n) {297 Set<Integer> adj = nw.nodes.get(n);298 if (adj == null || adj.isEmpty()) return null;299 Integer j = adj.iterator().next();300 return j;301 }302 303 private void deleteWayNode(NodesWays nw, Integer way, Node n){304 if(nw.oneWay)305 doneOneway(way);306 else307 done(way);308 nw.ways.get(way).remove(n);309 }310 311 /**312 132 * Returns some remaining member or null if 313 133 * every sortable member has been processed. 314 134 */ 315 135 public Integer pop() { 316 if (!remaining.isEmpty()){ 317 Integer i = remaining.iterator().next(); 318 done(i); 319 return i; 320 } 321 322 if (remainingOneway.isEmpty()) return null; 323 for(Integer i :remainingOneway.keySet()){ //find oneway, whic is connected to more than one way (is between two oneway loops) 324 for(Node n : onewayReverseMap.ways.get(i)){ 325 if(onewayReverseMap.nodes.containsKey(n) && onewayReverseMap.nodes.get(n).size() > 1) { 326 doneOneway(i); 327 firstCircular = n; 328 return i; 329 } 330 } 331 } 332 333 Integer i = remainingOneway.keySet().iterator().next(); 334 doneOneway(i); 136 if (remaining.isEmpty()) return null; 137 Integer i = remaining.iterator().next(); 138 done(i); 335 139 return i; 336 140 } 337 141 338 142 /** 339 143 * This relation member has been processed. 340 * Remove references in the map.nodes.144 * Remove references in the nodesMap. 341 145 */ 342 private void doneOneway(Integer i) {343 Set<Node> nodesForward = remainingOneway.get(i);344 for (Node n : nodesForward) {345 if(onewayMap.nodes.containsKey(n)) onewayMap.nodes.get(n).remove(i);346 if(onewayReverseMap.nodes.containsKey(n)) onewayReverseMap.nodes.get(n).remove(i);347 }348 remainingOneway.remove(i);349 }350 351 146 private void done(Integer i) { 352 147 remaining.remove(i); 353 Set<Node> nodes = map.ways.get(i);148 TreeSet<Node> nodes = waysMap.get(i); 354 149 for (Node n : nodes) { 355 boolean result = map.nodes.get(n).remove(i);150 boolean result = nodesMap.get(n).remove(i); 356 151 if (!result) throw new AssertionError(); 357 152 } 358 153 } -
src/org/openstreetmap/josm/gui/dialogs/relation/WayConnectionType.java
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/WayConnectionType.java b/src/org/openstreetmap/josm/gui/dialogs/relation/WayConnectionType.java index 5beb882..347c722 100644
a b public class WayConnectionType { 10 10 private final boolean invalid; 11 11 12 12 /** True, if linked to the previous / next member. */ 13 public boolean linkPrev;14 public boolean linkNext;13 public final boolean linkPrev; 14 public final boolean linkNext; 15 15 16 16 /** 17 17 * direction is FORWARD if the first node of this way is connected to the previous way … … public class WayConnectionType { 22 22 * If there is no connection to the previous or next member, then 23 23 * direction has the value NONE. 24 24 */ 25 public Direction direction;25 public final Direction direction; 26 26 27 27 public enum Direction { 28 28 FORWARD, BACKWARD, ROUNDABOUT_LEFT, ROUNDABOUT_RIGHT, NONE; … … public class WayConnectionType { 35 35 /** True, if the element is part of a closed loop of ways. */ 36 36 public boolean isLoop; 37 37 38 public boolean isOnewayLoopForwardPart = false;39 public boolean isOnewayLoopBackwardPart = false;40 public boolean isOnewayHead = false;41 public boolean isOnewayTail = false;42 // public boolean isOnewayOppositeConnected = true;43 44 38 public boolean isRoundabout = false; 45 39 46 40 public WayConnectionType(boolean linkPrev, boolean linkNext, Direction direction) { … … public class WayConnectionType { 51 45 invalid = false; 52 46 } 53 47 54 public WayConnectionType(boolean invalid){55 this.invalid = invalid;56 }57 58 48 /** construct invalid instance */ 59 49 public WayConnectionType() { 60 50 this.linkPrev = false;
