/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/exse/
lat/lon GmbH
http://www.lat-lon.de
It has been implemented within SEAGIS - An OpenSource implementation of OpenGIS specification
(C) 2001, Institut de Recherche pour le D�veloppement (http://sourceforge.net/projects/seagis/)
SEAGIS Contacts: Surveillance de l'Environnement Assist�e par Satellite
Institut de Recherche pour le D�veloppement / US-Espace
mailto:seasnet@teledetection.fr
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53115 Bonn
Germany
E-Mail: poth@lat-lon.de
Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: klaus.greve@uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.model.csct.ct;
// OpenGIS dependencies
import java.util.Locale;
import org.deegree.model.csct.cs.CoordinateSystem;
import org.deegree.model.csct.cs.Info;
import org.deegree.model.csct.resources.Utilities;
import org.deegree.model.csct.resources.css.ResourceKeys;
import org.deegree.model.csct.resources.css.Resources;
/**
* Describes a coordinate transformation. A coordinate transformation class establishes
* an association between a source and a target coordinate reference system, and provides
* a {@link MathTransform} for transforming coordinates in the source coordinate reference
* system to coordinates in the target coordinate reference system. These coordinate
* systems can be ground or image coordinates. In general mathematics, "transformation"
* is the general term for mappings between coordinate systems (see tensor analysis).
* <br><br>
* For a ground coordinate point, if the transformation depends only on mathematically
* derived parameters (as in a cartographic projection), then this is an ISO conversion.
* If the transformation depends on empirically derived parameters (as in datum
* transformations), then this is an ISO transformation.
*
* @version 1.00
* @author OpenGIS (www.opengis.org)
* @author Martin Desruisseaux
*
* @see org.opengis.ct.CT_CoordinateTransformation
*/
public class CoordinateTransformation extends Info {
/**
* Serial number for interoperability with different versions.
*/
private static final long serialVersionUID = -1850470924499685544L;
/**
* The source coordinate system.
*/
private final CoordinateSystem sourceCS;
/**
* The destination coordinate system.
*/
private final CoordinateSystem targetCS;
/**
* The transform type.
*/
private final TransformType type;
/**
* The underlying math transform, or <code>null</code> if it
* doesn't has been constructed yet. If <code>null</code>,
* then subclass <strong>must</strong> initialize this field
* the first time {@link #getMathTransform} is invoked.
*/
protected MathTransform transform;
/**
* The inverse transform. This field
* will be computed only when needed.
*/
transient CoordinateTransformation inverse;
/**
* Construct a coordinate transformation.
*
* @param name The coordinate transformation name, or <code>null</code>
* for an automatically generated name.
* @param sourceCS The source coordinate system.
* @param targetCS The destination coordinate system.
* @param type The transform type.
* @param transform The math transform. This argument is allowed to
* be <code>null</code> only if this constructor is
* invoked from within a subclass constructor. In
* this case, the subclass <strong>must</strong>
* construct a math transform no later than the first
* time {@link #getMathTransform} is invoked.
*/
public CoordinateTransformation( final String name, final CoordinateSystem sourceCS,
final CoordinateSystem targetCS, final TransformType type,
final MathTransform transform ) {
super( ( name != null ) ? name : "" );
this.sourceCS = sourceCS;
this.targetCS = targetCS;
this.type = type;
this.transform = transform;
ensureNonNull( "sourceCS", sourceCS );
ensureNonNull( "targetCS", targetCS );
ensureNonNull( "type", type );
if ( getClass().equals( CoordinateTransformation.class ) ) {
ensureNonNull( "transform", transform );
}
if ( transform.getDimSource() != sourceCS.getDimension() ) {
throw new IllegalArgumentException( "sourceCS" );
}
if ( transform.getDimTarget() != targetCS.getDimension() ) {
throw new IllegalArgumentException( "targetCS" );
}
}
/**
* Gets the name of this coordinate transformation.
*
* @param locale The desired locale, or <code>null</code> for the default locale.
*/
public String getName( final Locale locale ) {
final String name = super.getName( locale );
if ( name.length() != 0 )
return name;
else if ( transform instanceof AbstractMathTransform )
return ( (AbstractMathTransform) transform ).getName( locale );
else
return sourceCS.getName( locale ) + "\u00A0\u21E8\u00A0" + targetCS.getName( locale );
}
/**
* Gets the source coordinate system.
*
* @see org.opengis.ct.CT_CoordinateTransformation#getSourceCS()
*/
public CoordinateSystem getSourceCS() {
return sourceCS;
}
/**
* Gets the target coordinate system.
*
* @see org.opengis.ct.CT_CoordinateTransformation#getTargetCS()
*/
public CoordinateSystem getTargetCS() {
return targetCS;
}
/**
* Gets the semantic type of transform.
* For example, a datum transformation or a coordinate conversion.
*
* @see org.opengis.ct.CT_CoordinateTransformation#getTransformType()
*/
public TransformType getTransformType() {
return type;
}
/**
* Gets the math transform. The math transform will transform positions in
* the source coordinate system into positions in the target coordinate system.
*
* @see org.opengis.ct.CT_CoordinateTransformation#getMathTransform()
*/
public MathTransform getMathTransform() {
if ( transform != null ) {
return transform;
}
throw new IllegalStateException();
}
/**
* Returns the inverse transform of this object.
*/
public synchronized CoordinateTransformation inverse()
throws NoninvertibleTransformException {
if ( inverse == null ) {
inverse = new Inverse( this );
}
return inverse;
}
/**
* The inverse coordinate transformation. This class override
* {@link #getName} in order to delegate part of the call to
* the underlying direct transformation.
*
* @version 1.0
* @author Martin Desruisseaux
*/
private static final class Inverse extends CoordinateTransformation {
/**
* Construct a coordinate transformation.
*/
public Inverse( final CoordinateTransformation transform )
throws NoninvertibleTransformException {
super( null, transform.getTargetCS(), transform.getSourceCS(),
transform.getTransformType(), transform.getMathTransform().inverse() );
this.inverse = transform;
}
/**
* Gets the name of this coordinate transformation.
*/
public String getName( final Locale locale ) {
return Resources.getResources( locale ).getString( ResourceKeys.INVERSE_$1,
this.inverse.getName( locale ) );
}
}
/**
* Returns a hash value for this
* coordinate transformation.
*/
public int hashCode() {
int code = 7851236;
CoordinateSystem cs;
if ( ( cs = getSourceCS() ) != null )
code = code * 37 + cs.hashCode();
if ( ( cs = getTargetCS() ) != null )
code = code * 37 + cs.hashCode();
return code;
}
/**
* Compares the specified object with this coordinate transformation
* for equality. The default implementation compare name, transform
* type, source and target coordinate systems. It doesn't compare the
* math transform, since it should be equivalents if the above mentionned
* parameters are equal.
*/
public boolean equals( final Object object ) {
if ( object == this )
return true;
if ( super.equals( object ) ) {
final CoordinateTransformation that = (CoordinateTransformation) object;
return Utilities.equals( this.getTransformType(), that.getTransformType() )
&& Utilities.equals( this.getSourceCS(), that.getSourceCS() )
&& Utilities.equals( this.getTargetCS(), that.getTargetCS() );
}
return false;
}
}