001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/csct/pt/Angle.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001 by:
006 EXSE, Department of Geography, University of Bonn
007 http://www.giub.uni-bonn.de/exse/
008 lat/lon GmbH
009 http://www.lat-lon.de
010
011 It has been implemented within SEAGIS - An OpenSource implementation of OpenGIS specification
012 (C) 2001, Institut de Recherche pour le D�veloppement (http://sourceforge.net/projects/seagis/)
013 SEAGIS Contacts: Surveillance de l'Environnement Assist�e par Satellite
014 Institut de Recherche pour le D�veloppement / US-Espace
015 mailto:seasnet@teledetection.fr
016
017
018 This library is free software; you can redistribute it and/or
019 modify it under the terms of the GNU Lesser General Public
020 License as published by the Free Software Foundation; either
021 version 2.1 of the License, or (at your option) any later version.
022
023 This library is distributed in the hope that it will be useful,
024 but WITHOUT ANY WARRANTY; without even the implied warranty of
025 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
026 Lesser General Public License for more details.
027
028 You should have received a copy of the GNU Lesser General Public
029 License along with this library; if not, write to the Free Software
030 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
031
032 Contact:
033
034 Andreas Poth
035 lat/lon GmbH
036 Aennchenstr. 19
037 53115 Bonn
038 Germany
039 E-Mail: poth@lat-lon.de
040
041 Klaus Greve
042 Department of Geography
043 University of Bonn
044 Meckenheimer Allee 166
045 53115 Bonn
046 Germany
047 E-Mail: klaus.greve@uni-bonn.de
048
049
050 ---------------------------------------------------------------------------*/
051 package org.deegree.model.csct.pt;
052
053 // Miscellaneous
054 import java.io.Serializable;
055 import java.lang.ref.Reference;
056 import java.lang.ref.SoftReference;
057 import java.text.Format;
058 import java.text.ParseException;
059 import java.util.Locale;
060
061 import org.deegree.model.csct.resources.ClassChanger;
062
063 /**
064 * An angle in degrees. An angle is the amount of rotation needed to bring one line or plane into
065 * coincidence with another, generally measured in degrees, sexagesimal degrees or grads.
066 *
067 * @version 1.0
068 * @author Martin Desruisseaux
069 *
070 * @see Latitude
071 * @see Longitude
072 * @see AngleFormat
073 */
074 public class Angle implements Comparable, Serializable {
075 /**
076 * Serial number for interoperability with different versions.
077 */
078 private static final long serialVersionUID = 1158747349433104534L;
079
080 /**
081 * A shared instance of {@link AngleFormat}.
082 */
083 private static Reference format;
084
085 /**
086 * Define how angle can be converted to {@link Number} objects.
087 */
088 static {
089 ClassChanger.register( new ClassChanger( Angle.class, Double.class ) {
090 protected Number convert( final Comparable o ) {
091 return new Double( ( (Angle) o ).theta );
092 }
093
094 protected Comparable inverseConvert( final Number value ) {
095 return new Angle( value.doubleValue() );
096 }
097 } );
098 }
099
100 /**
101 * Angle value in degres.
102 */
103 private final double theta;
104
105 /**
106 * Contruct a new angle with the specified value.
107 *
108 * @param theta
109 * Angle in degrees.
110 */
111 public Angle( final double theta ) {
112 this.theta = theta;
113 }
114
115 /**
116 * Constructs a newly allocated <code>Angle</code> object that represents the angle value
117 * represented by the string. The string should represents an angle in either fractional degrees
118 * (e.g. 45.5�) or degrees with minutes and seconds (e.g. 45�30').
119 *
120 * @param string
121 * A string to be converted to an <code>Angle</code>.
122 * @throws NumberFormatException
123 * if the string does not contain a parsable angle.
124 */
125 public Angle( final String string ) throws NumberFormatException {
126 try {
127 final Angle theta = (Angle) getAngleFormat().parseObject( string );
128 if ( getClass().isAssignableFrom( theta.getClass() ) ) {
129 this.theta = theta.theta;
130 } else
131 throw new NumberFormatException();
132 } catch ( ParseException exception ) {
133 NumberFormatException e = new NumberFormatException( exception.getLocalizedMessage() );
134 e.initCause( exception );
135 throw e;
136 }
137 }
138
139 /**
140 * Returns the angle value in degrees.
141 */
142 public double degrees() {
143 return theta;
144 }
145
146 /**
147 * Returns the angle value in radians.
148 */
149 public double radians() {
150 return Math.toRadians( theta );
151 }
152
153 /**
154 * Returns a hash code for this <code>Angle</code> object.
155 */
156 public int hashCode() {
157 final long code = Double.doubleToLongBits( theta );
158 return (int) code ^ (int) ( code >>> 32 );
159 }
160
161 /**
162 * Compares the specified object with this angle for equality.
163 */
164 public boolean equals( final Object that ) {
165 if ( that == this )
166 return true;
167 if ( that != null && getClass().equals( that.getClass() ) ) {
168 return Double.doubleToLongBits( theta ) == Double.doubleToLongBits( ( (Angle) that ).theta );
169 }
170 return false;
171 }
172
173 /**
174 * Compares two <code>Angle</code> objects numerically. The comparaison is done as if by the
175 * {@link Double#compare(double,double)} method.
176 */
177 public int compareTo( final Object that ) {
178 final double d1 = this.theta;
179 final double d2 = ( (Angle) that ).theta;
180 if ( d1 < d2 )
181 return -1;
182 if ( d1 > d2 )
183 return +1;
184 if ( d1 == d2 )
185 return 0;
186 final long bits1 = Double.doubleToLongBits( d1 );
187 final long bits2 = Double.doubleToLongBits( d2 );
188 if ( bits1 < bits2 )
189 return -1; // (-0.0, 0.0) or (!NaN, NaN)
190 if ( bits1 > bits2 )
191 return +1; // (0.0, -0.0) or (NaN, !NaN)
192 return 0;
193
194 }
195
196 /**
197 * Returns a string representation of this <code>Angle</code> object.
198 */
199 public String toString() {
200 return getAngleFormat().format( this, new StringBuffer(), null ).toString();
201 }
202
203 /**
204 * Returns a shared instance of {@link AngleFormat}. The return type is {@link Format} in order
205 * to avoid class loading before necessary.
206 */
207 private static synchronized Format getAngleFormat() {
208 if ( format != null ) {
209 final Format angleFormat = (Format) format.get();
210 if ( angleFormat != null )
211 return angleFormat;
212 }
213 final Format newFormat = new AngleFormat( "D�MM.m'", Locale.US );
214 format = new SoftReference<Format>( newFormat );
215 return newFormat;
216 }
217 }