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