source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/sort/WayConnectionTypeCalculator.java@ 8285

Last change on this file since 8285 was 8285, checked in by Don-vip, 9 years ago

fix sonar squid:S2039 - Member variable visibility should be specified

  • Property svn:eol-style set to native
File size: 10.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.relation.sort;
3
4import static org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction.BACKWARD;
5import static org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction.FORWARD;
6import static org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction.NONE;
7
8import java.util.ArrayList;
9import java.util.List;
10
11import org.openstreetmap.josm.data.osm.Node;
12import org.openstreetmap.josm.data.osm.RelationMember;
13import org.openstreetmap.josm.data.osm.Way;
14import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction;
15
16public class WayConnectionTypeCalculator {
17
18 private static final int UNCONNECTED = Integer.MIN_VALUE;
19
20 private List<RelationMember> members;
21
22 /**
23 * refresh the cache of member WayConnectionTypes
24 */
25 public List<WayConnectionType> updateLinks(List<RelationMember> members) {
26 this.members = members;
27 final List<WayConnectionType> con = new ArrayList<>();
28
29 for (int i=0; i<members.size(); ++i) {
30 con.add(null);
31 }
32
33 firstGroupIdx=0;
34
35 lastForwardWay = UNCONNECTED;
36 lastBackwardWay = UNCONNECTED;
37 onewayBeginning = false;
38 WayConnectionType lastWct = null;
39
40 for (int i=0; i<members.size(); ++i) {
41 final RelationMember m = members.get(i);
42 if (!m.isWay() || m.getWay() == null || m.getWay().isIncomplete()) {
43 if (i > 0) {
44 makeLoopIfNeeded(con, i-1);
45 }
46 con.set(i, new WayConnectionType());
47 firstGroupIdx = i;
48 continue;
49 }
50
51 WayConnectionType wct = new WayConnectionType(false);
52 wct.linkPrev = i>0 && con.get(i-1) != null && con.get(i-1).isValid();
53 wct.direction = NONE;
54
55 if (RelationSortUtils.isOneway(m)){
56 if (lastWct != null && lastWct.isOnewayTail) {
57 wct.isOnewayHead = true;
58 }
59 if (lastBackwardWay == UNCONNECTED && lastForwardWay == UNCONNECTED){ //Beginning of new oneway
60 wct.isOnewayHead = true;
61 lastForwardWay = i-1;
62 lastBackwardWay = i-1;
63 onewayBeginning = true;
64 }
65 }
66
67 if (wct.linkPrev) {
68 if (lastBackwardWay != UNCONNECTED && lastForwardWay != UNCONNECTED) {
69 wct = determineOnewayConnectionType(con, m, i, wct);
70 if (!wct.linkPrev) {
71 firstGroupIdx = i;
72 }
73 }
74
75 if (!RelationSortUtils.isOneway(m)) {
76 wct.direction = determineDirection(i-1, lastWct.direction, i);
77 wct.linkPrev = (wct.direction != NONE);
78 }
79 }
80
81 if (!wct.linkPrev) {
82 wct.direction = determineDirectionOfFirst(i, m);
83 if (RelationSortUtils.isOneway(m)){
84 wct.isOnewayLoopForwardPart = true;
85 lastForwardWay = i;
86 }
87 }
88
89 wct.linkNext = false;
90 if (lastWct != null) {
91 lastWct.linkNext = wct.linkPrev;
92 }
93 con.set(i, wct);
94 lastWct = wct;
95
96 if (!wct.linkPrev) {
97 if (i > 0) {
98 makeLoopIfNeeded(con, i-1);
99 }
100 firstGroupIdx = i;
101 }
102 }
103 makeLoopIfNeeded(con, members.size()-1);
104
105 return con;
106 }
107
108 private int firstGroupIdx;
109 private void makeLoopIfNeeded(final List<WayConnectionType> con, final int i) {
110 boolean loop;
111 if (i == firstGroupIdx) { //is primitive loop
112 loop = determineDirection(i, FORWARD, i) == FORWARD;
113 } else {
114 loop = determineDirection(i, con.get(i).direction, firstGroupIdx) == con.get(firstGroupIdx).direction;
115 }
116 if (loop) {
117 for (int j=firstGroupIdx; j <= i; ++j) {
118 con.get(j).isLoop = true;
119 }
120 }
121 }
122
123 private Direction determineDirectionOfFirst(final int i, final RelationMember m) {
124 Direction result = RelationSortUtils.roundaboutType(m);
125 if (result != NONE)
126 return result;
127
128 if (RelationSortUtils.isOneway(m)){
129 if (RelationSortUtils.isBackward(m)) return BACKWARD;
130 else return FORWARD;
131 } else { /** guess the direction and see if it fits with the next member */
132 if (determineDirection(i, FORWARD, i+1) != NONE) return FORWARD;
133 if (determineDirection(i, BACKWARD, i+1) != NONE) return BACKWARD;
134 }
135 return NONE;
136 }
137
138 private int lastForwardWay;
139 private int lastBackwardWay;
140 private boolean onewayBeginning;
141 private WayConnectionType determineOnewayConnectionType(final List<WayConnectionType> con,
142 RelationMember m, int i, final WayConnectionType wct) {
143 Direction dirFW = determineDirection(lastForwardWay, con.get(lastForwardWay).direction, i);
144 Direction dirBW = NONE;
145 if (onewayBeginning) {
146 if (lastBackwardWay < 0) {
147 dirBW = determineDirection(firstGroupIdx, reverse(con.get(firstGroupIdx).direction), i, true);
148 } else {
149 dirBW = determineDirection(lastBackwardWay, con.get(lastBackwardWay).direction, i, true);
150 }
151
152 if (dirBW != NONE) {
153 onewayBeginning = false;
154 }
155 } else {
156 dirBW = determineDirection(lastBackwardWay, con.get(lastBackwardWay).direction, i, true);
157 }
158
159 if (RelationSortUtils.isOneway(m)) {
160 if (dirBW != NONE){
161 wct.direction = dirBW;
162 lastBackwardWay = i;
163 wct.isOnewayLoopBackwardPart = true;
164 }
165 if (dirFW != NONE){
166 wct.direction = dirFW;
167 lastForwardWay = i;
168 wct.isOnewayLoopForwardPart = true;
169 }
170 // Not connected to previous
171 if (dirFW == NONE && dirBW == NONE) {
172 wct.linkPrev = false;
173 if (RelationSortUtils.isOneway(m)) {
174 wct.isOnewayHead = true;
175 lastForwardWay = i-1;
176 lastBackwardWay = i-1;
177 } else {
178 lastForwardWay = UNCONNECTED;
179 lastBackwardWay = UNCONNECTED;
180 }
181 onewayBeginning = true;
182 }
183
184 if (dirFW != NONE && dirBW != NONE) { //End of oneway loop
185 if (i+1<members.size() && determineDirection(i, dirFW, i+1) != NONE) {
186 wct.isOnewayLoopBackwardPart = false;
187 wct.direction = dirFW;
188 } else {
189 wct.isOnewayLoopForwardPart = false;
190 wct.direction = dirBW;
191 }
192
193 wct.isOnewayTail = true;
194 }
195
196 } else {
197 lastForwardWay = UNCONNECTED;
198 lastBackwardWay = UNCONNECTED;
199 if (dirFW == NONE || dirBW == NONE) {
200 wct.linkPrev = false;
201 }
202 }
203 return wct;
204 }
205
206 private static Direction reverse(final Direction dir){
207 if (dir == FORWARD) return BACKWARD;
208 if (dir == BACKWARD) return FORWARD;
209 return dir;
210 }
211
212 private Direction determineDirection(int ref_i, Direction ref_direction, int k) {
213 return determineDirection(ref_i, ref_direction, k, false);
214 }
215 /**
216 * Determines the direction of way k with respect to the way ref_i.
217 * The way ref_i is assumed to have the direction ref_direction and
218 * to be the predecessor of k.
219 *
220 * If both ways are not linked in any way, NONE is returned.
221 *
222 * Else the direction is given as follows:
223 * Let the relation be a route of oneway streets, and someone travels them in the given order.
224 * Direction is FORWARD if it is legal and BACKWARD if it is illegal to do so for the given way.
225 *
226 **/
227 private Direction determineDirection(int ref_i, final Direction ref_direction, int k, boolean reversed) {
228 if (ref_i < 0 || k < 0 || ref_i >= members.size() || k >= members.size())
229 return NONE;
230 if (ref_direction == NONE)
231 return NONE;
232
233 final RelationMember m_ref = members.get(ref_i);
234 final RelationMember m = members.get(k);
235 Way way_ref = null;
236 Way way = null;
237
238 if (m_ref.isWay()) {
239 way_ref = m_ref.getWay();
240 }
241 if (m.isWay()) {
242 way = m.getWay();
243 }
244
245 if (way_ref == null || way == null)
246 return NONE;
247
248 /** the list of nodes the way k can dock to */
249 List<Node> refNodes= new ArrayList<>();
250
251 switch (ref_direction) {
252 case FORWARD:
253 refNodes.add(way_ref.lastNode());
254 break;
255 case BACKWARD:
256 refNodes.add(way_ref.firstNode());
257 break;
258 case ROUNDABOUT_LEFT:
259 case ROUNDABOUT_RIGHT:
260 refNodes = way_ref.getNodes();
261 break;
262 }
263
264 for (Node n : refNodes) {
265 if (n == null) {
266 continue;
267 }
268 if (RelationSortUtils.roundaboutType(members.get(k)) != NONE) {
269 for (Node nn : way.getNodes()) {
270 if (n == nn)
271 return RelationSortUtils.roundaboutType(members.get(k));
272 }
273 } else if (RelationSortUtils.isOneway(m)) {
274 if (n == RelationNodeMap.firstOnewayNode(m) && !reversed) {
275 if (RelationSortUtils.isBackward(m))
276 return BACKWARD;
277 else
278 return FORWARD;
279 }
280 if (n == RelationNodeMap.lastOnewayNode(m) && reversed) {
281 if (RelationSortUtils.isBackward(m))
282 return FORWARD;
283 else
284 return BACKWARD;
285 }
286 } else {
287 if (n == way.firstNode())
288 return FORWARD;
289 if (n == way.lastNode())
290 return BACKWARD;
291 }
292 }
293 return NONE;
294 }
295}
Note: See TracBrowser for help on using the repository browser.