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