View Javadoc
1   package org.opentrafficsim.road.gtu.lane.perception;
2   
3   import java.io.Serializable;
4   
5   import org.opentrafficsim.core.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-2016 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/node/13">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      /**
45       * Constructor.
46       * @param lat lateral direction (use {@code null} for the current lane)
47       * @param numLanes number of lanes in the lateral direction (not important for the current lane)
48       * @throws IllegalArgumentException if numLanes is not at least 1, except if {@code lat == null} (current lane)
49       * @throws IllegalArgumentException if numLanes is not 0 if {@code lat == null} (current lane)
50       */
51      public RelativeLane(final LateralDirectionality lat, final int numLanes)
52      {
53          Throw.whenNull(lat, "Lateral directionality may not be null.");
54          Throw.when(lat.equals(LateralDirectionality.NONE) && numLanes != 0, IllegalArgumentException.class,
55                  "Number of lanes must be zero if the lateral directionality is NONE.");
56          Throw.when(numLanes < 0, IllegalArgumentException.class,
57              "Relative lane with %d lanes in %s direction is not allowed, use values > 0.", numLanes, lat);
58          this.lat = lat;
59          this.numLanes = numLanes;
60      }
61  
62      /**
63       * Returns the lateral direction.
64       * @return lat lateral direction
65       */
66      public final LateralDirectionality getLateralDirectionality()
67      {
68          return this.lat;
69      }
70  
71      /**
72       * Returns the number of lanes in the lateral direction.
73       * @return number of lanes in the lateral direction
74       */
75      public final int getNumLanes()
76      {
77          return this.numLanes;
78      }
79  
80      /**
81       * Returns whether the second left lane is referred to.
82       * @return whether the second left lane is referred to
83       */
84      public final boolean isSecondLeft()
85      {
86          return this.equals(SECOND_LEFT);
87      }
88  
89      /**
90       * Returns whether the left lane is referred to.
91       * @return whether the left lane is referred to
92       */
93      public final boolean isLeft()
94      {
95          return this.equals(LEFT);
96      }
97  
98      /**
99       * Returns whether the current lane is referred to.
100      * @return whether the current lane is referred to
101      */
102     public final boolean isCurrent()
103     {
104         return this.equals(CURRENT);
105     }
106 
107     /**
108      * Returns whether the right lane is referred to.
109      * @return whether the right lane is referred to
110      */
111     public final boolean isRight()
112     {
113         return this.equals(RIGHT);
114     }
115 
116     /**
117      * Returns whether the second right lane is referred to.
118      * @return whether the second right lane is referred to
119      */
120     public final boolean isSecondRight()
121     {
122         return this.equals(SECOND_RIGHT);
123     }
124 
125     /**
126      * Returns the left hand relative lane of this relative lane.
127      * @return left hand relative lane of this relative lane.
128      */
129     public final RelativeLane getLeft()
130     {
131         return this.add(LEFT);
132     }
133 
134     /**
135      * Returns the right hand relative lane of this relative lane.
136      * @return right hand relative lane of this relative lane.
137      */
138     public final RelativeLane getRight()
139     {
140         return this.add(RIGHT);
141     }
142 
143     /**
144      * Returns the relative lane relative to this lane, for example "the left lane" of "the 3rd right lane" is
145      * "the 2nd right lane".
146      * @param relativeLane relative lane to get of this lane
147      * @return relative lane relative to this lane
148      */
149     public final RelativeLane add(final RelativeLane relativeLane)
150     {
151         int nThis = this.lat.isNone() ? 0 : this.lat.isLeft() ? -this.numLanes : this.numLanes;
152         int nOther =
153             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("]")
205             .toString();
206     }
207 
208     /** {@inheritDoc} */
209     @Override
210     public final int compareTo(final RelativeLane rel)
211     {
212         int nThis = this.lat.isNone() ? 0 : this.lat.isLeft() ? -this.numLanes : this.numLanes;
213         int nRel = rel.lat.isNone() ? 0 : rel.lat.isLeft() ? -rel.numLanes : rel.numLanes;
214         return nThis - nRel;
215     }
216 
217 }