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.Identifiable;
042    import org.deegree.crs.projections.ProjectionUtils;
043    
044    /**
045     * The <code>PrimeMeridian</code> class saves the longitude to the greenwich meridian.
046     * 
047     * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
048     * 
049     * @author last edited by: $Author:$
050     * 
051     * @version $Revision:$, $Date:$
052     * 
053     */
054    
055    public class PrimeMeridian extends Identifiable {
056    
057        private double longitude;
058    
059        private Unit units;
060    
061        /**
062         * The PrimeMeridian of greenwich with epsg:8901 code and radian units.
063         */
064        public static final PrimeMeridian GREENWICH = new PrimeMeridian( Unit.RADIAN, 0, new String[]{"EPSG:8901", "http://www.opengis.net/gml/srs/epsg.xml#8901","URN:OPENGIS:DEF:CRS:EPSG::8901", "URN:OGC:DEF:CRS:EPSG::"}, new String[]{"Greenwich"}, new String[]{"1995-06-02"}, null, null );
065    
066        /**
067         * @param units
068         *            Angular units of longitude, normally radians.
069         * @param longitude (in given units) normally radians.
070         * @param identifiers
071         * @param names
072         * @param versions
073         * @param descriptions
074         * @param areasOfUse
075         */
076        public PrimeMeridian( Unit units, double longitude, String[] identifiers, String[] names, String[] versions,
077                              String[] descriptions, String[] areasOfUse ) {
078            super( identifiers, names, versions, descriptions, areasOfUse );
079            this.units = units;
080            this.longitude = longitude;
081        }
082    
083        /**
084         * @param units
085         *            Angular units of longitude.
086         * @param longitude
087         * @param identifier
088         * @param name
089         * @param version
090         * @param description
091         * @param areaOfUse
092         */
093        public PrimeMeridian( Unit units, double longitude, String identifier, String name, String version,
094                              String description, String areaOfUse ) {
095            this( units,
096                  longitude,
097                  new String[] { identifier },
098                  new String[] { name },
099                  new String[] { version },
100                  new String[] { description },
101                  new String[] { areaOfUse } );
102        }
103        
104        /**
105         * @param units
106         *            Angular units of longitude.
107         * @param longitude
108         * @param identifiers
109         */
110        public PrimeMeridian( Unit units, double longitude, String[] identifiers ) {
111            this( units, longitude, identifiers, null,null,null,null );
112        }
113    
114        /**
115         * @param units
116         *            Angular units of longitude.
117         * @param longitude
118         * @param identifier
119         */
120        public PrimeMeridian( Unit units, double longitude, String identifier ) {
121            this( units, longitude, new String[]{identifier} );
122        }
123        
124        /**
125         * A Prime meredian with 0 degrees longitude from the greenwich meridian.
126         * 
127         * @param units
128         *            Angular units of longitude.
129         * @param identifiers
130         */
131        public PrimeMeridian( Unit units, String[] identifiers ) {
132            this( units, 0, identifiers );
133        }
134    
135        /**
136         * A Prime meredian with 0 degrees longitude from the greenwich meridian.
137         * 
138         * @param units
139         *            Angular units of longitude.
140         * @param identifier
141         * @param name human readable name
142         */
143        public PrimeMeridian( Unit units, String identifier, String name ) {
144            this( units, 0, new String[]{identifier}, new String[]{name}, null,null,null );
145        }
146    
147        /**
148         * @return the longitude value relative to the Greenwich Meridian. The longitude is expressed in this objects
149         *         angular units.
150         */
151        public double getLongitude() {
152            return longitude;
153        }
154    
155        /**
156         * @param targetUnit
157         *            The unit in which to express longitude.
158         * @return the longitude value relative to the Greenwich Meridian, expressed in the specified units. This
159         *         convenience method make easier to obtains longitude in degrees (<code>getLongitude(Unit.DEGREE)</code>),
160         *         no matter the underlying angular unit of this prime meridian.
161         */
162        public double getLongitude( final Unit targetUnit ) {
163            return targetUnit.convert( getLongitude(), getAngularUnit() );
164        }
165    
166        /**
167         * @return the angular unit.
168         */
169        public Unit getAngularUnit() {
170            return units;
171        }
172    
173        @Override
174        public boolean equals( Object other ) {
175            if ( other != null && other instanceof PrimeMeridian ) {
176                PrimeMeridian that = (PrimeMeridian) other;
177                return ( Math.abs( this.longitude - that.longitude ) < ProjectionUtils.EPS11 ) && ( ( this.units != null ) ? this.units.equals( that.units )
178                                                                                                                          : ( that.units == null ) );
179            }
180            return false;
181        }
182    
183        @Override
184        public String toString() {
185            StringBuilder sb = new StringBuilder( super.toString() );
186            sb.append( ", Units: " ).append( units );
187            sb.append( ", longitude: " ).append( longitude );
188            return sb.toString();
189        }
190        
191        /**
192         * Implementation as proposed by Joshua Block in Effective Java (Addison-Wesley 2001), which supplies an even
193         * distribution and is relatively fast. It is created from field <b>f</b> as follows:
194         * <ul>
195         * <li>boolean -- code = (f ? 0 : 1)</li>
196         * <li>byte, char, short, int -- code = (int)f </li>
197         * <li>long -- code = (int)(f ^ (f &gt;&gt;&gt;32))</li>
198         * <li>float -- code = Float.floatToIntBits(f);</li>
199         * <li>double -- long l = Double.doubleToLongBits(f); code = (int)(l ^ (l &gt;&gt;&gt; 32))</li>
200         * <li>all Objects, (where equals(&nbsp;) calls equals(&nbsp;) for this field) -- code = f.hashCode(&nbsp;)</li>
201         * <li>Array -- Apply above rules to each element</li>
202         * </ul>
203         * <p>
204         * Combining the hash code(s) computed above: result = 37 * result + code;
205         * </p>
206         * 
207         * @return (int) ( result >>> 32 ) ^ (int) result;
208         * 
209         * @see java.lang.Object#hashCode()
210         */
211        @Override
212        public int hashCode() {
213            // the 2.nd million th. prime, :-)
214            long code = 32452843;
215            long ll = Double.doubleToLongBits( longitude);
216            code = code * 37 + (int)( ll ^ (ll >>> 32 ));
217            if( units != null ){
218                code = code * 37 + units.hashCode();
219            }
220            return (int) ( code >>> 32 ) ^ (int) code;
221        }
222    
223    }