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