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.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     /** {@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             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         /** {@inheritDoc} */
159         @Override
160         public DirectedPoint getLocation() throws RemoteException
161         {
162             return this.location;
163         }
164 
165         /** {@inheritDoc} */
166         @Override
167         public Bounds getBounds() throws RemoteException
168         {
169             return this.bounds;
170         }
171 
172         /** {@inheritDoc} */
173         @Override
174         public Object getParentIntrospectionObject()
175         {
176             return this.node;
177         }
178 
179     }
180 
181     /**
182      * Text animation for the Node. Separate class to be able to turn it on and off...
183      * <p>
184      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
185      * <br>
186      * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
187      * </p>
188      * $LastChangedDate: 2018-10-11 22:54:04 +0200 (Thu, 11 Oct 2018) $, @version $Revision: 4696 $, by $Author: averbraeck $,
189      * initial version Dec 11, 2016 <br>
190      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
191      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
192      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
193      */
194     public class Text extends TextAnimation
195     {
196         /** */
197         private static final long serialVersionUID = 20161211L;
198 
199         /**
200          * @param source Locatable; the object for which the text is displayed
201          * @param text String; the text to display
202          * @param dx float; the horizontal movement of the text, in meters
203          * @param dy float; the vertical movement of the text, in meters
204          * @param textPlacement TextAlignment; where to place the text
205          * @param color Color; the color of the text
206          * @param simulator SimulatorInterface.TimeDoubleUnit; the simulator
207          * @param scaleDependentRendering ScaleDependendentRendering; size limiter for text animation
208          * @throws NamingException when animation context cannot be created or retrieved
209          * @throws RemoteException - when remote context cannot be found
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         /** {@inheritDoc} */
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         /** {@inheritDoc} */
232         @Override
233         public final String toString()
234         {
235             return "NodeAnimation.Text []";
236         }
237     }
238 
239 }