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.coordinatesystems;
040    
041    import org.deegree.crs.Identifiable;
042    import org.deegree.crs.components.Axis;
043    import org.deegree.crs.projections.Projection;
044    
045    /**
046     * A <code>ProjectedCRS</code> is a coordinatesystem defined with a projection and a geographic crs. It allows for
047     * transformation between projected coordinates (mostly in meters) and the lat/lon coordinates of the geographic crs and
048     * vice versa.
049     * 
050     * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
051     * 
052     * @author last edited by: $Author:$
053     * 
054     * @version $Revision:$, $Date:$
055     * 
056     */
057    
058    public class ProjectedCRS extends CoordinateSystem {
059    
060        private final GeographicCRS underlyingCRS;
061    
062        private Projection projection;
063    
064        /**
065         * @param projection
066         *            the projection which converts coordinates from this ProjectedCRS into the underlying GeographicCRS and
067         *            vice versa.
068         * @param axisOrder
069         *            of this projection.
070         * @param identity
071         */
072        public ProjectedCRS( Projection projection, Axis[] axisOrder, Identifiable identity ) {
073            super( projection.getGeographicCRS().getGeodeticDatum(), axisOrder, identity );
074            this.underlyingCRS = projection.getGeographicCRS();
075            this.projection = projection;
076        }
077    
078        /**
079         * @param projection
080         *            the projection which converts coordinates from this ProjectedCRS into the underlying GeographicCRS and
081         *            vice versa.
082         * @param axisOrder
083         *            of this projection.
084         * @param identifiers
085         * @param names
086         * @param versions
087         * @param descriptions
088         * @param areasOfUse
089         */
090        public ProjectedCRS( Projection projection, Axis[] axisOrder, String[] identifiers, String[] names,
091                             String[] versions, String[] descriptions, String[] areasOfUse ) {
092            super( projection.getGeographicCRS().getGeodeticDatum(),
093                   axisOrder,
094                   identifiers,
095                   names,
096                   versions,
097                   descriptions,
098                   areasOfUse );
099            this.underlyingCRS = projection.getGeographicCRS();
100            this.projection = projection;
101        }
102    
103        /**
104         * 
105         * @param projection
106         *            the projection which converts coordinates from this ProjectedCRS into the underlying GeographicCRS and
107         *            vice versa.
108         * @param axisOrder
109         *            of this projection.
110         * @param identifiers
111         */
112        public ProjectedCRS( Projection projection, Axis[] axisOrder, String[] identifiers ) {
113            this( projection, axisOrder, identifiers, null, null, null, null );
114        }
115    
116        /**
117         * @param projection
118         *            the projection which converts coordinates from this ProjectedCRS into the underlying GeographicCRS and
119         *            vice versa.
120         * @param axisOrder
121         *            of this projection.
122         * @param identifier
123         * @param name
124         * @param version
125         * @param description
126         * @param areaOfUse
127         */
128        public ProjectedCRS( Projection projection, Axis[] axisOrder, String identifier, String name, String version,
129                             String description, String areaOfUse ) {
130            this( projection,
131                  axisOrder,
132                  new String[] { identifier },
133                  new String[] { name },
134                  new String[] { version },
135                  new String[] { description },
136                  new String[] { areaOfUse } );
137        }
138    
139        /**
140         * 
141         * @param projection
142         *            the projection which converts coordinates from this ProjectedCRS into the underlying GeographicCRS and
143         *            vice versa.
144         * @param axisOrder
145         *            of this projection.
146         * @param identifier
147         */
148        public ProjectedCRS( Projection projection, Axis[] axisOrder, String identifier ) {
149            this( projection, axisOrder, identifier, null, null, null, null );
150        }
151    
152        /*
153         * (non-Javadoc)
154         * 
155         * @see org.deegree.crs.coordinatesystems.CoordinateSystem#getDimension()
156         */
157        @Override
158        public int getDimension() {
159            return getAxis().length;
160        }
161    
162        /**
163         * @return the underlyingCRS.
164         */
165        public final GeographicCRS getGeographicCRS() {
166            return underlyingCRS;
167        }
168    
169        @Override
170        public final int getType() {
171            return PROJECTED_CRS;
172        }
173    
174        /**
175         * @return the projection.
176         */
177        public final Projection getProjection() {
178            return projection;
179        }
180        
181        @Override
182        public boolean equals( Object other ) {
183            if ( other != null && other instanceof ProjectedCRS ) {
184                final ProjectedCRS that = (ProjectedCRS) other;
185                return super.equals( that ) && this.projection.equals( that.projection );
186            }
187            return false;
188        }
189    
190        @Override
191        public String toString() {
192            StringBuilder sb = new StringBuilder( super.toString() );
193            sb.append( "\n - Projection: " ).append( projection );
194            return sb.toString();
195        }
196        
197        /**
198         * Implementation as proposed by Joshua Block in Effective Java (Addison-Wesley 2001), which supplies an even
199         * distribution and is relatively fast. It is created from field <b>f</b> as follows:
200         * <ul>
201         * <li>boolean -- code = (f ? 0 : 1)</li>
202         * <li>byte, char, short, int -- code = (int)f </li>
203         * <li>long -- code = (int)(f ^ (f &gt;&gt;&gt;32))</li>
204         * <li>float -- code = Float.floatToIntBits(f);</li>
205         * <li>double -- long l = Double.doubleToLongBits(f); code = (int)(l ^ (l &gt;&gt;&gt; 32))</li>
206         * <li>all Objects, (where equals(&nbsp;) calls equals(&nbsp;) for this field) -- code = f.hashCode(&nbsp;)</li>
207         * <li>Array -- Apply above rules to each element</li>
208         * </ul>
209         * <p>
210         * Combining the hash code(s) computed above: result = 37 * result + code;
211         * </p>
212         * 
213         * @return (int) ( result >>> 32 ) ^ (int) result;
214         * 
215         * @see java.lang.Object#hashCode()
216         */
217        @Override
218        public int hashCode() {
219            // the 2nd millionth prime, :-)
220            long code = 32452843;
221            code = code * 37 + super.hashCode();
222            if( projection != null ){
223                code = code * 37 + projection.hashCode();
224            }
225    
226            return (int) ( code >>> 32 ) ^ (int) code;
227        }
228    }