RouteGeneratorOD.java

  1. package org.opentrafficsim.road.gtu.strategical.route;

  2. import java.util.ArrayList;
  3. import java.util.LinkedHashMap;
  4. import java.util.List;
  5. import java.util.Map;

  6. import org.djutils.exceptions.Throw;
  7. import org.djutils.exceptions.Try;
  8. import org.opentrafficsim.core.gtu.GTUDirectionality;
  9. import org.opentrafficsim.core.gtu.GTUType;
  10. import org.opentrafficsim.core.gtu.NestedCache;
  11. import org.opentrafficsim.core.math.Draw;
  12. import org.opentrafficsim.core.network.Link;
  13. import org.opentrafficsim.core.network.Node;
  14. import org.opentrafficsim.core.network.route.Route;
  15. import org.opentrafficsim.road.network.lane.CrossSectionLink;

  16. import nl.tudelft.simulation.jstats.streams.StreamInterface;

  17. /**
  18.  * Generates a route by determining one. This class is different from {@code RouteGenerator} in that it has the origin,
  19.  * destination and GTU type as input.
  20.  * <p>
  21.  * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  22.  * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  23.  * <p>
  24.  * @version $Revision$, $LastChangedDate$, by $Author$, initial version 24 mrt. 2018 <br>
  25.  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  26.  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  27.  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  28.  */
  29. public interface RouteGeneratorOD
  30. {
  31.     /** No route route generator. */
  32.     RouteGeneratorOD NULL = new RouteGeneratorOD()
  33.     {
  34.         @Override
  35.         public Route getRoute(final Node origin, final Node destination, final GTUType gtuType)
  36.         {
  37.             return null;
  38.         }
  39.     };

  40.     /** Cache of default route generators per stream. */
  41.     Map<StreamInterface, RouteGeneratorOD> DEFAULT_MAP = new LinkedHashMap<>();

  42.     /**
  43.      * Returns a default route generator for shortest routes based on the given stream.
  44.      * @param stream StreamInterface; random number stream
  45.      * @return RouteSupplier; default route generator for shortest routes based on the given stream
  46.      */
  47.     static RouteGeneratorOD getDefaultRouteSupplier(final StreamInterface stream)
  48.     {
  49.         RouteGeneratorOD def = DEFAULT_MAP.get(stream);
  50.         if (def == null)
  51.         {
  52.             def = new DefaultRouteGenerator(stream);
  53.             DEFAULT_MAP.put(stream, def);
  54.         }
  55.         return def;
  56.     }

  57.     /** Shortest route route generator. */
  58.     class DefaultRouteGenerator implements RouteGeneratorOD
  59.     {
  60.         /** Shortest route cache. */
  61.         private NestedCache<Route> shortestRouteCache = new NestedCache<>(GTUType.class, Node.class, Node.class, List.class);

  62.         /** Stream of random numbers. */
  63.         private final StreamInterface stream;

  64.         /**
  65.          * Constructor.
  66.          * @param stream StreamInterface; stream of random numbers
  67.          */
  68.         public DefaultRouteGenerator(final StreamInterface stream)
  69.         {
  70.             Throw.whenNull(stream, "Stream may not be null.");
  71.             this.stream = stream;
  72.         }

  73.         @Override
  74.         public Route getRoute(final Node origin, final Node destination, final GTUType gtuType)
  75.         {
  76.             List<Node> viaNodes = new ArrayList<>();
  77.             double cumulWeight = 0.0;
  78.             List<Double> weights = new ArrayList<>();
  79.             Map<Link, Double> links = new LinkedHashMap<>();
  80.             for (Link link : destination.getLinks())
  81.             {
  82.                 GTUDirectionality direction =
  83.                         link.getEndNode().equals(destination) ? GTUDirectionality.DIR_PLUS : GTUDirectionality.DIR_MINUS;
  84.                 if (link.getLinkType().isConnector() && link.getDirectionality(gtuType).permits(direction)
  85.                         && link instanceof CrossSectionLink && ((CrossSectionLink) link).getDemandWeight() != null)
  86.                 {
  87.                     Double weight = ((CrossSectionLink) link).getDemandWeight();
  88.                     weights.add(weight);
  89.                     links.put(link, weight);
  90.                     cumulWeight += weight;
  91.                 }
  92.             }
  93.             if (cumulWeight > 0.0)
  94.             {
  95.                 Link via = Draw.drawWeighted(links, this.stream);
  96.                 viaNodes.add(via.getStartNode().equals(destination) ? via.getEndNode() : via.getStartNode());
  97.             }
  98.             // XXX make silent, as the higher level method should draw another destination if the route does not exist
  99.             return this.shortestRouteCache.getValue(
  100.                     () -> Try.assign(() -> origin.getNetwork().getShortestRouteBetween(gtuType, origin, destination, viaNodes),
  101.                             "Could not determine the shortest route from %s to %s via %s.", origin, destination, viaNodes),
  102.                     gtuType, origin, destination, viaNodes);
  103.         }

  104.         /** {@inheritDoc} */
  105.         @Override
  106.         public String toString()
  107.         {
  108.             return "ShortestRouteGTUCharacteristicsGeneratorOD [shortestRouteCache=" + this.shortestRouteCache + "]";
  109.         }
  110.     };

  111.     /**
  112.      * Returns a route.
  113.      * @param origin Node; origin
  114.      * @param destination Node; destination
  115.      * @param gtuType GTUType; gtu type
  116.      * @return Route; route
  117.      */
  118.     Route getRoute(Node origin, Node destination, GTUType gtuType);
  119. }