1 package org.opentrafficsim.road.gtu.lane.perception;
2
3 import java.io.Serializable;
4
5 import org.opentrafficsim.core.network.LateralDirectionality;
6
7 import nl.tudelft.simulation.language.Throw;
8
9
10
11
12
13
14
15
16
17
18 public class RelativeLane implements Comparable<RelativeLane>, Serializable
19 {
20
21
22 private static final long serialVersionUID = 20160502L;
23
24
25 public static final RelativeLane SECOND_LEFT = new RelativeLane(LateralDirectionality.LEFT, 2);
26
27
28 public static final RelativeLane LEFT = new RelativeLane(LateralDirectionality.LEFT, 1);
29
30
31 public static final RelativeLane CURRENT = new RelativeLane(LateralDirectionality.NONE, 0);
32
33
34 public static final RelativeLane RIGHT = new RelativeLane(LateralDirectionality.RIGHT, 1);
35
36
37 public static final RelativeLane SECOND_RIGHT = new RelativeLane(LateralDirectionality.RIGHT, 2);
38
39
40 private final LateralDirectionality lat;
41
42
43 private final int numLanes;
44
45
46 private final int rank;
47
48
49
50
51
52
53
54
55 public RelativeLane(final LateralDirectionality lat, final int numLanes)
56 {
57 Throw.whenNull(lat, "Lateral directionality may not be null.");
58 Throw.when(lat.isNone() && numLanes != 0, IllegalArgumentException.class,
59 "Number of lanes must be zero if the lateral directionality is NONE.");
60 Throw.when(numLanes < 0, IllegalArgumentException.class,
61 "Relative lane with %d lanes in %s direction is not allowed, use values > 0.", numLanes, lat);
62 this.lat = lat;
63 this.numLanes = numLanes;
64 this.rank = lat.isLeft() ? -numLanes : numLanes;
65 }
66
67
68
69
70
71 public final LateralDirectionality getLateralDirectionality()
72 {
73 return this.lat;
74 }
75
76
77
78
79
80 public final int getNumLanes()
81 {
82 return this.numLanes;
83 }
84
85
86
87
88
89 public final boolean isSecondLeft()
90 {
91 return this.equals(SECOND_LEFT);
92 }
93
94
95
96
97
98 public final boolean isLeft()
99 {
100 return this.equals(LEFT);
101 }
102
103
104
105
106
107 public final boolean isCurrent()
108 {
109 return this.equals(CURRENT);
110 }
111
112
113
114
115
116 public final boolean isRight()
117 {
118 return this.equals(RIGHT);
119 }
120
121
122
123
124
125 public final boolean isSecondRight()
126 {
127 return this.equals(SECOND_RIGHT);
128 }
129
130
131
132
133
134 public final RelativeLane getLeft()
135 {
136 return this.add(LEFT);
137 }
138
139
140
141
142
143 public final RelativeLane getRight()
144 {
145 return this.add(RIGHT);
146 }
147
148
149
150
151
152
153
154 public final RelativeLane add(final RelativeLane relativeLane)
155 {
156 int rankSum = this.rank + relativeLane.rank;
157 if (rankSum < 0)
158 {
159 return new RelativeLane(LateralDirectionality.LEFT, -rankSum);
160 }
161 if (rankSum > 0)
162 {
163 return new RelativeLane(LateralDirectionality.RIGHT, rankSum);
164 }
165 return CURRENT;
166 }
167
168
169 @Override
170 public int hashCode()
171 {
172 final int prime = 31;
173 int result = 1;
174 result = prime * result + this.rank;
175 return result;
176 }
177
178
179 @Override
180 public boolean equals(final Object obj)
181 {
182 if (this == obj)
183 {
184 return true;
185 }
186 if (obj == null)
187 {
188 return false;
189 }
190 if (getClass() != obj.getClass())
191 {
192 return false;
193 }
194 RelativeLane other = (RelativeLane) obj;
195 if (this.rank != other.rank)
196 {
197 return false;
198 }
199 return true;
200 }
201
202
203 @Override
204 public final String toString()
205 {
206 if (this.equals(CURRENT))
207 {
208 return "RelativeLane [CURRENT]";
209 }
210 return new StringBuilder("RelativeLane [").append(this.lat).append(", ").append(this.numLanes).append("]").toString();
211 }
212
213
214 @Override
215 public final int compareTo(final RelativeLane rel)
216 {
217 return this.rank - rel.rank;
218 }
219
220 }