View Javadoc
1   package org.opentrafficsim.draw.network;
2   
3   import java.awt.Color;
4   import java.awt.Graphics2D;
5   import java.awt.image.ImageObserver;
6   import java.io.Serializable;
7   import java.rmi.RemoteException;
8   
9   import javax.naming.NamingException;
10  
11  import org.djutils.logger.CategoryLogger;
12  import org.opentrafficsim.core.geometry.OTSGeometryException;
13  import org.opentrafficsim.core.geometry.OTSLine3D;
14  import org.opentrafficsim.core.geometry.OTSPoint3D;
15  import org.opentrafficsim.core.network.Link;
16  import org.opentrafficsim.core.network.LinkType;
17  import org.opentrafficsim.draw.core.ClonableRenderable2DInterface;
18  import org.opentrafficsim.draw.core.PaintLine;
19  import org.opentrafficsim.draw.core.TextAlignment;
20  import org.opentrafficsim.draw.core.TextAnimation;
21  
22  import nl.tudelft.simulation.dsol.animation.Locatable;
23  import nl.tudelft.simulation.dsol.animation.D2.Renderable2D;
24  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
25  import nl.tudelft.simulation.language.d2.Angle;
26  import nl.tudelft.simulation.language.d3.DirectedPoint;
27  
28  /**
29   * Draws a Link.
30   * <p>
31   * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
32   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
33   * <p>
34   * $LastChangedDate: 2018-10-11 22:54:04 +0200 (Thu, 11 Oct 2018) $, @version $Revision: 4696 $, by $Author: averbraeck $,
35   * initial version Sep 13, 2014 <br>
36   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
37   */
38  public class LinkAnimation extends Renderable2D<Link> implements ClonableRenderable2DInterface<Link>, Serializable
39  {
40      /** */
41      private static final long serialVersionUID = 20140000L;
42  
43      /** */
44      private float width;
45  
46      /** the Text object to destroy when the animation is destroyed. */
47      private Text text;
48  
49      /**
50       * @param link Link; Link
51       * @param simulator SimulatorInterface.TimeDoubleUnit; simulator
52       * @param width float; width
53       * @throws NamingException for problems with registering in context
54       * @throws RemoteException on communication failure
55       */
56      public LinkAnimation(final Link link, final SimulatorInterface.TimeDoubleUnit simulator, final float width)
57              throws NamingException, RemoteException
58      {
59          super(link, simulator);
60          this.width = width;
61          this.text = new Text(link, link.getId(), 0.0f, 1.5f, TextAlignment.CENTER, Color.BLACK, simulator,
62                  link.getLinkType().getId().equals(LinkType.DEFAULTS.FREEWAY.getId()) ? TextAnimation.RENDERWHEN10
63                          : TextAnimation.RENDERWHEN1);
64      }
65  
66      /** {@inheritDoc} */
67      @Override
68      public final void paint(final Graphics2D graphics, final ImageObserver observer) throws RemoteException
69      {
70          Color color = getSource().getLinkType().isConnector() ? Color.PINK.darker() : Color.BLUE;
71          OTSLine3D designLine = getSource().getDesignLine();
72          PaintLine.paintLine(graphics, color, this.width, getSource().getLocation(), designLine);
73          // Accentuate the end points
74          try
75          {
76              drawEndPoint(designLine.getFirst(), designLine.get(1), graphics);
77              drawEndPoint(designLine.getLast(), designLine.get(designLine.size() - 2), graphics);
78          }
79          catch (OTSGeometryException exception)
80          {
81              // Cannot happen
82              CategoryLogger.always().error(exception);
83          }
84      }
85  
86      /**
87       * Draw end point on design line.
88       * @param endPoint OTSPoint3D; the end of the design line where a end point must be highlighted
89       * @param nextPoint OTSPoint3D; the point nearest <code>endPoint</code> (needed to figure out the direction of the design
90       *            line)
91       * @param graphics Graphics2D; graphics content
92       */
93      private void drawEndPoint(final OTSPoint3D endPoint, final OTSPoint3D nextPoint, final Graphics2D graphics)
94      {
95          // End point marker is 2 times the width of the design line
96          double dx = nextPoint.x - endPoint.x;
97          double dy = nextPoint.y - endPoint.y;
98          double length = endPoint.distanceSI(nextPoint);
99          // scale dx, dy so that size is this.width
100         dx *= this.width / length;
101         dy *= this.width / length;
102         try
103         {
104             OTSLine3D line = new OTSLine3D(new OTSPoint3D(endPoint.x - dy, endPoint.y + dx, endPoint.z),
105                     new OTSPoint3D(endPoint.x + dy, endPoint.y - dx, endPoint.z));
106             PaintLine.paintLine(graphics, getSource().getLinkType().isConnector() ? Color.PINK.darker() : Color.BLUE,
107                     this.width / 30, getSource().getLocation(), line);
108         }
109         catch (OTSGeometryException exception)
110         {
111             CategoryLogger.always().error(exception);
112         }
113         catch (RemoteException exception)
114         {
115             CategoryLogger.always().error(exception);
116         }
117     }
118 
119     /** {@inheritDoc} */
120     @Override
121     public final void destroy() throws NamingException, RemoteException
122     {
123         super.destroy();
124         this.text.destroy();
125     }
126 
127     /** {@inheritDoc} */
128     @Override
129     @SuppressWarnings("checkstyle:designforextension")
130     public ClonableRenderable2DInterface<Link> clone(final Link newSource, final SimulatorInterface.TimeDoubleUnit newSimulator)
131             throws NamingException, RemoteException
132     {
133         // the constructor also constructs the corresponding Text object
134         return new LinkAnimation(newSource, newSimulator, this.width);
135     }
136 
137     /** {@inheritDoc} */
138     @Override
139     public final String toString()
140     {
141         return "LinkAnimation [width=" + this.width + ", link=" + super.getSource() + "]";
142     }
143 
144     /**
145      * Text animation for the Link. Separate class to be able to turn it on and off...
146      * <p>
147      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
148      * <br>
149      * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
150      * </p>
151      * $LastChangedDate: 2018-10-11 22:54:04 +0200 (Thu, 11 Oct 2018) $, @version $Revision: 4696 $, by $Author: averbraeck $,
152      * initial version Dec 11, 2016 <br>
153      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
154      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
155      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
156      */
157     public class Text extends TextAnimation
158     {
159         /** */
160         private static final long serialVersionUID = 20161211L;
161 
162         /**
163          * @param source Locatable; the object for which the text is displayed
164          * @param text String; the text to display
165          * @param dx float; the horizontal movement of the text, in meters
166          * @param dy float; the vertical movement of the text, in meters
167          * @param textPlacement TextAlignment; where to place the text
168          * @param color Color; the color of the text
169          * @param simulator SimulatorInterface.TimeDoubleUnit; the simulator
170          * @param scaleDependentRendering ScaleDependentRendering; enables rendering in a scale dependent fashion
171          * @throws NamingException when animation context cannot be created or retrieved
172          * @throws RemoteException - when remote context cannot be found
173          */
174         public Text(final Locatable source, final String text, final float dx, final float dy,
175                 final TextAlignment textPlacement, final Color color, final SimulatorInterface.TimeDoubleUnit simulator,
176                 final ScaleDependentRendering scaleDependentRendering) throws RemoteException, NamingException
177         {
178             super(source, text, dx, dy, textPlacement, color, 2.0f, 12.0f, 50f, simulator, null, scaleDependentRendering);
179         }
180 
181         /** {@inheritDoc} */
182         @Override
183         @SuppressWarnings("checkstyle:designforextension")
184         public DirectedPoint getLocation() throws RemoteException
185         {
186             // draw always on top, and not upside down.
187             DirectedPoint p = ((Link) getSource()).getDesignLine().getLocationFractionExtended(0.5);
188             double a = Angle.normalizePi(p.getRotZ());
189             if (a > Math.PI / 2.0 || a < -0.99 * Math.PI / 2.0)
190             {
191                 a += Math.PI;
192             }
193             return new DirectedPoint(p.x, p.y, Double.MAX_VALUE, 0.0, 0.0, a);
194         }
195 
196         /** {@inheritDoc} */
197         @Override
198         @SuppressWarnings("checkstyle:designforextension")
199         public TextAnimation clone(final Locatable newSource, final SimulatorInterface.TimeDoubleUnit newSimulator)
200                 throws RemoteException, NamingException
201         {
202             return new Text(newSource, getText(), getDx(), getDy(), getTextAlignment(), getColor(), newSimulator,
203                     super.getScaleDependentRendering());
204         }
205 
206         /** {@inheritDoc} */
207         @Override
208         public final String toString()
209         {
210             return "LinkAnimation.Text []";
211         }
212     }
213 
214 }