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