1 package org.opentrafficsim.core.animation;
2
3 import java.awt.Color;
4 import java.awt.Font;
5 import java.awt.FontMetrics;
6 import java.awt.Graphics2D;
7 import java.awt.geom.Rectangle2D;
8 import java.awt.image.ImageObserver;
9 import java.io.Serializable;
10 import java.rmi.RemoteException;
11
12 import javax.media.j3d.Bounds;
13 import javax.naming.NamingException;
14
15 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
16
17 import nl.tudelft.simulation.dsol.animation.Locatable;
18 import nl.tudelft.simulation.dsol.animation.D2.Renderable2D;
19 import nl.tudelft.simulation.language.d3.BoundingBox;
20 import nl.tudelft.simulation.language.d3.DirectedPoint;
21
22 /**
23 * Display a text for another Locatable object.
24 * <p>
25 * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
26 * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
27 * </p>
28 * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
29 * initial version Dec 11, 2016 <br>
30 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
31 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
32 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
33 */
34 public abstract class TextAnimation implements Locatable, Serializable
35 {
36 /** */
37 private static final long serialVersionUID = 20161211L;
38
39 /** the object for which the text is displayed. */
40 private final Locatable source;
41
42 /** the text to display. */
43 private String text;
44
45 /** the horizontal movement of the text, in meters. */
46 private final float dx;
47
48 /** the vertical movement of the text, in meters. */
49 private final float dy;
50
51 /** whether to center or not. */
52 private final TextAlignment textAlignment;
53
54 /** the color of the text. */
55 private Color color;
56
57 /** fontSize the size of the font; default = 2.0 (meters). */
58 private final float fontSize;
59
60 /** the animation implementation. */
61 private final AnimationImpl animationImpl;
62
63 /** the font. */
64 private Font font;
65
66 /** the font rectangle. */
67 private Rectangle2D fontRectangle = null;
68
69 /**
70 * @param source the object for which the text is displayed
71 * @param text the text to display
72 * @param dx the horizontal movement of the text, in meters
73 * @param dy the vertical movement of the text, in meters
74 * @param textAlignment where to place the text
75 * @param color the color of the text
76 * @param fontSize the size of the font; default = 2.0 (meters)
77 * @param simulator the simulator
78 * @throws NamingException when animation context cannot be created or retrieved
79 * @throws RemoteException - when remote context cannot be found
80 */
81 @SuppressWarnings("checkstyle:parameternumber")
82 public TextAnimation(final Locatable source, final String text, final float dx, final float dy,
83 final TextAlignment textAlignment, final Color color, final float fontSize, final OTSSimulatorInterface simulator)
84 throws RemoteException, NamingException
85 {
86 this.source = source;
87 this.text = text;
88 this.dx = dx;
89 this.dy = dy;
90 this.textAlignment = textAlignment;
91 this.color = color;
92 this.fontSize = fontSize;
93
94 this.font = new Font("SansSerif", Font.PLAIN, 2);
95 if (this.fontSize != 2.0f)
96 {
97 this.font = this.font.deriveFont(this.fontSize);
98 }
99
100 this.animationImpl = new AnimationImpl(this, simulator);
101 }
102
103 /**
104 * @param source the object for which the text is displayed
105 * @param text the text to display
106 * @param dx the horizontal movement of the text, in meters
107 * @param dy the vertical movement of the text, in meters
108 * @param textAlignment where to place the text
109 * @param color the color of the text
110 * @param simulator the simulator
111 * @throws NamingException when animation context cannot be created or retrieved
112 * @throws RemoteException - when remote context cannot be found
113 */
114 public TextAnimation(final Locatable source, final String text, final float dx, final float dy,
115 final TextAlignment textAlignment, final Color color, final OTSSimulatorInterface simulator)
116 throws RemoteException, NamingException
117 {
118 this(source, text, dx, dy, textAlignment, color, 2.0f, simulator);
119 }
120
121 /** {@inheritDoc} */
122 @Override
123 @SuppressWarnings("checkstyle:designforextension")
124 public DirectedPoint getLocation() throws RemoteException
125 {
126 // draw always on top.
127 DirectedPoint p = this.source.getLocation();
128 return new DirectedPoint(p.x, p.y, Double.MAX_VALUE, 0.0, 0.0, p.getRotZ());
129 }
130
131 /** {@inheritDoc} */
132 @Override
133 public final Bounds getBounds() throws RemoteException
134 {
135 return new BoundingBox(0.0, 0.0, 0.0);
136 }
137
138 /**
139 * paint() method so it can be overridden or extended.
140 * @param graphics the graphics object
141 * @param observer the observer
142 * @throws RemoteException on network exception
143 */
144 @SuppressWarnings("checkstyle:designforextension")
145 public void paint(final Graphics2D graphics, final ImageObserver observer) throws RemoteException
146 {
147 graphics.setFont(this.font);
148 synchronized (this.font)
149 {
150 if (this.fontRectangle == null)
151 {
152 FontMetrics fm = graphics.getFontMetrics();
153 this.fontRectangle = fm.getStringBounds(this.text, graphics);
154 }
155 graphics.setColor(this.color);
156 float dxText =
157 this.textAlignment.equals(TextAlignment.LEFT) ? 0.0f : this.textAlignment.equals(TextAlignment.CENTER)
158 ? (float) -this.fontRectangle.getWidth() / 2.0f : (float) -this.fontRectangle.getWidth();
159 graphics.drawString(this.text, dxText + this.dx, this.fontSize / 2.0f - this.dy);
160 }
161 }
162
163 /**
164 * Destroy the text animation.
165 */
166 public final void destroy()
167 {
168 try
169 {
170 this.animationImpl.destroy();
171 }
172 catch (NamingException exception)
173 {
174 System.err.println("Tried to destroy Text for GTU animation of GTU " + this.source.toString());
175 }
176 }
177
178 /**
179 * Clone the TextAnimation and return a copy for the new source on the new simulator.
180 * @param newSource the new source to link to the text animation
181 * @param newSimulator the new simulator to register the animation on
182 * @return a copy of the TextAnimation
183 * @throws RemoteException when remote animation cannot be reached
184 * @throws NamingException when animation name cannot be found or bound in the Context
185 */
186 public abstract TextAnimation clone(final Locatable newSource, final OTSSimulatorInterface newSimulator)
187 throws RemoteException, NamingException;
188
189 /**
190 * @return source
191 */
192 protected final Locatable getSource()
193 {
194 return this.source;
195 }
196
197 /**
198 * @return dx
199 */
200 protected final float getDx()
201 {
202 return this.dx;
203 }
204
205 /**
206 * @return dy
207 */
208 protected final float getDy()
209 {
210 return this.dy;
211 }
212
213 /**
214 * @return textAlignment
215 */
216 protected final TextAlignment getTextAlignment()
217 {
218 return this.textAlignment;
219 }
220
221 /**
222 * @return fontSize
223 */
224 protected final float getFontSize()
225 {
226 return this.fontSize;
227 }
228
229 /**
230 * @return font
231 */
232 protected final Font getFont()
233 {
234 return this.font;
235 }
236
237 /**
238 * @return current text
239 */
240 protected final String getText()
241 {
242 return this.text;
243 }
244
245 /**
246 * @param text set new text
247 */
248 protected final void setText(final String text)
249 {
250 this.text = text;
251 synchronized (this.font)
252 {
253 this.fontRectangle = null;
254 }
255 }
256
257 /**
258 * @return current color
259 */
260 protected final Color getColor()
261 {
262 return this.color;
263 }
264
265 /**
266 * @param color set new color
267 */
268 protected final void setColor(final Color color)
269 {
270 this.color = color;
271 }
272
273 /**
274 * @return Returns the flip.
275 */
276 public final boolean isFlip()
277 {
278 return this.animationImpl.isFlip();
279 }
280
281 /**
282 * @param flip The flip to set.
283 */
284 public final void setFlip(final boolean flip)
285 {
286 this.animationImpl.setFlip(flip);
287 }
288
289 /**
290 * @return Returns the rotate.
291 */
292 public final boolean isRotate()
293 {
294 return this.animationImpl.isRotate();
295 }
296
297 /**
298 * @param rotate The rotate to set.
299 */
300 public final void setRotate(final boolean rotate)
301 {
302 this.animationImpl.setRotate(rotate);
303
304 }
305
306 /**
307 * @return Returns the scale.
308 */
309 public final boolean isScale()
310 {
311 return this.animationImpl.isScale();
312 }
313
314 /**
315 * @param scale The scale to set.
316 */
317 public final void setScale(final boolean scale)
318 {
319 this.animationImpl.setScale(scale);
320 }
321
322 /**
323 * @return Returns the translate.
324 */
325 public final boolean isTranslate()
326 {
327 return this.animationImpl.isTranslate();
328 }
329
330 /**
331 * @param translate The translate to set.
332 */
333 public final void setTranslate(final boolean translate)
334 {
335 this.animationImpl.setTranslate(translate);
336 }
337
338 /**
339 * The implementation of the text animation. Cloning will be taken care of by the overarching TextAnimation-derived class.
340 * <p>
341 * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
342 * <br>
343 * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
344 * </p>
345 * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
346 * initial version Dec 11, 2016 <br>
347 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
348 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
349 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
350 */
351 private static class AnimationImpl extends Renderable2D implements Serializable
352 {
353 /** */
354 private static final long serialVersionUID = 20170400L;
355
356 /**
357 * @param source the source
358 * @param simulator the simulator
359 * @throws NamingException when animation context cannot be created or retrieved
360 * @throws RemoteException - when remote context cannot be found
361 */
362 AnimationImpl(final Locatable source, final OTSSimulatorInterface simulator) throws NamingException, RemoteException
363 {
364 super(source, simulator);
365 }
366
367 /** {@inheritDoc} */
368 @Override
369 public final void paint(final Graphics2D graphics, final ImageObserver observer) throws RemoteException
370 {
371 TextAnimation ta = ((TextAnimation) getSource());
372 ta.paint(graphics, observer);
373 }
374
375 /** {@inheritDoc} */
376 @Override
377 public final String toString()
378 {
379 return "TextAnimation.AnimationImpl []";
380 }
381
382 }
383 }