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