001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/csct/cs/WGS84ConversionInfo.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.cs;
052    
053    // Miscellaneous
054    import java.io.Serializable;
055    
056    import org.deegree.model.csct.pt.Matrix;
057    import org.deegree.model.csct.resources.Utilities;
058    
059    /**
060     * Parameters for a geographic transformation into WGS84. The Bursa Wolf parameters should be
061     * applied to geocentric coordinates, where the X axis points towards the Greenwich Prime Meridian,
062     * the Y axis points East, and the Z axis points North.
063     * 
064     * @version 1.00
065     * @author OpenGIS (www.opengis.org)
066     * @author Martin Desruisseaux
067     * 
068     * @author last edited by: $Author: bezema $
069     * 
070     * @version $Revision: 6259 $, $Date: 2007-03-20 10:15:15 +0100 (Di, 20 Mär 2007) $
071     * 
072     * @see "org.opengis.cs.CS_WGS84ConversionInfo"
073     */
074    public class WGS84ConversionInfo implements Cloneable, Serializable {
075        /**
076         * Serial number for interoperability with different versions.
077         */
078        private static final long serialVersionUID = 3427461418504464735L;
079    
080        /** Bursa Wolf shift in meters. */
081        public double dx;
082    
083        /** Bursa Wolf shift in meters. */
084        public double dy;
085    
086        /** Bursa Wolf shift in meters. */
087        public double dz;
088    
089        /** Bursa Wolf rotation in arc seconds. */
090        public double ex;
091    
092        /** Bursa Wolf rotation in arc seconds. */
093        public double ey;
094    
095        /** Bursa Wolf rotation in arc seconds. */
096        public double ez;
097    
098        /** Bursa Wolf scaling in parts per million. */
099        public double ppm;
100    
101        /** Human readable text describing intended region of transformation. */
102        public String areaOfUse;
103    
104        /**
105         * Construct a conversion info with all parameters set to 0.
106         */
107        public WGS84ConversionInfo() {
108        }
109    
110        /**
111         * Returns an affine maps that can be used to define this Bursa Wolf transformation. The formula
112         * is as follows:
113         * 
114         * <blockquote>
115         * 
116         * <pre>
117         *  S = 1 + {@link #ppm}/1000000
118         * 
119         *  [ X ]    [     S   -{@link #ez}*S   +{@link #ey}*S   {@link #dx} ]  [ X ]
120         *  [ Y ]  = [ +{@link #ez}*S       S   -{@link #ex}*S   {@link #dy} ]  [ Y ]
121         *  [ Z ]    [ -{@link #ey}*S   +{@link #ex}*S       S   {@link #dz} ]  [ Z ]
122         *  [ 1  ]    [     0       0       0    1 ]  [ 1 ]
123         * </pre>
124         * 
125         * </blockquote>
126         * 
127         * This affine transform can be applied on <strong>geocentric</strong> coordinates.
128         * 
129         * @return an affine maps that can be used to define this Bursa Wolf transformation.
130         */
131        public Matrix getAffineTransform() {
132            // Note: (ex, ey, ez) is a rotation in arc seconds.
133            // We need to convert it into radians (the R
134            // factor in RS).
135            final double S = 1 + ppm / 1E+6;
136            final double RS = ( Math.PI / ( 180 * 3600 ) ) * S;
137            return new Matrix( 4, 4, new double[] { S, -ez * RS, +ey * RS, dx, +ez * RS, S, -ex * RS,
138                                                   dy, -ey * RS, +ex * RS, S, dz, 0, 0, 0, 1 } );
139        }
140    
141        /**
142         * Returns a hash value for this object. This value need not remain consistent between different
143         * implementations of the same class.
144         * 
145         * @return a hash value for this object. This value need not remain consistent between different
146         *         implementations of the same class.
147         */
148        public int hashCode() {
149            long code = 14698129;
150            code = code * 37 + Double.doubleToLongBits( dx );
151            code = code * 37 + Double.doubleToLongBits( dy );
152            code = code * 37 + Double.doubleToLongBits( dz );
153            code = code * 37 + Double.doubleToLongBits( ex );
154            code = code * 37 + Double.doubleToLongBits( ey );
155            code = code * 37 + Double.doubleToLongBits( ez );
156            code = code * 37 + Double.doubleToLongBits( ppm );
157            return (int) ( code >>> 32 ) ^ (int) code;
158        }
159    
160        /**
161         * Returns a copy of this object.
162         * 
163         * @return a copy of this object.
164         */
165        public Object clone() {
166            try {
167                return super.clone();
168            } catch ( CloneNotSupportedException exception ) {
169                // Should not happen, since we are cloneable.
170                final InternalError error = new InternalError( exception.getMessage() );
171                throw error;
172            }
173        }
174    
175        /**
176         * Compares the specified object with this object for equality.
177         * 
178         * @param object
179         * @return
180         */
181        public boolean equals( final Object object ) {
182            if ( object instanceof WGS84ConversionInfo ) {
183                final WGS84ConversionInfo that = (WGS84ConversionInfo) object;
184                return Double.doubleToLongBits( this.dx ) == Double.doubleToLongBits( that.dx )
185                       && Double.doubleToLongBits( this.dy ) == Double.doubleToLongBits( that.dy )
186                       && Double.doubleToLongBits( this.dz ) == Double.doubleToLongBits( that.dz )
187                       && Double.doubleToLongBits( this.ex ) == Double.doubleToLongBits( that.ex )
188                       && Double.doubleToLongBits( this.ey ) == Double.doubleToLongBits( that.ey )
189                       && Double.doubleToLongBits( this.ez ) == Double.doubleToLongBits( that.ez )
190                       && Double.doubleToLongBits( this.ppm ) == Double.doubleToLongBits( that.ppm )
191                       && Utilities.equals( this.areaOfUse, that.areaOfUse );
192            }
193            return false;
194        }
195    
196        /**
197         * Returns the Well Know Text (WKT) for this object. The WKT is part of OpenGIS's specification
198         * and looks like <code>TOWGS84[dx, dy, dz, ex, ey, ez, ppm]</code>.
199         * 
200         * @return the Well Know Text (WKT) for this object.
201         */
202        public String toString() {
203            final StringBuffer buffer = new StringBuffer( "TOWGS84[\"" );
204            buffer.append( areaOfUse );
205            buffer.append( "\", " );
206            buffer.append( dx );
207            buffer.append( ", " );
208            buffer.append( dy );
209            buffer.append( ", " );
210            buffer.append( dz );
211            buffer.append( ", " );
212            buffer.append( ex );
213            buffer.append( ", " );
214            buffer.append( ey );
215            buffer.append( ", " );
216            buffer.append( ez );
217            buffer.append( ", " );
218            buffer.append( ppm );
219            buffer.append( ']' );
220            return buffer.toString();
221        }
222    }