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