View Javadoc
1   package org.opentrafficsim.animation.road;
2   
3   import java.awt.BasicStroke;
4   import java.awt.Color;
5   import java.awt.Graphics2D;
6   import java.awt.Stroke;
7   import java.awt.geom.Path2D;
8   import java.awt.image.ImageObserver;
9   import java.rmi.RemoteException;
10  import java.util.Set;
11  
12  import javax.naming.NamingException;
13  
14  import org.djunits.unit.LengthUnit;
15  import org.djunits.value.vdouble.scalar.Length;
16  import org.opentrafficsim.animation.PaintPolygons;
17  import org.opentrafficsim.animation.OtsRenderableLabeled.NoText;
18  import org.opentrafficsim.animation.road.AbstractLineAnimation.LaneBasedObjectData;
19  import org.opentrafficsim.animation.road.ConflictAnimation.ConflictData;
20  
21  import nl.tudelft.simulation.naming.context.Contextualized;
22  
23  /**
24   * Animate a conflict.
25   * <p>
26   * Copyright (c) 2013-2026 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
27   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
28   * </p>
29   * @author Alexander Verbraeck
30   * @author Peter Knoppers
31   * @author Wouter Schakel
32   */
33  public class ConflictAnimation extends AbstractLineAnimation<ConflictData, NoText<ConflictData>>
34  {
35  
36      /** Drawable paths. */
37      private final Set<Path2D.Float> paths;
38  
39      /**
40       * Constructor.
41       * @param source the conflict to draw
42       * @param contextualized context provider
43       * @throws NamingException in case of registration failure of the animation
44       * @throws RemoteException on communication failure
45       */
46      public ConflictAnimation(final ConflictData source, final Contextualized contextualized)
47              throws NamingException, RemoteException
48      {
49          super(source, contextualized, new Length(0.5, LengthUnit.SI));
50          // geometry of area (not the line) is absolute; pre-transform geometry to fit rotation of source
51          this.paths = this.getSource().getAbsoluteContour() == null ? null
52                  : PaintPolygons.getPaths(getSource().getLocation(), getSource().getAbsoluteContour().getPointList());
53      }
54  
55      @Override
56      protected NoText<ConflictData> createText(final ConflictData source, final Contextualized contextualized,
57              final String prefix)
58      {
59          return null; // no label for conflicts
60      }
61  
62      @Override
63      public final void paint(final Graphics2D graphics, final ImageObserver observer)
64      {
65          // paint the bar that represents the line where the conflict starts, like any other AbstractLineAnimation
66          Color fillColor = getSource().getColor();
67          graphics.setColor(fillColor);
68          super.paint(graphics, observer);
69  
70          // paint the additional area with dashed lines
71          Stroke oldStroke = graphics.getStroke();
72          BasicStroke stroke;
73          float factor = getSource().isPermitted() ? .5f : 1f;
74          if (getSource().isCrossing())
75          {
76              stroke = new BasicStroke(.1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f,
77                      new float[] {factor * 1.0f, factor * 2.0f}, 0.0f);
78          }
79          else
80          {
81              stroke = new BasicStroke(.1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f,
82                      new float[] {factor * 1.0f, factor * 0.95f, factor * 0.1f, factor * 0.95f}, 0.0f);
83          }
84          graphics.setStroke(stroke);
85          if (this.paths != null)
86          {
87              setRendering(graphics);
88              PaintPolygons.paintPaths(graphics, fillColor, this.paths, false);
89              resetRendering(graphics);
90          }
91          graphics.setStroke(oldStroke);
92      }
93  
94      @Override
95      public final String toString()
96      {
97          return "ConflictAnimation [source=" + getSource() + "]";
98      }
99  
100     /**
101      * Provides the information required to draw a conflict.
102      */
103     public interface ConflictData extends LaneBasedObjectData
104     {
105 
106         /**
107          * Returns the conflict color.
108          * @return conflict color
109          */
110         Color getColor();
111 
112         /**
113          * Whether the conflict is a crossing.
114          * @return whether the conflict is a crossing
115          */
116         boolean isCrossing();
117 
118         /**
119          * Whether the conflict is a permitted conflict.
120          * @return whether the conflict is a permitted conflict
121          */
122         boolean isPermitted();
123 
124     }
125 
126 }