View Javadoc
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-2017 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      /**
46       * Constructor.
47       * @param lat lateral direction (use {@code null} for the current lane)
48       * @param numLanes number of lanes in the lateral direction (not important for the current lane)
49       * @throws IllegalArgumentException if numLanes is not at least 1, except if {@code lat == null} (current lane)
50       * @throws IllegalArgumentException if numLanes is not 0 if {@code lat == null} (current lane)
51       */
52      public RelativeLane(final LateralDirectionality lat, final int numLanes)
53      {
54          Throw.whenNull(lat, "Lateral directionality may not be null.");
55          Throw.when(lat.equals(LateralDirectionality.NONE) && numLanes != 0, IllegalArgumentException.class,
56                  "Number of lanes must be zero if the lateral directionality is NONE.");
57          Throw.when(numLanes < 0, IllegalArgumentException.class,
58                  "Relative lane with %d lanes in %s direction is not allowed, use values > 0.", numLanes, lat);
59          this.lat = lat;
60          this.numLanes = numLanes;
61      }
62  
63      /**
64       * Returns the lateral direction.
65       * @return lat lateral direction
66       */
67      public final LateralDirectionality getLateralDirectionality()
68      {
69          return this.lat;
70      }
71  
72      /**
73       * Returns the number of lanes in the lateral direction.
74       * @return number of lanes in the lateral direction
75       */
76      public final int getNumLanes()
77      {
78          return this.numLanes;
79      }
80  
81      /**
82       * Returns whether the second left lane is referred to.
83       * @return whether the second left lane is referred to
84       */
85      public final boolean isSecondLeft()
86      {
87          return this.equals(SECOND_LEFT);
88      }
89  
90      /**
91       * Returns whether the left lane is referred to.
92       * @return whether the left lane is referred to
93       */
94      public final boolean isLeft()
95      {
96          return this.equals(LEFT);
97      }
98  
99      /**
100      * Returns whether the current lane is referred to.
101      * @return whether the current lane is referred to
102      */
103     public final boolean isCurrent()
104     {
105         return this.equals(CURRENT);
106     }
107 
108     /**
109      * Returns whether the right lane is referred to.
110      * @return whether the right lane is referred to
111      */
112     public final boolean isRight()
113     {
114         return this.equals(RIGHT);
115     }
116 
117     /**
118      * Returns whether the second right lane is referred to.
119      * @return whether the second right lane is referred to
120      */
121     public final boolean isSecondRight()
122     {
123         return this.equals(SECOND_RIGHT);
124     }
125 
126     /**
127      * Returns the left hand relative lane of this relative lane.
128      * @return left hand relative lane of this relative lane.
129      */
130     public final RelativeLane getLeft()
131     {
132         return this.add(LEFT);
133     }
134 
135     /**
136      * Returns the right hand relative lane of this relative lane.
137      * @return right hand relative lane of this relative lane.
138      */
139     public final RelativeLane getRight()
140     {
141         return this.add(RIGHT);
142     }
143 
144     /**
145      * Returns the relative lane relative to this lane, for example "the left lane" of "the 3rd right lane" is "the 2nd right
146      * lane".
147      * @param relativeLane relative lane to get of this lane
148      * @return relative lane relative to this lane
149      */
150     public final RelativeLane add(final RelativeLane relativeLane)
151     {
152         int nThis = this.lat.isNone() ? 0 : this.lat.isLeft() ? -this.numLanes : this.numLanes;
153         int nOther = relativeLane.lat.isNone() ? 0 : relativeLane.lat.isLeft() ? -relativeLane.numLanes : relativeLane.numLanes;
154         int nSum = nThis + nOther;
155         if (nSum < 0)
156         {
157             return new RelativeLane(LateralDirectionality.LEFT, -nSum);
158         }
159         if (nSum > 0)
160         {
161             return new RelativeLane(LateralDirectionality.RIGHT, nSum);
162         }
163         return CURRENT;
164     }
165 
166     /** {@inheritDoc} */
167     @Override
168     public final int hashCode()
169     {
170         int result = 17;
171         result = 31 * result + (this.lat != null ? this.lat.hashCode() : 0);
172         result = 31 * result + this.numLanes;
173         return result;
174     }
175 
176     /** {@inheritDoc} */
177     @Override
178     public final boolean equals(final Object obj)
179     {
180         if (obj == this)
181         {
182             return true;
183         }
184         if (!(obj instanceof RelativeLane))
185         {
186             return false;
187         }
188         RelativeLane rel = (RelativeLane) obj;
189         if (rel.lat == this.lat && rel.numLanes == this.numLanes)
190         {
191             return true;
192         }
193         return false;
194     }
195 
196     /** {@inheritDoc} */
197     @Override
198     public final String toString()
199     {
200         if (this.equals(CURRENT))
201         {
202             return "RelativeLane [CURRENT]";
203         }
204         return new StringBuilder("RelativeLane [").append(this.lat).append(", ").append(this.numLanes).append("]").toString();
205     }
206 
207     /** {@inheritDoc} */
208     @Override
209     public final int compareTo(final RelativeLane rel)
210     {
211         int nThis = this.lat.isNone() ? 0 : this.lat.isLeft() ? -this.numLanes : this.numLanes;
212         int nRel = rel.lat.isNone() ? 0 : rel.lat.isLeft() ? -rel.numLanes : rel.numLanes;
213         return nThis - nRel;
214     }
215 
216 }