View Javadoc
1   package org.opentrafficsim.draw.road;
2   
3   import java.awt.Color;
4   import java.awt.Graphics2D;
5   import java.awt.geom.Path2D;
6   import java.awt.image.ImageObserver;
7   import java.util.function.Supplier;
8   
9   import org.djutils.base.Identifiable;
10  import org.djutils.draw.line.PolyLine2d;
11  import org.djutils.draw.line.Polygon2d;
12  import org.djutils.draw.point.OrientedPoint2d;
13  import org.opentrafficsim.base.geometry.OtsLocatable;
14  import org.opentrafficsim.base.geometry.OtsShape;
15  import org.opentrafficsim.draw.ClickableLineLocatable;
16  import org.opentrafficsim.draw.DrawLevel;
17  import org.opentrafficsim.draw.OtsRenderable;
18  import org.opentrafficsim.draw.PaintLine;
19  import org.opentrafficsim.draw.TextAlignment;
20  import org.opentrafficsim.draw.TextAnimation;
21  import org.opentrafficsim.draw.road.CrossSectionElementAnimation.CrossSectionElementData;
22  import org.opentrafficsim.draw.road.LaneAnimation.LaneData;
23  
24  import nl.tudelft.simulation.naming.context.Contextualized;
25  
26  /**
27   * Draws LaneData.
28   * <p>
29   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
30   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
31   * </p>
32   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
33   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
34   */
35  public class LaneAnimation extends CrossSectionElementAnimation<LaneData>
36  {
37      /** */
38      private static final long serialVersionUID = 20141017L;
39  
40      /** Color of the lane. */
41      private final Color color;
42  
43      /** the Text object to destroy when the animation is destroyed. */
44      private final Text text;
45  
46      /** Center line animation. */
47      private final CenterLineAnimation centerLineAnimation;
48  
49      /**
50       * Animate a Lane.
51       * @param lane the lane
52       * @param contextualized context provider
53       * @param color Color of the lane.
54       */
55      public LaneAnimation(final LaneData lane, final Contextualized contextualized, final Color color)
56      {
57          super(lane, contextualized, color);
58          this.color = color;
59          this.text = new Text(lane, lane::getId, 0.0f, 0.0f, TextAlignment.CENTER, Color.BLACK, contextualized);
60          this.centerLineAnimation = new CenterLineAnimation(
61                  new CenterLine(lane.getCenterLine(), lane.getLinkId() + "." + lane.getId()), contextualized);
62      }
63  
64      /**
65       * @return text.
66       */
67      public final Text getText()
68      {
69          return this.text;
70      }
71  
72      @Override
73      public void destroy(final Contextualized contextProvider)
74      {
75          super.destroy(contextProvider);
76          this.text.destroy(contextProvider);
77          this.centerLineAnimation.destroy(contextProvider);
78      }
79  
80      @Override
81      public final String toString()
82      {
83          return "LaneAnimation [lane = " + getSource().toString() + ", color=" + this.color + "]";
84      }
85  
86      /**
87       * Draw center line of a lane.
88       */
89      public static class CenterLine implements ClickableLineLocatable
90      {
91          /** The center line. */
92          private final PolyLine2d centerLine;
93  
94          /** Location. */
95          private final OrientedPoint2d location;
96  
97          /** Shape (cached). */
98          private OtsShape shape;
99  
100         /** Lane id. */
101         private final String fullId;
102 
103         /**
104          * Construct a new CenterLine.
105          * @param centerLine the center line of a lane
106          * @param fullId lane id.
107          */
108         CenterLine(final PolyLine2d centerLine, final String fullId)
109         {
110             this.centerLine = centerLine;
111             this.location = new OrientedPoint2d(this.centerLine.getBounds().midPoint(), 0.0);
112             this.fullId = fullId;
113         }
114 
115         @Override
116         public final OrientedPoint2d getLocation()
117         {
118             return this.location;
119         }
120 
121         @Override
122         public OtsShape getShape()
123         {
124             if (this.shape == null)
125             {
126                 this.shape = ClickableLineLocatable.super.getShape();
127             }
128             return this.shape;
129         }
130 
131         @Override
132         public Polygon2d getContour()
133         {
134             return new Polygon2d(this.centerLine.getPoints());
135         }
136 
137         /**
138          * Returns the center line.
139          * @return the center line
140          */
141         public PolyLine2d getCenterLine()
142         {
143             return this.centerLine;
144         }
145 
146         @Override
147         public PolyLine2d getLine()
148         {
149             return OtsLocatable.transformLine(this.centerLine, getLocation());
150         }
151 
152         @Override
153         public double getZ()
154         {
155             return DrawLevel.CENTER_LINE.getZ();
156         }
157 
158         @Override
159         public String toString()
160         {
161             return "Center line " + this.fullId;
162         }
163 
164     }
165 
166     /**
167      * Animation for center line of a lane.
168      */
169     public static class CenterLineAnimation extends OtsRenderable<CenterLine>
170     {
171         /** Drawing color for the center line. */
172         private static final Color COLOR = Color.MAGENTA.darker().darker();
173 
174         /**  */
175         private static final long serialVersionUID = 20180426L;
176 
177         /** Drawable path. */
178         private final Path2D.Float path;
179 
180         /**
181          * Construct a new CenterLineAnimation.
182          * @param centerLine the center line of a lane
183          * @param contextualized context provider
184          */
185         public CenterLineAnimation(final CenterLine centerLine, final Contextualized contextualized)
186         {
187             super(centerLine, contextualized);
188             this.path = PaintLine.getPath(getSource().getLocation(), getSource().getCenterLine());
189         }
190 
191         @Override
192         public final void paint(final Graphics2D graphics, final ImageObserver observer)
193         {
194             setRendering(graphics);
195             PaintLine.paintLine(graphics, COLOR, 0.1, this.path);
196             resetRendering(graphics);
197         }
198 
199     }
200 
201     /**
202      * Text animation for the Node. Separate class to be able to turn it on and off...
203      * <p>
204      * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
205      * <br>
206      * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
207      * </p>
208      * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
209      * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
210      * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
211      */
212     public class Text extends TextAnimation<LaneData, Text>
213     {
214         /** */
215         private static final long serialVersionUID = 20161211L;
216 
217         /**
218          * @param source the object for which the text is displayed
219          * @param text the text to display
220          * @param dx the horizontal movement of the text, in meters
221          * @param dy the vertical movement of the text, in meters
222          * @param textPlacement where to place the text
223          * @param color the color of the text
224          * @param contextualized context provider
225          */
226         public Text(final LaneData source, final Supplier<String> text, final float dx, final float dy,
227                 final TextAlignment textPlacement, final Color color, final Contextualized contextualized)
228         {
229             super(source, text, dx, dy, textPlacement, color, contextualized, TextAnimation.RENDERWHEN10);
230         }
231 
232         @Override
233         public final String toString()
234         {
235             return "Text []";
236         }
237 
238     }
239 
240     /**
241      * LaneData provides the information required to draw a lane.
242      * <p>
243      * Copyright (c) 2023-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
244      * <br>
245      * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
246      * </p>
247      * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
248      */
249     public interface LaneData extends CrossSectionElementData, Identifiable
250     {
251         @Override
252         default double getZ()
253         {
254             return DrawLevel.LANE.getZ();
255         }
256     }
257 
258 }