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) throws SimRuntimeException, NamingException,
114 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 = new DefaultSwitchableGTUColorer();
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
176
177 protected void addTabs(final SimpleSimulatorInterface simulator) throws OTSSimulationException, PropertyException
178 {
179
180 }
181
182
183
184
185 @SuppressWarnings("checkstyle:designforextension")
186 protected void addAnimationToggles()
187 {
188
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202 public final void addToggleAnimationButtonIcon(final String name, final Class<? extends Locatable> locatableClass,
203 final String iconPath, final String toolTipText, final boolean initiallyVisible, final boolean idButton)
204 {
205 this.panel.addToggleAnimationButtonIcon(name, locatableClass, iconPath, toolTipText, initiallyVisible, idButton);
206 }
207
208
209
210
211
212
213
214
215 public final void addToggleAnimationButtonText(final String name, final Class<? extends Locatable> locatableClass,
216 final String toolTipText, final boolean initiallyVisible)
217 {
218 this.panel.addToggleAnimationButtonText(name, locatableClass, toolTipText, initiallyVisible);
219 }
220
221
222
223
224
225 public final void showAnimationClass(final Class<? extends Locatable> locatableClass)
226 {
227 this.panel.getAnimationPanel().showClass(locatableClass);
228 }
229
230
231
232
233
234 public final void hideAnimationClass(final Class<? extends Locatable> locatableClass)
235 {
236 this.panel.getAnimationPanel().hideClass(locatableClass);
237 }
238
239
240
241
242
243 public final void toggleAnimationClass(final Class<? extends Locatable> locatableClass)
244 {
245 this.panel.getAnimationPanel().toggleClass(locatableClass);
246 }
247
248
249
250
251
252
253
254 public final void addToggleGISButtonText(final String header, final GisRenderable2D gisMap, final String toolTipText)
255 {
256 this.panel.addToggleText(" ");
257 this.panel.addToggleText(header);
258 try
259 {
260 for (String layerName : gisMap.getMap().getLayerMap().keySet())
261 {
262 this.panel.addToggleGISButtonText(layerName, layerName, gisMap, toolTipText);
263 }
264 }
265 catch (RemoteException exception)
266 {
267 exception.printStackTrace();
268 }
269 }
270
271
272
273
274
275 public final void showGISLayer(final String layerName)
276 {
277 this.panel.showGISLayer(layerName);
278 }
279
280
281
282
283
284 public final void hideGISLayer(final String layerName)
285 {
286 this.panel.hideGISLayer(layerName);
287 }
288
289
290
291
292
293 public final void toggleGISLayer(final String layerName)
294 {
295 this.panel.toggleGISLayer(layerName);
296 }
297
298
299
300
301
302
303 protected abstract OTSModelInterface makeModel(GTUColorer colorer) throws OTSSimulationException;
304
305
306
307
308
309
310 @SuppressWarnings("checkstyle:designforextension")
311 protected Rectangle2D makeAnimationRectangle()
312 {
313 double minX = Double.MAX_VALUE;
314 double maxX = -Double.MAX_VALUE;
315 double minY = Double.MAX_VALUE;
316 double maxY = -Double.MAX_VALUE;
317 Point3d p3dL = new Point3d();
318 Point3d p3dU = new Point3d();
319 try
320 {
321 for (Link link : this.model.getNetwork().getLinkMap().values())
322 {
323 DirectedPoint l = link.getLocation();
324 BoundingBox b = new BoundingBox(link.getBounds());
325 b.getLower(p3dL);
326 b.getUpper(p3dU);
327 minX = Math.min(minX, l.x + Math.min(p3dL.x, p3dU.x));
328 minY = Math.min(minY, l.y + Math.min(p3dL.y, p3dU.y));
329 maxX = Math.max(maxX, l.x + Math.max(p3dL.x, p3dU.x));
330 maxY = Math.max(maxY, l.y + Math.max(p3dL.y, p3dU.y));
331 }
332 }
333 catch (Exception e)
334 {
335
336 }
337
338 minX = minX - 0.05 * Math.abs(minX);
339 minY = minY - 0.05 * Math.abs(minY);
340 maxX = maxX + 0.05 * Math.abs(maxX);
341 maxY = maxY + 0.05 * Math.abs(maxY);
342
343 return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
344 }
345
346
347 @Override
348 public final ArrayList<Property<?>> getProperties()
349 {
350 return new ArrayList<Property<?>>(this.properties);
351 }
352
353
354 @Override
355 public final SimpleSimulatorInterface rebuildSimulator(final Rectangle rect) throws SimRuntimeException, NetworkException,
356 NamingException, OTSSimulationException, PropertyException
357 {
358 return buildAnimator(this.savedStartTime, this.savedWarmupPeriod, this.savedRunLength,
359 this.savedUserModifiedProperties, rect, this.exitOnClose);
360 }
361
362
363 @Override
364 public final List<Property<?>> getUserModifiedProperties()
365 {
366 return this.savedUserModifiedProperties;
367 }
368
369
370 @Override
371 @SuppressWarnings("checkstyle:designforextension")
372 public void stopTimersThreads()
373 {
374 if (this.panel != null && this.panel.getStatusBar() != null)
375 {
376 this.panel.getStatusBar().cancelTimer();
377 }
378 this.panel = null;
379 }
380
381
382
383
384 public final OTSAnimationPanel getPanel()
385 {
386 return this.panel;
387 }
388
389
390
391
392
393
394
395
396 public final void addTab(final int index, final String caption, final Container container)
397 {
398 this.panel.getTabbedPane().addTab(index, caption, container);
399 }
400
401
402
403
404
405
406 public final int getTabCount()
407 {
408 return this.panel.getTabbedPane().getTabCount();
409 }
410
411
412 @Override
413 public final void setNextReplication(final Integer nextReplication)
414 {
415 this.replication = nextReplication;
416 }
417
418 }