1 package org.opentrafficsim.draw.road;
2
3 import java.awt.BasicStroke;
4 import java.awt.Color;
5 import java.awt.Graphics2D;
6 import java.awt.geom.Path2D;
7 import java.awt.image.ImageObserver;
8 import java.util.Set;
9
10 import org.djutils.draw.line.PolyLine2d;
11 import org.opentrafficsim.base.geometry.OtsShape;
12 import org.opentrafficsim.draw.DrawLevel;
13 import org.opentrafficsim.draw.OtsRenderable;
14 import org.opentrafficsim.draw.PaintPolygons;
15 import org.opentrafficsim.draw.road.CrossSectionElementAnimation.CrossSectionElementData;
16
17 import nl.tudelft.simulation.naming.context.Contextualized;
18
19 /**
20 * Draws cross section elements (those that are not defined more specifically).
21 * <p>
22 * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
23 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
24 * </p>
25 * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
26 * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
27 * @param <L> cross section element data type
28 */
29 public class CrossSectionElementAnimation<L extends CrossSectionElementData> extends OtsRenderable<L>
30 {
31 /** The animation color. */
32 private final Color color;
33
34 /** Drawable paths. */
35 private final Set<Path2D.Float> paths;
36
37 /**
38 * Constructor.
39 * @param source cross section element
40 * @param contextualized context provider
41 * @param color the color to draw the shoulder with
42 */
43 public CrossSectionElementAnimation(final L source, final Contextualized contextualized, final Color color)
44 {
45 super(source, contextualized);
46 this.color = color;
47 this.paths = PaintPolygons.getPaths(source.getRelativeContour().getPointList());
48 }
49
50 @Override
51 public void paint(final Graphics2D graphics, final ImageObserver observer)
52 {
53 setRendering(graphics);
54 PaintPolygons.paintPaths(graphics, this.color, this.paths, true);
55 // drawing some extra width by painting the edge (i.e. fill = false) prevents anti-alias lines between adjacent elements
56 double scale = Math.min(Math.max(3.0 / graphics.getTransform().getDeterminant(), 0.1), 0.5);
57 graphics.setStroke(new BasicStroke((float) scale, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER));
58 PaintPolygons.paintPaths(graphics, this.color, this.paths, false);
59 resetRendering(graphics);
60 }
61
62 @Override
63 public String toString()
64 {
65 return "CrossSectionElementAnimation [source = " + getSource().toString() + ", color=" + this.color + "]";
66 }
67
68 /**
69 * CrossSectionElementData provides the information required to draw a cross section element.
70 * <p>
71 * Copyright (c) 2023-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
72 * <br>
73 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
74 * </p>
75 * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
76 */
77 public interface CrossSectionElementData extends OtsShape
78 {
79 /**
80 * Returns the center line in world coordinates.
81 * @return the center line in world coordinates
82 */
83 PolyLine2d getCenterLine();
84
85 /**
86 * Return the id of the link.
87 * @return link id.
88 */
89 String getLinkId();
90 }
91
92 /**
93 * ShoulderData provides the information required to draw a shoulder.
94 * <p>
95 * Copyright (c) 2023-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/wjschakel">Wouter Schakel</a>
100 */
101 public interface ShoulderData extends CrossSectionElementData
102 {
103 @Override
104 default double getZ()
105 {
106 return DrawLevel.SHOULDER.getZ();
107 }
108 }
109 }