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

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

checkstyle: enable relevant whitespace checks and fix them

  • Property svn:eol-style set to native
File size: 10.3 KB
RevLine 
[5630]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
[6286]18 private static final int UNCONNECTED = Integer.MIN_VALUE;
[5630]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;
[7005]27 final List<WayConnectionType> con = new ArrayList<>();
[5630]28
[8510]29 for (int i = 0; i < members.size(); ++i) {
[5630]30 con.add(null);
31 }
32
[8510]33 firstGroupIdx = 0;
[5630]34
35 lastForwardWay = UNCONNECTED;
36 lastBackwardWay = UNCONNECTED;
37 onewayBeginning = false;
38 WayConnectionType lastWct = null;
39
[8510]40 for (int i = 0; i < members.size(); ++i) {
[5630]41 final RelationMember m = members.get(i);
42 if (!m.isWay() || m.getWay() == null || m.getWay().isIncomplete()) {
[6289]43 if (i > 0) {
[5630]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);
[8510]52 wct.linkPrev = i > 0 && con.get(i-1) != null && con.get(i-1).isValid();
[5630]53 wct.direction = NONE;
54
[8510]55 if (RelationSortUtils.isOneway(m)) {
[6289]56 if (lastWct != null && lastWct.isOnewayTail) {
[5630]57 wct.isOnewayHead = true;
58 }
[8510]59 if (lastBackwardWay == UNCONNECTED && lastForwardWay == UNCONNECTED) { //Beginning of new oneway
[5630]60 wct.isOnewayHead = true;
61 lastForwardWay = i-1;
62 lastBackwardWay = i-1;
63 onewayBeginning = true;
64 }
65 }
66
67 if (wct.linkPrev) {
[6289]68 if (lastBackwardWay != UNCONNECTED && lastForwardWay != UNCONNECTED) {
[8406]69 determineOnewayConnectionType(con, m, i, wct);
[6289]70 if (!wct.linkPrev) {
[5630]71 firstGroupIdx = i;
72 }
73 }
74
[6289]75 if (!RelationSortUtils.isOneway(m)) {
[5630]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);
[8510]83 if (RelationSortUtils.isOneway(m)) {
[5630]84 wct.isOnewayLoopForwardPart = true;
85 lastForwardWay = i;
86 }
87 }
88
89 wct.linkNext = false;
[6289]90 if (lastWct != null) {
[5630]91 lastWct.linkNext = wct.linkPrev;
92 }
93 con.set(i, wct);
94 lastWct = wct;
95
[6289]96 if (!wct.linkPrev) {
97 if (i > 0) {
[5630]98 makeLoopIfNeeded(con, i-1);
99 }
100 firstGroupIdx = i;
101 }
102 }
103 makeLoopIfNeeded(con, members.size()-1);
104
105 return con;
106 }
107
[8285]108 private int firstGroupIdx;
[5630]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) {
[8510]117 for (int j = firstGroupIdx; j <= i; ++j) {
[5630]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
[8510]128 if (RelationSortUtils.isOneway(m)) {
[6289]129 if (RelationSortUtils.isBackward(m)) return BACKWARD;
[5630]130 else return FORWARD;
131 } else { /** guess the direction and see if it fits with the next member */
[6289]132 if (determineDirection(i, FORWARD, i+1) != NONE) return FORWARD;
133 if (determineDirection(i, BACKWARD, i+1) != NONE) return BACKWARD;
[5630]134 }
135 return NONE;
136 }
137
[8285]138 private int lastForwardWay;
139 private int lastBackwardWay;
140 private boolean onewayBeginning;
[8406]141
142 private void determineOnewayConnectionType(final List<WayConnectionType> con,
[5630]143 RelationMember m, int i, final WayConnectionType wct) {
144 Direction dirFW = determineDirection(lastForwardWay, con.get(lastForwardWay).direction, i);
145 Direction dirBW = NONE;
[6289]146 if (onewayBeginning) {
147 if (lastBackwardWay < 0) {
[5630]148 dirBW = determineDirection(firstGroupIdx, reverse(con.get(firstGroupIdx).direction), i, true);
149 } else {
150 dirBW = determineDirection(lastBackwardWay, con.get(lastBackwardWay).direction, i, true);
151 }
152
[6289]153 if (dirBW != NONE) {
[5630]154 onewayBeginning = false;
155 }
156 } else {
157 dirBW = determineDirection(lastBackwardWay, con.get(lastBackwardWay).direction, i, true);
158 }
159
[6289]160 if (RelationSortUtils.isOneway(m)) {
[8510]161 if (dirBW != NONE) {
[5630]162 wct.direction = dirBW;
163 lastBackwardWay = i;
164 wct.isOnewayLoopBackwardPart = true;
165 }
[8510]166 if (dirFW != NONE) {
[5630]167 wct.direction = dirFW;
168 lastForwardWay = i;
169 wct.isOnewayLoopForwardPart = true;
170 }
[6296]171 // Not connected to previous
172 if (dirFW == NONE && dirBW == NONE) {
[5630]173 wct.linkPrev = false;
[6296]174 if (RelationSortUtils.isOneway(m)) {
[5630]175 wct.isOnewayHead = true;
176 lastForwardWay = i-1;
177 lastBackwardWay = i-1;
178 } else {
179 lastForwardWay = UNCONNECTED;
180 lastBackwardWay = UNCONNECTED;
181 }
182 onewayBeginning = true;
183 }
184
[6289]185 if (dirFW != NONE && dirBW != NONE) { //End of oneway loop
[8510]186 if (i+1 < members.size() && determineDirection(i, dirFW, i+1) != NONE) {
[5630]187 wct.isOnewayLoopBackwardPart = false;
188 wct.direction = dirFW;
189 } else {
190 wct.isOnewayLoopForwardPart = false;
191 wct.direction = dirBW;
192 }
193
194 wct.isOnewayTail = true;
195 }
196
197 } else {
198 lastForwardWay = UNCONNECTED;
199 lastBackwardWay = UNCONNECTED;
[6289]200 if (dirFW == NONE || dirBW == NONE) {
[5630]201 wct.linkPrev = false;
202 }
203 }
204 }
205
[8510]206 private static Direction reverse(final Direction dir) {
[6289]207 if (dir == FORWARD) return BACKWARD;
208 if (dir == BACKWARD) return FORWARD;
[5630]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 */
[8510]249 List<Node> refNodes = new ArrayList<>();
[5630]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 }
[6289]273 } else if (RelationSortUtils.isOneway(m)) {
[5630]274 if (n == RelationNodeMap.firstOnewayNode(m) && !reversed) {
[6289]275 if (RelationSortUtils.isBackward(m))
[5630]276 return BACKWARD;
277 else
278 return FORWARD;
279 }
280 if (n == RelationNodeMap.lastOnewayNode(m) && reversed) {
[6289]281 if (RelationSortUtils.isBackward(m))
[5630]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.