- Timestamp:
- 2011-01-13T20:46:54+01:00 (14 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/gui/dialogs/relation
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableLinkedCellRenderer.java
r3083 r3788 2 2 package org.openstreetmap.josm.gui.dialogs.relation; 3 3 4 import java.awt.BasicStroke; 4 5 import java.awt.Color; 5 6 import java.awt.Component; 6 7 import java.awt.Graphics; 8 import java.awt.Graphics2D; 7 9 import java.awt.Image; 8 10 … … 40 42 41 43 int ymax=this.getSize().height - 1; 42 int xloop = 8; 44 int xloop = 10; 45 int xowloop = 0; 46 if(value.isOnewayLoopForwardPart) xowloop = -3; 47 if(value.isOnewayLoopBackwardPart) xowloop = 3; 48 43 49 int xoff = this.getSize().width / 2; 44 50 if (value.isLoop) { … … 52 58 if (value.linkPrev) { 53 59 g.setColor(Color.black); 54 g.fillRect(xoff - 1, 0, 3, 1); 60 if(value.isOnewayHead) 61 g.fillRect(xoff - 1, 0, 3, 1); 62 else 63 g.fillRect(xoff - 1 + xowloop, 0, 3, 1); 55 64 y1 = 0; 56 65 } else { … … 64 73 else { 65 74 g.setColor(Color.red); 66 g.drawRect(xoff-1, p - 1 - w, w, w); 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); 67 79 y1 = p; 68 80 } … … 71 83 if (value.linkNext) { 72 84 g.setColor(Color.black); 73 g.fillRect(xoff - 1, ymax, 3, 1); 85 if(value.isOnewayTail) 86 g.fillRect(xoff - 1, ymax, 3, 1); 87 else 88 g.fillRect(xoff - 1 + xowloop, ymax, 3, 1); 74 89 y2 = ymax; 75 90 } else { … … 84 99 else { 85 100 g.setColor(Color.red); 86 g.drawRect(xoff-1, ymax - p + 1, w, w); 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); 87 105 y2 = ymax - p; 88 106 } … … 91 109 /* vertical lines */ 92 110 g.setColor(Color.black); 93 g.drawLine(xoff, y1, xoff, y2);94 111 if (value.isLoop) { 95 112 g.drawLine(xoff+xloop, y1, xoff+xloop, y2); 96 113 } 97 114 115 if (value.isOnewayHead) { 116 setDotted(g); 117 y1 = 7; 118 119 int xValues [] = {xoff - xowloop + 1, xoff - xowloop + 1, xoff}; 120 int yValues [] = {ymax, y1+1, 1}; 121 g.drawPolyline(xValues, yValues, 3); 122 unsetDotted(g); 123 g.drawLine(xoff + xowloop, y1+1, xoff, 1); 124 } 125 126 if(value.isOnewayTail){ 127 setDotted(g); 128 y2 = ymax - 7; 129 130 int xValues [] = {xoff+1, xoff - xowloop + 1, xoff - xowloop + 1}; 131 int yValues [] = {ymax-1, y2, y1}; 132 g.drawPolyline(xValues, yValues, 3); 133 unsetDotted(g); 134 g.drawLine(xoff + xowloop, y2, xoff, ymax-1); 135 } 136 137 if ((value.isOnewayLoopForwardPart || value.isOnewayLoopBackwardPart) && !value.isOnewayTail && !value.isOnewayHead) { 138 setDotted(g); 139 g.drawLine(xoff - xowloop+1, y1, xoff - xowloop+1, y2 + 1); 140 unsetDotted(g); 141 } 142 143 if (!value.isOnewayLoopForwardPart && !value.isOnewayLoopBackwardPart){ 144 g.drawLine(xoff, y1, xoff, y2); 145 } 146 147 g.drawLine(xoff+xowloop, y1, xoff+xowloop, y2); 148 98 149 /* special icons */ 99 150 Image arrow = null; … … 106 157 break; 107 158 } 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) { 159 if (value.direction == Direction.ROUNDABOUT_LEFT) { 112 160 g.drawImage(roundabout_left, xoff-6, 1, null); 113 161 } else if (value.direction == Direction.ROUNDABOUT_RIGHT) { 114 162 g.drawImage(roundabout_right, xoff-6, 1, null); 115 163 } 164 165 if (!value.isOnewayLoopForwardPart && !value.isOnewayLoopBackwardPart && 166 (arrow != null)) { 167 g.drawImage(arrow, xoff-3, (y1 + y2) / 2 - 2, null); 168 } 169 170 if (value.isOnewayLoopBackwardPart && value.isOnewayLoopForwardPart) { 171 if(arrow == arrowDown) 172 arrow = arrowUp; 173 else if (arrow == arrowUp) 174 arrow = arrowDown; 175 } 176 177 if ((arrow != null)) { 178 g.drawImage(arrow, xoff+xowloop-3, (y1 + y2) / 2 - 2, null); 179 } 180 } 181 182 private void setDotted(Graphics g) { 183 ((Graphics2D)g).setStroke(new BasicStroke( 184 1f, 185 BasicStroke.CAP_BUTT, 186 BasicStroke.CAP_BUTT, 187 5f, 188 new float[] {1f, 2f}, 189 0f)); 190 } 191 192 private void unsetDotted(Graphics g) { 193 ((Graphics2D)g).setStroke(new BasicStroke()); 116 194 } 117 195 } -
trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java
r3712 r3788 2 2 package org.openstreetmap.josm.gui.dialogs.relation; 3 3 4 import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.BACKWARD; 5 import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.FORWARD; 6 import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.NONE; 7 import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.ROUNDABOUT_LEFT; 8 import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.ROUNDABOUT_RIGHT; 4 import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.*; 9 5 10 6 import java.util.ArrayList; … … 57 53 private CopyOnWriteArrayList<IMemberModelListener> listeners; 58 54 private OsmDataLayer layer; 55 56 private final int UNCONNECTED = Integer.MIN_VALUE; 59 57 60 58 /** … … 787 785 } 788 786 787 private Direction determineDirection(int ref_i, Direction ref_direction, int k) { 788 return determineDirection(ref_i, ref_direction, k, false); 789 } 789 790 /** 790 791 * Determines the direction of way k with respect to the way ref_i. … … 796 797 * Else the direction is given as follows: 797 798 * Let the relation be a route of oneway streets, and someone travels them in the given order. 798 * Direction is FORWARD if it is leg el and BACKWARD if it is illegal to do so for the given way.799 * Direction is FORWARD if it is legal and BACKWARD if it is illegal to do so for the given way. 799 800 * 800 801 **/ 801 private Direction determineDirection(int ref_i, Direction ref_direction, int k) {802 private Direction determineDirection(int ref_i, final Direction ref_direction, int k, boolean reversed) { 802 803 if (ref_i < 0 || k < 0 || ref_i >= members.size() || k >= members.size()) 803 804 return NONE; … … 805 806 return NONE; 806 807 807 RelationMember m_ref = members.get(ref_i);808 RelationMember m = members.get(k);808 final RelationMember m_ref = members.get(ref_i); 809 final RelationMember m = members.get(k); 809 810 Way way_ref = null; 810 811 Way way = null; … … 847 848 if (n == nn) 848 849 return roundaboutType(k); 850 } 851 } else if(isOneway(m)) { 852 if (n == RelationNodeMap.firstOnewayNode(m) && !reversed) { 853 if(isBackward(m)) 854 return BACKWARD; 855 else 856 return FORWARD; 857 } 858 if (n == RelationNodeMap.lastOnewayNode(m) && reversed) { 859 if(isBackward(m)) 860 return FORWARD; 861 else 862 return BACKWARD; 849 863 } 850 864 } else { … … 932 946 public void updateLinks() { 933 947 connectionType = null; 934 ArrayList<WayConnectionType> con = new ArrayList<WayConnectionType>();948 final List<WayConnectionType> con = new ArrayList<WayConnectionType>(); 935 949 936 950 for (int i=0; i<members.size(); ++i) { … … 939 953 940 954 int firstGroupIdx=0; 941 boolean resetFirstGoupIdx=false; 955 956 lastForwardWay = UNCONNECTED; 957 lastBackwardWay = UNCONNECTED; 958 onewayBeginning = false; 959 WayConnectionType lastWct = null; 942 960 943 961 for (int i=0; i<members.size(); ++i) { 944 if (resetFirstGoupIdx) { 945 firstGroupIdx = i; 946 resetFirstGoupIdx = false; 947 } 948 949 RelationMember m = members.get(i); 962 final RelationMember m = members.get(i); 950 963 if (! m.isWay()) { 951 964 con.set(i, new WayConnectionType()); 952 resetFirstGoupIdx = true;965 firstGroupIdx = i; 953 966 continue; 954 967 } 955 968 956 Way w = m.getWay();969 final Way w = m.getWay(); 957 970 if (w == null || w.isIncomplete()) { 958 971 con.set(i, new WayConnectionType()); 959 resetFirstGoupIdx = true;972 firstGroupIdx = i; 960 973 continue; 961 974 } 962 963 boolean linkPrev = (i != firstGroupIdx); 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); 969 } 970 else { 971 if (roundaboutType(i) != NONE) { 972 dir = determineDirection(i, roundaboutType(i), i+1) != NONE ? roundaboutType(i) : NONE; 973 } else { /** guess the direction and see if it fits with the next member */ 974 dir = determineDirection(i, FORWARD, i+1) != NONE ? FORWARD : NONE; 975 if (dir == NONE) { 976 dir = determineDirection(i, BACKWARD, i+1) != NONE ? BACKWARD : NONE; 977 } 975 976 WayConnectionType wct = new WayConnectionType(false); 977 wct.linkPrev = i>0 && con.get(i-1) != null && con.get(i-1).isValid(); 978 wct.direction = NONE; 979 980 if(isOneway(m)){ 981 if(lastWct != null && lastWct.isOnewayTail) 982 wct.isOnewayHead = true; 983 if(lastBackwardWay == UNCONNECTED && lastForwardWay == UNCONNECTED){ //Beginning of new oneway 984 wct.isOnewayHead = true; 985 lastForwardWay = i-1; 986 lastBackwardWay = i; 987 onewayBeginning = true; 978 988 } 979 linkNext = (dir != NONE); 980 if (dir == NONE) { 981 if (roundaboutType(i) != NONE) { 982 dir = roundaboutType(i); 983 } 989 } 990 991 if (wct.linkPrev) { 992 if(lastBackwardWay != UNCONNECTED && lastForwardWay != UNCONNECTED) { 993 wct = determineOnewayConnectionType(con, m, i, wct); 994 if(!wct.linkPrev) 995 firstGroupIdx = i; 984 996 } 985 997 986 } 987 988 con.set(i, new WayConnectionType(linkPrev, linkNext, dir)); 989 990 if (! linkNext) { 991 boolean loop; 992 if (i == firstGroupIdx) { 993 loop = determineDirection(i, FORWARD, i) == FORWARD; 994 } else { 995 loop = determineDirection(i, dir, firstGroupIdx) == con.get(firstGroupIdx).direction; 998 if(!isOneway(m)) { 999 wct.direction = determineDirection(i-1, lastWct.direction, i); 1000 wct.linkPrev = (wct.direction != NONE); 1001 } 1002 } 1003 1004 if (!wct.linkPrev) { 1005 wct.direction = determineDirectionOfFirst(i, m); 1006 if(isOneway(m)){ 1007 wct.isOnewayLoopForwardPart = true; 1008 lastForwardWay = i; 996 1009 } 997 if (loop) { 998 for (int j=firstGroupIdx; j <= i; ++j) { 999 con.get(j).isLoop = true; 1000 } 1001 } 1002 resetFirstGoupIdx = true; 1003 } 1004 } 1010 } 1011 1012 wct.linkNext = false; 1013 if(lastWct != null) 1014 lastWct.linkNext = wct.linkPrev; 1015 con.set(i, wct); 1016 lastWct = wct; 1017 1018 if(!wct.linkPrev) { 1019 if(i > 0) makeLoopIfNeeded(con, i-1, firstGroupIdx); 1020 firstGroupIdx = i; 1021 } 1022 } 1023 makeLoopIfNeeded(con, members.size()-1, firstGroupIdx); 1005 1024 connectionType = con; 1006 1025 // for (int i=0; i<con.size(); ++i) { … … 1008 1027 // } 1009 1028 } 1029 1030 // private static void unconnectPreviousLink(List<WayConnectionType> con, int beg, boolean backward){ 1031 // int i = beg; 1032 // while(true){ 1033 // WayConnectionType t = con.get(i--); 1034 // t.isOnewayOppositeConnected = false; 1035 // if(backward && t.isOnewayLoopBackwardPart) break; 1036 // if(!backward && t.isOnewayLoopForwardPart) break; 1037 // } 1038 // } 1039 1040 private static Direction reverse(final Direction dir){ 1041 if(dir == FORWARD) return BACKWARD; 1042 if(dir == BACKWARD) return FORWARD; 1043 return dir; 1044 } 1045 1046 private static boolean isBackward(final RelationMember member){ 1047 return member.getRole().equals("backward"); 1048 } 1049 1050 private static boolean isForward(final RelationMember member){ 1051 return member.getRole().equals("forward"); 1052 } 1053 1054 public static boolean isOneway(final RelationMember member){ 1055 return isForward(member) || isBackward(member); 1056 } 1057 1058 private void makeLoopIfNeeded(final List<WayConnectionType> con, final int i, final int firstGroupIdx) { 1059 boolean loop; 1060 if (i == firstGroupIdx) { //is primitive loop 1061 loop = determineDirection(i, FORWARD, i) == FORWARD; 1062 } else { 1063 loop = determineDirection(i, con.get(i).direction, firstGroupIdx) == con.get(firstGroupIdx).direction; 1064 } 1065 if (loop) { 1066 for (int j=firstGroupIdx; j <= i; ++j) { 1067 con.get(j).isLoop = true; 1068 } 1069 } 1070 } 1071 1072 private Direction determineDirectionOfFirst(final int i, final RelationMember m) { 1073 if (roundaboutType(i) != NONE) { 1074 return roundaboutType(i); 1075 } 1076 1077 if (isOneway(m)){ 1078 if(isBackward(m)) return BACKWARD; 1079 else return FORWARD; 1080 } else { /** guess the direction and see if it fits with the next member */ 1081 if(determineDirection(i, FORWARD, i+1) != NONE) return FORWARD; 1082 if(determineDirection(i, BACKWARD, i+1) != NONE) return BACKWARD; 1083 } 1084 return NONE; 1085 } 1086 1087 int lastForwardWay, lastBackwardWay; 1088 boolean onewayBeginning; 1089 private WayConnectionType determineOnewayConnectionType(final List<WayConnectionType> con, 1090 RelationMember m, int i, final WayConnectionType wct) { 1091 Direction dirFW = determineDirection(lastForwardWay, con.get(lastForwardWay).direction, i); 1092 Direction dirBW = NONE; 1093 if(onewayBeginning) { 1094 if(lastBackwardWay != i) 1095 dirBW = determineDirection(lastBackwardWay, reverse(con.get(lastBackwardWay).direction), i, true); 1096 if(dirBW != NONE) 1097 onewayBeginning = false; 1098 } else 1099 dirBW = determineDirection(lastBackwardWay, con.get(lastBackwardWay).direction, i, true); 1100 1101 if(isOneway(m)) { 1102 if(dirBW != NONE){ 1103 wct.direction = dirBW; 1104 lastBackwardWay = i; 1105 wct.isOnewayLoopBackwardPart = true; 1106 } 1107 if(dirFW != NONE){ 1108 wct.direction = dirFW; 1109 lastForwardWay = i; 1110 wct.isOnewayLoopForwardPart = true; 1111 } 1112 if(dirFW == NONE && dirBW == NONE) { //Not connected to previous 1113 // unconnectPreviousLink(con, i, true); 1114 // unconnectPreviousLink(con, i, false); 1115 wct.linkPrev = false; 1116 if(isOneway(m)){ 1117 wct.isOnewayHead = true; 1118 lastForwardWay = i-1; 1119 lastBackwardWay = i; 1120 } else { 1121 lastForwardWay = UNCONNECTED; 1122 lastBackwardWay = UNCONNECTED; 1123 } 1124 onewayBeginning = true; 1125 } 1126 1127 if(dirFW != NONE && dirBW != NONE) { //End of oneway loop 1128 if(i+1<members.size() && determineDirection(i, dirFW, i+1) != NONE) { 1129 wct.isOnewayLoopBackwardPart = false; 1130 dirBW = NONE; 1131 wct.direction = dirFW; 1132 } else { 1133 wct.isOnewayLoopForwardPart = false; 1134 dirFW = NONE; 1135 wct.direction = dirBW; 1136 } 1137 1138 wct.isOnewayTail = true; 1139 } 1140 1141 } else { 1142 lastForwardWay = UNCONNECTED; 1143 lastBackwardWay = UNCONNECTED; 1144 if(dirFW == NONE || dirBW == NONE) 1145 wct.linkPrev = false; 1146 } 1147 return wct; 1148 } 1010 1149 } -
trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationNodeMap.java
r3095 r3788 5 5 6 6 import java.util.ArrayList; 7 import java.util.Iterator;8 7 import java.util.List; 9 8 import java.util.Map; 9 import java.util.Set; 10 10 import java.util.TreeMap; 11 11 import java.util.TreeSet; … … 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 32 41 /* 33 42 * the maps. (Need TreeMap for efficiency.) 34 43 */ 35 private TreeMap<Node, TreeSet<Integer>> nodesMap; 36 private TreeMap<Integer, TreeSet<Node>> waysMap; 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); 37 51 /* 38 52 * Used to keep track of what members are done. 39 53 */ 40 private TreeSet<Integer> remaining; 54 private Set<Integer> remaining; 55 private Map<Integer, Set<Node>> remainingOneway = new TreeMap<Integer, Set<Node>>();; 41 56 42 57 /** … … 45 60 private List<Integer> notSortable = new ArrayList<Integer>(); 46 61 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 47 74 RelationNodeMap(List<RelationMember> members) { 48 nodesMap = new TreeMap<Node, TreeSet<Integer>>();49 waysMap = new TreeMap<Integer, TreeSet<Node>>();75 map.nodes = new TreeMap<Node, Set<Integer>>(); 76 map.ways = new TreeMap<Integer, Set<Node>>(); 50 77 51 78 for (int i = 0; i < members.size(); ++i) { 52 79 RelationMember m = members.get(i); 53 if (m.getMember().isIncomplete() || !m.isWay()) 54 { 80 if (m.getMember().isIncomplete() || !m.isWay()) { 55 81 notSortable.add(i); 56 } 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); 66 } 82 continue; 83 } 84 85 Way w = m.getWay(); 86 if ((MemberTableModel.roundaboutType(w) != NONE)) { 87 for (Node nd : w.getNodes()) { 88 addPair(nd, i); 89 } 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); 67 100 } 68 101 } 69 102 70 103 remaining = new TreeSet<Integer>(); 71 for (Integer k : waysMap.keySet()) { 72 remaining.add(k); 73 } 104 remaining.addAll(map.ways.keySet()); 74 105 75 106 /* … … 77 108 * cannot be used in future. (only for performance) 78 109 */ 79 Iterator<Map.Entry<Node,TreeSet<Integer>>> it = nodesMap.entrySet().iterator();80 while (it.hasNext()) {81 Map.Entry<Node,TreeSet<Integer>> nodeLinks = it.next();82 83 if (nodeLinks.getValue().size() < 2) {84 if (nodeLinks.getValue().size() != 1) throw new AssertionError();85 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());89 90 it.remove();91 continue;92 }93 }94 }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 } 95 126 96 127 private void addPair(Node n, int i) { 97 TreeSet<Integer> ts = nodesMap.get(n);128 Set<Integer> ts = map.nodes.get(n); 98 129 if (ts == null) { 99 130 ts = new TreeSet<Integer>(); 100 nodesMap.put(n, ts);131 map.nodes.put(n, ts); 101 132 } 102 133 ts.add(i); 103 134 104 TreeSet<Node> ts2 = waysMap.get(i);135 Set<Node> ts2 = map.ways.get(i); 105 136 if (ts2 == null) { 106 137 ts2 = new TreeSet<Node>(); 107 waysMap.put(i, ts2);138 map.ways.put(i, ts2); 108 139 } 109 140 ts2.add(n); 110 141 } 111 142 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); 157 } 158 ts2.add(n); 159 } 160 161 private void addNodeWayMapReverse(Node n, int i) { 162 Set<Integer> ts = onewayReverseMap.nodes.get(n); 163 if (ts == null) { 164 ts = new TreeSet<Integer>(); 165 onewayReverseMap.nodes.put(n, ts); 166 } 167 ts.add(i); 168 } 169 170 private void addWayNodeMapReverse(Node n, int i) { 171 Set<Node> ts2 = onewayReverseMap.ways.get(i); 172 if (ts2 == null) { 173 ts2 = new TreeSet<Node>(); 174 onewayReverseMap.ways.put(i, ts2); 175 } 176 ts2.add(n); 177 } 178 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 112 192 /** 113 193 * Return a relation member that is linked to the 114 * member 'i', but has not been popped jet.194 * member 'i', but has not been popped yet. 115 195 * Return null if there is no such member left. 116 196 */ 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; 126 } 127 } 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; 128 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; 274 } 275 } 276 277 firstOneway = null; 278 lastOnewayNode = null; 279 280 return null; 281 } 282 283 /** 284 * find next node in nw NodeWays structure, if the node is found delete and return it 285 * @param nw 286 * @param n 287 * @return node next to n 288 */ 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 else 307 done(way); 308 nw.ways.get(way).remove(n); 129 309 } 130 310 … … 134 314 */ 135 315 public Integer pop() { 136 if (remaining.isEmpty()) return null; 137 Integer i = remaining.iterator().next(); 138 done(i); 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); 139 335 return i; 140 336 } … … 142 338 /** 143 339 * This relation member has been processed. 144 * Remove references in the nodesMap. 145 */ 340 * Remove references in the map.nodes. 341 */ 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 146 351 private void done(Integer i) { 147 352 remaining.remove(i); 148 TreeSet<Node> nodes = waysMap.get(i);353 Set<Node> nodes = map.ways.get(i); 149 354 for (Node n : nodes) { 150 boolean result = nodesMap.get(n).remove(i);355 boolean result = map.nodes.get(n).remove(i); 151 356 if (!result) throw new AssertionError(); 152 357 } -
trunk/src/org/openstreetmap/josm/gui/dialogs/relation/WayConnectionType.java
r3083 r3788 11 11 12 12 /** True, if linked to the previous / next member. */ 13 public finalboolean linkPrev;14 public finalboolean linkNext;13 public boolean linkPrev; 14 public boolean linkNext; 15 15 16 16 /** … … 23 23 * direction has the value NONE. 24 24 */ 25 public finalDirection direction;25 public Direction direction; 26 26 27 27 public enum Direction { … … 36 36 public boolean isLoop; 37 37 38 public boolean isRoundabout = false; 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; 39 43 40 44 public WayConnectionType(boolean linkPrev, boolean linkNext, Direction direction) { … … 44 48 this.direction = direction; 45 49 invalid = false; 50 } 51 52 public WayConnectionType(boolean invalid){ 53 this.invalid = invalid; 46 54 } 47 55 … … 61 69 @Override 62 70 public String toString() { 63 return "[P "+linkPrev+" ;N "+linkNext+" ;D "+direction+" ;L "+isLoop+"]"; 71 return "[P "+linkPrev+" ;N "+linkNext+" ;D "+direction+" ;L "+isLoop+ 72 " ;FP " + isOnewayLoopForwardPart+";BP " + isOnewayLoopBackwardPart+ 73 ";OH " + isOnewayHead+";OT " + isOnewayTail+"]"; 64 74 } 65 75
Note:
See TracChangeset
for help on using the changeset viewer.