1 package org.opentrafficsim.draw.network;
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.GeneralPath;
8 import java.awt.geom.Path2D;
9 import java.awt.image.ImageObserver;
10 import java.util.function.Supplier;
11
12 import org.djutils.base.Identifiable;
13 import org.djutils.draw.point.DirectedPoint2d;
14 import org.djutils.draw.point.Point2d;
15 import org.opentrafficsim.base.geometry.OtsShape;
16 import org.opentrafficsim.draw.DrawLevel;
17 import org.opentrafficsim.draw.OtsRenderable;
18 import org.opentrafficsim.draw.RenderableTextSource;
19 import org.opentrafficsim.draw.TextAlignment;
20 import org.opentrafficsim.draw.network.NodeAnimation.NodeData;
21
22 import nl.tudelft.simulation.naming.context.Contextualized;
23
24
25
26
27
28
29
30
31
32
33 public class NodeAnimation extends OtsRenderable<NodeData>
34 {
35
36 private Text text;
37
38
39
40
41
42
43 public NodeAnimation(final NodeData node, final Contextualized contextualized)
44 {
45 super(node, contextualized);
46 this.text = new Text(node, node::getId, 0.0f, 3.0f, TextAlignment.CENTER, Color.BLACK, contextualized,
47 RenderableTextSource.RENDERWHEN10);
48 setScaleY(false);
49 }
50
51
52 @Override
53 public boolean isScaleY()
54 {
55 return super.isScaleY();
56 }
57
58 @Override
59 public final void paint(final Graphics2D graphics, final ImageObserver observer)
60 {
61 setRendering(graphics);
62 double scale = Math.sqrt(graphics.getTransform().getDeterminant());
63 double factor = 3.0 / Math.min(scale, 3.0);
64 graphics.setColor(Color.BLACK);
65 graphics.setStroke(new BasicStroke((float) (factor * 0.5), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
66 graphics.draw(new Ellipse2D.Double(-0.5 * factor, -0.5 * factor, 1.0 * factor, 1.0 * factor));
67 double direction = getSource().getLocation().getDirZ();
68 if (!Double.isNaN(direction))
69 {
70 GeneralPath arrow = new GeneralPath(Path2D.WIND_EVEN_ODD, 3);
71 arrow.moveTo(0.5 * factor, -0.5 * factor);
72 arrow.lineTo(2.0 * factor, 0.0);
73 arrow.lineTo(0.5 * factor, 0.5 * factor);
74 graphics.draw(arrow);
75 }
76 resetRendering(graphics);
77 }
78
79 @Override
80 public void destroy(final Contextualized contextProvider)
81 {
82 super.destroy(contextProvider);
83 this.text.destroy(contextProvider);
84 }
85
86 @Override
87 public final String toString()
88 {
89 return "NodeAnimation [node=" + super.getSource() + "]";
90 }
91
92
93
94
95
96
97
98
99
100
101
102
103 public static class Text extends RenderableTextSource<NodeData, Text>
104 {
105
106
107
108
109
110
111
112
113
114
115
116 @SuppressWarnings("checkstyle:parameternumber")
117 public Text(final NodeData source, final Supplier<String> text, final float dx, final float dy,
118 final TextAlignment textPlacement, final Color color, final Contextualized contextualized,
119 final ScaleDependentRendering scaleDependentRendering)
120 {
121 super(source, text, dx, dy, textPlacement, color, 2.0f, 12.0f, 50f, contextualized, scaleDependentRendering);
122 setFlip(false);
123 setRotate(false);
124 }
125
126 @Override
127 public final String toString()
128 {
129 return "NodeAnimation.Text []";
130 }
131 }
132
133
134
135
136
137
138
139
140
141
142 public interface NodeData extends OtsShape, Identifiable
143 {
144 @Override
145 DirectedPoint2d getLocation();
146
147 @Override
148 default double signedDistance(final Point2d point)
149 {
150 return Math.hypot(point.x, point.y);
151 }
152
153 @Override
154 default boolean contains(final Point2d point)
155 {
156 return signedDistance(point) < WORLD_MARGIN_LINE;
157 }
158
159 @Override
160 default double getZ()
161 {
162 return DrawLevel.NODE.getZ();
163 }
164 }
165
166 }