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