View Javadoc
1   package org.opentrafficsim.draw.network;
2   
3   import java.awt.BasicStroke;
4   import java.awt.Color;
5   import java.awt.Graphics2D;
6   import java.awt.geom.Ellipse2D;
7   import java.awt.geom.GeneralPath;
8   import java.awt.geom.Path2D;
9   import java.awt.image.ImageObserver;
10  import java.util.function.Supplier;
11  
12  import org.djutils.base.Identifiable;
13  import org.djutils.draw.point.DirectedPoint2d;
14  import org.djutils.draw.point.Point2d;
15  import org.opentrafficsim.base.geometry.OtsShape;
16  import org.opentrafficsim.draw.DrawLevel;
17  import org.opentrafficsim.draw.OtsRenderable;
18  import org.opentrafficsim.draw.RenderableTextSource;
19  import org.opentrafficsim.draw.TextAlignment;
20  import org.opentrafficsim.draw.network.NodeAnimation.NodeData;
21  
22  import nl.tudelft.simulation.naming.context.Contextualized;
23  
24  /**
25   * Draws NodeData.
26   * <p>
27   * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
28   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
29   * </p>
30   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
31   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
32   */
33  public class NodeAnimation extends OtsRenderable<NodeData>
34  {
35      /** the Text object to destroy when the animation is destroyed. */
36      private Text text;
37  
38      /**
39       * Constructor.
40       * @param node node data.
41       * @param contextualized context provider
42       */
43      public NodeAnimation(final NodeData node, final Contextualized contextualized)
44      {
45          super(node, contextualized);
46          this.text = new Text(node, node::getId, 0.0f, 3.0f, TextAlignment.CENTER, Color.BLACK, contextualized,
47                  RenderableTextSource.RENDERWHEN10);
48          setScaleY(false);
49      }
50  
51      /** {@inheritDoc} */
52      @Override
53      public boolean isScaleY()
54      {
55          return super.isScaleY();
56      }
57  
58      @Override
59      public final void paint(final Graphics2D graphics, final ImageObserver observer)
60      {
61          setRendering(graphics);
62          double scale = Math.sqrt(graphics.getTransform().getDeterminant());
63          double factor = 3.0 / Math.min(scale, 3.0); // do not make smaller when zooming out below scale 3
64          graphics.setColor(Color.BLACK);
65          graphics.setStroke(new BasicStroke((float) (factor * 0.5), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
66          graphics.draw(new Ellipse2D.Double(-0.5 * factor, -0.5 * factor, 1.0 * factor, 1.0 * factor));
67          double direction = getSource().getLocation().getDirZ();
68          if (!Double.isNaN(direction))
69          {
70              GeneralPath arrow = new GeneralPath(Path2D.WIND_EVEN_ODD, 3);
71              arrow.moveTo(0.5 * factor, -0.5 * factor);
72              arrow.lineTo(2.0 * factor, 0.0);
73              arrow.lineTo(0.5 * factor, 0.5 * factor);
74              graphics.draw(arrow);
75          }
76          resetRendering(graphics);
77      }
78  
79      @Override
80      public void destroy(final Contextualized contextProvider)
81      {
82          super.destroy(contextProvider);
83          this.text.destroy(contextProvider);
84      }
85  
86      @Override
87      public final String toString()
88      {
89          return "NodeAnimation [node=" + super.getSource() + "]";
90      }
91  
92      /**
93       * Text animation for the Node. Separate class to be able to turn it on and off...
94       * <p>
95       * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
96       * <br>
97       * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
98       * </p>
99       * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
100      * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
101      * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
102      */
103     public static class Text extends RenderableTextSource<NodeData, Text>
104     {
105         /**
106          * Constructor.
107          * @param source the object for which the text is displayed
108          * @param text the text to display
109          * @param dx the horizontal movement of the text, in meters
110          * @param dy the vertical movement of the text, in meters
111          * @param textPlacement where to place the text
112          * @param color the color of the text
113          * @param contextualized context provider
114          * @param scaleDependentRendering size limiter for text animation
115          */
116         @SuppressWarnings("checkstyle:parameternumber")
117         public Text(final NodeData source, final Supplier<String> text, final float dx, final float dy,
118                 final TextAlignment textPlacement, final Color color, final Contextualized contextualized,
119                 final ScaleDependentRendering scaleDependentRendering)
120         {
121             super(source, text, dx, dy, textPlacement, color, 2.0f, 12.0f, 50f, contextualized, scaleDependentRendering);
122             setFlip(false);
123             setRotate(false);
124         }
125 
126         @Override
127         public final String toString()
128         {
129             return "NodeAnimation.Text []";
130         }
131     }
132 
133     /**
134      * NodeData provides the information required to draw a node.
135      * <p>
136      * Copyright (c) 2023-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
137      * <br>
138      * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
139      * </p>
140      * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
141      */
142     public interface NodeData extends OtsShape, Identifiable
143     {
144         @Override
145         DirectedPoint2d getLocation();
146 
147         @Override
148         default double signedDistance(final Point2d point)
149         {
150             return Math.hypot(point.x, point.y);
151         }
152 
153         @Override
154         default boolean contains(final Point2d point)
155         {
156             return signedDistance(point) < WORLD_MARGIN_LINE;
157         }
158 
159         @Override
160         default double getZ()
161         {
162             return DrawLevel.NODE.getZ();
163         }
164     }
165 
166 }