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