1 package org.opentrafficsim.draw.factory;
2
3 import java.awt.Color;
4 import java.rmi.RemoteException;
5 import java.util.Collections;
6 import java.util.LinkedHashMap;
7 import java.util.Map;
8
9 import javax.naming.NamingException;
10
11 import org.djutils.event.Event;
12 import org.djutils.event.EventListener;
13 import org.djutils.logger.CategoryLogger;
14 import org.opentrafficsim.core.animation.gtu.colorer.GtuColorer;
15 import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
16 import org.opentrafficsim.core.geometry.OtsGeometryException;
17 import org.opentrafficsim.core.gtu.Gtu;
18 import org.opentrafficsim.core.gtu.GtuGenerator.GtuGeneratorPosition;
19 import org.opentrafficsim.core.network.Link;
20 import org.opentrafficsim.core.network.Node;
21 import org.opentrafficsim.core.network.Network;
22 import org.opentrafficsim.core.object.LocatedObject;
23 import org.opentrafficsim.core.object.NonLocatedObject;
24 import org.opentrafficsim.draw.core.OtsDrawingException;
25 import org.opentrafficsim.draw.gtu.DefaultCarAnimation;
26 import org.opentrafficsim.draw.network.LinkAnimation;
27 import org.opentrafficsim.draw.network.NodeAnimation;
28 import org.opentrafficsim.draw.road.BusStopAnimation;
29 import org.opentrafficsim.draw.road.ConflictAnimation;
30 import org.opentrafficsim.draw.road.CrossSectionElementAnimation;
31 import org.opentrafficsim.draw.road.DetectorAnimation;
32 import org.opentrafficsim.draw.road.GtuGeneratorPositionAnimation;
33 import org.opentrafficsim.draw.road.LaneAnimation;
34 import org.opentrafficsim.draw.road.SpeedSignAnimation;
35 import org.opentrafficsim.draw.road.StripeAnimation;
36 import org.opentrafficsim.draw.road.TrafficLightAnimation;
37 import org.opentrafficsim.draw.road.TrafficLightDetectorAnimation;
38 import org.opentrafficsim.road.gtu.generator.LaneBasedGtuGenerator;
39 import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
40 import org.opentrafficsim.road.network.lane.CrossSectionElement;
41 import org.opentrafficsim.road.network.lane.CrossSectionLink;
42 import org.opentrafficsim.road.network.lane.Lane;
43 import org.opentrafficsim.road.network.lane.Stripe;
44 import org.opentrafficsim.road.network.lane.conflict.Conflict;
45 import org.opentrafficsim.road.network.lane.object.BusStop;
46 import org.opentrafficsim.road.network.lane.object.SpeedSign;
47 import org.opentrafficsim.road.network.lane.object.detector.DestinationDetector;
48 import org.opentrafficsim.road.network.lane.object.detector.LaneDetector;
49 import org.opentrafficsim.road.network.lane.object.detector.SinkDetector;
50 import org.opentrafficsim.road.network.lane.object.detector.TrafficLightDetector;
51 import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLight;
52
53 import nl.tudelft.simulation.dsol.SimRuntimeException;
54 import nl.tudelft.simulation.dsol.animation.Locatable;
55 import nl.tudelft.simulation.dsol.animation.D2.Renderable2D;
56
57
58
59
60
61
62
63
64
65 public class DefaultAnimationFactory implements EventListener
66 {
67
68 private static final long serialVersionUID = 20230129L;
69
70
71 private final Network network;
72
73
74 private final OtsSimulatorInterface simulator;
75
76
77 private final GtuColorer gtuColorer;
78
79
80 private Map<LaneBasedGtu, Renderable2D<LaneBasedGtu>> animatedGTUs = Collections.synchronizedMap(new LinkedHashMap<>());
81
82
83 private Map<Locatable, Renderable2D<?>> animatedLocatedObjects = Collections.synchronizedMap(new LinkedHashMap<>());
84
85
86 private Map<NonLocatedObject, Renderable2D<?>> animatedNonLocatedObjects =
87 Collections.synchronizedMap(new LinkedHashMap<>());
88
89
90
91
92
93
94
95
96
97 protected DefaultAnimationFactory(final Network network, final GtuColorer gtuColorer, final boolean animateNetwork)
98 throws OtsDrawingException
99 {
100 this.network = network;
101 this.simulator = network.getSimulator();
102 this.gtuColorer = gtuColorer;
103
104
105 network.addListener(this, Network.GTU_ADD_EVENT);
106 network.addListener(this, Network.GTU_REMOVE_EVENT);
107 network.addListener(this, Network.OBJECT_ADD_EVENT);
108 network.addListener(this, Network.OBJECT_REMOVE_EVENT);
109 network.addListener(this, Network.NONLOCATED_OBJECT_ADD_EVENT);
110 network.addListener(this, Network.NONLOCATED_OBJECT_REMOVE_EVENT);
111
112
113 try
114 {
115 if (animateNetwork)
116 {
117 for (Node node : network.getNodeMap().values())
118 {
119 new NodeAnimation(node, this.simulator);
120 }
121 for (Link link : network.getLinkMap().values())
122 {
123 new LinkAnimation(link, this.simulator, 0.5f);
124 if (link instanceof CrossSectionLink)
125 {
126 for (CrossSectionElement element : ((CrossSectionLink) link).getCrossSectionElementList())
127 {
128 if (element instanceof Lane)
129 {
130 new LaneAnimation((Lane) element, this.simulator, Color.GRAY.brighter());
131 }
132 else if (element instanceof Stripe)
133 {
134 new StripeAnimation((Stripe) element, this.simulator);
135 }
136 else
137 {
138
139 new CrossSectionElementAnimation(element, this.simulator, Color.DARK_GRAY);
140 }
141 }
142 }
143 }
144 }
145
146 for (Gtu gtu : network.getGTUs())
147 {
148 Renderable2D<LaneBasedGtu> gtuAnimation =
149 new DefaultCarAnimation((LaneBasedGtu) gtu, this.simulator, this.gtuColorer);
150 this.animatedGTUs.put((LaneBasedGtu) gtu, gtuAnimation);
151 }
152
153 for (LocatedObject object : network.getObjectMap().values())
154 {
155 animateLocatedObject(object);
156 }
157
158 for (NonLocatedObject object : network.getNonLocatedObjectMap().values())
159 {
160 animateNonLocatedObject(object);
161 }
162 }
163 catch (RemoteException | NamingException | OtsGeometryException exception)
164 {
165 throw new OtsDrawingException("Exception while creating network animation.", exception);
166 }
167
168 }
169
170
171
172
173
174
175
176
177
178
179 public static DefaultAnimationFactory animateNetwork(final Network network, final OtsSimulatorInterface simulator,
180 final GtuColorer gtuColorer) throws OtsDrawingException
181 {
182 return new DefaultAnimationFactory(network, gtuColorer, true);
183 }
184
185
186
187
188
189
190
191
192
193 public static DefaultAnimationFactory animateXmlNetwork(final Network network, final GtuColorer gtuColorer)
194 throws OtsDrawingException
195 {
196 return new DefaultAnimationFactory(network, gtuColorer, false);
197 }
198
199
200 @Override
201 public void notify(final Event event) throws RemoteException
202 {
203 try
204 {
205 if (event.getType().equals(Network.GTU_ADD_EVENT))
206 {
207
208 LaneBasedGtu gtu = (LaneBasedGtu) this.network.getGTU((String) event.getContent());
209 this.simulator.scheduleEventNow(this, "animateGTU", new Object[] {gtu});
210 }
211 else if (event.getType().equals(Network.GTU_REMOVE_EVENT))
212 {
213 LaneBasedGtu gtu = (LaneBasedGtu) this.network.getGTU((String) event.getContent());
214 if (this.animatedGTUs.containsKey(gtu))
215 {
216 this.animatedGTUs.get(gtu).destroy(gtu.getSimulator());
217 this.animatedGTUs.remove(gtu);
218 }
219 }
220 else if (event.getType().equals(Network.OBJECT_ADD_EVENT))
221 {
222 LocatedObject object = this.network.getObjectMap().get((String) event.getContent());
223 animateLocatedObject(object);
224 }
225 else if (event.getType().equals(Network.OBJECT_REMOVE_EVENT))
226 {
227 LocatedObject object = this.network.getObjectMap().get((String) event.getContent());
228
229
230 this.animatedLocatedObjects.remove(object);
231 }
232 else if (event.getType().equals(Network.NONLOCATED_OBJECT_ADD_EVENT))
233 {
234 NonLocatedObject object = this.network.getNonLocatedObjectMap().get((String) event.getContent());
235 animateNonLocatedObject(object);
236 }
237 else if (event.getType().equals(Network.NONLOCATED_OBJECT_REMOVE_EVENT))
238 {
239 NonLocatedObject object = this.network.getNonLocatedObjectMap().get((String) event.getContent());
240
241
242 this.animatedNonLocatedObjects.remove(object);
243 }
244 }
245 catch (SimRuntimeException exception)
246 {
247 CategoryLogger.always().error(exception, "Exception while updating network animation.");
248 }
249 }
250
251
252
253
254
255 protected void animateGTU(final LaneBasedGtu gtu)
256 {
257 try
258 {
259 Renderable2D<LaneBasedGtu> gtuAnimation = new DefaultCarAnimation(gtu, this.simulator, this.gtuColorer);
260 this.animatedGTUs.put(gtu, gtuAnimation);
261 }
262 catch (RemoteException | NamingException exception)
263 {
264 gtu.getSimulator().getLogger().always().error(exception, "Exception while drawing GTU.");
265 }
266 }
267
268
269
270
271
272 protected void animateLocatedObject(final LocatedObject object)
273 {
274 try
275 {
276 if (object instanceof SinkDetector)
277 {
278 SinkDetector detector = (SinkDetector) object;
279
280 Renderable2D<LaneDetector> objectAnimation = new DetectorAnimation(detector, this.simulator, Color.ORANGE);
281 this.animatedLocatedObjects.put(object, objectAnimation);
282 }
283 else if (object instanceof DestinationDetector)
284 {
285 DestinationDetector detector = (DestinationDetector) object;
286
287 Renderable2D<LaneDetector> objectAnimation = new DetectorAnimation(detector, this.simulator, Color.ORANGE);
288 this.animatedLocatedObjects.put(object, objectAnimation);
289 }
290 else if (object instanceof TrafficLightDetector)
291 {
292 TrafficLightDetector trafficLigthDetector = (TrafficLightDetector) object;
293 Renderable2D<TrafficLightDetector> objectAnimation =
294 new TrafficLightDetectorAnimation(trafficLigthDetector, this.simulator);
295 this.animatedLocatedObjects.put(object, objectAnimation);
296 }
297 else if (object instanceof TrafficLightDetector.StartEndDetector)
298 {
299
300 return;
301 }
302 else if (object instanceof LaneDetector)
303 {
304 LaneDetector detector = (LaneDetector) object;
305 Renderable2D<LaneDetector> objectAnimation = new DetectorAnimation(detector, this.simulator, Color.BLACK);
306 this.animatedLocatedObjects.put(object, objectAnimation);
307 }
308 else if (object instanceof Conflict)
309 {
310 Conflict conflict = (Conflict) object;
311 Renderable2D<Conflict> objectAnimation = new ConflictAnimation(conflict, this.simulator);
312 this.animatedLocatedObjects.put(object, objectAnimation);
313 }
314 else if (object instanceof TrafficLight)
315 {
316 TrafficLight trafficLight = (TrafficLight) object;
317 Renderable2D<TrafficLight> objectAnimation = new TrafficLightAnimation(trafficLight, this.simulator);
318 this.animatedLocatedObjects.put(object, objectAnimation);
319 }
320 else if (object instanceof SpeedSign)
321 {
322 SpeedSign speedSign = (SpeedSign) object;
323 Renderable2D<SpeedSign> objectAnimation = new SpeedSignAnimation(speedSign, this.simulator);
324 this.animatedLocatedObjects.put(object, objectAnimation);
325 }
326 else if (object instanceof BusStop)
327 {
328 BusStop busStop = (BusStop) object;
329 Renderable2D<BusStop> objectAnimation = new BusStopAnimation(busStop, this.simulator);
330 this.animatedLocatedObjects.put(object, objectAnimation);
331 }
332 }
333 catch (RemoteException | NamingException | OtsGeometryException exception)
334 {
335 CategoryLogger.always().error(exception, "Exception while drawing Object of class LocatedObject.");
336 }
337 }
338
339
340
341
342
343 protected void animateNonLocatedObject(final NonLocatedObject object)
344 {
345 try
346 {
347 if (object instanceof LaneBasedGtuGenerator)
348 {
349 LaneBasedGtuGenerator generator = (LaneBasedGtuGenerator) object;
350 for (GtuGeneratorPosition position : generator.getPositions())
351 {
352 Renderable2D<GtuGeneratorPosition> objectAnimation =
353 new GtuGeneratorPositionAnimation(position, this.simulator);
354 this.animatedLocatedObjects.put(position, objectAnimation);
355 }
356 }
357 }
358 catch (RemoteException | NamingException exception)
359 {
360 CategoryLogger.always().error(exception, "Exception while drawing Object of class NonLocatedObject.");
361 }
362 }
363
364 }