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 * Defines a lane relative to the current lane.
11 * <p>
12 * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
13 * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
14 * <p>
15 * @version $Revision$, $LastChangedDate$, by $Author$, initial version May 2, 2016 <br>
16 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
17 */
18 public class RelativeLane implements Comparable<RelativeLane>, Serializable
19 {
20
21 /** */
22 private static final long serialVersionUID = 20160502L;
23
24 /** Second left lane. */
25 public static final RelativeLane SECOND_LEFT = new RelativeLane(LateralDirectionality.LEFT, 2);
26
27 /** Left lane. */
28 public static final RelativeLane LEFT = new RelativeLane(LateralDirectionality.LEFT, 1);
29
30 /** Current lane. */
31 public static final RelativeLane CURRENT = new RelativeLane(LateralDirectionality.NONE, 0);
32
33 /** right lane. */
34 public static final RelativeLane RIGHT = new RelativeLane(LateralDirectionality.RIGHT, 1);
35
36 /** Second right lane. */
37 public static final RelativeLane SECOND_RIGHT = new RelativeLane(LateralDirectionality.RIGHT, 2);
38
39 /** Lateral direction. */
40 private final LateralDirectionality lat;
41
42 /** Number of lanes to lateral direction. */
43 private final int numLanes;
44
45 /** Rank, for sorting. Is equal to number of lanes, but negative for left lanes. */
46 private final int rank;
47
48 /**
49 * Constructor.
50 * @param lat lateral direction (use {@code null} for the current lane)
51 * @param numLanes number of lanes in the lateral direction (not important for the current lane)
52 * @throws IllegalArgumentException if numLanes is not at least 1, except if {@code lat == null} (current lane)
53 * @throws IllegalArgumentException if numLanes is not 0 if {@code lat == null} (current lane)
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 * Returns the lateral direction.
69 * @return lat lateral direction
70 */
71 public final LateralDirectionality getLateralDirectionality()
72 {
73 return this.lat;
74 }
75
76 /**
77 * Returns the number of lanes in the lateral direction.
78 * @return number of lanes in the lateral direction
79 */
80 public final int getNumLanes()
81 {
82 return this.numLanes;
83 }
84
85 /**
86 * Returns whether the second left lane is referred to.
87 * @return whether the second left lane is referred to
88 */
89 public final boolean isSecondLeft()
90 {
91 return this.equals(SECOND_LEFT);
92 }
93
94 /**
95 * Returns whether the left lane is referred to.
96 * @return whether the left lane is referred to
97 */
98 public final boolean isLeft()
99 {
100 return this.equals(LEFT);
101 }
102
103 /**
104 * Returns whether the current lane is referred to.
105 * @return whether the current lane is referred to
106 */
107 public final boolean isCurrent()
108 {
109 return this.equals(CURRENT);
110 }
111
112 /**
113 * Returns whether the right lane is referred to.
114 * @return whether the right lane is referred to
115 */
116 public final boolean isRight()
117 {
118 return this.equals(RIGHT);
119 }
120
121 /**
122 * Returns whether the second right lane is referred to.
123 * @return whether the second right lane is referred to
124 */
125 public final boolean isSecondRight()
126 {
127 return this.equals(SECOND_RIGHT);
128 }
129
130 /**
131 * Returns the left hand relative lane of this relative lane.
132 * @return left hand relative lane of this relative lane.
133 */
134 public final RelativeLane getLeft()
135 {
136 return this.add(LEFT);
137 }
138
139 /**
140 * Returns the right hand relative lane of this relative lane.
141 * @return right hand relative lane of this relative lane.
142 */
143 public final RelativeLane getRight()
144 {
145 return this.add(RIGHT);
146 }
147
148 /**
149 * Returns the relative lane relative to this lane, for example "the left lane" of "the 3rd right lane" is "the 2nd right
150 * lane".
151 * @param relativeLane relative lane to get of this lane
152 * @return relative lane relative to this lane
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 /** {@inheritDoc} */
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 /** {@inheritDoc} */
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) // relative lane us uniquely defined by the rank
196 {
197 return false;
198 }
199 return true;
200 }
201
202 /** {@inheritDoc} */
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 /** {@inheritDoc} */
214 @Override
215 public final int compareTo(final RelativeLane rel)
216 {
217 return this.rank - rel.rank;
218 }
219
220 }