View Javadoc
1   package org.djunits.quantity;
2   
3   import org.djunits.quantity.Direction.Reference;
4   import org.djunits.quantity.def.AbsBasic;
5   import org.djunits.quantity.def.AbstractReference;
6   import org.djunits.quantity.def.Quantity;
7   
8   /**
9    * Direction is the absolute equivalent of Angle, and can, e.g., represent an angle relative to a defined "zero" angle such as
10   * NORTH or EAST. The relative operations such as gt, lt, eq and ne are not available in the Direction class.
11   * <p>
12   * Copyright (c) 2025-2026 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
13   * for project information <a href="https://djunits.org" target="_blank">https://djunits.org</a>. The DJUNITS project is
14   * distributed under a <a href="https://djunits.org/docs/license.html" target="_blank">three-clause BSD-style license</a>.
15   * @author Alexander Verbraeck
16   */
17  public class Direction extends AbsBasic<Direction, Angle, Reference>
18  {
19      /** */
20      private static final long serialVersionUID = 600L;
21  
22      /**
23       * Instantiate a Direction quantity with a unit and a reference point.
24       * @param valueInUnit the angle value, expressed in a angle unit
25       * @param unit the angle unit in which the value is expressed, relative to the reference point
26       * @param reference the reference point of this direction
27       */
28      public Direction(final double valueInUnit, final Angle.Unit unit, final Reference reference)
29      {
30          super(new Angle(valueInUnit, unit), reference);
31      }
32  
33      /**
34       * Instantiate a Direction instance based on an angle and a reference point.
35       * @param angle the angle, relative to the reference point
36       * @param reference the reference point of this direction
37       */
38      public Direction(final Angle angle, final Reference reference)
39      {
40          super(angle, reference);
41      }
42  
43      /**
44       * Return a Direction instance based on an SI value and a reference point.
45       * @param si the angle si value, relative to the reference point
46       * @param reference the reference point of this direction
47       * @return the Direction instance based on an SI value
48       */
49      public static Direction ofSi(final double si, final Reference reference)
50      {
51          return new Direction(si, Angle.Unit.SI, reference);
52      }
53  
54      @Override
55      public Direction instantiate(final Angle angle, final Reference reference)
56      {
57          return new Direction(angle, reference);
58      }
59  
60      /**
61       * Returns a Direction representation of a textual representation of a value with a unit. The String representation that can
62       * be parsed is the double value in the unit, followed by a localized or English abbreviation of the unit. Spaces are
63       * allowed, but not required, between the value and the unit.
64       * @param text the textual representation to parse into a Direction
65       * @param reference the reference point of this direction
66       * @return the Scalar representation of the value in its unit
67       * @throws IllegalArgumentException when the text cannot be parsed
68       * @throws NullPointerException when the text argument is null
69       */
70      public static Direction valueOf(final String text, final Reference reference)
71      {
72          return new Direction(Quantity.valueOf(text, Angle.ZERO), reference);
73      }
74  
75      /**
76       * Returns a Direction based on a value and the textual representation of the unit, which can be localized.
77       * @param valueInUnit the value, expressed in the unit as given by unitString
78       * @param unitString the textual representation of the unit
79       * @param reference the reference point of this direction
80       * @return the Scalar representation of the value in its unit
81       * @throws IllegalArgumentException when the unit cannot be parsed or is incorrect
82       * @throws NullPointerException when the unitString argument is null
83       */
84      public static Direction of(final double valueInUnit, final String unitString, final Reference reference)
85      {
86          return new Direction(Quantity.of(valueInUnit, unitString, Angle.ZERO), reference);
87      }
88  
89      @Override
90      public Angle subtract(final Direction other)
91      {
92          var otherRef = other.relativeTo(getReference());
93          return Angle.ofSi(si() - otherRef.si()).setDisplayUnit(getDisplayUnit());
94      }
95  
96      @Override
97      public Direction add(final Angle other)
98      {
99          return new Direction(Angle.ofSi(si() + other.si()).setDisplayUnit(getDisplayUnit()), getReference());
100     }
101 
102     @Override
103     public Direction subtract(final Angle other)
104     {
105         return new Direction(Angle.ofSi(si() - other.si()).setDisplayUnit(getDisplayUnit()), getReference());
106     }
107 
108     /**
109      * The reference class to define a reference point for the direction.
110      */
111     public static final class Reference extends AbstractReference<Reference, Direction, Angle>
112     {
113         /** East is zero. */
114         public static final Reference EAST = new Reference("EAST", "East = 0 degrees (counter-clockwise)", Angle.ZERO, null);
115 
116         /** North is zero. */
117         public static final Reference NORTH =
118                 new Reference("NORTH", "North = 0 degrees (counter-clockwise)", Angle.HALF_PI, EAST);
119 
120         /**
121          * Define a new reference point for the direction.
122          * @param id the id
123          * @param name the name or explanation
124          * @param offset the offset w.r.t. the offsetReference
125          * @param offsetReference the reference to which the offset is relative
126          */
127         public Reference(final String id, final String name, final Angle offset, final Reference offsetReference)
128         {
129             super(id, name, offset, offsetReference);
130         }
131 
132         /**
133          * Define a new reference point for the direction.
134          * @param id the id
135          * @param name the name or explanation
136          * @param offset the offset w.r.t. EAST
137          */
138         public Reference(final String id, final String name, final Angle offset)
139         {
140             this(id, name, offset, EAST);
141         }
142 
143         /**
144          * Define a new reference point for the direction.
145          * @param id the id
146          * @param name the name or explanation
147          * @param offset the offset w.r.t. offsetReference
148          * @param offsetReference the reference to which the offset is relative
149          */
150         public static void add(final String id, final String name, final Angle offset, final Reference offsetReference)
151         {
152             new Reference(id, name, offset, offsetReference);
153         }
154 
155         /**
156          * Define a new reference point for the direction.
157          * @param id the id
158          * @param name the name or explanation
159          * @param offset the offset w.r.t. EAST
160          */
161         public static void add(final String id, final String name, final Angle offset)
162         {
163             new Reference(id, name, offset);
164         }
165 
166         /**
167          * Get a reference point for the direction, based on its id. Return null when the id could not be found.
168          * @param id the id
169          * @return the DirectionReference object
170          */
171         public static Reference get(final String id)
172         {
173             return AbstractReference.get(Direction.Reference.class, id);
174         }
175 
176         @Override
177         public Direction instantiate(final Angle angle)
178         {
179             return new Direction(angle, this);
180         }
181     }
182 }