001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/csct/cs/GeographicCoordinateSystem.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.Collections;
055    import java.util.Map;
056    import java.util.Set;
057    
058    import org.deegree.model.csct.pt.CoordinatePoint;
059    import org.deegree.model.csct.pt.Envelope;
060    import org.deegree.model.csct.pt.Latitude;
061    import org.deegree.model.csct.pt.Longitude;
062    import org.deegree.model.csct.resources.Utilities;
063    import org.deegree.model.csct.resources.css.ResourceKeys;
064    import org.deegree.model.csct.resources.css.Resources;
065    import org.deegree.model.csct.units.Unit;
066    
067    /**
068     * A coordinate system based on latitude and longitude. Some geographic coordinate systems are
069     * <var>latitude</var>/<var>longiude</var>, and some are <var>longitude</var>/<var>latitude</var>.
070     * You can find out which this is by examining the axes. You should also check the angular units,
071     * since not all geographic coordinate systems use degrees.
072     * 
073     * @version 1.00
074     * @author OpenGIS (www.opengis.org)
075     * @author Martin Desruisseaux
076     * 
077     * @author last edited by: $Author: bezema $
078     * 
079     * @version $Revision: 6259 $, $Date: 2007-03-20 10:15:15 +0100 (Di, 20 Mär 2007) $
080     * 
081     * @see "org.opengis.cs.CS_GeographicCoordinateSystem"
082     */
083    public class GeographicCoordinateSystem extends HorizontalCoordinateSystem {
084        /**
085         * Serial number for interoperability with different versions.
086         */
087        private static final long serialVersionUID = -2024367470686889008L;
088    
089        /**
090         * A geographic coordinate system using WGS84 datum. This coordinate system use <var>longitude</var>/<var>latitude</var>
091         * ordinates with longitude values increasing north and latitude values increasing east. Angular
092         * units are degrees and prime meridian is Greenwich.
093         */
094        public static final GeographicCoordinateSystem WGS84 = (GeographicCoordinateSystem) pool.intern( new GeographicCoordinateSystem(
095                                                                                                                                         "WGS84",
096                                                                                                                                         HorizontalDatum.WGS84 ) );
097    
098        /**
099         * The angular unit.
100         */
101        private final Unit unit;
102    
103        /**
104         * The prime meridian.
105         */
106        private final PrimeMeridian meridian;
107    
108        /**
109         * Creates a geographic coordinate system. This coordinate system will use <var>longitude</var>/<var>latitude</var>
110         * ordinates with longitude values increasing east and latitude values increasing north. Angular
111         * units are degrees and prime meridian is Greenwich.
112         * 
113         * @param name
114         *            Name to give new object.
115         * @param datum
116         *            Horizontal datum for created coordinate system.
117         */
118        public GeographicCoordinateSystem( final String name, final HorizontalDatum datum ) {
119            this( name, Unit.DEGREE, datum, PrimeMeridian.GREENWICH, AxisInfo.LONGITUDE,
120                  AxisInfo.LATITUDE );
121        }
122    
123        /**
124         * Creates a geographic coordinate system, which could be <var>latitude</var>/<var>longiude</var>
125         * or <var>longitude</var>/<var>latitude</var>.
126         * 
127         * @param name
128         *            Name to give new object.
129         * @param unit
130         *            Angular units for created coordinate system.
131         * @param datum
132         *            Horizontal datum for created coordinate system.
133         * @param meridian
134         *            Prime Meridian for created coordinate system.
135         * @param axis0
136         *            Details of 0th ordinates.
137         * @param axis1
138         *            Details of 1st ordinates.
139         * 
140         */
141        public GeographicCoordinateSystem( final String name, final Unit unit,
142                                           final HorizontalDatum datum, final PrimeMeridian meridian,
143                                           final AxisInfo axis0, final AxisInfo axis1 ) {
144            super( name, datum, axis0, axis1 );
145            ensureNonNull( "unit", unit );
146            ensureNonNull( "meridian", meridian );
147            ensureAngularUnit( unit );
148            this.unit = unit;
149            this.meridian = meridian;
150        }
151    
152        /**
153         * Creates a geographic coordinate system, which could be <var>latitude</var>/<var>longiude</var>
154         * or <var>longitude</var>/<var>latitude</var>.
155         * 
156         * @param properties
157         *            The set of properties (see {@link Info}).
158         * @param unit
159         *            Angular units for created coordinate system.
160         * @param datum
161         *            Horizontal datum for created coordinate system.
162         * @param meridian
163         *            Prime Meridian for created coordinate system.
164         * @param axis0
165         *            Details of 0th ordinates.
166         * @param axis1
167         *            Details of 1st ordinates.
168         */
169        GeographicCoordinateSystem( final Map properties, final Unit unit, final HorizontalDatum datum,
170                                    final PrimeMeridian meridian, final AxisInfo axis0,
171                                    final AxisInfo axis1 ) {
172            super( properties, datum, axis0, axis1 );
173            this.unit = unit;
174            this.meridian = meridian;
175            // Accept null values.
176        }
177    
178        /**
179         * Gets units for dimension within coordinate system. This angular unit is the same for all
180         * axis.
181         * 
182         * @param dimension
183         *            Zero based index of axis.
184         * @return units for dimension within coordinate system. This angular unit is the same for all
185         *         axis.
186         * 
187         * @see "org.opengis.cs.CS_GeographicCoordinateSystem#getUnits(int)"
188         */
189        public Unit getUnits( final int dimension ) {
190            if ( dimension >= 0 && dimension < getDimension() )
191                return unit;
192            throw new IndexOutOfBoundsException(
193                                                 Resources.format(
194                                                                   ResourceKeys.ERROR_INDEX_OUT_OF_BOUNDS_$1,
195                                                                   new Integer( dimension ) ) );
196        }
197    
198        /**
199         * Returns the prime meridian.
200         * 
201         * @return the prime meridian.
202         * 
203         * @see "org.opengis.cs.CS_GeographicCoordinateSystem#getPrimeMeridian()"
204         */
205        public PrimeMeridian getPrimeMeridian() {
206            return meridian;
207        }
208    
209        /**
210         * Gets default envelope of coordinate system.
211         * 
212         * @return default envelope of coordinate system.
213         * 
214         * @see "org.opengis.cs.CS_GeographicCoordinateSystem#getDefaultEnvelope()"
215         */
216        public Envelope getDefaultEnvelope() {
217            final int dimension = getDimension();
218            final CoordinatePoint minCP = new CoordinatePoint( dimension );
219            final CoordinatePoint maxCP = new CoordinatePoint( dimension );
220            for ( int i = 0; i < dimension; i++ ) {
221                double min, max;
222                final Unit unit = getUnits( i );
223                final AxisOrientation orientation = getAxis( i ).orientation;
224                if ( AxisOrientation.NORTH.equals( orientation.absolute() ) ) {
225                    min = Latitude.MIN_VALUE;
226                    max = Latitude.MAX_VALUE;
227                } else if ( AxisOrientation.EAST.equals( orientation.absolute() ) ) {
228                    min = Longitude.MIN_VALUE;
229                    max = Longitude.MAX_VALUE;
230                } else {
231                    min = Double.NEGATIVE_INFINITY;
232                    max = Double.POSITIVE_INFINITY;
233                }
234                min = unit.convert( min, Unit.DEGREE );
235                max = unit.convert( max, Unit.DEGREE );
236                minCP.ord[i] = Math.min( min, max );
237                maxCP.ord[i] = Math.max( min, max );
238            }
239            return new Envelope( minCP, maxCP );
240        }
241    
242        /**
243         * Gets details on conversions to WGS84. Some geographic coordinate systems provide several
244         * transformations into WGS84, which are designed to provide good accuracy in different areas of
245         * interest. The first conversion should provide acceptable accuracy over the largest possible
246         * area of interest.
247         * 
248         * @return A set of conversions info to WGS84. The default implementation returns an empty set.
249         * 
250         * @see "org.opengis.cs.CS_GeographicCoordinateSystem#getNumConversionToWGS84()"
251         * @see "org.opengis.cs.CS_GeographicCoordinateSystem#getWGS84ConversionInfo(int)"
252         */
253        public Set getWGS84ConversionInfos() {
254            return Collections.EMPTY_SET;
255        }
256    
257        /**
258         * Returns <code>true</code> if this coordinate system is equivalents to the specified
259         * coordinate system. Two coordinate systems are considered equivalent if the
260         * {@link org.deegree.model.csct.ct.CoordinateTransformation} from <code>this</code> to
261         * <code>cs</code> would be the identity transform. The default implementation compare datum,
262         * units and axis, but ignore name, alias and other meta-data informations.
263         * 
264         * @param cs
265         *            The coordinate system (may be <code>null</code>).
266         * @return <code>true</code> if both coordinate systems are equivalent.
267         */
268        public boolean equivalents( final CoordinateSystem cs ) {
269            if ( cs == this )
270                return true;
271            if ( super.equivalents( cs ) ) {
272                final GeographicCoordinateSystem that = (GeographicCoordinateSystem) cs;
273                return Utilities.equals( this.unit, that.unit )
274                       && Utilities.equals( this.meridian, that.meridian );
275            }
276            return false;
277        }
278    
279        /**
280         * Fill the part inside "[...]". Used for formatting Well Know Text (WKT).
281         * 
282         * @param buffer
283         * @return
284         */
285        String addString( final StringBuffer buffer ) {
286            buffer.append( ", " );
287            buffer.append( getDatum() );
288            buffer.append( ", " );
289            buffer.append( meridian );
290            buffer.append( ", " );
291            addUnit( buffer, unit );
292            buffer.append( ", " );
293            buffer.append( getAxis( 0 ) );
294            buffer.append( ", " );
295            buffer.append( getAxis( 1 ) );
296            return "GEOGCS";
297        }
298    
299    }