1 package org.opentrafficsim.simulationengine;
2
3 import java.awt.Container;
4 import java.awt.Dimension;
5 import java.awt.Frame;
6 import java.awt.Rectangle;
7 import java.awt.geom.Rectangle2D;
8 import java.io.Serializable;
9 import java.rmi.RemoteException;
10 import java.util.ArrayList;
11 import java.util.List;
12
13 import javax.naming.NamingException;
14 import javax.swing.WindowConstants;
15 import javax.vecmath.Point3d;
16
17 import org.djunits.value.vdouble.scalar.Duration;
18 import org.djunits.value.vdouble.scalar.Time;
19 import org.opentrafficsim.base.modelproperties.Property;
20 import org.opentrafficsim.base.modelproperties.PropertyException;
21 import org.opentrafficsim.core.dsol.OTSModelInterface;
22 import org.opentrafficsim.core.gtu.animation.DefaultSwitchableGTUColorer;
23 import org.opentrafficsim.core.gtu.animation.GTUColorer;
24 import org.opentrafficsim.core.network.Link;
25 import org.opentrafficsim.core.network.NetworkException;
26 import org.opentrafficsim.gui.OTSAnimationPanel;
27 import org.opentrafficsim.gui.SimulatorFrame;
28
29 import nl.tudelft.simulation.dsol.SimRuntimeException;
30 import nl.tudelft.simulation.dsol.animation.Locatable;
31 import nl.tudelft.simulation.dsol.animation.D2.GisRenderable2D;
32 import nl.tudelft.simulation.language.d3.BoundingBox;
33 import nl.tudelft.simulation.language.d3.DirectedPoint;
34
35
36
37
38
39
40
41
42
43
44
45 public abstract class AbstractWrappableAnimation implements WrappableAnimation, Serializable
46 {
47
48 private static final long serialVersionUID = 20150000L;
49
50
51 @SuppressWarnings("checkstyle:visibilitymodifier")
52 protected List<Property<?>> properties = new ArrayList<>();
53
54
55 @SuppressWarnings("checkstyle:visibilitymodifier")
56 protected List<Property<?>> savedUserModifiedProperties;
57
58
59 @SuppressWarnings("checkstyle:visibilitymodifier")
60 protected boolean exitOnClose;
61
62
63 @SuppressWarnings("checkstyle:visibilitymodifier")
64 protected OTSAnimationPanel panel;
65
66
67 private Time savedStartTime;
68
69
70 private Duration savedWarmupPeriod;
71
72
73 private Duration savedRunLength;
74
75
76 private OTSModelInterface model;
77
78
79 private Integer replication = null;
80
81
82
83
84
85
86
87
88
89
90
91
92 @SuppressWarnings("checkstyle:designforextension")
93 protected SimpleAnimator buildSimpleAnimator(final Time startTime, final Duration warmupPeriod, final Duration runLength,
94 final OTSModelInterface otsModel) throws SimRuntimeException, NamingException, PropertyException
95 {
96 return new SimpleAnimator(startTime, warmupPeriod, runLength, otsModel);
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110
111 @SuppressWarnings("checkstyle:designforextension")
112 protected SimpleAnimator buildSimpleAnimator(final Time startTime, final Duration warmupPeriod, final Duration runLength,
113 final OTSModelInterface otsModel, final int replicationNumber)
114 throws SimRuntimeException, NamingException, PropertyException
115 {
116 return new SimpleAnimator(startTime, warmupPeriod, runLength, otsModel, replicationNumber);
117 }
118
119
120 @Override
121 @SuppressWarnings("checkstyle:designforextension")
122 public SimpleAnimator buildAnimator(final Time startTime, final Duration warmupPeriod, final Duration runLength,
123 final List<Property<?>> userModifiedProperties, final Rectangle rect, final boolean eoc)
124 throws SimRuntimeException, NamingException, OTSSimulationException, PropertyException
125 {
126 this.savedUserModifiedProperties = userModifiedProperties;
127 this.exitOnClose = eoc;
128
129 this.savedStartTime = startTime;
130 this.savedWarmupPeriod = warmupPeriod;
131 this.savedRunLength = runLength;
132
133 GTUColorer colorer = getColorer();
134 this.model = makeModel(colorer);
135
136 if (null == this.model)
137 {
138 return null;
139 }
140
141 final SimpleAnimator simulator =
142 null == this.replication ? buildSimpleAnimator(startTime, warmupPeriod, runLength, this.model)
143 : buildSimpleAnimator(startTime, warmupPeriod, runLength, this.model, this.replication);
144 try
145 {
146 this.panel = new OTSAnimationPanel(makeAnimationRectangle(), new Dimension(1024, 768), simulator, this, colorer);
147 }
148 catch (RemoteException exception)
149 {
150 throw new SimRuntimeException(exception);
151 }
152
153 addAnimationToggles();
154 addTabs(simulator);
155
156 SimulatorFrame frame = new SimulatorFrame(shortName(), this.panel);
157 if (rect != null)
158 {
159 frame.setBounds(rect);
160 }
161 else
162 {
163 frame.setExtendedState(Frame.MAXIMIZED_BOTH);
164 }
165
166 frame.setDefaultCloseOperation(this.exitOnClose ? WindowConstants.EXIT_ON_CLOSE : WindowConstants.DISPOSE_ON_CLOSE);
167
168 return simulator;
169 }
170
171
172
173
174
175 protected GTUColorer getColorer()
176 {
177 return new DefaultSwitchableGTUColorer();
178 }
179
180
181
182
183
184
185
186 protected void addTabs(final SimpleSimulatorInterface simulator) throws OTSSimulationException, PropertyException
187 {
188
189 }
190
191
192
193
194 @SuppressWarnings("checkstyle:designforextension")
195 protected void addAnimationToggles()
196 {
197
198 }
199
200
201
202
203
204
205
206
207
208
209
210
211 public final void addToggleAnimationButtonIcon(final String name, final Class<? extends Locatable> locatableClass,
212 final String iconPath, final String toolTipText, final boolean initiallyVisible, final boolean idButton)
213 {
214 this.panel.addToggleAnimationButtonIcon(name, locatableClass, iconPath, toolTipText, initiallyVisible, idButton);
215 }
216
217
218
219
220
221
222
223
224 public final void addToggleAnimationButtonText(final String name, final Class<? extends Locatable> locatableClass,
225 final String toolTipText, final boolean initiallyVisible)
226 {
227 this.panel.addToggleAnimationButtonText(name, locatableClass, toolTipText, initiallyVisible);
228 }
229
230
231
232
233
234 public final void showAnimationClass(final Class<? extends Locatable> locatableClass)
235 {
236 this.panel.getAnimationPanel().showClass(locatableClass);
237 }
238
239
240
241
242
243 public final void hideAnimationClass(final Class<? extends Locatable> locatableClass)
244 {
245 this.panel.getAnimationPanel().hideClass(locatableClass);
246 }
247
248
249
250
251
252 public final void toggleAnimationClass(final Class<? extends Locatable> locatableClass)
253 {
254 this.panel.getAnimationPanel().toggleClass(locatableClass);
255 }
256
257
258
259
260
261
262
263 public final void addToggleGISButtonText(final String header, final GisRenderable2D gisMap, final String toolTipText)
264 {
265 this.panel.addToggleText(" ");
266 this.panel.addToggleText(header);
267 try
268 {
269 for (String layerName : gisMap.getMap().getLayerMap().keySet())
270 {
271 this.panel.addToggleGISButtonText(layerName, layerName, gisMap, toolTipText);
272 }
273 }
274 catch (RemoteException exception)
275 {
276 exception.printStackTrace();
277 }
278 }
279
280
281
282
283
284 public final void showGISLayer(final String layerName)
285 {
286 this.panel.showGISLayer(layerName);
287 }
288
289
290
291
292
293 public final void hideGISLayer(final String layerName)
294 {
295 this.panel.hideGISLayer(layerName);
296 }
297
298
299
300
301
302 public final void toggleGISLayer(final String layerName)
303 {
304 this.panel.toggleGISLayer(layerName);
305 }
306
307
308
309
310
311
312 protected abstract OTSModelInterface makeModel(GTUColorer colorer) throws OTSSimulationException;
313
314
315
316
317
318
319 @SuppressWarnings("checkstyle:designforextension")
320 protected Rectangle2D makeAnimationRectangle()
321 {
322 double minX = Double.MAX_VALUE;
323 double maxX = -Double.MAX_VALUE;
324 double minY = Double.MAX_VALUE;
325 double maxY = -Double.MAX_VALUE;
326 Point3d p3dL = new Point3d();
327 Point3d p3dU = new Point3d();
328 try
329 {
330 for (Link link : this.model.getNetwork().getLinkMap().values())
331 {
332 DirectedPoint l = link.getLocation();
333 BoundingBox b = new BoundingBox(link.getBounds());
334 b.getLower(p3dL);
335 b.getUpper(p3dU);
336 minX = Math.min(minX, l.x + Math.min(p3dL.x, p3dU.x));
337 minY = Math.min(minY, l.y + Math.min(p3dL.y, p3dU.y));
338 maxX = Math.max(maxX, l.x + Math.max(p3dL.x, p3dU.x));
339 maxY = Math.max(maxY, l.y + Math.max(p3dL.y, p3dU.y));
340 }
341 }
342 catch (Exception e)
343 {
344
345 }
346
347 minX = minX - 0.05 * Math.abs(minX);
348 minY = minY - 0.05 * Math.abs(minY);
349 maxX = maxX + 0.05 * Math.abs(maxX);
350 maxY = maxY + 0.05 * Math.abs(maxY);
351
352 return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
353 }
354
355
356 @Override
357 public final ArrayList<Property<?>> getProperties()
358 {
359 return new ArrayList<Property<?>>(this.properties);
360 }
361
362
363 @Override
364 public final SimpleSimulatorInterface rebuildSimulator(final Rectangle rect)
365 throws SimRuntimeException, NetworkException, NamingException, OTSSimulationException, PropertyException
366 {
367 return buildAnimator(this.savedStartTime, this.savedWarmupPeriod, this.savedRunLength, this.savedUserModifiedProperties,
368 rect, this.exitOnClose);
369 }
370
371
372 @Override
373 public final List<Property<?>> getUserModifiedProperties()
374 {
375 return this.savedUserModifiedProperties;
376 }
377
378
379 @Override
380 @SuppressWarnings("checkstyle:designforextension")
381 public void stopTimersThreads()
382 {
383 if (this.panel != null && this.panel.getStatusBar() != null)
384 {
385 this.panel.getStatusBar().cancelTimer();
386 }
387 this.panel = null;
388 }
389
390
391
392
393 public final OTSAnimationPanel getPanel()
394 {
395 return this.panel;
396 }
397
398
399
400
401
402
403
404
405 public final void addTab(final int index, final String caption, final Container container)
406 {
407 this.panel.getTabbedPane().addTab(index, caption, container);
408 }
409
410
411
412
413
414
415 public final int getTabCount()
416 {
417 return this.panel.getTabbedPane().getTabCount();
418 }
419
420
421 @Override
422 public final void setNextReplication(final Integer nextReplication)
423 {
424 this.replication = nextReplication;
425 }
426
427 }