1 package org.opentrafficsim.draw.gtu;
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.geom.RectangularShape;
9 import java.awt.image.ImageObserver;
10 import java.util.function.Supplier;
11
12 import org.djunits.value.vdouble.scalar.Length;
13 import org.djutils.base.Identifiable;
14 import org.djutils.draw.point.OrientedPoint2d;
15 import org.opentrafficsim.base.geometry.OtsLocatable;
16 import org.opentrafficsim.draw.DrawLevel;
17 import org.opentrafficsim.draw.OtsRenderable;
18 import org.opentrafficsim.draw.TextAlignment;
19 import org.opentrafficsim.draw.TextAnimation;
20 import org.opentrafficsim.draw.gtu.DefaultCarAnimation.GtuData;
21
22 import nl.tudelft.simulation.naming.context.Contextualized;
23
24
25
26
27
28
29
30
31
32
33
34 public class DefaultCarAnimation extends OtsRenderable<GtuData>
35 {
36
37 private static final long serialVersionUID = 20150000L;
38
39
40 private Text text;
41
42
43 private final int hashCode;
44
45
46 private Rectangle2D.Double rectangle;
47
48
49 private Ellipse2D.Double frontIndicator;
50
51
52 private Rectangle2D.Double leftIndicator;
53
54
55 private Rectangle2D.Double rightIndicator;
56
57
58 private Rectangle2D.Double leftBrake;
59
60
61 private Rectangle2D.Double rightBrake;
62
63
64 private RectangularShape marker;
65
66
67
68
69
70
71 public DefaultCarAnimation(final GtuData gtu, final Contextualized contextualized)
72 {
73 super(gtu, contextualized);
74 this.hashCode = gtu.hashCode();
75 this.text = new Text(gtu, gtu::getId, 0.0f, 0.0f, TextAlignment.CENTER, Color.BLACK, contextualized,
76 new TextAnimation.ContrastToBackground()
77 {
78 @Override
79 public Color getBackgroundColor()
80 {
81 return gtu.getColor();
82 }
83 }).setDynamic(true);
84 }
85
86 @Override
87 public final void paint(final Graphics2D graphics, final ImageObserver observer)
88 {
89 setRendering(graphics);
90 final GtuData gtu = getSource();
91 if (this.rectangle == null)
92 {
93
94
95 final double length = gtu.getLength().si;
96 final double lFront = gtu.getFront().si;
97 final double lRear = gtu.getRear().si;
98 final double width = gtu.getWidth().si;
99 final double w2 = width / 2;
100 final double w4 = width / 4;
101 this.rectangle = new Rectangle2D.Double(lRear, -w2, length, width);
102 this.frontIndicator = new Ellipse2D.Double(lFront - w2 - w4, -w4, w2, w2);
103 this.leftIndicator = new Rectangle2D.Double(lFront - w4, -w2, w4, w4);
104 this.rightIndicator = new Rectangle2D.Double(lFront - w4, w2 - w4, w4, w4);
105 this.leftBrake = new Rectangle2D.Double(lRear, w2 - w4, w4, w4);
106 this.rightBrake = new Rectangle2D.Double(lRear, -w2, w4, w4);
107 this.marker = gtu.getMarker();
108 }
109
110 double scale = graphics.getTransform().getDeterminant();
111
112
113 if (scale > 1)
114 {
115 Color color = gtu.getColor();
116 graphics.setColor(color);
117 BasicStroke saveStroke = (BasicStroke) graphics.getStroke();
118 graphics.setStroke(new BasicStroke(0.05f));
119 graphics.fill(this.rectangle);
120
121 graphics.setColor(Color.WHITE);
122 graphics.fill(this.frontIndicator);
123
124 if (color.equals(Color.WHITE))
125 {
126
127 graphics.setColor(Color.BLACK);
128 graphics.draw(this.frontIndicator);
129 }
130
131
132 graphics.setColor(Color.YELLOW);
133 if (gtu.leftIndicatorOn())
134 {
135 graphics.fill(this.leftIndicator);
136 if (color.equals(Color.YELLOW))
137 {
138 graphics.setColor(Color.BLACK);
139 graphics.draw(this.leftIndicator);
140 }
141 }
142 if (gtu.rightIndicatorOn())
143 {
144 graphics.fill(this.rightIndicator);
145 if (color.equals(Color.YELLOW))
146 {
147 graphics.setColor(Color.BLACK);
148 graphics.draw(this.rightIndicator);
149 }
150 }
151
152
153 if (gtu.isBrakingLightsOn())
154 {
155 graphics.setColor(Color.RED);
156 graphics.fill(this.leftBrake);
157 graphics.fill(this.rightBrake);
158 if (color.equals(Color.RED))
159 {
160 graphics.setColor(Color.BLACK);
161 graphics.draw(this.leftBrake);
162 graphics.draw(this.rightBrake);
163 }
164 }
165 graphics.setStroke(saveStroke);
166 }
167 else
168 {
169
170 graphics.setColor(gtu.getColor());
171 double w = 7.0 / Math.sqrt(scale);
172 double x = -w / 2.0;
173 this.marker.setFrame(x, x, w, w);
174 graphics.fill(this.marker);
175 }
176 resetRendering(graphics);
177 }
178
179 @Override
180 public void destroy(final Contextualized contextProvider)
181 {
182 super.destroy(contextProvider);
183 this.text.destroy(contextProvider);
184 }
185
186 @Override
187 public int hashCode()
188 {
189 return this.hashCode;
190 }
191
192 @Override
193 public boolean equals(final Object object)
194 {
195
196 return super.equals(object);
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210 public class Text extends TextAnimation<GtuData, Text>
211 {
212
213 private static final long serialVersionUID = 20161211L;
214
215
216 private boolean isTextDestroyed = false;
217
218
219
220
221
222
223
224
225
226
227 public Text(final GtuData source, final Supplier<String> text, final float dx, final float dy,
228 final TextAlignment textAlignment, final Color color, final Contextualized contextualized)
229 {
230 super(source, text, dx, dy, textAlignment, color, 1.0f, 12.0f, 50f, contextualized, TextAnimation.RENDERWHEN1);
231 }
232
233
234
235
236
237
238
239
240
241
242
243 @SuppressWarnings("parameternumber")
244 public Text(final GtuData source, final Supplier<String> text, final float dx, final float dy,
245 final TextAlignment textAlignment, final Color color, final Contextualized contextualized,
246 final TextAnimation.ContrastToBackground background)
247 {
248 super(source, text, dx, dy, textAlignment, color, 1.0f, 12.0f, 50f, contextualized, background, RENDERWHEN1);
249 }
250
251 @Override
252 public final String toString()
253 {
254 return "Text [isTextDestroyed=" + this.isTextDestroyed + "]";
255 }
256
257 }
258
259
260
261
262
263
264
265
266
267
268
269
270 public interface GtuData extends OtsLocatable, Identifiable
271 {
272
273
274
275
276 Color getColor();
277
278
279
280
281
282 Length getLength();
283
284
285
286
287
288 Length getWidth();
289
290
291
292
293
294 Length getFront();
295
296
297
298
299
300 Length getRear();
301
302
303
304
305
306 boolean leftIndicatorOn();
307
308
309
310
311
312 boolean rightIndicatorOn();
313
314
315
316
317
318 default RectangularShape getMarker()
319 {
320 return new Ellipse2D.Double(0, 0, 0, 0);
321 }
322
323
324
325
326
327 boolean isBrakingLightsOn();
328
329 @Override
330 OrientedPoint2d getLocation();
331
332 @Override
333 default double getZ()
334 {
335 return DrawLevel.GTU.getZ();
336 }
337
338
339
340
341 enum GtuMarker
342 {
343
344 CIRCLE(new Ellipse2D.Double(0, 0, 0, 0)),
345
346
347 SQUARE(new Rectangle2D.Double(0, 0, 0, 0));
348
349
350 private RectangularShape shape;
351
352
353
354
355
356 GtuMarker(final RectangularShape shape)
357 {
358 this.shape = shape;
359 }
360
361
362
363
364
365 public RectangularShape getShape()
366 {
367 return this.shape;
368 }
369 }
370 }
371
372 }