1 package org.opentrafficsim.road.network.lane.conflict;
2
3 import java.util.LinkedHashMap;
4 import java.util.Map;
5
6 import org.djunits.value.vdouble.scalar.Length;
7 import org.djutils.draw.point.OrientedPoint2d;
8 import org.djutils.exceptions.Throw;
9 import org.opentrafficsim.road.network.lane.CrossSectionLink.Priority;
10 import org.opentrafficsim.road.network.lane.Lane;
11
12
13
14
15
16
17
18
19
20
21
22
23
24 public class DefaultConflictRule implements ConflictRule
25 {
26
27
28 private Map<String, ConflictPriority> map = null;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 @Override
67 public ConflictPriority determinePriority(final Conflict conflict)
68 {
69 if (this.map == null)
70 {
71 ConflictPriority[] conflictPriorities = getConflictRules(conflict.getLane(), conflict.getLongitudinalPosition(),
72 conflict.getOtherConflict().getLane(), conflict.getOtherConflict().getLongitudinalPosition(),
73 conflict.getConflictType());
74 this.map = new LinkedHashMap<>();
75 this.map.put(conflict.getId(), conflictPriorities[0]);
76 this.map.put(conflict.getOtherConflict().getId(), conflictPriorities[1]);
77 }
78 ConflictPriority out = this.map.get(conflict.getId());
79 Throw.when(out == null, IllegalArgumentException.class,
80 "Conflict %s is not related to a conflict that was used before in the same conflict rule.", conflict);
81 return out;
82 }
83
84
85
86
87
88
89
90
91
92
93 private static ConflictPriority[] getConflictRules(final Lane lane1, final Length longitudinalPosition1, final Lane lane2,
94 final Length longitudinalPosition2, final ConflictType conflictType)
95 {
96 Throw.when(conflictType.equals(ConflictType.SPLIT), UnsupportedOperationException.class,
97 "DefaultConflictRule is not for use on a split conflict. Use SplitConflictRule instead.");
98 ConflictPriority[] conflictRules = new ConflictPriority[2];
99 Priority priority1 = lane1.getLink().getPriority();
100 Priority priority2 = lane2.getLink().getPriority();
101 if (priority1.isAllStop() && priority2.isAllStop())
102 {
103 conflictRules[0] = ConflictPriority.ALL_STOP;
104 conflictRules[1] = ConflictPriority.ALL_STOP;
105 }
106 else if (priority1.equals(priority2) || (priority1.isYield() && priority2.isStop())
107 || (priority2.isYield() && priority1.isStop()))
108 {
109 Throw.when(priority1.isBusStop(), IllegalArgumentException.class,
110 "Both priorities are 'bus stop', which is not allowed. Use BusStopConflictRule for bus stops.");
111
112 OrientedPoint2d p1 = lane1.getCenterLine().getLocation(longitudinalPosition1);
113 OrientedPoint2d p2 = lane2.getCenterLine().getLocation(longitudinalPosition2);
114 double diff = p2.getDirZ() - p1.getDirZ();
115 while (diff > Math.PI)
116 {
117 diff -= 2 * Math.PI;
118 }
119 while (diff < -Math.PI)
120 {
121 diff += 2 * Math.PI;
122 }
123 if (diff > 0.0)
124 {
125
126 conflictRules[0] = priority1.isStop() ? ConflictPriority.STOP : ConflictPriority.YIELD;
127 conflictRules[1] = ConflictPriority.PRIORITY;
128 }
129 else
130 {
131
132 conflictRules[0] = ConflictPriority.PRIORITY;
133 conflictRules[1] = priority2.isStop() ? ConflictPriority.STOP : ConflictPriority.YIELD;
134 }
135 }
136 else if ((priority1.isPriority() || priority1.isNone())
137 && (priority2.isNone() || priority2.isYield() || priority2.isStop()))
138 {
139 conflictRules[0] = ConflictPriority.PRIORITY;
140 conflictRules[1] = priority2.isStop() ? ConflictPriority.STOP : ConflictPriority.YIELD;
141 }
142 else if ((priority2.isPriority() || priority2.isNone())
143 && (priority1.isNone() || priority1.isYield() || priority1.isStop()))
144 {
145 conflictRules[0] = priority1.isStop() ? ConflictPriority.STOP : ConflictPriority.YIELD;
146 conflictRules[1] = ConflictPriority.PRIORITY;
147 }
148 else
149 {
150 throw new IllegalArgumentException(
151 "Could not sort out conflict priority from link priorities " + priority1 + " and " + priority2);
152 }
153 return conflictRules;
154 }
155
156 @Override
157 public final String toString()
158 {
159 return "DefaultConflictRule";
160 }
161
162 }