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