View Javadoc
1   package org.opentrafficsim.core.network;
2   
3   import java.util.Arrays;
4   import java.util.LinkedHashSet;
5   
6   import org.opentrafficsim.core.gtu.GTUDirectionality;
7   
8   import nl.tudelft.simulation.immutablecollections.Immutable;
9   import nl.tudelft.simulation.immutablecollections.ImmutableHashSet;
10  import nl.tudelft.simulation.immutablecollections.ImmutableSet;
11  
12  /**
13   * Permitted longitudinal driving directions.
14   * <p>
15   * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
16   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
17   * <p>
18   * $LastChangedDate: 2018-09-19 13:55:45 +0200 (Wed, 19 Sep 2018) $, @version $Revision: 4006 $, by $Author: averbraeck $,
19   * initial version Oct 15, 2014 <br>
20   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
21   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
22   * @author <a href="http://www.citg.tudelft.nl">Guus Tamminga</a>
23   */
24  public enum LongitudinalDirectionality
25  {
26      /** Direction the same as the direction of the graph, increasing fractional position when driving in this direction. */
27      DIR_PLUS(new GTUDirectionality[] { GTUDirectionality.DIR_PLUS }),
28      /** Direction opposite to the direction of the graph, decreasing fractional position when driving in this direction. */
29      DIR_MINUS(new GTUDirectionality[] { GTUDirectionality.DIR_MINUS }),
30      /** Bidirectional. */
31      DIR_BOTH(new GTUDirectionality[] { GTUDirectionality.DIR_PLUS, GTUDirectionality.DIR_MINUS }),
32      /** No traffic possible. */
33      DIR_NONE(new GTUDirectionality[] {});
34  
35      /** Array of permitted driving directions. */
36      private final ImmutableSet<GTUDirectionality> directions;
37  
38      /**
39       * Construct a new LongitudinalDirectionality.
40       * @param directions GTUDirectionality[]; array containing the permitted driving directions
41       */
42      LongitudinalDirectionality(final GTUDirectionality[] directions)
43      {
44          this.directions = new ImmutableHashSet<>(new LinkedHashSet<>(Arrays.asList(directions)), Immutable.WRAP);
45      }
46  
47      /**
48       * Retrieve the permitted driving directions.
49       * @return ImmutableSet&lt;GTUDirectionality&gt;; immutable set containing the permitted driving directions
50       */
51      public final ImmutableSet<GTUDirectionality> getDirectionalities()
52      {
53          return this.directions;
54      }
55  
56      /**
57       * This method looks if this directionality "contains" the provided other directionality. The logic table looks as follows:
58       * <table border="1" summary="">
59       * <tr>
60       * <td><b>THIS &darr; &nbsp; OTHER &rarr;</b></td>
61       * <td><b>DIR_BOTH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b></td>
62       * <td><b>DIR_PLUS&nbsp;&nbsp;&nbsp;</b></td>
63       * <td><b>DIR_MINUS</b></td>
64       * <td><b>DIR_NONE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b></td>
65       * </tr>
66       * <tr>
67       * <td><b>DIR_BOTH</b></td>
68       * <td>true</td>
69       * <td>true</td>
70       * <td>true</td>
71       * <td>true</td>
72       * </tr>
73       * <tr>
74       * <td><b>DIR_PLUS</b></td>
75       * <td>false</td>
76       * <td>true</td>
77       * <td>false</td>
78       * <td>true</td>
79       * </tr>
80       * <tr>
81       * <td><b>DIR_MINUS</b></td>
82       * <td>false</td>
83       * <td>false</td>
84       * <td>true</td>
85       * <td>true</td>
86       * </tr>
87       * <tr>
88       * <td><b>DIR_NONE</b></td>
89       * <td>false</td>
90       * <td>false</td>
91       * <td>false</td>
92       * <td>true</td>
93       * </tr>
94       * </table>
95       * @param directionality the directionality to compare with
96       * @return whether this directionality "contains" the provided other directionality
97       */
98      public final boolean contains(final LongitudinalDirectionality directionality)
99      {
100         return (this.equals(directionality) || this.equals(DIR_BOTH) || directionality.equals(DIR_NONE)) ? true : false;
101     }
102 
103     /**
104      * Easy access method to test if the directionality is FORWARD or BOTH.
105      * @return whether the directionality is FORWARD or BOTH
106      */
107     public final boolean isForwardOrBoth()
108     {
109         return this.equals(DIR_PLUS) || this.equals(DIR_BOTH);
110     }
111 
112     /**
113      * Easy access method to test if the directionality is BACKWARD or BOTH.
114      * @return whether the directionality is BACKWARD or BOTH
115      */
116     public final boolean isBackwardOrBoth()
117     {
118         return this.equals(DIR_MINUS) || this.equals(DIR_BOTH);
119     }
120 
121     /**
122      * Easy access method to test if the directionality is FORWARD.
123      * @return whether the directionality is FORWARD
124      */
125     public final boolean isForward()
126     {
127         return this.equals(DIR_PLUS);
128     }
129 
130     /**
131      * Easy access method to test if the directionality is BACKWARD.
132      * @return whether the directionality is BACKWARD
133      */
134     public final boolean isBackward()
135     {
136         return this.equals(DIR_MINUS);
137     }
138 
139     /**
140      * Easy access method to test if the directionality is BACKWARD or BOTH.
141      * @return whether the directionality is BACKWARD or BOTH
142      */
143     public final boolean isBoth()
144     {
145         return this.equals(DIR_BOTH);
146     }
147 
148     /**
149      * Compute the intersection of this LongitudinalDirectionality with another LongitudinalDirectionality.
150      * @param other LongitudinalDirectionality; the other LongitudinalDirectionality
151      * @return LongitudinalDirectionality; the intersection of <code>this</code> and <code>other</code>
152      */
153     public final LongitudinalDirectionality intersect(final LongitudinalDirectionality other)
154     {
155         switch (other)
156         {
157             case DIR_BOTH:
158                 return this;
159             case DIR_MINUS:
160                 if (this.equals(other))
161                 {
162                     return this;
163                 }
164                 if (this.equals(DIR_BOTH))
165                 {
166                     return other;
167                 }
168                 return DIR_NONE;
169             case DIR_NONE:
170                 return other;
171             case DIR_PLUS:
172                 if (this.equals(other))
173                 {
174                     return this;
175                 }
176                 if (this.equals(DIR_BOTH))
177                 {
178                     return other;
179                 }
180                 return DIR_NONE;
181             default:
182                 System.err.println("intersect with null (returns DIR_NONE)");
183                 return DIR_NONE;
184         }
185     }
186 
187     /**
188      * Check if a direction is permitted by this LongitudinalDirectionality.
189      * @param direction GTUDirectionality; the direction of motion in which a GTU moves, or wants to move
190      * @return boolean; true if the direction is permitted by this LongitudinalDirectionality; false if it is not permitted
191      */
192     public final boolean permits(final GTUDirectionality direction)
193     {
194         switch (direction)
195         {
196             case DIR_MINUS:
197                 return isBackwardOrBoth();
198             case DIR_PLUS:
199                 return isForwardOrBoth();
200             default:
201                 System.out.println("Bad direction: " + direction);
202                 return false;
203         }
204     }
205 
206     /**
207      * Return the inverse if this LongitudinalDirectionality.
208      * @return LongitudinalDirectionality; the directional inverse of this LongitudinalDirectionality
209      */
210     public LongitudinalDirectionality invert()
211     {
212         switch (this)
213         {
214             case DIR_BOTH:
215                 return this;
216             case DIR_MINUS:
217                 return DIR_PLUS;
218             case DIR_NONE:
219                 return this;
220             case DIR_PLUS:
221                 return DIR_MINUS;
222             default:
223                 return this; // cannot happen
224         }
225     }
226 
227 }