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