001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/csct/cs/CompoundCoordinateSystem.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.CoordinatePoint;
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     * An aggregate of two coordinate systems. One of these is usually a two dimensional coordinate
065     * system such as a geographic or a projected coordinate system with a horizontal datum. The other
066     * is one-dimensional coordinate system with a vertical datum.
067     * 
068     * @version 1.00
069     * @author OpenGIS (www.opengis.org)
070     * @author Martin Desruisseaux
071     * 
072     * @author last edited by: $Author: bezema $
073     * 
074     * @version $Revision: 6259 $, $Date: 2007-03-20 10:15:15 +0100 (Di, 20 Mär 2007) $
075     * 
076     * @see "org.opengis.cs.CS_CompoundCoordinateSystem"
077     */
078    public class CompoundCoordinateSystem extends CoordinateSystem {
079        /**
080         * Serial number for interoperability with different versions.
081         */
082        private static final long serialVersionUID = -488997059924367289L;
083    
084        /**
085         * A default three-dimensional coordinate system for use with geographic coordinates with
086         * heights above the ellipsoid. The head coordinate system is
087         * {@link GeographicCoordinateSystem#WGS84} and the tail coordinate system is
088         * {@link VerticalCoordinateSystem#ELLIPSOIDAL}.
089         */
090        public static final CompoundCoordinateSystem WGS84 = (CompoundCoordinateSystem) pool.intern( new CompoundCoordinateSystem(
091                                                                                                                                   "WGS84",
092                                                                                                                                   GeographicCoordinateSystem.WGS84,
093                                                                                                                                   VerticalCoordinateSystem.ELLIPSOIDAL ) );
094    
095        /**
096         * First sub-coordinate system.
097         */
098        private final CoordinateSystem head;
099    
100        /**
101         * Second sub-coordinate system.
102         */
103        private final CoordinateSystem tail;
104    
105        /**
106         * Creates a compound coordinate system.
107         * 
108         * @param name
109         *            Name to give new object.
110         * @param head
111         *            Coordinate system to use for earlier ordinates.
112         * @param tail
113         *            Coordinate system to use for later ordinates.
114         * 
115         */
116        public CompoundCoordinateSystem( final String name, final CoordinateSystem head,
117                                         final CoordinateSystem tail ) {
118            super( name );
119            this.head = head;
120            this.tail = tail;
121            ensureNonNull( "head", head );
122            ensureNonNull( "tail", tail );
123            checkAxis( null );
124        }
125    
126        /**
127         * Creates a compound coordinate system.
128         * 
129         * @param properties
130         *            The set of properties (see {@link Info}).
131         * @param head
132         *            Coordinate system to use for earlier ordinates.
133         * @param tail
134         *            Coordinate system to use for later ordinates.
135         */
136        CompoundCoordinateSystem( final Map properties, final CoordinateSystem head,
137                                  final CoordinateSystem tail ) {
138            super( properties );
139            this.head = head;
140            this.tail = tail;
141            // Accept null values.
142        }
143    
144        /**
145         * Returns the first sub-coordinate system.
146         * 
147         * @return the first sub-coordinate system.
148         * 
149         * @see "org.opengis.cs.CS_CompoundCoordinateSystem#getHeadCS()"
150         */
151        public CoordinateSystem getHeadCS() {
152            return head;
153        }
154    
155        /**
156         * Returns the second sub-coordinate system.
157         * 
158         * @return the second sub-coordinate system.
159         * 
160         * @see "org.opengis.cs.CS_CompoundCoordinateSystem#getTailCS()"
161         */
162        public CoordinateSystem getTailCS() {
163            return tail;
164        }
165    
166        /**
167         * Returns the dimension of the coordinate system.
168         * 
169         * @return the dimension of the coordinate system.
170         * 
171         * @see "org.opengis.cs.CS_CompoundCoordinateSystem#getDimension()"
172         */
173        public int getDimension() {
174            return head.getDimension() + tail.getDimension();
175        }
176    
177        /**
178         * Gets axis details for dimension within coordinate system. Each dimension in the coordinate
179         * system has a corresponding axis.
180         * 
181         * @param dimension
182         * @return
183         * 
184         * @see "org.opengis.cs.CS_CompoundCoordinateSystem#getAxis(int)"
185         */
186        public AxisInfo getAxis( final int dimension ) {
187            if ( dimension >= 0 ) {
188                final int headDim = head.getDimension();
189                if ( dimension < headDim ) {
190                    return head.getAxis( dimension );
191                }
192                final int dim = dimension - headDim;
193                if ( dim < tail.getDimension() ) {
194                    return tail.getAxis( dim );
195                }
196            }
197            throw new IndexOutOfBoundsException(
198                                                 Resources.format(
199                                                                   ResourceKeys.ERROR_INDEX_OUT_OF_BOUNDS_$1,
200                                                                   new Integer( dimension ) ) );
201        }
202    
203        /**
204         * Gets units for dimension within coordinate system. Each dimension in the coordinate system
205         * has corresponding units.
206         * 
207         * @param dimension
208         * @return
209         * 
210         * @see "org.opengis.cs.CS_CompoundCoordinateSystem#getUnits(int)"
211         */
212        public Unit getUnits( final int dimension ) {
213            if ( dimension >= 0 ) {
214                final int headDim = head.getDimension();
215                if ( dimension < headDim ) {
216                    return head.getUnits( dimension );
217                }
218                final int dim = dimension - headDim;
219                if ( dim < tail.getDimension() ) {
220                    return head.getUnits( dim );
221                }
222            }
223            throw new IndexOutOfBoundsException(
224                                                 Resources.format(
225                                                                   ResourceKeys.ERROR_INDEX_OUT_OF_BOUNDS_$1,
226                                                                   new Integer( dimension ) ) );
227        }
228    
229        /**
230         * Gets default envelope of coordinate system.
231         * 
232         * @return
233         * 
234         * @see "org.opengis.cs.CS_CompoundCoordinateSystem#getDefaultEnvelope()"
235         */
236        public Envelope getDefaultEnvelope() {
237            final Envelope headEnv = head.getDefaultEnvelope();
238            final Envelope tailEnv = tail.getDefaultEnvelope();
239            final int headDim = headEnv.getDimension();
240            final int tailDim = tailEnv.getDimension();
241            final CoordinatePoint min = new CoordinatePoint( headDim + tailDim );
242            final CoordinatePoint max = new CoordinatePoint( headDim + tailDim );
243            for ( int i = 0; i < headDim; i++ ) {
244                min.ord[i] = headEnv.getMinimum( i );
245                max.ord[i] = headEnv.getMaximum( i );
246            }
247            for ( int i = 0; i < tailDim; i++ ) {
248                min.ord[headDim + i] = tailEnv.getMinimum( i );
249                max.ord[headDim + i] = tailEnv.getMaximum( i );
250            }
251            return new Envelope( min, max );
252        }
253    
254        /**
255         * Returns <code>true</code> if this coordinate system is equivalents to the specified
256         * coordinate system. Two coordinate systems are considered equivalent if the
257         * {@link org.deegree.model.csct.ct.CoordinateTransformation} from <code>this</code> to
258         * <code>cs</code> would be the identity transform.
259         * 
260         * @param cs
261         *            The coordinate system (may be <code>null</code>).
262         * @return <code>true</code> if both coordinate systems are equivalent.
263         */
264        public boolean equivalents( final CoordinateSystem cs ) {
265            if ( cs == this )
266                return true;
267            if ( super.equivalents( cs ) ) {
268                final CompoundCoordinateSystem that = (CompoundCoordinateSystem) cs;
269                return head.equivalents( that.head ) && tail.equivalents( that.tail );
270            }
271            return false;
272        }
273    
274        /**
275         * Compares the specified object with this coordinate system for equality.
276         * 
277         * @param object
278         * @return
279         */
280        public boolean equals( final Object object ) {
281            if ( object == this )
282                return true;
283            if ( super.equals( object ) ) {
284                final CompoundCoordinateSystem that = (CompoundCoordinateSystem) object;
285                return Utilities.equals( this.head, that.head )
286                       && Utilities.equals( this.tail, that.tail );
287            }
288            return false;
289        }
290    
291        /**
292         * Fill the part inside "[...]". Used for formatting Well Know Text (WKT).
293         * 
294         * @param buffer
295         * @return
296         */
297        String addString( final StringBuffer buffer ) {
298            buffer.append( ", " );
299            buffer.append( head );
300            buffer.append( ", " );
301            buffer.append( tail );
302            return "COMPD_CS";
303        }
304    
305    }