1 package org.opentrafficsim.road.gtu.lane.perception;
2
3 import org.djutils.exceptions.Throw;
4 import org.opentrafficsim.core.network.LateralDirectionality;
5
6
7
8
9
10
11
12
13
14 public class RelativeLane implements Comparable<RelativeLane>
15 {
16
17
18 public static final RelativeLane SECOND_LEFT = new RelativeLane(LateralDirectionality.LEFT, 2);
19
20
21 public static final RelativeLane LEFT = new RelativeLane(LateralDirectionality.LEFT, 1);
22
23
24 public static final RelativeLane CURRENT = new RelativeLane(LateralDirectionality.NONE, 0);
25
26
27 public static final RelativeLane RIGHT = new RelativeLane(LateralDirectionality.RIGHT, 1);
28
29
30 public static final RelativeLane SECOND_RIGHT = new RelativeLane(LateralDirectionality.RIGHT, 2);
31
32
33
34
35
36 private final int rank;
37
38
39
40
41
42 private RelativeLane(final int rank)
43 {
44 this.rank = rank;
45 }
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((!lat.isNone()) && numLanes <= 0, IllegalArgumentException.class,
60 "Relative lane with %d lanes in %s direction is not allowed, use values > 0.", numLanes, lat);
61 this.rank = lat.isLeft() ? -numLanes : numLanes;
62 }
63
64
65
66
67
68 public final LateralDirectionality getLateralDirectionality()
69 {
70
71 return this.rank == 0 ? LateralDirectionality.NONE
72 : this.rank < 0 ? LateralDirectionality.LEFT : LateralDirectionality.RIGHT;
73 }
74
75
76
77
78
79 public final int getNumLanes()
80 {
81 return Math.abs(this.rank);
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 return new RelativeLane(this.rank + relativeLane.rank);
156 }
157
158 @Override
159 public int hashCode()
160 {
161 final int prime = 31;
162 int result = 1;
163 result = prime * result + this.rank;
164 return result;
165 }
166
167 @Override
168 public boolean equals(final Object obj)
169 {
170 if (this == obj)
171 {
172 return true;
173 }
174 if (obj == null)
175 {
176 return false;
177 }
178 if (getClass() != obj.getClass())
179 {
180 return false;
181 }
182 RelativeLane other = (RelativeLane) obj;
183 if (this.rank != other.rank)
184 {
185 return false;
186 }
187 return true;
188 }
189
190 @Override
191 public final String toString()
192 {
193 if (this.equals(CURRENT))
194 {
195 return "RelativeLane [CURRENT]";
196 }
197 return new StringBuilder("RelativeLane [").append(getLateralDirectionality()).append(", ").append(getNumLanes())
198 .append("]").toString();
199 }
200
201 @Override
202 public final int compareTo(final RelativeLane rel)
203 {
204 return this.rank - rel.rank;
205 }
206
207 }