1 package org.opentrafficsim.draw.factory;
2
3 import java.awt.Color;
4 import java.rmi.RemoteException;
5 import java.util.HashMap;
6 import java.util.Map;
7
8 import javax.naming.NamingException;
9
10 import org.opentrafficsim.core.animation.gtu.colorer.GTUColorer;
11 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
12 import org.opentrafficsim.core.geometry.OTSGeometryException;
13 import org.opentrafficsim.core.gtu.GTU;
14 import org.opentrafficsim.core.gtu.GTUType;
15 import org.opentrafficsim.core.network.LateralDirectionality;
16 import org.opentrafficsim.core.network.Link;
17 import org.opentrafficsim.core.network.Network;
18 import org.opentrafficsim.core.network.Node;
19 import org.opentrafficsim.core.network.OTSNetwork;
20 import org.opentrafficsim.core.object.ObjectInterface;
21 import org.opentrafficsim.draw.core.OTSDrawingException;
22 import org.opentrafficsim.draw.gtu.DefaultCarAnimation;
23 import org.opentrafficsim.draw.gtu.GTUGeneratorAnimation;
24 import org.opentrafficsim.draw.network.LinkAnimation;
25 import org.opentrafficsim.draw.network.NodeAnimation;
26 import org.opentrafficsim.draw.road.BusStopAnimation;
27 import org.opentrafficsim.draw.road.ConflictAnimation;
28 import org.opentrafficsim.draw.road.LaneAnimation;
29 import org.opentrafficsim.draw.road.SensorAnimation;
30 import org.opentrafficsim.draw.road.ShoulderAnimation;
31 import org.opentrafficsim.draw.road.SpeedSignAnimation;
32 import org.opentrafficsim.draw.road.StripeAnimation;
33 import org.opentrafficsim.draw.road.StripeAnimation.TYPE;
34 import org.opentrafficsim.road.gtu.generator.AbstractGTUGenerator;
35 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
36 import org.opentrafficsim.road.network.lane.CrossSectionElement;
37 import org.opentrafficsim.road.network.lane.CrossSectionLink;
38 import org.opentrafficsim.road.network.lane.Lane;
39 import org.opentrafficsim.road.network.lane.Shoulder;
40 import org.opentrafficsim.road.network.lane.Stripe;
41 import org.opentrafficsim.road.network.lane.conflict.Conflict;
42 import org.opentrafficsim.road.network.lane.object.BusStop;
43 import org.opentrafficsim.road.network.lane.object.SpeedSign;
44 import org.opentrafficsim.road.network.lane.object.sensor.SingleSensor;
45
46 import nl.tudelft.simulation.dsol.SimRuntimeException;
47 import nl.tudelft.simulation.dsol.animation.D2.Renderable2D;
48 import nl.tudelft.simulation.dsol.logger.SimLogger;
49 import nl.tudelft.simulation.event.EventInterface;
50 import nl.tudelft.simulation.event.EventListenerInterface;
51
52
53
54
55
56
57
58
59
60 public class DefaultAnimationFactory implements EventListenerInterface
61 {
62
63 private final OTSSimulatorInterface simulator;
64
65
66 private final GTUColorer gtuColorer;
67
68
69 private Map<LaneBasedGTU, Renderable2D<LaneBasedGTU>> animatedGTUs = new HashMap<>();
70
71
72 private Map<ObjectInterface, Renderable2D<?>> animatedObjects = new HashMap<>();
73
74
75
76
77
78
79
80
81
82
83 protected DefaultAnimationFactory(final OTSNetwork network, final OTSSimulatorInterface simulator,
84 final GTUColorer gtuColorer, final boolean animateNetwork) throws OTSDrawingException
85 {
86 this.simulator = simulator;
87 this.gtuColorer = gtuColorer;
88
89
90 network.addListener(this, Network.ANIMATION_GTU_ADD_EVENT);
91 network.addListener(this, Network.ANIMATION_GTU_REMOVE_EVENT);
92 network.addListener(this, Network.ANIMATION_OBJECT_ADD_EVENT);
93 network.addListener(this, Network.ANIMATION_OBJECT_REMOVE_EVENT);
94 network.addListener(this, Network.ANIMATION_GENERATOR_ADD_EVENT);
95 network.addListener(this, Network.ANIMATION_GENERATOR_REMOVE_EVENT);
96
97
98 try
99 {
100 if (animateNetwork)
101 {
102 for (Node node : network.getNodeMap().values())
103 {
104 new NodeAnimation(node, simulator);
105 }
106 for (Link link : network.getLinkMap().values())
107 {
108 new LinkAnimation(link, simulator, 0.5f);
109 if (link instanceof CrossSectionLink)
110 {
111 for (CrossSectionElement element : ((CrossSectionLink) link).getCrossSectionElementList())
112 {
113 if (element instanceof Lane)
114 {
115 new LaneAnimation((Lane) element, simulator, Color.GRAY.brighter(), false);
116 }
117 else if (element instanceof Shoulder)
118 {
119 new ShoulderAnimation((Shoulder) element, simulator, Color.DARK_GRAY);
120 }
121 else if (element instanceof Stripe)
122 {
123 Stripe stripe = (Stripe) element;
124 TYPE type;
125 if (stripe.isPermeable(GTUType.CAR, LateralDirectionality.LEFT))
126 {
127 type = stripe.isPermeable(GTUType.CAR, LateralDirectionality.RIGHT) ? TYPE.DASHED
128 : TYPE.LEFTONLY;
129 }
130 else
131 {
132 type = stripe.isPermeable(GTUType.CAR, LateralDirectionality.RIGHT) ? TYPE.RIGHTONLY
133 : TYPE.SOLID;
134 }
135 new StripeAnimation((Stripe) element, simulator, type);
136 }
137 }
138 }
139 }
140 }
141
142 for (GTU gtu : network.getGTUs())
143 {
144 Renderable2D<LaneBasedGTU> gtuAnimation =
145 new DefaultCarAnimation((LaneBasedGTU) gtu, simulator, this.gtuColorer);
146 this.animatedGTUs.put((LaneBasedGTU) gtu, gtuAnimation);
147 }
148
149 for (ObjectInterface object : network.getObjectMap().values())
150 {
151 animateStaticObject(object);
152 }
153 }
154 catch (RemoteException | NamingException | OTSGeometryException exception)
155 {
156 throw new OTSDrawingException("Exception while creating network animation.", exception);
157 }
158 }
159
160
161
162
163
164
165
166
167
168 public static void animateNetwork(final OTSNetwork network, final OTSSimulatorInterface simulator,
169 final GTUColorer gtuColorer) throws OTSDrawingException
170 {
171 new DefaultAnimationFactory(network, simulator, gtuColorer, true);
172 }
173
174
175
176
177
178
179
180
181
182 public static void animateXmlNetwork(final OTSNetwork network, final OTSSimulatorInterface simulator,
183 final GTUColorer gtuColorer) throws OTSDrawingException
184 {
185 new DefaultAnimationFactory(network, simulator, gtuColorer, false);
186 }
187
188
189 @Override
190 public void notify(final EventInterface event) throws RemoteException
191 {
192 try
193 {
194 if (event.getType().equals(Network.ANIMATION_GTU_ADD_EVENT))
195 {
196
197 LaneBasedGTU gtu = (LaneBasedGTU) event.getContent();
198 this.simulator.scheduleEventNow(this, this, "animateGTU", new Object[] { gtu });
199 }
200 else if (event.getType().equals(Network.ANIMATION_GTU_REMOVE_EVENT))
201 {
202 LaneBasedGTU gtu = (LaneBasedGTU) event.getContent();
203 if (this.animatedGTUs.containsKey(gtu))
204 {
205 this.animatedGTUs.get(gtu).destroy();
206 this.animatedGTUs.remove(gtu);
207 }
208 }
209 else if (event.getType().equals(Network.ANIMATION_OBJECT_ADD_EVENT))
210 {
211 ObjectInterface object = (ObjectInterface) event.getContent();
212 animateStaticObject(object);
213 }
214 else if (event.getType().equals(Network.ANIMATION_OBJECT_REMOVE_EVENT))
215 {
216 ObjectInterface object = (ObjectInterface) event.getContent();
217 if (this.animatedObjects.containsKey(object))
218 {
219 this.animatedObjects.get(object).destroy();
220 this.animatedObjects.remove(object);
221 }
222 }
223 else if (event.getType().equals(Network.ANIMATION_GENERATOR_ADD_EVENT))
224 {
225 AbstractGTUGenerator gtuGenerator = (AbstractGTUGenerator) event.getContent();
226 animateGTUGenerator(gtuGenerator);
227 }
228 else if (event.getType().equals(Network.ANIMATION_GENERATOR_REMOVE_EVENT))
229 {
230
231 }
232 }
233 catch (NamingException | SimRuntimeException exception)
234 {
235 SimLogger.always().error(exception, "Exception while updating network animation.");
236 }
237 }
238
239
240
241
242
243 protected void animateGTU(final LaneBasedGTU gtu)
244 {
245 try
246 {
247 Renderable2D<LaneBasedGTU> gtuAnimation = new DefaultCarAnimation(gtu, this.simulator, this.gtuColorer);
248 this.animatedGTUs.put(gtu, gtuAnimation);
249 }
250 catch (RemoteException | NamingException exception)
251 {
252 SimLogger.always().error(exception, "Exception while drawing GTU.");
253 }
254 }
255
256
257
258
259
260 protected void animateStaticObject(final ObjectInterface object)
261 {
262 try
263 {
264 if (object instanceof SingleSensor)
265 {
266 SingleSensor sensor = (SingleSensor) object;
267 Renderable2D<SingleSensor> objectAnimation =
268 new SensorAnimation(sensor, sensor.getLongitudinalPosition(), this.simulator, Color.GREEN);
269 this.animatedObjects.put(object, objectAnimation);
270 }
271 else if (object instanceof Conflict)
272 {
273 Conflict conflict = (Conflict) object;
274 Renderable2D<Conflict> objectAnimation = new ConflictAnimation(conflict, this.simulator);
275 this.animatedObjects.put(object, objectAnimation);
276 }
277 else if (object instanceof SpeedSign)
278 {
279 SpeedSign speedSign = (SpeedSign) object;
280 Renderable2D<SpeedSign> objectAnimation = new SpeedSignAnimation(speedSign, this.simulator);
281 this.animatedObjects.put(object, objectAnimation);
282 }
283 else if (object instanceof BusStop)
284 {
285 BusStop busStop = (BusStop) object;
286 Renderable2D<BusStop> objectAnimation = new BusStopAnimation(busStop, this.simulator);
287 this.animatedObjects.put(object, objectAnimation);
288 }
289 }
290 catch (RemoteException | NamingException exception)
291 {
292 SimLogger.always().error(exception, "Exception while drawing Object of class ObjectInterface.");
293 }
294 }
295
296
297
298
299
300 protected void animateGTUGenerator(final AbstractGTUGenerator gtuGenerator)
301 {
302 try
303 {
304 new GTUGeneratorAnimation(gtuGenerator, this.simulator);
305 }
306 catch (RemoteException | NamingException exception)
307 {
308 SimLogger.always().error(exception, "Exception while drawing GTUGenerator.");
309 }
310 }
311
312 }