View Javadoc
1   package org.opentrafficsim.editor.extensions.map;
2   
3   import java.util.LinkedHashSet;
4   import java.util.Set;
5   
6   import org.djunits.value.vdouble.scalar.Length;
7   import org.opentrafficsim.editor.XsdTreeNode;
8   import org.opentrafficsim.road.network.factory.xml.utils.StripeSynchronization.SynchronizableStripe;
9   import org.opentrafficsim.road.network.lane.Lane;
10  import org.opentrafficsim.road.network.lane.StripeData;
11  import org.opentrafficsim.road.network.lane.StripeData.StripePhaseSync;
12  
13  /**
14   * Representation of a stripe that can be synchronized as used within the editor.
15   * <p>
16   * Copyright (c) 2024-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
17   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
18   * </p>
19   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
20   */
21  public class SynchronizableMapStripe implements SynchronizableStripe<MapStripeData>
22  {
23      /** Link data. */
24      private final MapLinkData linkData;
25  
26      /** Stripe data. */
27      private final MapStripeData data;
28  
29      /** Synchronization. */
30      private final StripePhaseSync phaseSync;
31  
32      /** Cached period. */
33      private Double period = null;
34  
35      /**
36       * Constructor.
37       * @param linkData link data
38       * @param data stripe data
39       * @param phaseSync synchronization
40       */
41      public SynchronizableMapStripe(final MapLinkData linkData, final MapStripeData data, final StripePhaseSync phaseSync)
42      {
43          this.linkData = linkData;
44          this.data = data;
45          this.phaseSync = phaseSync;
46      }
47  
48      @Override
49      public double getStartPhase()
50      {
51          if (getPeriod() < 0.0)
52          {
53              return 0.0;
54          }
55          return (this.data.getDashOffset().si % getPeriod()) / getPeriod();
56      }
57  
58      @Override
59      public double getEndPhase()
60      {
61          if (getPeriod() < 0.0)
62          {
63              return 0.0;
64          }
65          return ((this.data.getCenterLine().getLength() + this.data.getDashOffset().si) % getPeriod()) / getPeriod();
66      }
67  
68      @Override
69      public double getPeriod()
70      {
71          if (this.period == null)
72          {
73              this.period = StripeData.getPeriod(this.data.getElements());
74          }
75          return this.period;
76      }
77  
78      @Override
79      public MapStripeData getObject()
80      {
81          return this.data;
82      }
83  
84      @Override
85      public MapStripeData getUpstreamStripe()
86      {
87          XsdTreeNode fromNode = this.linkData.getNode().getCoupledKeyrefNodeAttribute("NodeStart");
88          if (fromNode == null)
89          {
90              return null;
91          }
92          for (XsdTreeNode networkChild : this.linkData.getNode().getParent().getChildren())
93          {
94              if (networkChild.getNodeName().equals("Link")
95                      && fromNode.equals(networkChild.getCoupledKeyrefNodeAttribute("NodeEnd")))
96              {
97                  MapLinkData otherLink = (MapLinkData) this.linkData.getMap().getData(networkChild);
98                  if (otherLink == null)
99                  {
100                     return null;
101                 }
102                 for (MapStripeData otherStripe : otherLink.getStripeData())
103                 {
104                     if (otherStripe.getCenterLine().getLast().distance(this.data.getCenterLine().getFirst()) < Lane.MARGIN.si)
105                     {
106                         return otherStripe;
107                     }
108                 }
109             }
110         }
111         return null;
112     }
113 
114     @Override
115     public MapStripeData getDownstreamStripe()
116     {
117         XsdTreeNode fromNode = this.linkData.getNode().getCoupledKeyrefNodeAttribute("NodeEnd");
118         if (fromNode == null)
119         {
120             return null;
121         }
122         for (XsdTreeNode networkChild : this.linkData.getNode().getParent().getChildren())
123         {
124             if (networkChild.getNodeName().equals("Link")
125                     && fromNode.equals(networkChild.getCoupledKeyrefNodeAttribute("NodeStart")))
126             {
127                 MapLinkData otherLink = (MapLinkData) this.linkData.getMap().getData(networkChild);
128                 if (otherLink == null)
129                 {
130                     return null;
131                 }
132                 for (MapStripeData otherStripe : otherLink.getStripeData())
133                 {
134                     if (otherStripe.getCenterLine().getFirst().distance(this.data.getCenterLine().getLast()) < Lane.MARGIN.si)
135                     {
136                         return otherStripe;
137                     }
138                 }
139             }
140         }
141         return null;
142     }
143 
144     @Override
145     public Set<MapStripeData> getCommonPhaseStripes()
146     {
147         Set<MapStripeData> out = new LinkedHashSet<>();
148         for (MapStripeData stripe : this.linkData.getStripeData())
149         {
150             SynchronizableMapStripe otherStripe = this.linkData.getMap().getSynchronizableStripes().get(stripe);
151             if (otherStripe != null && !otherStripe.equals(this))
152             {
153                 boolean equalPhaseSync = getSynchronization().equals(otherStripe.getSynchronization());
154                 boolean bothSyncUpOrDown = getSynchronization().isSync();
155                 boolean samePeriod = getPeriod() == otherStripe.getPeriod();
156                 boolean bothLatSyncToLink = this.data.getLateralSync().isLinkBased() && stripe.getLateralSync().isLinkBased();
157                 if (equalPhaseSync && bothSyncUpOrDown && samePeriod && bothLatSyncToLink)
158                 {
159                     out.add(stripe);
160                 }
161             }
162         }
163         return out;
164     }
165 
166     @Override
167     public StripePhaseSync getSynchronization()
168     {
169         return this.phaseSync;
170     }
171 
172     @Override
173     public void setStartPhase(final double phase)
174     {
175         this.data.setDashOffset(Length.instantiateSI(phase * getPeriod()));
176     }
177 
178     @Override
179     public void setEndPhase(final double phase)
180     {
181         double len = getPeriod() - ((this.data.getCenterLine().getLength() - phase * getPeriod()) % getPeriod());
182         this.data.setDashOffset(Length.instantiateSI(len));
183     }
184 
185 }