/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/exse/
lat/lon GmbH
http://www.lat-lon.de
It has been implemented within SEAGIS - An OpenSource implementation of OpenGIS specification
(C) 2001, Institut de Recherche pour le D�veloppement (http://sourceforge.net/projects/seagis/)
SEAGIS Contacts: Surveillance de l'Environnement Assist�e par Satellite
Institut de Recherche pour le D�veloppement / US-Espace
mailto:seasnet@teledetection.fr
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53115 Bonn
Germany
E-Mail: poth@lat-lon.de
Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: klaus.greve@uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.model.csct.pt;
// Miscellaneous
import java.io.Serializable;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.text.Format;
import java.text.ParseException;
import java.util.Locale;
import org.deegree.model.csct.resources.ClassChanger;
/**
* An angle in degrees. An angle is the amount of rotation needed
* to bring one line or plane into coincidence with another,
* generally measured in degrees, sexagesimal degrees or grads.
*
* @version 1.0
* @author Martin Desruisseaux
*
* @see Latitude
* @see Longitude
* @see AngleFormat
*/
public class Angle implements Comparable, Serializable
{
/**
* Serial number for interoperability with different versions.
*/
private static final long serialVersionUID = 1158747349433104534L;
/**
* A shared instance of {@link AngleFormat}.
*/
private static Reference format;
/**
* Define how angle can be converted
* to {@link Number} objects.
*/
static
{
ClassChanger.register(new ClassChanger(Angle.class, Double.class)
{
protected Number convert(final Comparable o)
{return new Double(((Angle) o).theta);}
protected Comparable inverseConvert(final Number value)
{return new Angle(value.doubleValue());}
});
}
/**
* Angle value in degres.
*/
private final double theta;
/**
* Contruct a new angle with the specified value.
*
* @param theta Angle in degrees.
*/
public Angle(final double theta)
{this.theta=theta;}
/**
* Constructs a newly allocated <code>Angle</code> object that
* represents the angle value represented by the string. The
* string should represents an angle in either fractional degrees
* (e.g. 45.5�) or degrees with minutes and seconds (e.g. 45�30').
*
* @param string A string to be converted to an <code>Angle</code>.
* @throws NumberFormatException if the string does not contain a parsable angle.
*/
public Angle(final String string) throws NumberFormatException
{
try
{
final Angle theta = (Angle) getAngleFormat().parseObject(string);
if (getClass().isAssignableFrom(theta.getClass()))
{
this.theta = theta.theta;
}
else throw new NumberFormatException();
}
catch (ParseException exception) {
NumberFormatException e=new NumberFormatException(exception.getLocalizedMessage());
e.initCause(exception);
throw e;
}
}
/**
* Returns the angle value in degrees.
*/
public double degrees()
{return theta;}
/**
* Returns the angle value in radians.
*/
public double radians()
{return Math.toRadians(theta);}
/**
* Returns a hash code for this <code>Angle</code> object.
*/
public int hashCode()
{
final long code = Double.doubleToLongBits(theta);
return (int) code ^ (int) (code >>> 32);
}
/**
* Compares the specified object
* with this angle for equality.
*/
public boolean equals(final Object that)
{
if (that==this) return true;
if (that!=null && getClass().equals(that.getClass()))
{
return Double.doubleToLongBits(theta) == Double.doubleToLongBits(((Angle) that).theta);
}
return false;
}
/**
* Compares two <code>Angle</code> objects numerically. The comparaison
* is done as if by the {@link Double#compare(double,double)} method.
*/
public int compareTo(final Object that)
{
final double d1 = this.theta;
final double d2 = ((Angle)that).theta;
if (d1 < d2) return -1;
if (d1 > d2) return +1;
if (d1 == d2) return 0;
final long bits1 = Double.doubleToLongBits(d1);
final long bits2 = Double.doubleToLongBits(d2);
if (bits1 < bits2) return -1; // (-0.0, 0.0) or (!NaN, NaN)
if (bits1 > bits2) return +1; // (0.0, -0.0) or (NaN, !NaN)
return 0;
}
/**
* Returns a string representation of this <code>Angle</code> object.
*/
public String toString()
{return getAngleFormat().format(this, new StringBuffer(), null).toString();}
/**
* Returns a shared instance of {@link AngleFormat}.
* The return type is {@link Format} in order to
* avoid class loading before necessary.
*/
private static synchronized Format getAngleFormat()
{
if (format!=null)
{
final Format angleFormat = (Format) format.get();
if (angleFormat!=null) return angleFormat;
}
final Format newFormat = new AngleFormat("D�MM.m'", Locale.US);
format = new SoftReference(newFormat);
return newFormat;
}
}