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