001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/csct/cs/CoordinateSystem.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    // OpenGIS dependencies
054    import java.util.Map;
055    
056    import org.deegree.model.csct.pt.Dimensioned;
057    import org.deegree.model.csct.pt.Envelope;
058    import org.deegree.model.csct.resources.Utilities;
059    import org.deegree.model.csct.resources.css.ResourceKeys;
060    import org.deegree.model.csct.resources.css.Resources;
061    import org.deegree.model.csct.units.Unit;
062    
063    /**
064     * Base class for all coordinate systems. A coordinate system is a mathematical space, where the
065     * elements of the space are called positions. Each position is described by a list of numbers. The
066     * length of the list corresponds to the dimension of the coordinate system. So in a 2D coordinate
067     * system each position is described by a list containing 2 numbers. <br>
068     * <br>
069     * However, in a coordinate system, not all lists of numbers correspond to a position - some lists
070     * may be outside the domain of the coordinate system. For example, in a 2D Lat/Lon coordinate
071     * system, the list (91,91) does not correspond to a position. <br>
072     * <br>
073     * Some coordinate systems also have a mapping from the mathematical space into locations in the
074     * real world. So in a Lat/Lon coordinate system, the mathematical position (lat, long) corresponds
075     * to a location on the surface of the Earth. This mapping from the mathematical space into
076     * real-world locations is called a Datum.
077     * 
078     * @version 1.00
079     * @author OpenGIS (www.opengis.org)
080     * @author Martin Desruisseaux
081     * 
082     * @author last edited by: $Author: bezema $
083     * 
084     * @version $Revision: 6259 $, $Date: 2007-03-20 10:15:15 +0100 (Di, 20 Mär 2007) $
085     * 
086     * @see "org.opengis.cs.CS_CoordinateSystem"
087     */
088    public abstract class CoordinateSystem extends Info implements Dimensioned {
089        /**
090         * Serial number for interoperability with different versions.
091         */
092        private static final long serialVersionUID = -4539963180028417479L;
093    
094        /**
095         * Construct a coordinate system.
096         * 
097         * @param name
098         *            The coordinate system name.
099         */
100        public CoordinateSystem( final String name ) {
101            super( name );
102        }
103    
104        /**
105         * Construct a coordinate system.
106         * 
107         * @param properties
108         *            The set of properties (see {@link Info}).
109         */
110        CoordinateSystem( final Map properties ) {
111            super( properties );
112        }
113    
114        /**
115         * Make sure there is no axis among the same direction (e.g. two north axis, or a east and a
116         * west axis). This methods may be invoked from subclasses constructors.
117         * 
118         * @param type
119         *            The datum type, or <code>null</code> if unknow.
120         * @throws IllegalArgumentException
121         *             if two axis have the same direction.
122         */
123        final void checkAxis( final DatumType type )
124                                throws IllegalArgumentException {
125            final int dimension = getDimension();
126            for ( int i = 0; i < dimension; i++ ) {
127                AxisOrientation check = getAxis( i ).orientation;
128                if ( type != null && !type.isCompatibleOrientation( check ) ) {
129                    throw new IllegalArgumentException(
130                                                        Resources.format(
131                                                                          ResourceKeys.ERROR_ILLEGAL_AXIS_ORIENTATION_$2,
132                                                                          check.getName( null ),
133                                                                          Utilities.getShortClassName( this ) ) );
134                }
135                check = check.absolute();
136                if ( !check.equals( AxisOrientation.OTHER ) ) {
137                    for ( int j = i + 1; j < dimension; j++ ) {
138                        if ( check.equals( getAxis( j ).orientation.absolute() ) ) {
139                            final String nameI = getAxis( i ).orientation.getName( null );
140                            final String nameJ = getAxis( j ).orientation.getName( null );
141                            throw new IllegalArgumentException(
142                                                                Resources.format(
143                                                                                  ResourceKeys.ERROR_COLINEAR_AXIS_$2,
144                                                                                  nameI, nameJ ) );
145                        }
146                    }
147                }
148            }
149        }
150    
151        /**
152         * Returns the dimension of the coordinate system.
153         * 
154         * @return the dimension of the coordinate system.
155         * 
156         * @see "org.opengis.cs.CS_CoordinateSystem#getDimension()"
157         */
158        public abstract int getDimension();
159    
160        /**
161         * Gets axis details for dimension within coordinate system. Each dimension in the coordinate
162         * system has a corresponding axis.
163         * 
164         * @param dimension
165         *            Zero based index of axis.
166         * @return
167         * 
168         * @see "org.opengis.cs.CS_CoordinateSystem#getAxis(int)"
169         */
170        public abstract AxisInfo getAxis( int dimension );
171    
172        /**
173         * Gets units for dimension within coordinate system. Each dimension in the coordinate system
174         * has corresponding units.
175         * 
176         * @param dimension
177         *            Zero based index of axis.
178         * @return
179         * 
180         * @see "org.opengis.cs.CS_CoordinateSystem#getUnits(int)"
181         */
182        public abstract Unit getUnits( int dimension );
183    
184        /**
185         * If all dimensions use the same units, returns this units. Otherwise, returns
186         * <code>null</code>.
187         * 
188         * @return this units, if all dimensions use the same units. Otherwise, returns
189         *         <code>null</code>.
190         */
191        final Unit getUnits() {
192            Unit units = null;
193            for ( int i = getDimension(); --i >= 0; ) {
194                final Unit check = getUnits( i );
195                if ( units == null )
196                    units = check;
197                else if ( !units.equals( check ) )
198                    return null;
199            }
200            return units;
201        }
202    
203        /**
204         * Returns the datum.
205         * 
206         * @return the datum.
207         */
208        Datum getDatum() {
209            return null;
210        }
211    
212        /**
213         * Gets default envelope of coordinate system. Coordinate systems which are bounded should
214         * return the minimum bounding box of their domain. Unbounded coordinate systems should return a
215         * box which is as large as is likely to be used. For example, a (lon,lat) geographic coordinate
216         * system in degrees should return a box from (-180,-90) to (180,90), and a geocentric
217         * coordinate system could return a box from (-r,-r,-r) to (+r,+r,+r) where r is the approximate
218         * radius of the Earth. <br>
219         * <br>
220         * The default implementation returns an envelope with infinite bounds.
221         * 
222         * @return
223         * 
224         * @see "org.opengis.cs.CS_CoordinateSystem#getDefaultEnvelope()"
225         */
226        public Envelope getDefaultEnvelope() {
227            final int dimension = getDimension();
228            final Envelope envelope = new Envelope( dimension );
229            for ( int i = dimension; --i >= 0; ) {
230                envelope.setRange( i, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY );
231            }
232            return envelope;
233        }
234    
235        /**
236         * Returns <code>true</code> if this coordinate system is equivalents to the specified
237         * coordinate system. Two coordinate systems are considered equivalent if the
238         * {@link org.deegree.model.csct.ct.CoordinateTransformation} from <code>this</code> to
239         * <code>cs</code> would be the identity transform. The <code>equivalents</code> method is
240         * less strict than <code>equals</code> in that it doesn't compare names, alias, authority
241         * codes or others similar informations.
242         * 
243         * @param cs
244         *            The coordinate system (may be <code>null</code>).
245         * @return <code>true</code> if both coordinate systems are equivalent.
246         */
247        public boolean equivalents( final CoordinateSystem cs ) {
248            return ( cs != null ) && cs.getClass().equals( getClass() );
249        }
250    
251        /**
252         * Compares the specified object with this coordinate system for equality.
253         * 
254         * @param object
255         * @return
256         */
257        public boolean equals( final Object object ) {
258            if ( object == this )
259                return true; // Slight optimization
260            return super.equals( object ) && equivalents( (CoordinateSystem) object );
261        }
262    
263    }