1 package org.opentrafficsim.road.gtu.animation;
2
3 import java.awt.BasicStroke;
4 import java.awt.Color;
5 import java.awt.Graphics2D;
6 import java.awt.geom.Ellipse2D;
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.naming.NamingException;
13
14 import org.opentrafficsim.core.animation.ClonableRenderable2DInterface;
15 import org.opentrafficsim.core.animation.TextAlignment;
16 import org.opentrafficsim.core.animation.TextAnimation;
17 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
18 import org.opentrafficsim.core.gtu.animation.GTUColorer;
19 import org.opentrafficsim.core.gtu.animation.IDGTUColorer;
20 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
21
22 import nl.tudelft.simulation.dsol.animation.Locatable;
23 import nl.tudelft.simulation.dsol.animation.D2.Renderable2D;
24 import nl.tudelft.simulation.language.d2.Angle;
25 import nl.tudelft.simulation.language.d3.DirectedPoint;
26
27
28
29
30
31
32
33
34
35
36
37
38 public class DefaultCarAnimation extends Renderable2D implements ClonableRenderable2DInterface, Serializable
39 {
40
41 private static final long serialVersionUID = 20150000L;
42
43
44 private GTUColorer gtuColorer;
45
46
47 private Text text;
48
49
50 private boolean isDestroyed = false;
51
52
53
54
55
56
57
58
59 public DefaultCarAnimation(final LaneBasedIndividualGTU gtu, final OTSSimulatorInterface simulator)
60 throws NamingException, RemoteException
61 {
62 this(gtu, simulator, null);
63 }
64
65
66
67
68
69
70
71
72
73 public DefaultCarAnimation(final LaneBasedIndividualGTU gtu, final OTSSimulatorInterface simulator,
74 final GTUColorer gtuColorer) throws NamingException, RemoteException
75 {
76 super(gtu, simulator);
77 if (null == gtuColorer)
78 {
79 this.gtuColorer = new IDGTUColorer();
80 }
81 else
82 {
83 this.gtuColorer = gtuColorer;
84 }
85
86 this.text = new Text(gtu, gtu.getId(), 0.0f, 0.0f, TextAlignment.CENTER, Color.BLACK, simulator);
87 }
88
89
90
91
92
93 public final void setGTUColorer(final GTUColorer newGTUColorer)
94 {
95 this.gtuColorer = newGTUColorer;
96 }
97
98
99 @Override
100 public final void paint(final Graphics2D graphics, final ImageObserver observer)
101 {
102 final LaneBasedIndividualGTU car = (LaneBasedIndividualGTU) getSource();
103
104 if (car.isDestroyed())
105 {
106 if (!this.isDestroyed)
107 {
108 try
109 {
110 destroy();
111 }
112 catch (Exception e)
113 {
114 System.err.println("Error while destroying GTU " + car.getId());
115 }
116 this.isDestroyed = true;
117 }
118 return;
119 }
120
121 final double length = car.getLength().getSI();
122 final double l2 = length / 2;
123 final double width = car.getWidth().getSI();
124 final double w2 = width / 2;
125 final double w4 = width / 4;
126 graphics.setColor(this.gtuColorer.getColor(car));
127 BasicStroke saveStroke = (BasicStroke) graphics.getStroke();
128 graphics.setStroke(new BasicStroke(0));
129 Rectangle2D rectangle = new Rectangle2D.Double(-l2, -w2, length, width);
130 graphics.draw(rectangle);
131 graphics.fill(rectangle);
132
133 graphics.setColor(Color.WHITE);
134 Ellipse2D.Double frontIndicator = new Ellipse2D.Double(l2 - w2 - w4, -w4, w2, w2);
135 graphics.draw(frontIndicator);
136 graphics.fill(frontIndicator);
137
138
139 graphics.setColor(Color.YELLOW);
140 if (car.getTurnIndicatorStatus() != null && car.getTurnIndicatorStatus().isLeftOrBoth())
141 {
142 Rectangle2D.Double leftIndicator = new Rectangle2D.Double(l2 - w4, -w2, w4, w4);
143 graphics.fill(leftIndicator);
144 }
145 if (car.getTurnIndicatorStatus() != null && car.getTurnIndicatorStatus().isRightOrBoth())
146 {
147 Rectangle2D.Double rightIndicator = new Rectangle2D.Double(l2 - w4, w2 - w4, w4, w4);
148 graphics.fill(rightIndicator);
149 }
150
151
152 graphics.setColor(Color.RED);
153 if (car.getAcceleration().si < -0.5)
154 {
155 Rectangle2D.Double leftBrake = new Rectangle2D.Double(-l2, w2 - w4, w4, w4);
156 Rectangle2D.Double rightBrake = new Rectangle2D.Double(-l2, -w2, w4, w4);
157 graphics.setColor(Color.RED);
158 graphics.fill(leftBrake);
159 graphics.fill(rightBrake);
160 }
161 graphics.setStroke(saveStroke);
162 }
163
164
165 @Override
166 public final void destroy() throws NamingException
167 {
168 super.destroy();
169 this.text.destroy();
170 }
171
172
173 @Override
174 @SuppressWarnings("checkstyle:designforextension")
175 public ClonableRenderable2DInterface clone(final Locatable newSource, final OTSSimulatorInterface newSimulator)
176 throws NamingException, RemoteException
177 {
178
179 return new DefaultCarAnimation((LaneBasedIndividualGTU) newSource, newSimulator, this.gtuColorer);
180 }
181
182
183 @Override
184 public final String toString()
185 {
186 return super.toString();
187 }
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 public class Text extends TextAnimation
203 {
204
205 private static final long serialVersionUID = 20161211L;
206
207
208 private boolean isTextDestroyed = false;
209
210
211
212
213
214
215
216
217
218
219
220
221 public Text(final Locatable source, final String text, final float dx, final float dy,
222 final TextAlignment textAlignment, final Color color, final OTSSimulatorInterface simulator)
223 throws RemoteException, NamingException
224 {
225 super(source, text, dx, dy, textAlignment, color, 1.0f, simulator);
226 }
227
228
229 @Override
230 public final void paint(final Graphics2D graphics, final ImageObserver observer) throws RemoteException
231 {
232 final LaneBasedIndividualGTU car = (LaneBasedIndividualGTU) getSource();
233
234 if (car.isDestroyed())
235 {
236 if (!this.isTextDestroyed)
237 {
238 try
239 {
240 destroy();
241 }
242 catch (Exception e)
243 {
244 System.err.println("Error while destroying text animation of GTU " + car.getId());
245 }
246 this.isTextDestroyed = true;
247 }
248 return;
249 }
250
251 super.paint(graphics, observer);
252 }
253
254
255 @Override
256 @SuppressWarnings("checkstyle:designforextension")
257 public DirectedPoint getLocation() throws RemoteException
258 {
259
260 DirectedPoint p = ((LaneBasedIndividualGTU) getSource()).getLocation();
261 double a = Angle.normalizePi(p.getRotZ());
262 if (a > Math.PI / 2.0 || a < -0.99 * Math.PI / 2.0)
263 {
264 a += Math.PI;
265 }
266 return new DirectedPoint(p.x, p.y, Double.MAX_VALUE, 0.0, 0.0, a);
267 }
268
269
270 @Override
271 @SuppressWarnings("checkstyle:designforextension")
272 public TextAnimation clone(final Locatable newSource, final OTSSimulatorInterface newSimulator)
273 throws RemoteException, NamingException
274 {
275 return new Text(newSource, getText(), getDx(), getDy(), getTextAlignment(), getColor(), newSimulator);
276 }
277
278 }
279
280 }