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.opentrafficsim.core.geometry.OTSGeometryException;
12  import org.opentrafficsim.core.geometry.OTSLine3D;
13  import org.opentrafficsim.core.geometry.OTSPoint3D;
14  import org.opentrafficsim.core.network.Link;
15  import org.opentrafficsim.core.network.LinkType;
16  import org.opentrafficsim.draw.core.ClonableRenderable2DInterface;
17  import org.opentrafficsim.draw.core.PaintLine;
18  import org.opentrafficsim.draw.core.TextAlignment;
19  import org.opentrafficsim.draw.core.TextAnimation;
20  
21  import nl.tudelft.simulation.dsol.animation.Locatable;
22  import nl.tudelft.simulation.dsol.animation.D2.Renderable2D;
23  import nl.tudelft.simulation.dsol.logger.SimLogger;
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  
30  
31  
32  
33  
34  
35  
36  
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      
47      private Text text;
48  
49      
50  
51  
52  
53  
54  
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      
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          
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              
82              SimLogger.always().error(exception);
83          }
84      }
85  
86      
87  
88  
89  
90  
91  
92  
93      private void drawEndPoint(final OTSPoint3D endPoint, final OTSPoint3D nextPoint, final Graphics2D graphics)
94      {
95          
96          double dx = nextPoint.x - endPoint.x;
97          double dy = nextPoint.y - endPoint.y;
98          double length = endPoint.distanceSI(nextPoint);
99          
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             SimLogger.always().error(exception);
112         }
113         catch (RemoteException exception)
114         {
115             SimLogger.always().error(exception);
116         }
117     }
118 
119     
120     @Override
121     public final void destroy() throws NamingException
122     {
123         super.destroy();
124         this.text.destroy();
125     }
126 
127     
128     @Override
129     @SuppressWarnings("checkstyle:designforextension")
130     public ClonableRenderable2DInterface<Link> clone(final Link newSource, final SimulatorInterface.TimeDoubleUnit newSimulator)
131             throws NamingException, RemoteException
132     {
133         
134         return new LinkAnimation(newSource, newSimulator, this.width);
135     }
136 
137     
138     @Override
139     public final String toString()
140     {
141         return "LinkAnimation [width=" + this.width + ", link=" + super.getSource() + "]";
142     }
143 
144     
145 
146 
147 
148 
149 
150 
151 
152 
153 
154 
155 
156 
157     public class Text extends TextAnimation
158     {
159         
160         private static final long serialVersionUID = 20161211L;
161 
162         
163 
164 
165 
166 
167 
168 
169 
170 
171 
172 
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         
182         @Override
183         @SuppressWarnings("checkstyle:designforextension")
184         public DirectedPoint getLocation() throws RemoteException
185         {
186             
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         
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         
207         @Override
208         public final String toString()
209         {
210             return "LinkAnimation.Text []";
211         }
212     }
213 
214 }