1 package org.opentrafficsim.road.gtu.lane.perception;
2
3 import java.util.LinkedHashSet;
4 import java.util.List;
5 import java.util.Set;
6
7 import org.djunits.value.vdouble.scalar.Length;
8 import org.opentrafficsim.core.gtu.RelativePosition;
9 import org.opentrafficsim.core.network.route.Route;
10 import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
11 import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
12 import org.opentrafficsim.road.gtu.lane.perception.structure.LaneRecordInterface;
13 import org.opentrafficsim.road.network.lane.object.LaneBasedObject;
14
15
16
17
18
19
20
21
22
23
24
25
26
27 public abstract class LaneBasedObjectIterable<H extends Headway, L extends LaneBasedObject>
28 extends AbstractPerceptionIterable<H, L, Boolean>
29 {
30
31
32 private static final Length MARGIN = Length.instantiateSI(1e-9);
33
34
35 private final Class<L> clazz;
36
37
38
39
40
41
42
43
44
45
46
47
48 public LaneBasedObjectIterable(final LaneBasedGtu perceivingGtu, final Class<L> clazz, final LaneRecordInterface<?> root,
49 final Length initialPosition, final boolean downstream, final Length maxDistance,
50 final RelativePosition relativePosition, final Route route)
51 {
52 super(perceivingGtu, root, initialPosition, downstream, maxDistance, relativePosition, route);
53 this.clazz = clazz;
54 }
55
56
57 @SuppressWarnings("unchecked")
58 @Override
59 protected Entry getNext(final LaneRecordInterface<?> record, final Length position, final Boolean counter)
60 {
61 List<LaneBasedObject> list;
62 if (isDownstream())
63 {
64 if (!record.isDownstreamBranch())
65 {
66 return null;
67 }
68 Length pos = position.eq0() && counter == null ? MARGIN.neg() : position;
69 list = record.getLane().getObjectAhead(pos);
70 }
71 else
72 {
73 Length pos = position.eq(record.getLane().getLength()) && counter == null
74 ? record.getLane().getLength().plus(MARGIN) : position;
75 list = record.getLane().getObjectBehind(pos);
76 }
77 while (list != null)
78 {
79 Set<L> set = new LinkedHashSet<>();
80 Length pos = list.get(0).getLongitudinalPosition();
81 for (LaneBasedObject object : list)
82 {
83 if (this.clazz.isAssignableFrom(object.getClass()))
84 {
85
86 set.add((L) object);
87 }
88 }
89 if (!set.isEmpty())
90 {
91 if (set.size() == 1)
92 {
93 return new Entry(set.iterator().next(), true, pos);
94 }
95 return new Entry(set, true, pos);
96 }
97 if (isDownstream())
98 {
99 list = record.getLane().getObjectAhead(pos);
100 }
101 else
102 {
103 list = record.getLane().getObjectBehind(pos);
104 }
105 }
106 return null;
107 }
108
109
110 @Override
111 protected final Length getDistance(final L object, final LaneRecordInterface<?> record, final Length position)
112 {
113 return isDownstream() ? record.getDistanceToPosition(position).minus(getDx())
114 : record.getDistanceToPosition(position).neg().plus(getDx());
115 }
116
117
118 @Override
119 public String toString()
120 {
121 return "LaneBasedObjectIterable [class=" + this.clazz + ", downstream=" + isDownstream() + "]";
122 }
123
124 }