1 package org.opentrafficsim.road.network.lane.conflict;
2
3 import java.util.UUID;
4
5 import org.djunits.value.vdouble.scalar.Length;
6 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
7 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
8 import org.opentrafficsim.core.geometry.OTSLine3D;
9 import org.opentrafficsim.core.network.NetworkException;
10 import org.opentrafficsim.road.network.lane.CrossSectionElement;
11 import org.opentrafficsim.road.network.lane.Lane;
12 import org.opentrafficsim.road.network.lane.object.AbstractLaneBasedObject;
13
14 import nl.tudelft.simulation.language.Throw;
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 public final class Conflict extends AbstractLaneBasedObject
31 {
32
33
34 private static final long serialVersionUID = 20160915L;
35
36
37 private final ConflictType conflictType;
38
39
40 private final ConflictRule conflictRule;
41
42
43 private Conflict otherConflict;
44
45
46 private final Length length;
47
48
49
50
51
52
53
54
55
56
57 private Conflict(final Lane lane, final Length longitudinalPosition, final Length length, final OTSLine3D geometry,
58 final ConflictType conflictType, final ConflictRule conflictRule) throws NetworkException
59 {
60 super(UUID.randomUUID().toString(), lane, longitudinalPosition, geometry);
61 this.length = length;
62 this.conflictType = conflictType;
63 this.conflictRule = conflictRule;
64 }
65
66
67
68
69 public ConflictType getConflictType()
70 {
71 return this.conflictType;
72 }
73
74
75
76
77 public ConflictRule getConflictRule()
78 {
79 return this.conflictRule;
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 @SuppressWarnings("checkstyle:parameternumber")
98 public static void generateConflictPair(final ConflictType conflictType, final Lane lane1,
99 final Length longitudinalPosition1, final Length length1, final OTSLine3D geometry1,
100 final ConflictRule conflictRule1, final Lane lane2, final Length longitudinalPosition2, final Length length2,
101 final OTSLine3D geometry2, final ConflictRule conflictRule2) throws NetworkException
102 {
103
104 Throw.whenNull(conflictType, "Conflict type may not be null.");
105 Throw.whenNull(conflictRule1, "Conflict rule may not be null.");
106 Throw.whenNull(conflictRule2, "Conflict rule may not be null.");
107 if (conflictType.equals(ConflictType.SPLIT))
108 {
109
110 Throw.when(!conflictRule1.equals(ConflictRule.SPLIT) || !conflictRule2.equals(ConflictRule.SPLIT),
111 NetworkException.class, "Both conflict rules should be split for conflict type split.");
112 }
113 else
114 {
115
116 boolean check1 = conflictRule1.equals(ConflictRule.PRIORITY) && !conflictRule2.equals(ConflictRule.GIVE_WAY)
117 && !conflictRule2.equals(ConflictRule.STOP);
118 boolean check2 = conflictRule2.equals(ConflictRule.PRIORITY) && !conflictRule1.equals(ConflictRule.GIVE_WAY)
119 && !conflictRule1.equals(ConflictRule.STOP);
120 boolean check3 = conflictRule1.equals(ConflictRule.GIVE_WAY) && !conflictRule2.equals(ConflictRule.PRIORITY);
121 boolean check4 = conflictRule2.equals(ConflictRule.GIVE_WAY) && !conflictRule1.equals(ConflictRule.PRIORITY);
122 boolean check5 = conflictRule1.equals(ConflictRule.STOP) && !conflictRule2.equals(ConflictRule.PRIORITY);
123 boolean check6 = conflictRule2.equals(ConflictRule.STOP) && !conflictRule1.equals(ConflictRule.PRIORITY);
124 Throw.when(check1 || check2 || check3 || check4 || check5 || check6, NetworkException.class,
125 "Conflict rules need to be a combination of 'PRIORITY' and 'GIVE_WAY' or 'STOP', "
126 + "if any of these types is used.");
127
128 boolean check7 = conflictRule1.equals(ConflictRule.ALL_STOP) && !conflictRule2.equals(ConflictRule.ALL_STOP);
129 boolean check8 = conflictRule2.equals(ConflictRule.ALL_STOP) && !conflictRule1.equals(ConflictRule.ALL_STOP);
130 Throw.when(check7 || check8, NetworkException.class,
131 "Conflict rule 'ALL_STOP' can only be combined with a conflict rule 'ALL_STOP'.");
132
133 Throw.when(conflictRule1.equals(ConflictRule.SPLIT) || conflictRule2.equals(ConflictRule.SPLIT),
134 NetworkException.class, "Conflict rule 'SPLIT' may only be used on conflicts of type SPLIT.");
135 }
136 Conflict conf1 = new Conflict(lane1, longitudinalPosition1, length1, geometry1, conflictType, conflictRule1);
137 Conflict conf2 = new Conflict(lane2, longitudinalPosition2, length2, geometry2, conflictType, conflictRule2);
138 conf1.otherConflict = conf2;
139 conf2.otherConflict = conf1;
140 }
141
142
143 @Override
144 public String toString()
145 {
146 return "Conflict [conflictType=" + this.conflictType + ", conflictRule=" + this.conflictRule + ", otherConflict="
147 + this.otherConflict + "]";
148 }
149
150
151 @Override
152 public Conflict clone(final CrossSectionElement newCSE, final OTSSimulatorInterface newSimulator, final boolean animation)
153 throws NetworkException
154 {
155 Throw.when(!(newCSE instanceof Lane), NetworkException.class, "sensors can only be cloned for Lanes");
156 Throw.when(!(newSimulator instanceof OTSDEVSSimulatorInterface), NetworkException.class,
157 "simulator should be a DEVSSimulator");
158
159 return new Conflict((Lane) newCSE, getLongitudinalPosition(), this.length, getGeometry(), this.conflictType,
160 this.conflictRule);
161 }
162
163 }