RelativeLane.java
package org.opentrafficsim.road.gtu.lane.perception;
import java.io.Serializable;
import org.opentrafficsim.core.network.LateralDirectionality;
import nl.tudelft.simulation.language.Throw;
/**
* Defines a lane relative to the current lane.
* <p>
* Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
* BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
* <p>
* @version $Revision$, $LastChangedDate$, by $Author$, initial version May 2, 2016 <br>
* @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
*/
public class RelativeLane implements Comparable<RelativeLane>, Serializable
{
/** */
private static final long serialVersionUID = 20160502L;
/** Second left lane. */
public static final RelativeLane SECOND_LEFT = new RelativeLane(LateralDirectionality.LEFT, 2);
/** Left lane. */
public static final RelativeLane LEFT = new RelativeLane(LateralDirectionality.LEFT, 1);
/** Current lane. */
public static final RelativeLane CURRENT = new RelativeLane(LateralDirectionality.NONE, 0);
/** right lane. */
public static final RelativeLane RIGHT = new RelativeLane(LateralDirectionality.RIGHT, 1);
/** Second right lane. */
public static final RelativeLane SECOND_RIGHT = new RelativeLane(LateralDirectionality.RIGHT, 2);
/** Lateral direction. */
private final LateralDirectionality lat;
/** Number of lanes to lateral direction. */
private final int numLanes;
/**
* Constructor.
* @param lat lateral direction (use {@code null} for the current lane)
* @param numLanes number of lanes in the lateral direction (not important for the current lane)
* @throws IllegalArgumentException if numLanes is not at least 1, except if {@code lat == null} (current lane)
* @throws IllegalArgumentException if numLanes is not 0 if {@code lat == null} (current lane)
*/
public RelativeLane(final LateralDirectionality lat, final int numLanes)
{
Throw.whenNull(lat, "Lateral directionality may not be null.");
Throw.when(lat.equals(LateralDirectionality.NONE) && numLanes != 0, IllegalArgumentException.class,
"Number of lanes must be zero if the lateral directionality is NONE.");
Throw.when(numLanes < 0, IllegalArgumentException.class,
"Relative lane with %d lanes in %s direction is not allowed, use values > 0.", numLanes, lat);
this.lat = lat;
this.numLanes = numLanes;
}
/**
* Returns the lateral direction.
* @return lat lateral direction
*/
public final LateralDirectionality getLateralDirectionality()
{
return this.lat;
}
/**
* Returns the number of lanes in the lateral direction.
* @return number of lanes in the lateral direction
*/
public final int getNumLanes()
{
return this.numLanes;
}
/**
* Returns whether the second left lane is referred to.
* @return whether the second left lane is referred to
*/
public final boolean isSecondLeft()
{
return this.equals(SECOND_LEFT);
}
/**
* Returns whether the left lane is referred to.
* @return whether the left lane is referred to
*/
public final boolean isLeft()
{
return this.equals(LEFT);
}
/**
* Returns whether the current lane is referred to.
* @return whether the current lane is referred to
*/
public final boolean isCurrent()
{
return this.equals(CURRENT);
}
/**
* Returns whether the right lane is referred to.
* @return whether the right lane is referred to
*/
public final boolean isRight()
{
return this.equals(RIGHT);
}
/**
* Returns whether the second right lane is referred to.
* @return whether the second right lane is referred to
*/
public final boolean isSecondRight()
{
return this.equals(SECOND_RIGHT);
}
/**
* Returns the left hand relative lane of this relative lane.
* @return left hand relative lane of this relative lane.
*/
public final RelativeLane getLeft()
{
return this.add(LEFT);
}
/**
* Returns the right hand relative lane of this relative lane.
* @return right hand relative lane of this relative lane.
*/
public final RelativeLane getRight()
{
return this.add(RIGHT);
}
/**
* Returns the relative lane relative to this lane, for example "the left lane" of "the 3rd right lane" is
* "the 2nd right lane".
* @param relativeLane relative lane to get of this lane
* @return relative lane relative to this lane
*/
public final RelativeLane add(final RelativeLane relativeLane)
{
int nThis = this.lat.isNone() ? 0 : this.lat.isLeft() ? -this.numLanes : this.numLanes;
int nOther =
relativeLane.lat.isNone() ? 0 : relativeLane.lat.isLeft() ? -relativeLane.numLanes : relativeLane.numLanes;
int nSum = nThis + nOther;
if (nSum < 0)
{
return new RelativeLane(LateralDirectionality.LEFT, -nSum);
}
if (nSum > 0)
{
return new RelativeLane(LateralDirectionality.RIGHT, nSum);
}
return CURRENT;
}
/** {@inheritDoc} */
@Override
public final int hashCode()
{
int result = 17;
result = 31 * result + (this.lat != null ? this.lat.hashCode() : 0);
result = 31 * result + this.numLanes;
return result;
}
/** {@inheritDoc} */
@Override
public final boolean equals(final Object obj)
{
if (obj == this)
{
return true;
}
if (!(obj instanceof RelativeLane))
{
return false;
}
RelativeLane rel = (RelativeLane) obj;
if (rel.lat == this.lat && rel.numLanes == this.numLanes)
{
return true;
}
return false;
}
/** {@inheritDoc} */
@Override
public final String toString()
{
if (this.equals(CURRENT))
{
return "RelativeLane [CURRENT]";
}
return new StringBuilder("RelativeLane [").append(this.lat).append(", ").append(this.numLanes).append("]")
.toString();
}
/** {@inheritDoc} */
@Override
public final int compareTo(final RelativeLane rel)
{
int nThis = this.lat.isNone() ? 0 : this.lat.isLeft() ? -this.numLanes : this.numLanes;
int nRel = rel.lat.isNone() ? 0 : rel.lat.isLeft() ? -rel.numLanes : rel.numLanes;
return nThis - nRel;
}
}