001    //$HeadURL: $
002    /*----------------    FILE HEADER  ------------------------------------------
003     This file is part of deegree.
004     Copyright (C) 2001-2008 by:
005     Department of Geography, University of Bonn
006     http://www.giub.uni-bonn.de/deegree/
007     lat/lon GmbH
008     http://www.lat-lon.de
009    
010     This library is free software; you can redistribute it and/or
011     modify it under the terms of the GNU Lesser General Public
012     License as published by the Free Software Foundation; either
013     version 2.1 of the License, or (at your option) any later version.
014     This library is distributed in the hope that it will be useful,
015     but WITHOUT ANY WARRANTY; without even the implied warranty of
016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     Lesser General Public License for more details.
018     You should have received a copy of the GNU Lesser General Public
019     License along with this library; if not, write to the Free Software
020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021     Contact:
022    
023     Andreas Poth
024     lat/lon GmbH
025     Aennchenstr. 19
026     53177 Bonn
027     Germany
028     E-Mail: poth@lat-lon.de
029    
030     Prof. Dr. Klaus Greve
031     Department of Geography
032     University of Bonn
033     Meckenheimer Allee 166
034     53115 Bonn
035     Germany
036     E-Mail: greve@giub.uni-bonn.de
037     ---------------------------------------------------------------------------*/
038    
039    package org.deegree.crs.components;
040    
041    import org.deegree.crs.transformations.WGS84ConversionInfo;
042    
043    /**
044     * A <code>GeodeticDatum</code> (aka. HorizontalDatum) holds an ellipse and a prime-meridian.
045     * 
046     * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
047     * 
048     * @author last edited by: $Author:$
049     * 
050     * @version $Revision:$, $Date:$
051     * 
052     */
053    
054    public class GeodeticDatum extends Datum {
055    
056        /**
057         * The default WGS 1984 datum, with primeMeridian set to Greenwich and default (no) wgs84 conversion info.
058         */
059        public static final GeodeticDatum WGS84 = new GeodeticDatum( Ellipsoid.WGS84, new WGS84ConversionInfo("-1"), "EPSG:6326", "WGS_1984" );
060    
061        private PrimeMeridian primeMeridian;
062    
063        private Ellipsoid ellipsoid;
064    
065        private WGS84ConversionInfo toWGS84;
066        
067        /**
068         * @param ellipsoid
069         *            of this datum
070         * @param primeMeridian
071         *            to which this datum is defined.
072         * @param toWGS84
073         *            bursa-wolf parameters describing the transform from this datum into the wgs84 datum.
074         * @param identifiers
075         * @param names
076         * @param versions
077         * @param descriptions
078         * @param areasOfUse
079         */
080        public GeodeticDatum( Ellipsoid ellipsoid, PrimeMeridian primeMeridian, WGS84ConversionInfo toWGS84,
081                              String[] identifiers, String[] names, String[] versions, String[] descriptions, String[] areasOfUse ) {
082            super( identifiers, names, versions, descriptions, areasOfUse );
083            this.ellipsoid = ellipsoid;
084            this.primeMeridian = primeMeridian;
085            this.toWGS84 = toWGS84;
086        }
087        
088        /**
089         * A datum with given ellipsoid and a GreenWich prime-meridian.
090         * 
091         * @param ellipsoid
092         *            of this datum
093         * @param toWGS84
094         *            bursa-wolf parameters describing the transform from this datum into the wgs84 datum.
095         * @param identifiers
096         */
097        public GeodeticDatum( Ellipsoid ellipsoid, WGS84ConversionInfo toWGS84, String[] identifiers ) {
098            this( ellipsoid, PrimeMeridian.GREENWICH, toWGS84, identifiers, null, null, null,null );
099        }
100        
101        /**
102         * A datum with given ellipsoid and a prime-meridian.
103         * 
104         * @param ellipsoid
105         *            of this datum
106         * @param primeMeridian 
107         *            to which this datum is defined.
108         * @param toWGS84
109         *            bursa-wolf parameters describing the transform from this datum into the wgs84 datum.
110         * @param identifiers
111         */
112        public GeodeticDatum( Ellipsoid ellipsoid, PrimeMeridian primeMeridian, WGS84ConversionInfo toWGS84, String[] identifiers ) {
113            this( ellipsoid, primeMeridian, toWGS84, identifiers, null, null, null,null );
114        }
115    
116        /**
117         * @param ellipsoid
118         *            of this datum
119         * @param primeMeridian
120         *            to which this datum is defined.
121         * @param toWGS84
122         *            bursa-wolf parameters describing the transform from this datum into the wgs84 datum.
123         * @param identifier
124         * @param name
125         * @param version
126         * @param description
127         * @param areaOfUse
128         */
129        public GeodeticDatum( Ellipsoid ellipsoid, PrimeMeridian primeMeridian, WGS84ConversionInfo toWGS84,
130                              String identifier, String name, String version, String description, String areaOfUse ) {
131            this( ellipsoid, primeMeridian, toWGS84, new String[]{identifier}, new String[]{name}, new String[]{version}, new String[]{description}, new String[]{areaOfUse} );
132        }
133    
134        /**
135         * A datum with given ellipsoid and a GreenWich prime-meridian.
136         * 
137         * @param ellipsoid
138         *            of this datum
139         * @param toWGS84
140         *            bursa-wolf parameters describing the transform from this datum into the wgs84 datum.
141         * @param identifier
142         * @param name
143         */
144        public GeodeticDatum( Ellipsoid ellipsoid, WGS84ConversionInfo toWGS84, String identifier, String name ) {
145            this( ellipsoid, PrimeMeridian.GREENWICH, toWGS84, new String[]{identifier}, new String[]{name}, null, null,null );
146        }
147    
148        /**
149         * @return the ellipsoid.
150         */
151        public final Ellipsoid getEllipsoid() {
152            return ellipsoid;
153        }
154    
155        /**
156         * @return the primeMeridian.
157         */
158        public final PrimeMeridian getPrimeMeridian() {
159            return primeMeridian;
160        }
161    
162        /**
163         * @return the toWGS84Conversion information needed to convert this geodetic Datum into the geocentric WGS84 Datum.
164         */
165        public final WGS84ConversionInfo getWGS84Conversion() {
166            return toWGS84;
167        }
168        
169        @Override
170        public boolean equals( Object other ) {
171            if ( other != null && other instanceof GeodeticDatum ) {
172                GeodeticDatum that = (GeodeticDatum) other;
173                return this.getPrimeMeridian().equals( that.getPrimeMeridian() ) && this.getEllipsoid().equals( that.getEllipsoid() ) && this.getWGS84Conversion().equals( that.getWGS84Conversion() );
174            }
175            return false;
176        }
177        
178        /* (non-Javadoc)
179         * @see org.deegree.crs.Identifiable#toString()
180         */
181        @Override
182        public String toString() {
183            StringBuilder sb = new StringBuilder( super.toString() );
184            sb.append( "\n - Ellipsoid: " ).append( ellipsoid );
185            sb.append( "\n - Primemeridian: " ).append( primeMeridian );
186            sb.append( "\n - wgs84-conversion-info: " ).append( toWGS84 );
187            return sb.toString();
188        }
189        
190        /**
191         * Implementation as proposed by Joshua Block in Effective Java (Addison-Wesley 2001), which supplies an even
192         * distribution and is relatively fast. It is created from field <b>f</b> as follows:
193         * <ul>
194         * <li>boolean -- code = (f ? 0 : 1)</li>
195         * <li>byte, char, short, int -- code = (int)f </li>
196         * <li>long -- code = (int)(f ^ (f &gt;&gt;&gt;32))</li>
197         * <li>float -- code = Float.floatToIntBits(f);</li>
198         * <li>double -- long l = Double.doubleToLongBits(f); code = (int)(l ^ (l &gt;&gt;&gt; 32))</li>
199         * <li>all Objects, (where equals(&nbsp;) calls equals(&nbsp;) for this field) -- code = f.hashCode(&nbsp;)</li>
200         * <li>Array -- Apply above rules to each element</li>
201         * </ul>
202         * <p>
203         * Combining the hash code(s) computed above: result = 37 * result + code;
204         * </p>
205         * 
206         * @return (int) ( result >>> 32 ) ^ (int) result;
207         * 
208         * @see java.lang.Object#hashCode()
209         */
210        @Override
211        public int hashCode() {
212            // the 2.nd million th. prime, :-)
213            long code = 32452843;
214            if( primeMeridian != null ){
215                code = code * 37 + primeMeridian.hashCode();
216            }
217            if( ellipsoid != null ){
218                code = code * 37 + ellipsoid.hashCode();
219            }   
220            if( toWGS84 != null ){
221                code = code * 37 + toWGS84.hashCode();
222            }
223            return (int) ( code >>> 32 ) ^ (int) code;
224        }
225    
226    }