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.draw(new Ellipse2D.Double(-0.5, -0.5, 1.0, 1.0));
81 try
82 {
83 double direction = getSource().getLocation().getZ();
84 if (!Double.isNaN(direction))
85 {
86 graphics.setStroke(new BasicStroke(0.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
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 super();
143 this.node = node;
144 try
145 {
146 DirectedPoint p = node.getLocation();
147 this.location = new DirectedPoint(p.x, p.y, p.z + ZOFFSET, p.getRotX(), p.getRotY(), p.getRotZ());
148 this.bounds = node.getBounds();
149 }
150 catch (RemoteException exception)
151 {
152 CategoryLogger.always().error(exception, "Could not construct elevated node for animation");
153 this.location = new DirectedPoint();
154 this.bounds = new BoundingSphere();
155 }
156 }
157
158
159 @Override
160 public DirectedPoint getLocation() throws RemoteException
161 {
162 return this.location;
163 }
164
165
166 @Override
167 public Bounds getBounds() throws RemoteException
168 {
169 return this.bounds;
170 }
171
172
173 @Override
174 public Object getParentIntrospectionObject()
175 {
176 return this.node;
177 }
178
179 }
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194 public class Text extends TextAnimation
195 {
196
197 private static final long serialVersionUID = 20161211L;
198
199
200
201
202
203
204
205
206
207
208
209
210
211 @SuppressWarnings("checkstyle:parameternumber")
212 public Text(final Locatable source, final String text, final float dx, final float dy,
213 final TextAlignment textPlacement, final Color color, final SimulatorInterface.TimeDoubleUnit simulator,
214 final ScaleDependentRendering scaleDependentRendering) throws RemoteException, NamingException
215 {
216 super(source, text, dx, dy, textPlacement, color, 2.0f, 12.0f, 50f, simulator, scaleDependentRendering);
217 setFlip(false);
218 setRotate(false);
219 }
220
221
222 @Override
223 @SuppressWarnings("checkstyle:designforextension")
224 public TextAnimation clone(final Locatable newSource, final SimulatorInterface.TimeDoubleUnit newSimulator)
225 throws RemoteException, NamingException
226 {
227 return new Text(newSource, getText(), getDx(), getDy(), getTextAlignment(), getColor(), newSimulator,
228 getScaleDependentRendering());
229 }
230
231
232 @Override
233 public final String toString()
234 {
235 return "NodeAnimation.Text []";
236 }
237 }
238
239 }