1 package org.opentrafficsim.animation.network;
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.point.DirectedPoint2d;
12 import org.djutils.draw.point.Point2d;
13 import org.opentrafficsim.animation.Colors;
14 import org.opentrafficsim.animation.DrawLevel;
15 import org.opentrafficsim.animation.LineLocatable;
16 import org.opentrafficsim.animation.OtsRenderableLabeled;
17 import org.opentrafficsim.animation.PaintLine;
18 import org.opentrafficsim.animation.RenderableTextSource;
19 import org.opentrafficsim.animation.TextAlignment;
20 import org.opentrafficsim.animation.network.LinkAnimation.LinkData;
21 import org.opentrafficsim.animation.network.LinkAnimation.Text;
22
23 import nl.tudelft.simulation.naming.context.Contextualized;
24
25
26
27
28
29
30
31
32
33
34 public class LinkAnimation extends OtsRenderableLabeled<LinkData, Text>
35 {
36
37
38 private float width;
39
40
41 private Path2D.Float path;
42
43
44 private Path2D.Float startPoint;
45
46
47 private Path2D.Float endPoint;
48
49
50 private final Color color;
51
52
53 private PolyLine2d designLine;
54
55
56
57
58
59
60
61 public LinkAnimation(final LinkData link, final Contextualized contextualized, final float width)
62 {
63 super(link, contextualized);
64 this.width = width;
65 setPath();
66 this.color = getSource().isConnector() ? Color.PINK.darker() : Colors.OTS_BLUE;
67 }
68
69 @Override
70 protected Text createText(final LinkData source, final Contextualized contextualized, final String prefix)
71 {
72 return new Text(source, source::getId, contextualized);
73 }
74
75 @Override
76 public final void paint(final Graphics2D graphics, final ImageObserver observer)
77 {
78 if (isDynamic())
79 {
80 PolyLine2d line = getSource().getCenterLine();
81 if (!line.equals(this.designLine))
82 {
83 setPath();
84 }
85 }
86 setRendering(graphics);
87 double scale = Math.sqrt(graphics.getTransform().getDeterminant());
88 double factor = 2.0 / Math.min(scale, 2.0);
89 PaintLine.paintLine(graphics, this.color, factor * this.width, this.path);
90 PaintLine.paintLine(graphics, this.color, this.width / 30, this.startPoint);
91 PaintLine.paintLine(graphics, this.color, this.width / 30, this.endPoint);
92 resetRendering(graphics);
93 }
94
95
96
97
98 private void setPath()
99 {
100 this.designLine = getSource().getCenterLine();
101 this.path = PaintLine.getPath(getSource().getLocation(), this.designLine);
102 this.startPoint = getEndPoint(this.designLine.getFirst(), this.designLine.get(1));
103 this.endPoint = getEndPoint(this.designLine.getLast(), this.designLine.get(this.designLine.size() - 2));
104 }
105
106
107
108
109
110
111 private Path2D.Float getEndPoint(final Point2d pointEnd, final Point2d nextPoint)
112 {
113 double dx = nextPoint.x - pointEnd.x;
114 double dy = nextPoint.y - pointEnd.y;
115 double length = pointEnd.distance(nextPoint);
116
117 dx *= this.width / length;
118 dy *= this.width / length;
119 PolyLine2d line = new PolyLine2d(0.0, new Point2d(pointEnd.x - dy, pointEnd.y + dx),
120 new Point2d(pointEnd.x + dy, pointEnd.y - dx));
121 return PaintLine.getPath(getSource().getLocation(), line);
122 }
123
124 @Override
125 public final String toString()
126 {
127 return "LinkAnimation [width=" + this.width + ", link=" + super.getSource() + "]";
128 }
129
130
131
132
133 public static class Text extends RenderableTextSource<LinkData, Text>
134 {
135
136
137
138
139
140
141 public Text(final LinkData source, final Supplier<String> text, final Contextualized contextualized)
142 {
143 super(source, text, 0.0f, 1.5f, TextAlignment.CENTER, Color.BLACK, 2.0f, 12.0f, 50f, contextualized, null,
144 RenderableTextSource.RENDERWHEN10);
145 }
146
147 @Override
148 public final String toString()
149 {
150 return "LinkAnimation.Text []";
151 }
152 }
153
154
155
156
157 public interface LinkData extends LineLocatable, Identifiable
158 {
159 @Override
160 DirectedPoint2d getLocation();
161
162
163
164
165
166 boolean isConnector();
167
168
169
170
171
172 PolyLine2d getCenterLine();
173
174 @Override
175 default double getZ()
176 {
177 return DrawLevel.LINK.getZ();
178 }
179 }
180
181 }