View Javadoc
1   package org.opentrafficsim.animation.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.animation.DrawLevel;
16  import org.opentrafficsim.animation.OtsRenderableLabeled;
17  import org.opentrafficsim.animation.RenderableTextSource;
18  import org.opentrafficsim.animation.TextAlignment;
19  import org.opentrafficsim.animation.network.NodeAnimation.NodeData;
20  import org.opentrafficsim.animation.network.NodeAnimation.Text;
21  import org.opentrafficsim.base.geometry.OtsShape;
22  
23  import nl.tudelft.simulation.naming.context.Contextualized;
24  
25  /**
26   * Draws node data.
27   * <p>
28   * Copyright (c) 2013-2026 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 Alexander Verbraeck
32   * @author Wouter Schakel
33   */
34  public class NodeAnimation extends OtsRenderableLabeled<NodeData, Text>
35  {
36  
37      /**
38       * Constructor.
39       * @param node node data
40       * @param contextualized context provider
41       */
42      public NodeAnimation(final NodeData node, final Contextualized contextualized)
43      {
44          super(node, contextualized);
45          setScaleY(false);
46      }
47  
48      @Override
49      protected Text createText(final NodeData source, final Contextualized contextualized, final String prefix)
50      {
51          return new Text(source, source::getId, contextualized);
52      }
53  
54      @Override
55      public boolean isScaleY()
56      {
57          return super.isScaleY();
58      }
59  
60      @Override
61      public final void paint(final Graphics2D graphics, final ImageObserver observer)
62      {
63          setRendering(graphics);
64          double scale = Math.sqrt(graphics.getTransform().getDeterminant());
65          double factor = 4.0 / Math.min(scale, 4.0); // do not make smaller when zooming out below scale 4
66          graphics.setColor(Color.BLACK);
67          graphics.setStroke(new BasicStroke((float) (factor * 0.5), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
68          graphics.draw(new Ellipse2D.Double(-0.5 * factor, -0.5 * factor, 1.0 * factor, 1.0 * factor));
69          if (!getSource().isCentroid())
70          {
71              double direction = getSource().getLocation().getDirZ();
72              if (!Double.isNaN(direction))
73              {
74                  GeneralPath arrow = new GeneralPath(Path2D.WIND_EVEN_ODD, 3);
75                  arrow.moveTo(0.7 * factor, -0.7 * factor);
76                  arrow.lineTo(1.4 * factor, 0.0);
77                  arrow.lineTo(0.7 * factor, 0.7 * factor);
78                  graphics.setStroke(new BasicStroke((float) (factor * 0.25), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
79                  graphics.draw(arrow);
80              }
81          }
82          resetRendering(graphics);
83      }
84  
85      @Override
86      public final String toString()
87      {
88          return "NodeAnimation [node=" + super.getSource() + "]";
89      }
90  
91      /**
92       * Text animation for the Node.
93       */
94      public static class Text extends RenderableTextSource<NodeData, Text>
95      {
96          /**
97           * Constructor.
98           * @param source the object for which the text is displayed
99           * @param text the text to display
100          * @param contextualized context provider
101          */
102         @SuppressWarnings("checkstyle:parameternumber")
103         public Text(final NodeData source, final Supplier<String> text, final Contextualized contextualized)
104         {
105             super(source, text, 0.0f, 3.0f, TextAlignment.CENTER, Color.BLACK, contextualized,
106                     RenderableTextSource.RENDERWHEN10);
107             setFlip(false);
108             setRotate(false);
109         }
110 
111         @Override
112         public final String toString()
113         {
114             return "NodeAnimation.Text []";
115         }
116     }
117 
118     /**
119      * NodeData provides the information required to draw a node.
120      */
121     public interface NodeData extends OtsShape, Identifiable
122     {
123         @Override
124         DirectedPoint2d getLocation();
125 
126         /**
127          * Returns whether this node is a centroid.
128          * @return whether this node is a centroid
129          */
130         boolean isCentroid();
131 
132         @Override
133         default double signedDistance(final Point2d point)
134         {
135             return Math.hypot(point.x, point.y);
136         }
137 
138         @Override
139         default boolean contains(final Point2d point)
140         {
141             return signedDistance(point) < WORLD_MARGIN_LINE;
142         }
143 
144         @Override
145         default double getZ()
146         {
147             return DrawLevel.NODE.getZ();
148         }
149     }
150 
151 }