View Javadoc
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   * <p>
33   * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
34   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
35   * <p>
36   * $LastChangedDate: 2018-10-11 22:54:04 +0200 (Thu, 11 Oct 2018) $, @version $Revision: 4696 $, by $Author: averbraeck $,
37   * initial version Oct 17, 2014 <br>
38   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
39   */
40  @SuppressWarnings("rawtypes")
41  public class NodeAnimation extends Renderable2D implements ClonableRenderable2DInterface, Serializable
42  {
43      /** */
44      private static final long serialVersionUID = 20140000L;
45  
46      /** the Text object to destroy when the animation is destroyed. */
47      private Text text;
48  
49      /** Ensure that node animations are slightly above lane surface. */
50      public static final double ZOFFSET = 0.01;
51  
52      /**
53       * @param node Node; n
54       * @param simulator SimulatorInterface.TimeDoubleUnit; s
55       * @throws NamingException when animation context cannot be found.
56       * @throws RemoteException on communication failure
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          // Figure out the relevance of this node
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      /** {@inheritDoc} */
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     /** {@inheritDoc} */
101     @Override
102     public final void destroy() throws NamingException, RemoteException
103     {
104         super.destroy();
105         this.text.destroy();
106     }
107 
108     /** {@inheritDoc} */
109     @Override
110     @SuppressWarnings("checkstyle:designforextension")
111     public ClonableRenderable2DInterface clone(final Locatable newSource, final SimulatorInterface.TimeDoubleUnit newSimulator)
112             throws NamingException, RemoteException
113     {
114         // the constructor also constructs the corresponding Text object and ElevatedNode
115         return new NodeAnimation((Node) newSource, newSimulator);
116     }
117 
118     /** {@inheritDoc} */
119     @Override
120     public final String toString()
121     {
122         return "NodeAnimation [node=" + super.getSource() + "]";
123     }
124 
125     /** Class for elevating the node for animation purposes. */
126     public static class ElevatedNode implements Locatable, DelegateIntrospection
127     {
128         /** the node for introspection. */
129         private final Node node;
130 
131         /** the location of the node to which the animation belongs. */
132         private DirectedPoint location;
133 
134         /** the bounds of the node to which the animation belongs. */
135         private Bounds bounds;
136 
137         /**
138          * @param node Node; the node to which the animation belongs
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         /** {@inheritDoc} */
158         @Override
159         public DirectedPoint getLocation() throws RemoteException
160         {
161             return this.location;
162         }
163 
164         /** {@inheritDoc} */
165         @Override
166         public Bounds getBounds() throws RemoteException
167         {
168             return this.bounds;
169         }
170 
171         /** {@inheritDoc} */
172         @Override
173         public Object getParentIntrospectionObject()
174         {
175             return this.node;
176         }
177 
178     }
179 
180     /**
181      * Text animation for the Node. Separate class to be able to turn it on and off...
182      * <p>
183      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
184      * <br>
185      * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
186      * </p>
187      * $LastChangedDate: 2018-10-11 22:54:04 +0200 (Thu, 11 Oct 2018) $, @version $Revision: 4696 $, by $Author: averbraeck $,
188      * initial version Dec 11, 2016 <br>
189      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
190      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
191      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
192      */
193     public class Text extends TextAnimation
194     {
195         /** */
196         private static final long serialVersionUID = 20161211L;
197 
198         /**
199          * @param source Locatable; the object for which the text is displayed
200          * @param text String; the text to display
201          * @param dx float; the horizontal movement of the text, in meters
202          * @param dy float; the vertical movement of the text, in meters
203          * @param textPlacement TextAlignment; where to place the text
204          * @param color Color; the color of the text
205          * @param simulator SimulatorInterface.TimeDoubleUnit; the simulator
206          * @param scaleDependentRendering ScaleDependendentRendering; size limiter for text animation
207          * @throws NamingException when animation context cannot be created or retrieved
208          * @throws RemoteException - when remote context cannot be found
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         /** {@inheritDoc} */
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         /** {@inheritDoc} */
231         @Override
232         public final String toString()
233         {
234             return "NodeAnimation.Text []";
235         }
236     }
237 
238 }