KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jscience > physics > quantities > Angle


1 /*
2  * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
3  * Copyright (C) 2005 - JScience (http://jscience.org/)
4  * All rights reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software is
7  * freely granted, provided that this notice is preserved.
8  */

9 package org.jscience.physics.quantities;
10
11 import javolution.lang.MathLib;
12 import org.jscience.physics.units.Unit;
13 import static org.jscience.physics.units.SI.*;
14
15 /**
16  * This class represents the figure formed by two lines diverging from a common
17  * point. The system unit for this quantity is "rad" (Système International
18  * d'Unités).
19  *
20  *
21  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
22  * @version 2.0, June 12, 2005
23  */

24 public class Angle extends Dimensionless {
25
26     /**
27      * Holds the acceleration unit.
28      */

29     private final static Unit<Angle> UNIT = RADIAN;
30
31     /**
32      * Holds the factory for this class.
33      */

34     private final static Factory<Angle> FACTORY = new Factory<Angle>(
35             UNIT) {
36         protected Angle create() {
37             return new Angle();
38         }
39     };
40
41     /**
42      * Represents a {@link Angle} amounting to nothing.
43      */

44     public final static Angle ZERO = Quantity.valueOf(0, UNIT);
45
46     /**
47      * Default constructor (allows for derivation).
48      */

49     protected Angle() {
50     }
51
52     /**
53      * Shows {@link Angle} instances in the specified unit.
54      *
55      * @param unit the display unit for {@link Angle} instances.
56      */

57     public static void showAs(Unit unit) {
58         QuantityFormat.show(Angle.class, unit);
59     }
60
61     ////////////////////
62
// ANGLE SPECIFIC //
63
////////////////////
64

65     /**
66      * Converts rectangular coordinates (<code>x</code>,&nbsp;<code>y</code>)
67      * to polar (&rho;,&nbsp;<i>&theta;</i>).
68      * This method computes the phase <i>&theta;</i> by computing an arc tangent
69      * of <code>y/x</code>.
70      *
71      * @param y y coordinate
72      * @param x x coordinate
73      * @return the <i>&theta;</i> component of the point
74      * (<i>&rho;</i>,&nbsp;<i>&theta;</i>) in polar coordinates that
75      * corresponds to the point(<i>x</i>,&nbsp;<i>y</i>) in Cartesian
76      * coordinates.
77      */

78     public static <Q extends Quantity> Angle atan2(Q y, Q x) {
79         if ((x.getMinimum() < 0.0) && (x.getMaximum() > 0.0) &&
80             (y.getMinimum() < 0.0) && (y.getMaximum() > 0.0)) {
81             // Encompasses (0,0), all angles are possible
82
return valueOf(0, MathLib.PI, RADIAN);
83         }
84         double a1 = MathLib.atan2(y.getMinimum(), x.getMinimum());
85         double a2 = MathLib.atan2(y.getMinimum(), x.getMaximum());
86         double a3 = MathLib.atan2(y.getMaximum(), x.getMinimum());
87         double a4 = MathLib.atan2(y.getMaximum(), x.getMaximum());
88         // Discontinuity at -Pi
89
if (x.getMaximum() <= 0.0) {
90             if (a1 < 0) {
91                 a1 += 2 * MathLib.PI;
92             }
93             if (a2 < 0) {
94                 a2 += 2 * MathLib.PI;
95             }
96             if (a3 < 0) {
97                 a3 += 2 * MathLib.PI;
98             }
99             if (a4 < 0) {
100                 a4 += 2 * MathLib.PI;
101             }
102         }
103         // Search for minimum
104
double min = a1;
105         if (a2 < min) {
106             min = a2;
107         }
108         if (a3 < min) {
109             min = a3;
110         }
111         if (a4 < min) {
112             min = a4;
113         }
114         // Search for maximum
115
double max = a1;
116         if (a2 > max) {
117             max = a2;
118         }
119         if (a3 > max) {
120             max = a3;
121         }
122         if (a4 > max) {
123             max = a4;
124         }
125         return Quantity.rangeOf(min, max, RADIAN);
126     }
127
128     /**
129      * Returns the trigonometric sine of this {@link Angle}.
130      *
131      * @return the sine of this angle.
132      */

133     public Dimensionless sine() {
134         return sine(this.getMinimum(), this.getMaximum());
135     }
136
137     /**
138      * Returns the trigonometric cosine of this {@link Angle}.
139      *
140      * @return the cosine of this angle.
141      */

142     public Dimensionless cos() {
143         return sine(this.getMinimum() + SQUARE_ANGLE,
144                 this.getMaximum() + SQUARE_ANGLE);
145     }
146     private static final double SQUARE_ANGLE = MathLib.PI / 2;
147
148     /**
149      * Returns the trigonometric tangent of this {@link Angle}.
150      *
151      * @return the tangent of this angle.
152      */

153     public Dimensionless tan() {
154         double minRadian = this.getMinimum();
155         double maxRadian = this.getMaximum();
156         // Bounds min to [-Pi/2, Pi/2]
157
double minBounded = MathLib.rem(minRadian, MathLib.PI);
158         // Measures distance to the next discontinuity
159
double nextDisc = MathLib.PI / 2 - minBounded;
160         // Test if this quantity passes across a discontinuity
161
if (minRadian + nextDisc < maxRadian) {
162             return Quantity.rangeOf(
163                 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Unit.ONE);
164         }
165         return Quantity.rangeOf(MathLib.tan(minRadian),
166                 MathLib.tan(maxRadian), Unit.ONE);
167     }
168
169     /**
170      * Returns the trigonometric sine for the specified minimum and maximum
171      * {@link Angle}.
172      *
173      * @param min the angle minimumm.
174      * @param max the angle maximumm.
175      * @return the sine quantity corresponding to the specified interval.
176      */

177     private Dimensionless sine(double min, double max) {
178         // Bounds min to [-Pi, Pi]
179
double minBounded = MathLib.rem(min, 2.0 * MathLib.PI);
180         double nextMax = MathLib.PI / 2 - minBounded;
181         if (nextMax < 0) {
182             nextMax += 2 * MathLib.PI;
183         }
184         double nextMin = -MathLib.PI / 2 - minBounded;
185         if (nextMin < 0) {
186             nextMin += 2 * MathLib.PI;
187         }
188         double sineMin = MathLib.sin(min);
189         double sineMax = MathLib.sin(max);
190         if (sineMin > sineMax) { // Swaps.
191
double tmp = sineMin;
192             sineMin = sineMax;
193             sineMax = tmp;
194         }
195         // Test if angle passes across a minima or a maxima
196
if (min + nextMax < max) {
197             sineMax = 1.0;
198         }
199         if (min + nextMin < max) {
200             sineMin = -1.0;
201         }
202         return Quantity.rangeOf(sineMin, sineMax, Unit.ONE);
203     }
204
205     private static final long serialVersionUID = 1L;
206
207 }
Popular Tags