Worldwind public release 0.2
[worldwind-tracker.git] / gov / nasa / worldwind / geom / Angle.java
bloba6690fb0bfb93ee55c1c9d92c66e8208c1453537
1 /*
2 Copyright (C) 2001, 2006 United States Government
3 as represented by the Administrator of the
4 National Aeronautics and Space Administration.
5 All Rights Reserved.
6 */
7 package gov.nasa.worldwind.geom;
9 import gov.nasa.worldwind.*;
11 /**
12 * Represents a geometric angle. Instances of <code>Angle</code> are immutable. An <code>Angle</code> can be obtained
13 * through the factory methods <code>fromDegrees</code> and <code>fromRadians</code>.
15 * @author Tom Gaskins
16 * @version $Id: Angle.java 1645 2007-04-27 00:16:09Z tgaskins $
18 public class Angle implements Comparable<Angle>
20 /**
21 * Represents an angle of zero degrees
23 public final static Angle ZERO = Angle.fromDegrees(0);
25 /**
26 * Represents a right angle of positive 90 degrees
28 public final static Angle POS90 = Angle.fromDegrees(90);
30 /**
31 * Represents a right angle of negative 90 degrees
33 public final static Angle NEG90 = Angle.fromDegrees(-90);
35 /**
36 * Represents an angle of positive 180 degrees
38 public final static Angle POS180 = Angle.fromDegrees(180);
40 /**
41 * Represents an angle of negative 180 degrees
43 public final static Angle NEG180 = Angle.fromDegrees(-180);
45 /**
46 * Represents an angle of positive 360 degrees
48 public final static Angle POS360 = Angle.fromDegrees(360);
50 private final static double DEGREES_TO_RADIANS = Math.PI / 180d;
51 private final static double RADIANS_TO_DEGREES = 180d / Math.PI;
53 /**
54 * Obtains an <code>Angle</code> from a specified number of degrees.
56 * @param degrees the size in degrees of the <code>Angle</code> to be obtained
57 * @return a new <code>Angle</code>, whose size in degrees is given by <code>degrees</code>
59 public static Angle fromDegrees(double degrees)
61 return new Angle(degrees, DEGREES_TO_RADIANS * degrees);
64 /**
65 * Obtains an <code>Angle</code> from a specified number of radians.
67 * @param radians the size in radians of the <code>Angle</code> to be obtained
68 * @return a new <code>Angle</code>, whose size in radians is given by <code>radians</code>
70 public static Angle fromRadians(double radians)
72 return new Angle(RADIANS_TO_DEGREES * radians, radians);
75 private static final double PIOver2 = Math.PI / 2;
77 public static Angle fromDegreesLatitude(double degrees)
79 degrees = degrees < -90 ? -90 : degrees > 90 ? 90 : degrees;
80 double radians = DEGREES_TO_RADIANS * degrees;
81 radians = radians < -PIOver2 ? -PIOver2 : radians > PIOver2 ? PIOver2 : radians;
83 return new Angle(degrees, radians);
86 public static Angle fromRadiansLatitude(double radians)
88 radians = radians < -PIOver2 ? -PIOver2 : radians > PIOver2 ? PIOver2 : radians;
89 double degrees = RADIANS_TO_DEGREES * radians;
90 degrees = degrees < -90 ? -90 : degrees > 90 ? 90 : degrees;
92 return new Angle(degrees, radians);
95 public static Angle fromDegreesLongitude(double degrees)
97 degrees = degrees < -180 ? -180 : degrees > 180 ? 180 : degrees;
98 double radians = DEGREES_TO_RADIANS * degrees;
99 radians = radians < -Math.PI ? -Math.PI : radians > Math.PI ? Math.PI : radians;
101 return new Angle(degrees, radians);
104 public static Angle fromRadiansLongitude(double radians)
106 radians = radians < -Math.PI ? -Math.PI : radians > Math.PI ? Math.PI : radians;
107 double degrees = RADIANS_TO_DEGREES * radians;
108 degrees = degrees < -180 ? -180 : degrees > 180 ? 180 : degrees;
110 return new Angle(degrees, radians);
114 * Obtains an <code>Angle</code> from rectangular coordinates.
116 * @param x the abscissa coordinate
117 * @param y the ordinate coordinate
118 * @return a new <code>Angle</code>, whose size is determined from <code>x</code> and <code>y</code>
120 public static Angle fromXY(double x, double y)
122 double radians = Math.atan2(y, x);
123 return new Angle(RADIANS_TO_DEGREES * radians, radians);
126 public final double degrees;
127 public final double radians;
129 public Angle(Angle angle)
131 this.degrees = angle.degrees;
132 this.radians = angle.radians;
135 // private Angle(double degrees)
136 // {
137 // this.degrees = degrees;
138 // this.radians = DEGREES_TO_RADIANS * this.degrees;
139 // }
141 private Angle(double degrees, double radians)
143 this.degrees = degrees;
144 this.radians = radians;
148 * Retrieves the size of this <code>Angle</code> in degrees. This method may be faster than first obtaining the
149 * radians and then converting to degrees.
151 * @return the size of this <code>Angle</code> in degrees
153 public final double getDegrees()
155 return this.degrees;
159 * Retrieves the size of this <code>Angle</code> in radians. This may be useful for <code>java.lang.Math</code>
160 * functions, which generally take radians as trigonometric arguments. This method may be faster that first
161 * obtaining the degrees and then converting to radians.
163 * @return the size of this <code>Angle</code> in radians.
165 public final double getRadians()
167 return this.radians;
171 * Obtains the sum of these two <code>Angle</code>s. Does not accept a null argument. This method is commutative, so
172 * <code>a.add(b)</code> and <code>b.add(a)</code> are equivalent. Neither this <code>Angle</code> nor
173 * <code>angle</code> is changed, instead the result is returned as a new <code>Angle</code>.
175 * @param angle the <code>Angle</code> to add to this one.
176 * @return an <code>Angle</code> whose size is the total of this <code>Angle</code>s and <code>angle</code>s size
177 * @throws IllegalArgumentException if <code>angle</code> is null
179 public final Angle add(Angle angle)
181 if (angle == null)
183 String message = WorldWind.retrieveErrMsg("nullValue.AngleIsNull");
184 WorldWind.logger().log(java.util.logging.Level.FINE, message);
185 throw new IllegalArgumentException(message);
188 return Angle.fromDegrees(this.degrees + angle.degrees);
192 * Obtains the difference of these two <code>Angle</code>s. Does not accept a null argument. This method is not
193 * commutative. Neither this <code>Angle</code> nor <code>angle</code> is changed, instead the result is returned as
194 * a new <code>Angle</code>.
196 * @param angle the <code>Angle</code> to subtract from this <code>Angle</code>
197 * @return a new <code>Angle</code> correpsonding to this <code>Angle</code>'s size minus <code>angle</code>'s size
198 * @throws IllegalArgumentException if <code>angle</code> is null
200 public final Angle subtract(Angle angle)
202 if (angle == null)
204 String message = WorldWind.retrieveErrMsg("nullValue.AngleIsNull");
205 WorldWind.logger().log(java.util.logging.Level.FINE, message);
206 throw new IllegalArgumentException(message);
209 return Angle.fromDegrees(this.degrees - angle.degrees);
213 * Multiplies this <code>Angle</code> by <code>multiplier</code>. This <code>Angle</code> remains unchanged. The
214 * result is returned as a new <code>Angle</code>.
216 * @param multiplier a scalar by which this <code>Angle</code> is multiplied
217 * @return a new <code>Angle</code> whose size equals this <code>Angle</code>'s size multiplied by
218 * <code>multiplier</code>
220 public final Angle multiply(double multiplier)
222 return Angle.fromDegrees(this.degrees * multiplier);
226 * Divides this <code>Angle</code> by another angle. This <code>Angle</code> remains unchanged, instead the
227 * resulting value in degrees is returned.
229 * @param angle the <code>Angle</code> by which to divide
230 * @return this <code>Angle</code>'s degrees divided by <code>angle</code>'s degrees
231 * @throws IllegalArgumentException if <code>angle</code> is null
233 public final double divide(Angle angle)
235 if (angle == null)
237 String message = WorldWind.retrieveErrMsg("nullValue.AngleIsNull");
238 WorldWind.logger().log(java.util.logging.Level.FINE, message);
239 throw new IllegalArgumentException(message);
242 return this.degrees / angle.degrees;
245 public final Angle addDegrees(double degrees)
246 { //Tom: this method is not used, should we delete it? (13th Dec 06)
247 return Angle.fromDegrees(this.degrees + degrees);
250 public final Angle subtractDegrees(double degrees)
251 { //Tom: this method is not used, should we delete it? (13th Dec 06)
252 return Angle.fromDegrees(this.degrees - degrees);
256 * Divides this <code>Angle</code> by <code>divisor</code>. This <code>Angle</code> remains unchanged. The result is
257 * returned as a new <code>Angle</code>. Behaviour is undefined if <code>divisor</code> equals zero.
259 * @param divisor the number to be divided by
260 * @return a new <code>Angle</code> equivalent to this <code>Angle</code> divided by <code>divisor</code>
262 public final Angle divide(double divisor)
264 return Angle.fromDegrees(this.degrees / divisor);
267 public final Angle addRadians(double radians)
269 return Angle.fromRadians(this.radians + radians);
272 public final Angle subtractRadians(double radians)
274 return Angle.fromRadians(this.radians - radians);
278 * Obtains the sine of this <code>Angle</code>.
280 * @return the trigonometric sine of this <code>Angle</code>
282 public final double sin()
284 return Math.sin(this.radians);
287 public final double sinHalfAngle()
288 { //Tom: this method is not used, should we delete it? (13th Dec 06)
289 return Math.sin(0.5 * this.radians);
292 public static Angle asin(double sine)
293 { //Tom: this method is not used, should we delete it? (13th Dec 06)
294 return Angle.fromRadians(Math.asin(sine));
298 * Obtains the cosine of this <code>Angle</code>
300 * @return the trigonometric cosine of this <code>Angle</code>
302 public final double cos()
304 return Math.cos(this.radians);
307 public final double cosHalfAngle()
308 { //Tom: this method is not used, should we delete it? (13th Dec 06)
309 return Math.cos(0.5 * this.radians);
312 public static Angle acos(double cosine)
313 { //Tom: this method is not used, should we delete it? (13th Dec 06)
314 return Angle.fromRadians(Math.acos(cosine));
318 * Obtains the tangent of half of this <code>Angle</code>.
320 * @return the trigonometric tangent of half of this <code>Angle</code>
322 public final double tanHalfAngle()
324 return Math.tan(0.5 * this.radians);
327 public static Angle atan(double tan)
328 { //Tom: this method is not used, should we delete it? (13th Dec 06)
329 return Angle.fromRadians(Math.atan(tan));
333 * Obtains the average of two <code>Angle</code>s. This method is commutative, so <code>midAngle(m, n)</code> and
334 * <code>midAngle(n, m)</code> are equivalent.
336 * @param a1 the first <code>Angle</code>
337 * @param a2 the second <code>Angle</code>
338 * @return the average of <code>a1</code> and <code>a2</code> throws IllegalArgumentException if either angle is
339 * null
341 public static Angle midAngle(Angle a1, Angle a2)
343 if (a1 == null || a2 == null)
345 String message = WorldWind.retrieveErrMsg("nullValue.AngleIsNull");
346 WorldWind.logger().log(java.util.logging.Level.FINE, message);
347 throw new IllegalArgumentException(message);
350 return Angle.fromDegrees(0.5 * (a1.degrees + a2.degrees));
354 * Obtains the average of three <code>Angle</code>s. The order of parameters does not matter.
356 * @param a the first <code>Angle</code>
357 * @param b the second <code>Angle</code>
358 * @return the average of <code>a1</code>, <code>a2</code> and <code>a3</code>
359 * @throws IllegalArgumentException if <code>a</code> or <code>b</code> is null
361 public static Angle average(Angle a, Angle b)
363 if (a == null || b == null)
365 String message = WorldWind.retrieveErrMsg("nullValue.AngleIsNull");
366 WorldWind.logger().log(java.util.logging.Level.FINE, message);
367 throw new IllegalArgumentException(message);
370 return Angle.fromDegrees(0.5 * (a.degrees + b.degrees));
374 * Obtains the average of three <code>Angle</code>s. The order of parameters does not matter.
376 * @param a the first <code>Angle</code>
377 * @param b the second <code>Angle</code>
378 * @param c the third <code>Angle</code>
379 * @return the average of <code>a1</code>, <code>a2</code> and <code>a3</code>
380 * @throws IllegalArgumentException if <code>a</code>, <code>b</code> or <code>c</code> is null
382 public static Angle average(Angle a, Angle b, Angle c)
384 if (a == null || b == null || c == null)
386 String message = WorldWind.retrieveErrMsg("nullValue.AngleIsNull");
387 WorldWind.logger().log(java.util.logging.Level.FINE, message);
388 throw new IllegalArgumentException(message);
391 return Angle.fromDegrees((a.degrees + b.degrees + c.degrees) / 3);
395 * Compares this <code>Angle</code> with <code>angle</code> for order. Returns a negative integer if this is the
396 * smaller <code>Angle</code>, a positive integer if this is the larger, and zero if both <code>Angle</code>s are
397 * equal.
399 * @param angle the <code>Angle</code> to compare against
400 * @return -1 if this <code>Angle</code> is smaller, 0 if both are equal and +1 if this <code>Angle</code> is
401 * larger.
402 * @throws IllegalArgumentException if <code>angle</code> is null
404 public final int compareTo(Angle angle)
406 if (angle == null)
408 String msg = WorldWind.retrieveErrMsg("nullValue.AngleIsNull");
409 WorldWind.logger().log(java.util.logging.Level.FINE, msg);
410 throw new IllegalArgumentException(msg);
413 if (this.degrees < angle.degrees)
414 return -1;
416 if (this.degrees > angle.degrees)
417 return 1;
419 return 0;
423 * Obtains a <code>String</code> representation of this <code>Angle</code>.
425 * @return the value of this <code>Angle</code> in degrees and as a <code>String</code>
427 @Override
428 public final String toString()
430 return Double.toString(this.degrees) + '\u00B0';
434 * Obtains the amount of memory this <code>Angle</code> consumes.
436 * @return the memory footprint of this <code>Angle</code> in bytes.
438 public long getSizeInBytes()
440 return Double.SIZE;
443 public boolean equals(Object o)
445 if (this == o)
446 return true;
447 if (o == null || getClass() != o.getClass())
448 return false;
450 Angle angle = (Angle) o;
452 if (angle.degrees!= this.degrees)
453 return false;
455 return true;
458 public int hashCode()
460 long temp = degrees != +0.0d ? Double.doubleToLongBits(degrees) : 0L;
461 return (int) (temp ^ (temp >>> 32));