LaneDirection.java

  1. package org.opentrafficsim.road.network.lane;

  2. import java.io.Serializable;
  3. import java.util.HashSet;
  4. import java.util.Map;
  5. import java.util.Set;

  6. import org.djunits.value.vdouble.scalar.Length;
  7. import org.djutils.exceptions.Try;
  8. import org.opentrafficsim.core.geometry.OTSGeometryException;
  9. import org.opentrafficsim.core.gtu.GTUDirectionality;
  10. import org.opentrafficsim.core.network.LateralDirectionality;
  11. import org.opentrafficsim.core.network.LinkDirection;
  12. import org.opentrafficsim.core.network.NetworkException;
  13. import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;

  14. import nl.tudelft.simulation.language.d3.DirectedPoint;

  15. /**
  16.  * <p>
  17.  * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  18.  * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
  19.  * </p>
  20.  * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
  21.  * initial version Mar 30, 2016 <br>
  22.  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  23.  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  24.  */
  25. public class LaneDirection implements Serializable
  26. {
  27.     /** */
  28.     private static final long serialVersionUID = 20160330L;

  29.     /** The lane. */
  30.     private final Lane lane;

  31.     /** The GTU direction to drive on this lane. */
  32.     private final GTUDirectionality direction;

  33.     /**
  34.      * @param lane Lane; the lane
  35.      * @param direction GTUDirectionality; the direction to drive on this lane
  36.      */
  37.     public LaneDirection(final Lane lane, final GTUDirectionality direction)
  38.     {
  39.         super();
  40.         this.lane = lane;
  41.         this.direction = direction;
  42.     }

  43.     /**
  44.      * @return the lane
  45.      */
  46.     public final Lane getLane()
  47.     {
  48.         return this.lane;
  49.     }

  50.     /**
  51.      * @return the direction to drive on this lane
  52.      */
  53.     public final GTUDirectionality getDirection()
  54.     {
  55.         return this.direction;
  56.     }

  57.     /**
  58.      * Returns the covered distance driven to the given fractional position.
  59.      * @param fraction double; fractional position
  60.      * @return Length; covered distance driven to the given fractional position
  61.      */
  62.     public final Length coveredDistance(final double fraction)
  63.     {
  64.         if (this.direction.isPlus())
  65.         {
  66.             return getLane().getLength().multiplyBy(fraction);
  67.         }
  68.         return getLane().getLength().multiplyBy(1.0 - fraction);
  69.     }

  70.     /**
  71.      * Returns the remaining distance to be driven from the given fractional position.
  72.      * @param fraction double; fractional position
  73.      * @return Length; remaining distance to be driven from the given fractional position
  74.      */
  75.     public final Length remainingDistance(final double fraction)
  76.     {
  77.         if (this.direction.isPlus())
  78.         {
  79.             return getLane().getLength().multiplyBy(1.0 - fraction);
  80.         }
  81.         return getLane().getLength().multiplyBy(fraction);
  82.     }

  83.     /**
  84.      * Returns the fraction along the design line for having covered the given distance.
  85.      * @param distance Length; covered distance
  86.      * @return double; fraction along the design line for having covered the given distance
  87.      */
  88.     public final double fractionAtCoveredDistance(final Length distance)
  89.     {
  90.         double f = this.lane.fraction(distance);
  91.         if (this.getDirection().isMinus())
  92.         {
  93.             f = 1.0 - f;
  94.         }
  95.         return f;
  96.     }

  97.     /**
  98.      * Returns the next lane and direction.
  99.      * @param gtu LaneBasedGTU; gtu
  100.      * @return LaneDirection; next lane and direction, {@code null} if none
  101.      */
  102.     public final LaneDirection getNextLaneDirection(final LaneBasedGTU gtu)
  103.     {
  104.         Map<Lane, GTUDirectionality> next = this.lane.downstreamLanes(this.direction, gtu.getGTUType());
  105.         if (next.isEmpty())
  106.         {
  107.             return null;
  108.         }
  109.         // ask strategical planner
  110.         LinkDirection ld;
  111.         try
  112.         {
  113.             ld = gtu.getStrategicalPlanner().nextLinkDirection(this.lane.getParentLink(), this.direction, gtu.getGTUType());
  114.         }
  115.         catch (NetworkException exception)
  116.         {
  117.             throw new RuntimeException("Strategical planner experiences exception on network.", exception);
  118.         }
  119.         Set<LaneDirection> out = new HashSet<>();
  120.         for (Lane l : next.keySet())
  121.         {
  122.             GTUDirectionality dir = next.get(l);
  123.             if (l.getParentLink().equals(ld.getLink()) && dir.equals(ld.getDirection()))
  124.             {
  125.                 out.add(new LaneDirection(l, dir));
  126.             }
  127.         }
  128.         if (out.isEmpty())
  129.         {
  130.             return null;
  131.         }
  132.         else if (out.size() == 1)
  133.         {
  134.             return out.iterator().next();
  135.         }
  136.         else
  137.         {
  138.             // ask tactical planner
  139.             return Try.assign(() -> gtu.getTacticalPlanner().chooseLaneAtSplit(out), "Missing parameter.");
  140.         }
  141.     }

  142.     /**
  143.      * Returns the length of the lane.
  144.      * @return Length; length of the lane
  145.      */
  146.     public Length getLength()
  147.     {
  148.         return this.lane.getLength();
  149.     }

  150.     /**
  151.      * Returns a directed point at the given fraction, in the direction of travel (not center line).
  152.      * @param fraction double; fractional position
  153.      * @return directed point at the given fraction, in the direction of travel
  154.      * @throws OTSGeometryException in case the fractional position is not correct
  155.      */
  156.     public DirectedPoint getLocationFraction(final double fraction) throws OTSGeometryException
  157.     {
  158.         DirectedPoint p = this.lane.getCenterLine().getLocationFraction(fraction);
  159.         if (this.direction.isMinus())
  160.         {
  161.             p.setRotZ(p.getRotZ() + Math.PI);
  162.         }
  163.         return p;
  164.     }

  165.     /**
  166.      * Returns the adjacent lane and direction.
  167.      * @param gtu LaneBasedGTU; gtu
  168.      * @param laneChangeDirection LateralDirectionality; lane change direction
  169.      * @return LaneDirection; adjacent lane and direction, {@code null} if none
  170.      */
  171.     public final LaneDirection getAdjacentLaneDirection(final LateralDirectionality laneChangeDirection, final LaneBasedGTU gtu)
  172.     {
  173.         Set<Lane> adjLanes = this.lane.accessibleAdjacentLanesLegal(laneChangeDirection, gtu.getGTUType(), this.direction);
  174.         if (!adjLanes.isEmpty())
  175.         {
  176.             return new LaneDirection(adjLanes.iterator().next(), this.direction);
  177.         }
  178.         return null;
  179.     }

  180.     /** {@inheritDoc} */
  181.     @Override
  182.     public final String toString()
  183.     {
  184.         return "[" + this.lane + (this.direction.isPlus() ? " +]" : " -]");
  185.     }

  186.     /** {@inheritDoc} */
  187.     @Override
  188.     public final int hashCode()
  189.     {
  190.         final int prime = 31;
  191.         int result = 1;
  192.         result = prime * result + ((this.direction == null) ? 0 : this.direction.hashCode());
  193.         result = prime * result + ((this.lane == null) ? 0 : this.lane.hashCode());
  194.         return result;
  195.     }

  196.     /** {@inheritDoc} */
  197.     @Override
  198.     public final boolean equals(final Object obj)
  199.     {
  200.         if (this == obj)
  201.         {
  202.             return true;
  203.         }
  204.         if (obj == null)
  205.         {
  206.             return false;
  207.         }
  208.         if (getClass() != obj.getClass())
  209.         {
  210.             return false;
  211.         }
  212.         LaneDirection other = (LaneDirection) obj;
  213.         if (this.direction != other.direction)
  214.         {
  215.             return false;
  216.         }
  217.         if (this.lane == null)
  218.         {
  219.             if (other.lane != null)
  220.             {
  221.                 return false;
  222.             }
  223.         }
  224.         else if (!this.lane.equals(other.lane))
  225.         {
  226.             return false;
  227.         }
  228.         return true;
  229.     }

  230. }