1 package org.opentrafficsim.road.network.lane;
2
3 import java.math.BigInteger;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.LinkedHashMap;
7 import java.util.LinkedHashSet;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11
12 import org.djunits.value.vdouble.scalar.Length;
13 import org.djutils.exceptions.Throw;
14 import org.opentrafficsim.base.OtsRuntimeException;
15 import org.opentrafficsim.base.StripeElement;
16 import org.opentrafficsim.base.StripeElement.StripeLateralSync;
17 import org.opentrafficsim.core.gtu.GtuType;
18 import org.opentrafficsim.core.network.LateralDirectionality;
19
20
21
22
23
24
25
26
27
28 public class StripeData
29 {
30
31
32 private List<StripeElement> elements;
33
34
35 private final boolean left;
36
37
38 private final boolean right;
39
40
41 private final Map<GtuType, Set<LateralDirectionality>> permeabilityMap = new LinkedHashMap<>();
42
43
44 private StripeLateralSync lateralSync = StripeLateralSync.LINK;
45
46
47 private StripePhaseSync phaseSync = StripePhaseSync.NONE;
48
49
50 private Double period;
51
52
53
54
55
56
57
58 public StripeData(final List<StripeElement> elements, final boolean left, final boolean right)
59 {
60 this.elements = elements;
61 this.left = left;
62 this.right = right;
63 }
64
65
66
67
68
69 public List<StripeElement> getElements()
70 {
71 return this.elements;
72 }
73
74
75
76
77
78 public void setElements(final List<StripeElement> elements)
79 {
80 this.elements = elements;
81 this.period = null;
82 }
83
84
85
86
87
88
89
90
91 public void addPermeability(final GtuType gtuType, final LateralDirectionality lateralDirection)
92 {
93 if (!this.permeabilityMap.containsKey(gtuType))
94 {
95 this.permeabilityMap.put(gtuType, new LinkedHashSet<LateralDirectionality>(2));
96 }
97 this.permeabilityMap.get(gtuType).add(lateralDirection);
98 }
99
100
101
102
103
104
105
106 public final boolean isPermeable(final GtuType gtuType, final LateralDirectionality lateralDirection)
107 {
108 Throw.when(lateralDirection.isNone(), OtsRuntimeException.class,
109 "May not request NONE lateral direction for permeability.");
110 for (GtuType testGtuType = gtuType; testGtuType != null; testGtuType = testGtuType.getParent().orElse(null))
111 {
112 Set<LateralDirectionality> set = this.permeabilityMap.get(testGtuType);
113 if (null != set)
114 {
115 return set.contains(lateralDirection);
116 }
117 }
118 return lateralDirection.isLeft() ? this.left : this.right;
119 }
120
121
122
123
124
125 public void setLateralSync(final StripeLateralSync lateralSync)
126 {
127 this.lateralSync = lateralSync;
128 }
129
130
131
132
133
134 public StripeLateralSync getLateralSync()
135 {
136 return this.lateralSync;
137 }
138
139
140
141
142
143 public void setPhaseSync(final StripePhaseSync phaseSync)
144 {
145 this.phaseSync = phaseSync;
146 }
147
148
149
150
151
152 public StripePhaseSync getPhaseSync()
153 {
154 return this.phaseSync;
155 }
156
157
158
159
160
161 public double getPeriod()
162 {
163 if (this.period == null)
164 {
165 this.period = getPeriod(this.elements);
166 }
167 return this.period;
168 }
169
170
171
172
173
174
175
176 public static double getPeriod(final List<StripeElement> elements)
177 {
178 List<Double> lineLengths = new ArrayList<>();
179 for (StripeElement element : elements)
180 {
181 if (element.dashes() != null)
182 {
183 double length = 0.0;
184 for (Length gapDash : element.dashes())
185 {
186 length += gapDash.si;
187 }
188 lineLengths.add(length);
189 }
190 }
191 return getPeriod(lineLengths);
192 }
193
194
195
196
197
198
199
200 private static double getPeriod(final Collection<Double> lineLengths)
201 {
202 Set<Double> set = new LinkedHashSet<>(lineLengths);
203 if (lineLengths.isEmpty())
204 {
205 return -1.0;
206 }
207 else if (set.size() == 1)
208 {
209 return ((long) (lineLengths.iterator().next() * 10000)) / 10000.0;
210 }
211 long gcd = 1L;
212 for (double length : set)
213 {
214 gcd = BigInteger.valueOf(gcd).gcd(BigInteger.valueOf((long) (length * 10000))).longValue();
215 }
216 return gcd / 10000.0;
217 }
218
219
220
221
222
223 public Length getWidth()
224 {
225 Length width = Length.ZERO;
226 for (StripeElement element : getElements())
227 {
228 width = width.plus(element.width());
229 }
230 return width;
231 }
232
233
234
235
236 public enum StripePhaseSync
237 {
238
239 NONE(false),
240
241
242 UPSTREAM(true),
243
244
245 DOWNSTREAM(true);
246
247
248 private final boolean sync;
249
250
251
252
253
254 StripePhaseSync(final boolean sync)
255 {
256 this.sync = sync;
257 }
258
259
260
261
262
263 public boolean isSync()
264 {
265 return this.sync;
266 }
267 }
268
269 }