/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2003-2008, Open Source Geospatial Foundation (OSGeo) * * 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; * version 2.1 of the License. * * 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. */ package org.geotools.referencing.operation.transform; import java.io.Serializable; import java.util.Collection; import java.util.Collections; import javax.measure.unit.SI; import static java.lang.Math.*; import org.opengis.util.GenericName; import org.opengis.parameter.ParameterDescriptor; import org.opengis.parameter.ParameterDescriptorGroup; import org.opengis.parameter.ParameterNotFoundException; import org.opengis.parameter.ParameterValue; import org.opengis.parameter.ParameterValueGroup; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.MathTransform2D; import org.opengis.referencing.operation.Transformation; import org.geotools.metadata.iso.citation.Citations; import org.geotools.parameter.DefaultParameterDescriptor; import org.geotools.parameter.FloatParameter; import org.geotools.parameter.Parameter; import org.geotools.parameter.ParameterGroup; import org.geotools.referencing.NamedIdentifier; import org.geotools.referencing.operation.MathTransformProvider; import org.geotools.resources.i18n.VocabularyKeys; import org.geotools.resources.i18n.Vocabulary; import org.geotools.resources.i18n.ErrorKeys; import org.geotools.resources.i18n.Errors; /** * Two- or three-dimensional datum shift using the (potentially abridged) Molodensky transformation. * The Molodensky transformation (EPSG code 9604) and the abridged Molodensky transformation (EPSG * code 9605) transform two or three dimensional geographic points from one geographic coordinate * reference system to another (a datum shift), using three shift parameters (delta X, delta Y, * delta Z) and the difference between the semi-major axis and flattenings of the two ellipsoids. *
* * Unlike the Bursa-Wolf 3 parameter method (which acts on geocentric coordinates), * this transformation can be performed directly on geographic coordinates. *
* * References:
daa = da*a
and {@code da_a = da/a}).
*/
private final double daa, da_a;
/**
* The square of excentricity of the ellipsoid: e² = (a²-b²)/a² where
* a is the semi-major axis length and
* b is the semi-minor axis length.
*/
private final double e2;
/**
* Defined as (a*df) + (f*da)
.
*/
private final double adf;
/**
* The inverse of this transform. Will be created only when first needed.
*/
private transient MolodenskiTransform inverse;
/**
* Constructs a Molodenski transform from the specified parameters.
*
* @param abridged {@code true} for the abridged formula, or {@code false} for the complete one.
* @param a The source semi-major axis length in meters.
* @param b The source semi-minor axis length in meters.
* @param source3D {@code true} if the source has a height.
* @param ta The target semi-major axis length in meters.
* @param tb The target semi-minor axis length in meters.
* @param target3D {@code true} if the target has a height.
* @param dx The x translation in meters.
* @param dy The y translation in meters.
* @param dz The z translation in meters.
*/
public MolodenskiTransform(final boolean abridged,
final double a, final double b, final boolean source3D,
final double ta, final double tb, final boolean target3D,
final double dx, final double dy, final double dz)
{
this.abridged = abridged;
this.source3D = source3D;
this.target3D = target3D;
this.dx = dx;
this.dy = dy;
this.dz = dz;
this.a = a;
this.b = b;
da = ta - a;
db = tb - b;
a_b = a / b;
b_a = b / a;
daa = da * a;
da_a = da / a;
df = (ta-tb)/ta - (a-b)/a;
e2 = 1 - (b*b)/(a*a);
adf = (a*df) + (a-b)*da/a;
}
/**
* Returns the parameter descriptors for this math transform.
*/
@Override
public ParameterDescriptorGroup getParameterDescriptors() {
return abridged ? ProviderAbridged.PARAMETERS : Provider.PARAMETERS;
}
/**
* Returns the parameters for this math transform.
*
* @return The parameters for this math transform.
*/
@Override
public ParameterValueGroup getParameterValues() {
final ParameterValue*
* Note:
* The EPSG does not use src_semi_major, etc. parameters and instead uses
* "Semi-major axis length difference" and "Flattening difference".
*
* @version $Id$
* @author Rueben Schulz
*/
public static class Provider extends MathTransformProvider {
/**
* Serial number for interoperability with different versions.
*/
private static final long serialVersionUID = -5332126871499059030L;
/**
* The default value for source and target geographic dimensions, which is 2.
*/
// NOTE: If this default value is modified, then
// the handling of the 3D cases must be adjusted.
static final int DEFAULT_DIMENSION = GeocentricTranslation.Provider.DEFAULT_DIMENSION;
/**
* The number of geographic dimension (2 or 3). This argument applies on
* both the source and the target dimension. The default value is 2.
*/
public static final ParameterDescriptor
* Note:
* The EPSG does not use src_semi_major, etc. parameters and instead uses
* "Semi-major axis length difference" and "Flattening difference".
*
* @version $Id$
* @author Martin Desruisseaux
* @author Rueben Schulz
*/
public static class ProviderAbridged extends Provider {
/**
* Serial number for interoperability with different versions.
*/
private static final long serialVersionUID = 9148242601566635131L;
/**
* The parameters group.
*/
static final ParameterDescriptorGroup PARAMETERS = createDescriptorGroup(new NamedIdentifier[] {
new NamedIdentifier(Citations.OGC, "Abridged_Molodenski"),
new NamedIdentifier(Citations.EPSG, "Abridged Molodenski"),
new NamedIdentifier(Citations.EPSG, "9605"),
new NamedIdentifier(Citations.GEOTOOLS, Vocabulary.format(
VocabularyKeys.ABRIDGED_MOLODENSKI_TRANSFORM))
}, new ParameterDescriptor[] {
DIM, DX, DY, DZ,
SRC_SEMI_MAJOR, SRC_SEMI_MINOR,
TGT_SEMI_MAJOR, TGT_SEMI_MINOR
});
/**
* Constructs a provider.
*/
public ProviderAbridged() {
super(DEFAULT_DIMENSION, DEFAULT_DIMENSION, PARAMETERS);
}
/**
* Constructs a provider from a set of parameters.
*
* @param sourceDimensions Number of dimensions in the source CRS of this operation method.
* @param targetDimensions Number of dimensions in the target CRS of this operation method.
* @param parameters The set of parameters (never {@code null}).
*/
private ProviderAbridged(final int sourceDimensions,
final int targetDimensions,
final ParameterDescriptorGroup parameters)
{
super(sourceDimensions, targetDimensions, parameters);
}
/**
* Creates the 3D-version of this provider.
*/
@Override
Provider create3D() {
return new ProviderAbridged(3, 3, PARAMETERS);
}
/**
* Returns {@code true} for the abridged formulas.
*/
@Override
boolean isAbridged() {
return true;
}
}
}