001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/csct/cs/ProjectedCoordinateSystem.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 javax.media.jai.ParameterList;
057    
058    import org.deegree.model.csct.ct.MissingParameterException;
059    import org.deegree.model.csct.resources.Utilities;
060    import org.deegree.model.csct.resources.css.ResourceKeys;
061    import org.deegree.model.csct.resources.css.Resources;
062    import org.deegree.model.csct.units.Unit;
063    
064    /**
065     * A 2D cartographic coordinate system. Projected coordinates are the two-dimensional cartesian
066     * coordinates typically found on maps and computer displays. The cartesian axes are often called
067     * "paper coordinates" or "display coordinates." The conversions from a three-dimensional
068     * curvilinear coordinate system (whether ellipsoidal or spherical) to projected coordinates may be
069     * assumed to be well known. Examples of projected coordinate systems are: Lambert, Mercator, and
070     * transverse Mercator. Conversions to, and conversions between, projected spatial coordinate
071     * systems often do not preserve distances, areas and angles.
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_ProjectedCoordinateSystem"
082     */
083    public class ProjectedCoordinateSystem extends HorizontalCoordinateSystem {
084        /**
085         * Serial number for interoperability with different versions.
086         */
087        private static final long serialVersionUID = 5412822472156531329L;
088    
089        /**
090         * The angular unit.
091         */
092        private final Unit unit;
093    
094        /**
095         * Geographic coordinate system to base projection on.
096         */
097        private final GeographicCoordinateSystem gcs;
098    
099        /**
100         * projection Projection from geographic to projected coordinate system.
101         */
102        private final Projection projection;
103    
104        /**
105         * Creates a projected coordinate system using the specified geographic system. Projected
106         * coordinates will be in meters, <var>x</var> values increasing east and <var>y</var> values
107         * increasing north.
108         * 
109         * @param name
110         *            Name to give new object.
111         * @param gcs
112         *            Geographic coordinate system to base projection on.
113         * @param projection
114         *            Projection from geographic to projected coordinate system.
115         */
116        public ProjectedCoordinateSystem( final String name, final GeographicCoordinateSystem gcs,
117                                          final Projection projection ) {
118            this( name, gcs, projection, Unit.METRE, AxisInfo.X, AxisInfo.Y );
119        }
120    
121        /**
122         * Creates a projected coordinate system using a projection object.
123         * 
124         * @param name
125         *            Name to give new object.
126         * @param gcs
127         *            Geographic coordinate system to base projection on.
128         * @param projection
129         *            Projection from geographic to projected coordinate system.
130         * @param unit
131         *            Linear units of created PCS.
132         * @param axis0
133         *            Details of 0th ordinates in created PCS coordinates.
134         * @param axis1
135         *            Details of 1st ordinates in created PCS coordinates.
136         * 
137         */
138        public ProjectedCoordinateSystem( final String name, final GeographicCoordinateSystem gcs,
139                                          Projection projection, final Unit unit, final AxisInfo axis0,
140                                          final AxisInfo axis1 ) {
141            super( name, gcs.getHorizontalDatum(), axis0, axis1 );
142            ensureNonNull( "gcs", gcs );
143            ensureNonNull( "projection", projection );
144            ensureNonNull( "unit", unit );
145            ensureLinearUnit( unit );
146    
147            final Ellipsoid ellipsoid = getHorizontalDatum().getEllipsoid();
148            final double semiMajor = ellipsoid.getSemiMajorAxis();
149            final double semiMinor = ellipsoid.getSemiMinorAxis();
150            String invalidParameter = null;
151            boolean resetAxisLength = false;
152            try {
153                if ( semiMinor != projection.getValue( "semi_minor" ) )
154                    invalidParameter = "semi_minor";
155            } catch ( MissingParameterException exception ) {
156                // Axis length not set.
157                resetAxisLength = true;
158            }
159            try {
160                if ( semiMajor != projection.getValue( "semi_major" ) )
161                    invalidParameter = "semi_major";
162            } catch ( MissingParameterException exception ) {
163                // Axis length not set.
164                resetAxisLength = true;
165            }
166            if ( invalidParameter != null ) {
167                throw new IllegalArgumentException(
168                                                    Resources.format(
169                                                                      ResourceKeys.ERROR_INCOMPATIBLE_ELLIPSOID_$2,
170                                                                      invalidParameter,
171                                                                      ellipsoid.getName() ) );
172            }
173            if ( resetAxisLength ) {
174                final ParameterList parameters = projection.getParameters();
175                parameters.setParameter( "semi_major", semiMajor );
176                parameters.setParameter( "semi_minor", semiMinor );
177                projection = new Projection( projection.getName(), projection.getClassName(),
178                                             parameters );
179            }
180            this.gcs = gcs;
181            this.projection = projection;
182            this.unit = unit;
183        }
184    
185        /**
186         * Creates a projected coordinate system using a projection object.
187         * 
188         * @param properties
189         *            The set of properties (see {@link Info}).
190         * @param gcs
191         *            Geographic coordinate system to base projection on.
192         * @param projection
193         *            Projection from geographic to projected coordinate system.
194         * @param unit
195         *            Linear units of created PCS.
196         * @param axis0
197         *            Details of 0th ordinates in created PCS coordinates.
198         * @param axis1
199         *            Details of 1st ordinates in created PCS coordinates.
200         */
201        ProjectedCoordinateSystem( final Map properties, final GeographicCoordinateSystem gcs,
202                                   final Projection projection, final Unit unit, final AxisInfo axis0,
203                                   final AxisInfo axis1 ) {
204            super( properties, gcs.getHorizontalDatum(), axis0, axis1 );
205            this.gcs = gcs;
206            this.projection = projection;
207            this.unit = unit;
208            // Accept null values.
209        }
210    
211        /**
212         * Returns the geographic coordinate system.
213         * 
214         * @return the geographic coordinate system.
215         * 
216         * @see "org.opengis.cs.CS_ProjectedCoordinateSystem#getGeographicCoordinateSystem()"
217         */
218        public GeographicCoordinateSystem getGeographicCoordinateSystem() {
219            return gcs;
220        }
221    
222        /**
223         * Gets the projection.
224         * 
225         * @return the projection.
226         * 
227         * @see "org.opengis.cs.CS_ProjectedCoordinateSystem#getProjection()"
228         */
229        public Projection getProjection() {
230            return projection;
231        }
232    
233        /**
234         * Gets units for dimension within coordinate system. This linear unit is the same for all axis.
235         * 
236         * @param dimension
237         *            Zero based index of axis.
238         * @return units for dimension within coordinate system.
239         * 
240         * @see "org.opengis.cs.CS_ProjectedCoordinateSystem#getUnits(int)"
241         * @see "org.opengis.cs.CS_ProjectedCoordinateSystem#getLinearUnit()"
242         */
243        public Unit getUnits( final int dimension ) {
244            if ( dimension >= 0 && dimension < getDimension() )
245                return unit;
246            throw new IndexOutOfBoundsException(
247                                                 Resources.format(
248                                                                   ResourceKeys.ERROR_INDEX_OUT_OF_BOUNDS_$1,
249                                                                   new Integer( dimension ) ) );
250        }
251    
252        /**
253         * Returns <code>true</code> if this coordinate system is equivalents to the specified
254         * coordinate system. Two coordinate systems are considered equivalent if the
255         * {@link org.deegree.model.csct.ct.CoordinateTransformation} from <code>this</code> to
256         * <code>cs</code> would be the identity transform. The default implementation compare datum,
257         * units and axis, but ignore name, alias and other meta-data informations.
258         * 
259         * @param cs
260         *            The coordinate system (may be <code>null</code>).
261         * @return <code>true</code> if both coordinate systems are equivalent.
262         */
263        public boolean equivalents( final CoordinateSystem cs ) {
264            if ( cs == this )
265                return true;
266            if ( super.equivalents( cs ) ) {
267                final ProjectedCoordinateSystem that = (ProjectedCoordinateSystem) cs;
268                return Utilities.equals( this.gcs, that.gcs )
269                       && Utilities.equals( this.projection, that.projection )
270                       && Utilities.equals( this.unit, that.unit );
271            }
272            return false;
273        }
274    
275        /**
276         * Fill the part inside "[...]". Used for formatting Well Know Text (WKT).
277         * 
278         * @param buffer
279         * @return
280         */
281        String addString( final StringBuffer buffer ) {
282            buffer.append( ", " );
283            buffer.append( gcs );
284            buffer.append( ", " );
285            buffer.append( projection );
286            buffer.append( ", " );
287            addUnit( buffer, unit );
288            buffer.append( ", " );
289            buffer.append( getAxis( 0 ) );
290            buffer.append( ", " );
291            buffer.append( getAxis( 1 ) );
292            return "PROJCS";
293        }
294    
295    }