1 package org.opentrafficsim.road.gtu.strategical;
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.djutils.multikeymap.MultiKeyMap;
11 import org.opentrafficsim.core.gtu.GtuType;
12 import org.opentrafficsim.core.math.Draw;
13 import org.opentrafficsim.core.network.Connector;
14 import org.opentrafficsim.core.network.Link;
15 import org.opentrafficsim.core.network.LinkWeight;
16 import org.opentrafficsim.core.network.NetworkException;
17 import org.opentrafficsim.core.network.Node;
18 import org.opentrafficsim.core.network.route.Route;
19
20 import nl.tudelft.simulation.jstats.streams.StreamInterface;
21
22
23
24
25
26
27
28
29
30
31
32
33 public interface RouteGenerator
34 {
35
36 RouteGenerator NULL = new RouteGenerator()
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 MultiKeyMap<RouteGenerator> DEFAULT_SUPPLIERS = new MultiKeyMap<>(StreamInterface.class, LinkWeight.class);
47
48
49
50
51
52
53
54 static RouteGenerator getDefaultRouteSupplier(final StreamInterface stream, final LinkWeight linkWeight)
55 {
56 RouteGenerator def = DEFAULT_SUPPLIERS.get(stream, linkWeight);
57 if (def == null)
58 {
59 def = new DefaultRouteGenerator(stream, linkWeight);
60 DEFAULT_SUPPLIERS.put(def, stream, linkWeight);
61 }
62 return def;
63 }
64
65
66 class DefaultRouteGenerator implements RouteGenerator
67 {
68
69 private final MultiKeyMap<Route> shortestRouteCache =
70 new MultiKeyMap<>(GtuType.class, Node.class, Node.class, List.class);
71
72
73 private final LinkWeight linkWeight;
74
75
76 private final StreamInterface stream;
77
78
79
80
81
82
83 public DefaultRouteGenerator(final StreamInterface stream, final LinkWeight linkWeight)
84 {
85 Throw.whenNull(stream, "Stream may not be null.");
86 Throw.whenNull(linkWeight, "Link weight may not be null.");
87 this.stream = stream;
88 this.linkWeight = linkWeight;
89 }
90
91 @Override
92 public Route getRoute(final Node origin, final Node destination, final GtuType gtuType)
93 {
94 List<Node> viaNodes = new ArrayList<>();
95 double cumulWeight = 0.0;
96 Map<Link, Double> links = new LinkedHashMap<>();
97 boolean directLinkExists = false;
98 for (Link link : destination.getLinks())
99 {
100 if (link.isConnector() && link instanceof Connector && ((Connector) link).getDemandWeight() > 0.0)
101 {
102
103 List<Node> testViaNode = new ArrayList<>();
104 Node linkEntryNode = link.getStartNode();
105 testViaNode.add(linkEntryNode);
106 try
107 {
108 if (origin.getNetwork().getShortestRouteBetween(gtuType, origin, destination, viaNodes,
109 this.linkWeight) != null)
110 {
111 Double weight = ((Connector) link).getDemandWeight();
112 links.put(link, weight);
113 cumulWeight += weight;
114 }
115 }
116 catch (NetworkException e)
117 {
118
119 }
120 }
121 if (link.getStartNode().equals(origin) || link.getEndNode().equals(origin))
122 {
123 directLinkExists = true;
124 }
125 }
126 if (cumulWeight > 0.0 && links.size() > 1 && (!directLinkExists))
127 {
128 Link via = Draw.drawWeighted(links, this.stream);
129 if (via.getEndNode().equals(destination))
130 {
131 viaNodes.add(via.getStartNode());
132 }
133 else if (via.getStartNode().equals(destination))
134 {
135 viaNodes.add(via.getEndNode());
136 }
137 else
138 {
139 viaNodes.add(via.getEndNode());
140 }
141 }
142 if (!this.linkWeight.isStatic())
143 {
144 return Try.assign(
145 () -> origin.getNetwork().getShortestRouteBetween(gtuType, origin, destination, viaNodes,
146 this.linkWeight),
147 "Could not determine the shortest route from %s to %s via %s.", origin, destination, viaNodes);
148 }
149 return this.shortestRouteCache.get(() -> Try.assign(
150 () -> origin.getNetwork().getShortestRouteBetween(gtuType, origin, destination, viaNodes, this.linkWeight),
151 "Could not determine the shortest route from %s to %s via %s.", origin, destination, viaNodes), gtuType,
152 origin, destination, viaNodes);
153 }
154
155 @Override
156 public String toString()
157 {
158 return "DefaultRouteGenerator [linkWeight=" + this.linkWeight + "shortestRouteCache=" + this.shortestRouteCache
159 + "]";
160 }
161 };
162
163
164
165
166
167
168
169
170 Route getRoute(Node origin, Node destination, GtuType gtuType);
171 }