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
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 }