Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2002-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2012, Geomatys
*
* 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.geotoolkit.referencing.operation.provider;
import java.util.Collection;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
import net.jcip.annotations.Immutable;
import org.opengis.util.GenericName;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.opengis.parameter.ParameterNotFoundException;
import org.opengis.parameter.InvalidParameterValueException;
import org.opengis.referencing.operation.Transformation;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.GeocentricCRS;
import org.opengis.referencing.ReferenceIdentifier;
import org.geotoolkit.metadata.iso.citation.Citations;
import org.geotoolkit.referencing.NamedIdentifier;
import org.geotoolkit.referencing.datum.BursaWolfParameters;
import org.geotoolkit.referencing.operation.MathTransformProvider;
import org.geotoolkit.referencing.operation.transform.MolodenskyTransform;
import org.geotoolkit.internal.referencing.MathTransformDecorator;
import org.geotoolkit.parameter.DefaultParameterDescriptor;
import org.geotoolkit.resources.Vocabulary;
import org.geotoolkit.resources.Errors;
import static java.util.Collections.singletonMap;
import static org.geotoolkit.parameter.Parameters.doubleValue;
import static org.geotoolkit.parameter.Parameters.integerValue;
import static org.geotoolkit.referencing.operation.provider.UniversalParameters.createDescriptor;
import static org.geotoolkit.referencing.operation.provider.UniversalParameters.createDescriptorGroup;
/**
* The provider for "Molodensky transformation" (EPSG:9604). This provider constructs
* transforms from {@linkplain GeographicCRS geographic} to geographic coordinate reference systems,
* without passing though {@linkplain GeocentricCRS geocentric} one.
*
* The translation terms (dx, dy and dz) are common to all authorities.
* But remaining parameters are specified in different ways depending on the authority:
*
OGC rather defines "{@code src_semi_major}", "{@code src_semi_minor}",
* "{@code tgt_semi_major}", "{@code tgt_semi_minor}" and "{@code dim}" parameters.
*
Geotk splits the OGC "{@code dim}" parameters in two separated
* "{@code src_dim}" and "{@code tgt_dim}" parameters.
*
*
*
*
The following table summarizes the parameters recognized by this provider.
* For a more detailed parameter list, see the {@link #PARAMETERS} constant.
*
Operation name: {@code Molodenski}
*
*
Parameter name
Default value
*
{@code dim}
2
*
{@code src_dim}
2
*
{@code tgt_dim}
2
*
{@code dx}
0 metres
*
{@code dy}
0 metres
*
{@code dz}
0 metres
*
{@code src_semi_major}
*
{@code src_semi_minor}
*
{@code tgt_semi_major}
*
{@code tgt_semi_minor}
*
{@code Semi-major axis length difference}
*
{@code Flattening difference}
*
*
*
* @author Rueben Schulz (UBC)
* @author Martin Desruisseaux (IRD, Geomatys)
* @version 3.20
*
* @see MolodenskyTransform
* @see Geotk coordinate operations matrix
*
* @since 2.1
* @module
*/
@Immutable
public class Molodensky extends MathTransformProvider {
/**
* Serial number for inter-operability with different versions.
*/
private static final long serialVersionUID = 8126525068450868912L;
/**
* The operation parameter descriptor for the number of geographic dimension (2 or 3).
* This argument applies on both the source and the target dimension. The default value
* is 2.
*
* Note: the default value may change in future versions, because the
* EPSG database implicitly uses the Molodensky transform in 3-dimensional operations.
* Users are well advised to always specify explicitely the dimension.
*
* @deprecated Invoke {@linkplain #PARAMETERS}.{@linkplain ParameterDescriptorGroup#descriptor(String)
* descriptor(String)} instead.
*/
@Deprecated
public static final ParameterDescriptor DIM = DefaultParameterDescriptor.create(
singletonMap(NAME_KEY, new NamedIdentifier(Citations.OGC, "dim")),
PositionVector7Param.DEFAULT_DIMENSION, 2, 3, false);
/**
* The operation parameter descriptor for the number of source geographic dimension (2 or 3).
* This is a Geotk-specific argument. The standard parameter is {@link #DIM}, which set both
* the source and target dimension.
*
* @deprecated Invoke {@linkplain #PARAMETERS}.{@linkplain ParameterDescriptorGroup#descriptor(String)
* descriptor(String)} instead.
*/
@Deprecated
public static final ParameterDescriptor SRC_DIM = PositionVector7Param.SRC_DIM;
/**
* The operation parameter descriptor for the number of target geographic dimension (2 or 3).
* This is a Geotk-specific argument. The standard parameter is {@link #DIM}, which set both
* the source and target dimension.
*
* @deprecated Invoke {@linkplain #PARAMETERS}.{@linkplain ParameterDescriptorGroup#descriptor(String)
* descriptor(String)} instead.
*/
@Deprecated
public static final ParameterDescriptor TGT_DIM = PositionVector7Param.TGT_DIM;
/**
* The operation parameter descriptor for the X-axis translation
* ({@linkplain BursaWolfParameters#dx dx}) parameter value. Valid values range
* from negative to positive infinity. Units are {@linkplain SI#METRE metres}.
*
* @deprecated Invoke {@linkplain #PARAMETERS}.{@linkplain ParameterDescriptorGroup#descriptor(String)
* descriptor(String)} instead.
*/
@Deprecated
public static final ParameterDescriptor DX = PositionVector7Param.DX;
/**
* The operation parameter descriptor for the Y-axis translation
* ({@linkplain BursaWolfParameters#dy dy}) parameter value. Valid values range
* from negative to positive infinity. Units are {@linkplain SI#METRE metres}.
*
* @deprecated Invoke {@linkplain #PARAMETERS}.{@linkplain ParameterDescriptorGroup#descriptor(String)
* descriptor(String)} instead.
*/
@Deprecated
public static final ParameterDescriptor DY = PositionVector7Param.DY;
/**
* The operation parameter descriptor for the Z-axis translation
* ({@linkplain BursaWolfParameters#dz dz}) parameter value. Valid values range
* from negative to positive infinity. Units are {@linkplain SI#METRE metres}.
*
* @deprecated Invoke {@linkplain #PARAMETERS}.{@linkplain ParameterDescriptorGroup#descriptor(String)
* descriptor(String)} instead.
*/
@Deprecated
public static final ParameterDescriptor DZ = PositionVector7Param.DZ;
/**
* The operation parameter descriptor for the {@code "src_semi_major"} parameter value.
* Valid values range from 0 to infinity. Units are {@linkplain SI#METRE metres}.
*
* @deprecated Invoke {@linkplain #PARAMETERS}.{@linkplain ParameterDescriptorGroup#descriptor(String)
* descriptor(String)} instead.
*/
@Deprecated
public static final ParameterDescriptor SRC_SEMI_MAJOR = createDescriptor(
identifiers(PositionVector7Param.SRC_SEMI_MAJOR),
Double.NaN, 0.0, Double.POSITIVE_INFINITY, SI.METRE, true);
/**
* The operation parameter descriptor for the {@code "src_semi_minor"} parameter value.
* Valid values range from 0 to infinity. Units are {@linkplain SI#METRE metres}.
*
* @deprecated Invoke {@linkplain #PARAMETERS}.{@linkplain ParameterDescriptorGroup#descriptor(String)
* descriptor(String)} instead.
*/
@Deprecated
public static final ParameterDescriptor SRC_SEMI_MINOR = createDescriptor(
identifiers(PositionVector7Param.SRC_SEMI_MINOR),
Double.NaN, 0.0, Double.POSITIVE_INFINITY, SI.METRE, true);
/**
* The operation parameter descriptor for the {@code "tgt_semi_major"} parameter value.
* Valid values range from 0 to infinity. Units are {@linkplain SI#METRE metres}.
*
* This parameter is mandatory, unless the {@link #AXIS_LENGTH_DIFFERENCE} parameter
* is defined in which case the later is used.
*
* @deprecated Invoke {@linkplain #PARAMETERS}.{@linkplain ParameterDescriptorGroup#descriptor(String)
* descriptor(String)} instead.
*/
@Deprecated
public static final ParameterDescriptor TGT_SEMI_MAJOR = createDescriptor(
identifiers(PositionVector7Param.TGT_SEMI_MAJOR),
Double.NaN, 0.0, Double.POSITIVE_INFINITY, SI.METRE, true);
/**
* The operation parameter descriptor for the {@code "tgt_semi_minor"} parameter value.
* Valid values range from 0 to infinity. Units are {@linkplain SI#METRE metres}.
*
* This parameter is mandatory, unless the {@link #FLATTENING_DIFFERENCE} parameter
* is defined in which case the later is used.
*
* @deprecated Invoke {@linkplain #PARAMETERS}.{@linkplain ParameterDescriptorGroup#descriptor(String)
* descriptor(String)} instead.
*/
@Deprecated
public static final ParameterDescriptor TGT_SEMI_MINOR = createDescriptor(
identifiers(PositionVector7Param.TGT_SEMI_MINOR),
Double.NaN, 0.0, Double.POSITIVE_INFINITY, SI.METRE, true);
/**
* The operation parameter descriptor for the Semi-major axis length difference
* optional parameter value. This parameter is defined by the EPSG database and can be used
* in replacement of {@link #TGT_SEMI_MAJOR}.
*
* Units are {@linkplain SI#METRE metres}.
*
* @since 3.19
*
* @deprecated Invoke {@linkplain #PARAMETERS}.{@linkplain ParameterDescriptorGroup#descriptor(String)
* descriptor(String)} instead.
*/
@Deprecated
public static final ParameterDescriptor AXIS_LENGTH_DIFFERENCE = createDescriptor(
new NamedIdentifier[] {
new NamedIdentifier(Citations.EPSG, "Semi-major axis length difference"),
},
Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, SI.METRE, false);
/**
* The operation parameter descriptor for the Flattening difference optional
* parameter value. This parameter is defined by the EPSG database and can be used in
* replacement of {@link #TGT_SEMI_MINOR}.
*
* Valid values range from -1 to +1, {@linkplain Unit#ONE dimensionless}.
*
* @since 3.19
*
* @deprecated Invoke {@linkplain #PARAMETERS}.{@linkplain ParameterDescriptorGroup#descriptor(String)
* descriptor(String)} instead.
*/
@Deprecated
public static final ParameterDescriptor FLATTENING_DIFFERENCE = createDescriptor(
new NamedIdentifier[] {
new NamedIdentifier(Citations.EPSG, "Flattening difference"),
},
Double.NaN, -1.0, +1.0, Unit.ONE, false);
/**
* Helper method for parameter descriptor creation.
*/
private static NamedIdentifier[] identifiers(final ParameterDescriptor parameter) {
final Collection id = parameter.getAlias();
return id.toArray(new NamedIdentifier[id.size()]);
}
/**
* The group of all parameters expected by this coordinate operation.
* The following table lists the operation names and the parameters recognized by Geotk.
* Note that the "Semi-major axis length difference" and "Flattening
* difference" parameters are exclusive with all {@code "src_*"} and {@code "tgt_*"}
* parameters (see class javadoc).
*
*
*
*
*
*
Name:
OGC:
Molodenski
*
Alias:
EPSG:
Molodensky
*
Geotk:
Molodensky transform
*
Identifier:
EPSG:
9604
*
*
*
*
*
Name:
OGC:
dim
*
*
*
*
Type:
{@code Integer}
*
Obligation:
optional
*
Value range:
[2…3]
*
Default value:
2
*
*
*
*
*
Name:
Geotk:
src_dim
*
*
*
*
Type:
{@code Integer}
*
Obligation:
optional
*
Value range:
[2…3]
*
Default value:
2
*
*
*
*
*
Name:
Geotk:
tgt_dim
*
*
*
*
Type:
{@code Integer}
*
Obligation:
optional
*
Value range:
[2…3]
*
Default value:
2
*
*
*
*
*
Name:
OGC:
dx
*
Alias:
EPSG:
X-axis translation
*
*
*
*
Type:
{@code Double}
*
Obligation:
mandatory
*
Value range:
(-∞ … ∞) metres
*
Default value:
0 metres
*
*
*
*
*
Name:
OGC:
dy
*
Alias:
EPSG:
Y-axis translation
*
*
*
*
Type:
{@code Double}
*
Obligation:
mandatory
*
Value range:
(-∞ … ∞) metres
*
Default value:
0 metres
*
*
*
*
*
Name:
OGC:
dz
*
Alias:
EPSG:
Z-axis translation
*
*
*
*
Type:
{@code Double}
*
Obligation:
mandatory
*
Value range:
(-∞ … ∞) metres
*
Default value:
0 metres
*
*
*
*
*
Name:
OGC:
src_semi_major
*
*
*
*
Type:
{@code Double}
*
Obligation:
mandatory
*
Value range:
[0…∞) metres
*
*
*
*
*
Name:
OGC:
src_semi_minor
*
*
*
*
Type:
{@code Double}
*
Obligation:
mandatory
*
Value range:
[0…∞) metres
*
*
*
*
*
Name:
OGC:
tgt_semi_major
*
*
*
*
Type:
{@code Double}
*
Obligation:
mandatory
*
Value range:
[0…∞) metres
*
*
*
*
*
Name:
OGC:
tgt_semi_minor
*
*
*
*
Type:
{@code Double}
*
Obligation:
mandatory
*
Value range:
[0…∞) metres
*
*
*
*
*
Name:
EPSG:
Semi-major axis length difference
*
*
*
*
Type:
{@code Double}
*
Obligation:
optional
*
Value range:
(-∞ … ∞) metres
*
*
*
*
*
Name:
EPSG:
Flattening difference
*
*
*
*
Type:
{@code Double}
*
Obligation:
optional
*
Value range:
[-1 … 1]
*
*
*
*/
public static final ParameterDescriptorGroup PARAMETERS = createDescriptorGroup(
new ReferenceIdentifier[] {
new NamedIdentifier(Citations.OGC, "Molodenski"),
new NamedIdentifier(Citations.EPSG, "Molodensky"),
new IdentifierCode (Citations.EPSG, 9604),
new NamedIdentifier(Citations.GEOTOOLKIT, Vocabulary.formatInternational(
Vocabulary.Keys.MOLODENSKY_TRANSFORM))
}, null, new ParameterDescriptor>[] {
DIM, SRC_DIM, TGT_DIM, DX, DY, DZ,
SRC_SEMI_MAJOR, SRC_SEMI_MINOR,
TGT_SEMI_MAJOR, TGT_SEMI_MINOR,
AXIS_LENGTH_DIFFERENCE,
FLATTENING_DIFFERENCE
}, 0);
/**
* The providers for all combinations between 2D and 3D cases. Array length is 4.
* Index is build with following rule:
*
*
Bit 1: dimension of source coordinates (0 for 2D, 1 for 3D).
*
Bit 0: dimension of target coordinates (0 for 2D, 1 for 3D).
*
*/
final Molodensky[] complements;
/**
* Returns the index in the {@link #complements} array for the given source and target
* dimensions, which must be either 2 or 3. This method assumes that the arguments have
* already been checked for validity.
*/
private static int index(final int sourceDimension, final int targetDimension) {
return ((sourceDimension & 1) << 1) | (targetDimension & 1);
}
/**
* Constructs a provider.
*/
public Molodensky() {
// Following constructors register themself in the "complements" array.
this(2, 2, PARAMETERS, new Molodensky[4]);
new Molodensky(2, 3, PARAMETERS, complements);
new Molodensky(3, 2, PARAMETERS, complements);
new Molodensky(3, 3, PARAMETERS, complements);
}
/**
* Constructs a provider from a set of parameters.
*
* @param sourceDimension Number of dimensions in the source CRS of this operation method.
* @param targetDimension Number of dimensions in the target CRS of this operation method.
* @param parameters The set of parameters (never {@code null}).
* @param complements Providers for all combinations between 2D and 3D cases.
*/
Molodensky(final int sourceDimension, final int targetDimension,
final ParameterDescriptorGroup parameters, final Molodensky[] complements)
{
super(sourceDimension, targetDimension, parameters);
this.complements = complements;
final int index = index(sourceDimension, targetDimension);
if (complements[index] != null) {
throw new AssertionError(index);
}
complements[index] = this;
}
/**
* Returns the operation type.
*/
@Override
public Class getOperationType() {
return Transformation.class;
}
/**
* Returns the dimension declared in the given parameter value, or 0 if none. If
* this method returns a non-zero value, then it is guaranteed to be either 2 or 3.
*
* @param descriptor The descriptor of the dimension to get.
* @param values The values from which to get the dimension.
* @return The dimension, or 0 if none.
* @throws InvalidParameterValueException if the dimension parameter has an invalid value.
*/
private static int dimension(final ParameterDescriptor descriptor, final ParameterValueGroup values)
throws InvalidParameterValueException
{
final Integer value = integerValue(descriptor, values);
if (value == null) {
return 0;
}
final int dimension = value; // Unboxing.
if (dimension != 2 && dimension != 3) {
final String name = descriptor.getName().getCode();
throw new InvalidParameterValueException(Errors.format(
Errors.Keys.ILLEGAL_ARGUMENT_$2, name, dimension), name, dimension);
}
return dimension;
}
/**
* Creates a math transform from the specified group of parameter values.
*
* @param values The group of parameter values.
* @return The created math transform.
* @throws ParameterNotFoundException if a required parameter was not found.
*/
@Override
protected MathTransform createMathTransform(final ParameterValueGroup values)
throws ParameterNotFoundException
{
int srcDim = sourceDimension;
int tgtDim = targetDimension;
int dimension = dimension(DIM, values);
if (dimension != 0) {
srcDim = tgtDim = dimension;
}
dimension = dimension(SRC_DIM, values);
if (dimension != 0) {
srcDim = dimension;
}
dimension = dimension(TGT_DIM, values);
if (dimension != 0) {
tgtDim = dimension;
}
final double a = doubleValue(SRC_SEMI_MAJOR, values);
final double b = doubleValue(SRC_SEMI_MINOR, values);
final double ta, tb;
double d = doubleValue(AXIS_LENGTH_DIFFERENCE, values);
ta = Double.isNaN(d) ? doubleValue(TGT_SEMI_MAJOR, values) : a + d;
d = doubleValue(FLATTENING_DIFFERENCE, values);
if (Double.isNaN(d)) {
tb = doubleValue(TGT_SEMI_MINOR, values);
} else {
tb = ta*(b/a - d);
}
final double dx = doubleValue(DX, values);
final double dy = doubleValue(DY, values);
final double dz = doubleValue(DZ, values);
MathTransform transform = MolodenskyTransform.create(isAbridged(),
a, b, srcDim == 3, ta, tb, tgtDim == 3, dx, dy, dz);
final Molodensky provider = complements[index(srcDim, tgtDim)];
if (provider != this) {
transform = new MathTransformDecorator(transform, provider);
}
return transform;
}
/**
* Returns {@code true} for the abridged formulas.
* This method is overridden by {@link AbridgedMolodensky}.
*/
boolean isAbridged() {
return false;
}
}