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 }