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.image.ImageObserver;
9 import java.io.Serializable;
10 import java.rmi.RemoteException;
11
12 import javax.media.j3d.BoundingSphere;
13 import javax.media.j3d.Bounds;
14 import javax.naming.NamingException;
15
16 import org.djutils.logger.CategoryLogger;
17 import org.opentrafficsim.core.network.Link;
18 import org.opentrafficsim.core.network.LinkType;
19 import org.opentrafficsim.core.network.Node;
20 import org.opentrafficsim.draw.core.ClonableRenderable2DInterface;
21 import org.opentrafficsim.draw.core.TextAlignment;
22 import org.opentrafficsim.draw.core.TextAnimation;
23 import org.opentrafficsim.draw.core.TextAnimation.ScaleDependentRendering;
24
25 import nl.tudelft.simulation.dsol.animation.Locatable;
26 import nl.tudelft.simulation.dsol.animation.D2.Renderable2D;
27 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
28 import nl.tudelft.simulation.introspection.DelegateIntrospection;
29 import nl.tudelft.simulation.language.d3.DirectedPoint;
30
31
32
33
34
35
36
37
38
39
40 @SuppressWarnings("rawtypes")
41 public class NodeAnimation extends Renderable2D implements ClonableRenderable2DInterface, Serializable
42 {
43
44 private static final long serialVersionUID = 20140000L;
45
46
47 private Text text;
48
49
50 public static final double ZOFFSET = 0.01;
51
52
53
54
55
56
57
58 @SuppressWarnings("unchecked")
59 public NodeAnimation(final Node node, final SimulatorInterface.TimeDoubleUnit simulator)
60 throws NamingException, RemoteException
61 {
62 super(new ElevatedNode(node), simulator);
63
64 ScaleDependentRendering sizeLimiter = TextAnimation.RENDERWHEN1;
65 for (Link link : node.getLinks())
66 {
67 if (link.getLinkType().getId().equals(LinkType.DEFAULTS.FREEWAY.getId()))
68 {
69 sizeLimiter = TextAnimation.RENDERWHEN10;
70 }
71 }
72 this.text = new Text(node, node.getId(), 0.0f, 3.0f, TextAlignment.CENTER, Color.BLACK, simulator, sizeLimiter);
73 }
74
75
76 @Override
77 public final void paint(final Graphics2D graphics, final ImageObserver observer)
78 {
79 graphics.setColor(Color.BLACK);
80 graphics.setStroke(new BasicStroke(0.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
81 graphics.draw(new Ellipse2D.Double(-0.5, -0.5, 1.0, 1.0));
82 try
83 {
84 double direction = getSource().getLocation().getZ();
85 if (!Double.isNaN(direction))
86 {
87 GeneralPath arrow = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 3);
88 arrow.moveTo(0.5, -0.5);
89 arrow.lineTo(2, 0);
90 arrow.lineTo(0.5, 0.5);
91 graphics.draw(arrow);
92 }
93 }
94 catch (RemoteException e)
95 {
96 e.printStackTrace();
97 }
98 }
99
100
101 @Override
102 public final void destroy() throws NamingException, RemoteException
103 {
104 super.destroy();
105 this.text.destroy();
106 }
107
108
109 @Override
110 @SuppressWarnings("checkstyle:designforextension")
111 public ClonableRenderable2DInterface clone(final Locatable newSource, final SimulatorInterface.TimeDoubleUnit newSimulator)
112 throws NamingException, RemoteException
113 {
114
115 return new NodeAnimation((Node) newSource, newSimulator);
116 }
117
118
119 @Override
120 public final String toString()
121 {
122 return "NodeAnimation [node=" + super.getSource() + "]";
123 }
124
125
126 public static class ElevatedNode implements Locatable, DelegateIntrospection
127 {
128
129 private final Node node;
130
131
132 private DirectedPoint location;
133
134
135 private Bounds bounds;
136
137
138
139
140 public ElevatedNode(final Node node)
141 {
142 this.node = node;
143 try
144 {
145 DirectedPoint p = node.getLocation();
146 this.location = new DirectedPoint(p.x, p.y, p.z + ZOFFSET, p.getRotX(), p.getRotY(), p.getRotZ());
147 this.bounds = node.getBounds();
148 }
149 catch (RemoteException exception)
150 {
151 CategoryLogger.always().error(exception, "Could not construct elevated node for animation");
152 this.location = new DirectedPoint();
153 this.bounds = new BoundingSphere();
154 }
155 }
156
157
158 @Override
159 public DirectedPoint getLocation() throws RemoteException
160 {
161 return this.location;
162 }
163
164
165 @Override
166 public Bounds getBounds() throws RemoteException
167 {
168 return this.bounds;
169 }
170
171
172 @Override
173 public Object getParentIntrospectionObject()
174 {
175 return this.node;
176 }
177
178 }
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193 public class Text extends TextAnimation
194 {
195
196 private static final long serialVersionUID = 20161211L;
197
198
199
200
201
202
203
204
205
206
207
208
209
210 @SuppressWarnings("checkstyle:parameternumber")
211 public Text(final Locatable source, final String text, final float dx, final float dy,
212 final TextAlignment textPlacement, final Color color, final SimulatorInterface.TimeDoubleUnit simulator,
213 final ScaleDependentRendering scaleDependentRendering) throws RemoteException, NamingException
214 {
215 super(source, text, dx, dy, textPlacement, color, 2.0f, 12.0f, 50f, simulator, scaleDependentRendering);
216 setFlip(false);
217 setRotate(false);
218 }
219
220
221 @Override
222 @SuppressWarnings("checkstyle:designforextension")
223 public TextAnimation clone(final Locatable newSource, final SimulatorInterface.TimeDoubleUnit newSimulator)
224 throws RemoteException, NamingException
225 {
226 return new Text(newSource, getText(), getDx(), getDy(), getTextAlignment(), getColor(), newSimulator,
227 getScaleDependentRendering());
228 }
229
230
231 @Override
232 public final String toString()
233 {
234 return "NodeAnimation.Text []";
235 }
236 }
237
238 }