1 package org.opentrafficsim.animation;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.Comparator;
6 import java.util.Iterator;
7 import java.util.LinkedHashMap;
8 import java.util.LinkedHashSet;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Set;
12
13 import org.djunits.value.vdouble.scalar.Length;
14 import org.djunits.value.vdouble.scalar.Speed;
15 import org.djutils.exceptions.Throw;
16 import org.djutils.immutablecollections.ImmutableSet;
17 import org.opentrafficsim.core.network.Link;
18 import org.opentrafficsim.core.network.LinkPosition;
19 import org.opentrafficsim.core.network.NetworkException;
20 import org.opentrafficsim.draw.graphs.GraphCrossSection;
21 import org.opentrafficsim.draw.graphs.GraphPath;
22 import org.opentrafficsim.draw.graphs.GraphPath.Section;
23 import org.opentrafficsim.road.network.lane.CrossSectionLink;
24 import org.opentrafficsim.road.network.lane.Lane;
25 import org.opentrafficsim.road.network.lane.LanePosition;
26 import org.opentrafficsim.road.network.lane.Shoulder;
27 import org.opentrafficsim.road.network.sampling.LaneDataRoad;
28
29
30
31
32
33
34
35
36
37
38
39 public final class GraphLaneUtil
40 {
41
42
43
44
45 private GraphLaneUtil()
46 {
47
48 }
49
50
51
52
53
54
55
56
57 public static GraphPath<LaneDataRoad> createPath(final String name, final Lane first) throws NetworkException
58 {
59 Throw.whenNull(name, "Name may not be null.");
60 Throw.whenNull(first, "First may not be null.");
61 List<Section<LaneDataRoad>> sections = new ArrayList<>();
62 Set<Lane> set = new LinkedHashSet<>();
63 Lane lane = first;
64 while (lane != null && !set.contains(lane))
65 {
66 LaneDataRoad laneData = new LaneDataRoad(lane);
67 List<LaneDataRoad> list = new ArrayList<>();
68 list.add(laneData);
69 Speed speed = lane.getLowestSpeedLimit();
70 Length length = lane.getLength();
71 sections.add(new Section<>(length, speed, list));
72 set.add(lane);
73 Set<Lane> nextLaneSet = lane.nextLanes(null);
74 if (nextLaneSet.size() == 1 && !(nextLaneSet.iterator().next() instanceof Shoulder))
75 {
76 lane = nextLaneSet.iterator().next();
77 }
78 }
79 return new GraphPath<>(name, sections);
80 }
81
82
83
84
85
86
87
88
89
90 public static GraphPath<LaneDataRoad> createPath(final List<String> names, final List<Lane> first) throws NetworkException
91 {
92 Throw.whenNull(names, "Names may not be null.");
93 Throw.whenNull(first, "First may not be null.");
94 Throw.when(names.size() != first.size(), IllegalArgumentException.class, "Size of 'names' and 'first' must be equal.");
95 List<Section<LaneDataRoad>> sections = new ArrayList<>();
96 Set<Lane> set = new LinkedHashSet<>();
97 List<Lane> lanes = first;
98 while (lanes != null && Collections.disjoint(set, lanes))
99 {
100 List<LaneDataRoad> list = new ArrayList<>();
101 Speed speed = null;
102 for (Lane lane : lanes)
103 {
104 if (lane == null)
105 {
106 list.add(null);
107 continue;
108 }
109 speed = speed == null ? lane.getLowestSpeedLimit() : Speed.min(speed, lane.getLowestSpeedLimit());
110 list.add(new LaneDataRoad(lane));
111 }
112 Speed finalSpeed = speed;
113 Lane firstNextLane = null;
114 for (Lane lane : lanes)
115 {
116 if (lane != null)
117 {
118 firstNextLane = lane;
119 continue;
120 }
121 }
122 Length length = firstNextLane.getLength();
123 sections.add(new Section<>(length, finalSpeed, list));
124 set.addAll(lanes);
125
126 Map<Link, List<Lane>> linkMap = new LinkedHashMap<>();
127 Link link = firstNextLane.getLink();
128 ImmutableSet<Link> links = link.getEndNode().getLinks();
129 for (Link nextLink : links)
130 {
131 if (!link.equals(nextLink))
132 {
133 List<Lane> nextLanes = new ArrayList<>();
134 for (Lane nextLane : lanes)
135 {
136 Set<Lane> nextLaneSet = nextLane.nextLanes(null);
137 int n = 0;
138 for (Lane nl : nextLaneSet)
139 {
140 if (nl.getLink().equals(nextLink))
141 {
142 n++;
143 nextLanes.add(nl);
144 }
145 }
146 if (n > 1)
147 {
148
149 nextLanes.clear();
150 break;
151 }
152 else if (n == 0)
153 {
154 nextLanes.add(null);
155 }
156 }
157 if (nextLanes.size() == lanes.size())
158 {
159 linkMap.put(nextLink, nextLanes);
160 }
161 }
162 }
163
164 if (linkMap.size() > 1)
165 {
166 Iterator<List<Lane>> it = linkMap.values().iterator();
167 while (it.hasNext())
168 {
169 if (it.next().contains(null))
170 {
171 it.remove();
172 }
173 }
174 }
175 if (linkMap.size() == 1)
176 {
177 lanes = linkMap.values().iterator().next();
178 }
179 else
180 {
181 lanes = null;
182 }
183 }
184 return new GraphPath<>(names, sections);
185 }
186
187
188
189
190
191
192
193
194 public static GraphPath<LaneDataRoad> createSingleLanePath(final String name, final Lane lane) throws NetworkException
195 {
196 List<LaneDataRoad> lanes = new ArrayList<>();
197 lanes.add(new LaneDataRoad(lane));
198 List<Section<LaneDataRoad>> sections = new ArrayList<>();
199 Speed speed = lane.getLowestSpeedLimit();
200 sections.add(new Section<>(lane.getLength(), speed, lanes));
201 return new GraphPath<>(name, sections);
202 }
203
204
205
206
207
208
209
210
211 public static GraphCrossSection<LaneDataRoad> createCrossSection(final String name, final LanePosition lanePosition)
212 throws NetworkException
213 {
214 Throw.whenNull(name, "Name may not be null.");
215 Throw.whenNull(lanePosition, "Lane position may not be null.");
216 List<LaneDataRoad> list = new ArrayList<>();
217 List<String> names = new ArrayList<>();
218 List<Length> positions = new ArrayList<>();
219 names.add(name);
220 positions.add(lanePosition.position());
221 list.add(new LaneDataRoad(lanePosition.lane()));
222 Speed speed = lanePosition.lane().getLowestSpeedLimit();
223 return createCrossSection(names, list, positions, speed);
224 }
225
226
227
228
229
230
231
232
233 public static GraphCrossSection<LaneDataRoad> createCrossSection(final List<String> names, final LinkPosition linkPosition)
234 throws NetworkException
235 {
236 Throw.whenNull(names, "Names may not be null.");
237 Throw.whenNull(linkPosition, "Link position may not be null.");
238 Throw.when(!(linkPosition.link() instanceof CrossSectionLink), IllegalArgumentException.class,
239 "The link is not a CrossEctionLink.");
240 List<Lane> lanes = ((CrossSectionLink) linkPosition.link()).getLanes();
241 Throw.when(names.size() != lanes.size(), IllegalArgumentException.class,
242 "Size of 'names' not equal to the number of lanes.");
243 Collections.sort(lanes, new Comparator<Lane>()
244 {
245
246 @Override
247 public int compare(final Lane o1, final Lane o2)
248 {
249 return o1.getOffsetAtBegin().compareTo(o2.getOffsetAtEnd());
250 }
251
252 });
253 List<LaneDataRoad> list = new ArrayList<>();
254 List<Length> positions = new ArrayList<>();
255 Speed speed = null;
256 for (Lane lane : lanes)
257 {
258 speed = speed == null ? lane.getLowestSpeedLimit() : Speed.min(speed, lane.getLowestSpeedLimit());
259 list.add(new LaneDataRoad(lane));
260 positions.add(lane.getLength().times(linkPosition.fractionalLongitudinalPosition()));
261 }
262 return createCrossSection(names, list, positions, speed);
263 }
264
265
266
267
268
269
270
271
272
273 public static GraphCrossSection<LaneDataRoad> createCrossSection(final List<String> names, final List<LaneDataRoad> lanes,
274 final List<Length> positions, final Speed speed)
275 {
276 Section<LaneDataRoad> section = new Section<>(lanes.get(0).getLength(), speed, lanes);
277 return new GraphCrossSection<>(names, section, positions);
278 }
279
280 }