package graphtea.library.util;
/**
handles angles in various units (degrees, grades, dms, radians, semicircles).
author hehl@tfh-berlin.de
version 17-May-2005
*/
public final class Angle {
/** global constant (2 * Pi) = 6.283185307179586... */
public static final double TWOPI = 2.*Math.PI;
/** global constant 'rho' in degrees */
public static final double RHODEG = 180. / Math.PI;
/** global constant 'rho' in grades */
public static final double RHOGON = 200. / Math.PI;
/** global constant 'rho' in 'semi circles' (Trimble) */
public static final double RHOSEMI = 1. / Math.PI;
/** unit 'radians' [-2pi..2pi] */
public static final int RAD = 0;
/** unit 'degrees' [-360..+360] */
public static final int DEG = 1;
/** unit 'grades' [-400..+400] */
public static final int GON = 2; // grades (german: gon)
/** unit 'grades' [-400..+400] */
public static final int GRA = 2; // grades
/** unit 'degrees minutes seconds' */
public static final int DMS = 3;
/** unit 'semicircles' [-2..+2] */
public static final int SEMI = 4;
/** private data */
private double _radians; // angle in radians
private int _unit; // defining unit on angle
/**
constructs an angle 0 rad
*/
public Angle() {
_radians = 0.0;
_unit = RAD;
}
/**
constructs an angle in default unit 'grades'.
@param x angle in grades
@exception Msg The message
*/
public Angle(double x) {
_radians = (x/RHOGON) % TWOPI;
_unit = GON;
}
/**
constructs an angle with given unit RAD, DEG, GON, etc.
@param x value of the angle
@param unit unit of: RAD, DEG, GON, DMS or SEMI
@exception Msg The message
*/
public Angle(double x, int unit) throws Msg {
String r = "Angle.constructor";
switch(unit) {
case RAD : _radians = x; break;
case DEG :
case DMS : _radians = x/RHODEG; break;
case GON : _radians = x/RHOGON; break;
case SEMI: _radians = x/RHOSEMI; break;
default: throw new Msg(r,"invalid angle unit "+unit);
}
_radians %= TWOPI;
_unit = unit;
}
/**
constructs an angle in (degrees, minutes, seconds) format
@param d degrees in [-359..359]
@param m minutes [0..59]
@param s seconds [0.0 to 59.999999999999]
@throws Msg
*/
public Angle(int d, int m, double s) throws Msg {
this((double)d + (double)m/60. + s/3600.0,DMS);
}
/**
* Returns value of current angle in radians
* @return value of current angle in radians
*/
public double rad() {
return _radians;
}
/**
* Returns value of current angle in degrees.
* @return value of current angle in degrees
*/
public double deg() {
return rad()*RHODEG;
}
/**
* Returns value of current angle in grades.
* @return value of current angle in grades
*/
public double gon() {
return rad()*RHOGON;
}
/**
* Returns value of current angle in grades.
* @return value of current angle in grades
*/
public double gra() {
return gon();
}
/**
/**
* Returns value of current angle in milligrades.
* @return value of current angle in milligrades
*/
public double mgon() {
return gon()*1000.0;
}
/**
* Returns value of current angle in seconds of arc.
* @return value of current angle in seconds of arc
*/
public double arcsec() {
return deg()*3600.0;
}
/**
* Returns value of current angle in semi-circles (Trimble).
* @return value of current angle in semi-circles
*/
public double semi() {
return rad()*RHOSEMI;
}
/**
* Computes the sine of the argument.
* @param x an angle
* @return sine of the argument
*/
public static double sin(Angle x) {
return Math.sin(x.rad());
}
/**
* Computes the cosine of the argument.
* @param x an angle
* @return cosine of the argument
*/
public static double cos(Angle x) {
return Math.cos(x.rad());
}
/**
* Computes the sine of current angle.
* @return sine of current angle
*/
public double sin() {
return Math.sin(this.rad());
}
/**
* Computes the cosine of current angle.
* @return cosine of current angle
*/
public double cos() {
return Math.cos(this.rad());
}
/**
* @return angle in degrees, minutes, and seconds in String respresentation
*/
public String toDMS() {
double x = deg();
boolean negative = (x < 0.0);
if(negative) x = -x;
int d = (int)x;
x = (x-d)*60.;
int m = (int)x;
double s = (x-m)*60.0;
String result = String.format("%3dd %02dm %012.9fs",d,m,s);
if(negative) result = "-"+result;
return result;
}
/**
* @return angle in same unit as in construction
*/
public String toString() {
String result;
switch(_unit) {
case RAD: result = "["+rad()+" rad]"; break;
case DEG: result = String.format("[%12.9f deg]",deg()); break;
case GON: result = "["+gon()+" gon]"; break;
case DMS: result = "["+toDMS()+"]"; break;
case SEMI:result = "["+semi()+" semi circles]"; break;
default : result = "[** invalid **]";
}
return result;
}
/**
adds the right hand side to current angle and returns their sum
@param rhs right hand side angle
@return sum of current and rhs angle
*/
public Angle add(Angle rhs) {
_radians += rhs.rad();
_radians %= TWOPI;
return this;
}
/** demonstrates functionality of class 'Angle' */
public static void demo() {
try {
System.out.println("*****************************");
System.out.println("*** Test of Class 'Angle' ***");
System.out.println("*****************************");
System.out.println();
Angle alpha = new Angle(Math.PI/2.,Angle.RAD); // in radians
Angle beta = new Angle(400.0,Angle.GON); // in grades
Angle gamma = new Angle(45.,Angle.DEG); // in degrees
Angle delta = new Angle(52,30,0.0); // in DMS
Angle eps = new Angle(100.); // in grades
System.out.println("alpha= "+alpha);
System.out.println("beta = "+beta);
System.out.println();
System.out.println("sin"+gamma+"= "+Math.sin(gamma.rad()));
System.out.println("sin"+gamma+"= "+gamma.sin());
System.out.println("sin"+gamma+"= "+Angle.sin(gamma));
System.out.println();
System.out.println("delta= "+delta);
System.out.println("eps = "+eps);
System.out.println("anonymous angle= "+new Angle(47.43,Angle.DEG));
}
catch(Exception ex) { }
}
} // end class Angle