1 package org.opentrafficsim.road.gtu.strategical.route;
2
3 import java.util.ArrayList;
4 import java.util.LinkedHashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import org.djutils.exceptions.Throw;
9 import org.djutils.exceptions.Try;
10 import org.opentrafficsim.core.gtu.GTUDirectionality;
11 import org.opentrafficsim.core.gtu.GTUType;
12 import org.opentrafficsim.core.gtu.NestedCache;
13 import org.opentrafficsim.core.math.Draw;
14 import org.opentrafficsim.core.network.Link;
15 import org.opentrafficsim.core.network.Node;
16 import org.opentrafficsim.core.network.route.Route;
17 import org.opentrafficsim.road.network.lane.CrossSectionLink;
18
19 import nl.tudelft.simulation.jstats.streams.StreamInterface;
20
21
22
23
24
25
26
27
28
29
30
31
32
33 public interface RouteGeneratorOD
34 {
35
36 RouteGeneratorOD NULL = new RouteGeneratorOD()
37 {
38 @Override
39 public Route getRoute(final Node origin, final Node destination, final GTUType gtuType)
40 {
41 return null;
42 }
43 };
44
45
46 Map<StreamInterface, RouteGeneratorOD> DEFAULT_MAP = new LinkedHashMap<>();
47
48
49
50
51
52
53 static RouteGeneratorOD getDefaultRouteSupplier(final StreamInterface stream)
54 {
55 RouteGeneratorOD def = DEFAULT_MAP.get(stream);
56 if (def == null)
57 {
58 def = new DefaultRouteGenerator(stream);
59 DEFAULT_MAP.put(stream, def);
60 }
61 return def;
62 }
63
64
65 class DefaultRouteGenerator implements RouteGeneratorOD
66 {
67
68 private NestedCache<Route> shortestRouteCache = new NestedCache<>(GTUType.class, Node.class, Node.class, List.class);
69
70
71 private final StreamInterface stream;
72
73
74
75
76
77 public DefaultRouteGenerator(final StreamInterface stream)
78 {
79 Throw.whenNull(stream, "Stream may not be null.");
80 this.stream = stream;
81 }
82
83 @Override
84 public Route getRoute(final Node origin, final Node destination, final GTUType gtuType)
85 {
86 List<Node> viaNodes = new ArrayList<>();
87 double cumulWeight = 0.0;
88 List<Double> weights = new ArrayList<>();
89 Map<Link, Double> links = new LinkedHashMap<>();
90 for (Link link : destination.getLinks())
91 {
92 GTUDirectionality direction =
93 link.getEndNode().equals(destination) ? GTUDirectionality.DIR_PLUS : GTUDirectionality.DIR_MINUS;
94 if (link.getLinkType().isConnector() && link.getDirectionality(gtuType).permits(direction)
95 && link instanceof CrossSectionLink && ((CrossSectionLink) link).getDemandWeight() != null)
96 {
97 Double weight = ((CrossSectionLink) link).getDemandWeight();
98 weights.add(weight);
99 links.put(link, weight);
100 cumulWeight += weight;
101 }
102 }
103 if (cumulWeight > 0.0)
104 {
105 Link via = Draw.drawWeighted(links, this.stream);
106 viaNodes.add(via.getStartNode().equals(destination) ? via.getEndNode() : via.getStartNode());
107 }
108 return this.shortestRouteCache.getValue(
109 () -> Try.assign(() -> origin.getNetwork().getShortestRouteBetween(gtuType, origin, destination, viaNodes),
110 "Could not determine the shortest route from %s to %s via %s.", origin, destination, viaNodes),
111 gtuType, origin, destination, viaNodes);
112 }
113
114
115 @Override
116 public String toString()
117 {
118 return "ShortestRouteGTUCharacteristicsGeneratorOD [shortestRouteCache=" + this.shortestRouteCache + "]";
119 }
120 };
121
122
123
124
125
126
127
128
129 Route getRoute(Node origin, Node destination, GTUType gtuType);
130 }