View Javadoc
1   package org.opentrafficsim.core.math;
2   
3   import java.io.Serializable;
4   import java.util.Locale;
5   
6   import org.djunits.unit.AccelerationUnit;
7   import org.djunits.unit.DirectionUnit;
8   import org.djunits.value.ValueRuntimeException;
9   import org.djunits.value.storage.StorageType;
10  import org.djunits.value.vdouble.scalar.Acceleration;
11  import org.djunits.value.vdouble.scalar.Direction;
12  import org.djunits.value.vdouble.vector.AccelerationVector;
13  import org.djunits.value.vdouble.vector.base.DoubleVector;
14  
15  /**
16   * A 3D acceleration vector, decomposed in X, Y, and Z-acceleration with easy conversion from and to a spherical coordinate
17   * system. <br>
18   * <a href="https://en.wikipedia.org/wiki/Spherical_coordinate_system">Physicists and mathematicians <strong>do not</strong>
19   * agree on the meaning of theta and phi.</a> In this class the convention in the physics domain is used:
20   * <ul>
21   * <li>theta is the angle from the z direction.</li>
22   * <li>phi is the projected angle in the xy-plane from the x direction.</li>
23   * </ul>
24   * N.B. In the geography domain yet another convention is used. <br>
25   * <p>
26   * Copyright (c) 2013-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
27   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
28   * </p>
29   * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
30   * initial version Dec 10, 2015 <br>
31   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
32   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
33   */
34  public class Acceleration3D implements Serializable
35  {
36      /** */
37      private static final long serialVersionUID = 20150000L;
38  
39      /** The acceleration in 3D (XYZ coded). */
40      private final AccelerationVector acceleration;
41  
42      /**
43       * Construct a new Acceleration3D from vector of strongly typed Cartesian coordinates.
44       * @param acceleration AccelerationVector; the accelerations in 3D (YPR coded)
45       * @throws ValueRuntimeException in case the vector does not have exactly three elements
46       */
47      public Acceleration3D(final AccelerationVector acceleration) throws ValueRuntimeException
48      {
49          if (acceleration.size() != 3)
50          {
51              throw new ValueRuntimeException("Size of an RPY-acceleration vector should be exactly 3. Got: " + acceleration);
52          }
53          this.acceleration = acceleration;
54      }
55  
56      /**
57       * Construct a new Acceleration3D from three strongly typed Cartesian coordinates.
58       * @param x Acceleration; the acceleration in the x-direction
59       * @param y Acceleration; the acceleration in the y-direction
60       * @param z Acceleration; the acceleration in the z-direction
61       * @throws ValueRuntimeException in case the units are incorrect
62       */
63      public Acceleration3D(final Acceleration x, final Acceleration y, final Acceleration z) throws ValueRuntimeException
64      {
65          this.acceleration = DoubleVector.instantiate(new Acceleration[] {x, y, z}, AccelerationUnit.SI, StorageType.DENSE);
66      }
67  
68      /**
69       * Construct a new Acceleration3D from three double Cartesian coordinates and a acceleration unit.
70       * @param x double; the acceleration in the x-direction
71       * @param y double; the acceleration in the y-direction
72       * @param z double; the acceleration in the z-direction
73       * @param unit AccelerationUnit; the unit of the xyz parameters
74       * @throws ValueRuntimeException in case the units are incorrect
75       */
76      public Acceleration3D(final double x, final double y, final double z, final AccelerationUnit unit)
77              throws ValueRuntimeException
78      {
79          this.acceleration = DoubleVector.instantiate(new double[] {x, y, z}, unit, StorageType.DENSE);
80      }
81  
82      /**
83       * Construct a new Acceleration3D from a strongly typed acceleration and polar coordinates.
84       * @param acceleration Acceleration; the acceleration in the direction of the angle along the vector
85       * @param theta Direction; the angle from the z direction
86       * @param phi Direction; the projected angle in the xy-plane from the x direction
87       * @throws ValueRuntimeException in case the vector does not have exactly three elements
88       */
89      public Acceleration3D(final Acceleration acceleration, final Direction theta, final Direction phi)
90              throws ValueRuntimeException
91      {
92          double[] xyz = Scalar3D.polarToCartesian(acceleration.getInUnit(), theta.si, phi.si);
93          this.acceleration = DoubleVector.instantiate(xyz, acceleration.getDisplayUnit(), StorageType.DENSE);
94      }
95  
96      /**
97       * Retrieve the x-component of this Acceleration3D.
98       * @return the acceleration in the x-direction.
99       */
100     public final Acceleration getX()
101     {
102         try
103         {
104             return this.acceleration.get(0);
105         }
106         catch (ValueRuntimeException exception)
107         {
108             // should be impossible as we constructed the vector always with three elements
109             throw new RuntimeException(
110                     "getX() gave an exception; apparently vector " + this.acceleration + " was not constructed right",
111                     exception);
112         }
113     }
114 
115     /**
116      * Retrieve the y-component of this Acceleration3D.
117      * @return the acceleration in the y-direction.
118      */
119     public final Acceleration getY()
120     {
121         try
122         {
123             return this.acceleration.get(1);
124         }
125         catch (ValueRuntimeException exception)
126         {
127             // should be impossible as we constructed the vector always with three elements
128             throw new RuntimeException(
129                     "getY() gave an exception; apparently vector " + this.acceleration + " was not constructed right",
130                     exception);
131         }
132     }
133 
134     /**
135      * Retrieve the z-component of this Acceleration3D.
136      * @return the acceleration in the z-direction.
137      */
138     public final Acceleration getZ()
139     {
140         try
141         {
142             return this.acceleration.get(2);
143         }
144         catch (ValueRuntimeException exception)
145         {
146             // should be impossible as we constructed the vector always with three elements
147             throw new RuntimeException(
148                     "getZ() gave an exception; apparently vector " + this.acceleration + " was not constructed right",
149                     exception);
150         }
151     }
152 
153     /**
154      * Retrieve the theta of this Acceleration3D.
155      * @return the angle of direction perpendicular to the xy-plane
156      */
157     public final Direction getTheta()
158     {
159         return Scalar3D.cartesianToTheta(getX().si, getY().si, getZ().si);
160     }
161 
162     /**
163      * Retrieve the phi of this Acceleration3D.
164      * @return the projected angle of direction in the xy-plane
165      */
166     public final Direction getPhi()
167     {
168         return Scalar3D.cartesianToPhi(getX().si, getY().si);
169     }
170 
171     /**
172      * Retrieve the norm of this Acceleration3D.
173      * @return the combined acceleration in the direction of the angle
174      */
175     public final Acceleration getAcceleration()
176     {
177         return new Acceleration(Scalar3D.cartesianToRadius(getX().si, getY().si, getZ().si), AccelerationUnit.SI);
178     }
179 
180     /** {@inheritDoc} */
181     @Override
182     public final String toString()
183     {
184         return String.format(Locale.US, "Acceleration3D %s (%s, theta %s, phi %s)", this.acceleration, getAcceleration(),
185                 new Direction(getTheta().getInUnit(DirectionUnit.EAST_DEGREE), DirectionUnit.EAST_DEGREE),
186                 new Direction(getPhi().getInUnit(DirectionUnit.EAST_DEGREE), DirectionUnit.EAST_DEGREE));
187     }
188 
189 }