Class EllipsoidToCentricTransform

All Implemented Interfaces:
Serializable, Parameterized, LenientComparable, org.opengis.referencing.operation.MathTransform

public class EllipsoidToCentricTransform extends AbstractMathTransform implements Serializable
Transform from two- or three- dimensional ellipsoidal coordinates to (geo)centric coordinates. This transform is usually (but not necessarily) part of a conversion from geographic to Cartesian geocentric coordinates. Each input coordinates is expected to contain:
  1. longitude (λ) relative to the prime meridian (usually Greenwich),
  2. latitude (φ),
  3. optionally height above the ellipsoid (h).
Output coordinates are as below:
  • In the Cartesian case:
    1. distance from Earth center on the X axis (toward the intersection of prime meridian and equator),
    2. distance from Earth center on the Y axis (toward the intersection of 90°E meridian and equator),
    3. distance from Earth center on the Z axis (toward North pole).
The units of measurements depend on how the MathTransform has been created:
  • EllipsoidToCentricTransform instances created directly by the constructor expect (λ,φ) values in radians and compute (X,Y,Z) values in units of an ellipsoid having a semi-major axis length of 1.
  • Transforms created by the createGeodeticConversion(…) static method expect (λ,φ) values in degrees and compute (X,Y,Z) values in units of the ellipsoid axes (usually metres).
Since:
0.7
Version:
1.3
See Also:
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    private static final class 
    Converts Cartesian coordinates (X,Y,Z) to ellipsoidal coordinates (λ,φ) or (λ,φ,h).
    static enum 
    Whether the output coordinate system is Cartesian or Spherical.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private double
    The b/a ratio where a is the semi-major axis length and b is the semi-minor axis length.
    (package private) final ContextualParameters
    The parameters used for creating this conversion.
    private static org.opengis.parameter.ParameterDescriptorGroup
    Internal parameter descriptor, used only for debugging purpose.
    private static final double
    Minimal eccentricity value before to consider that the approximated φ value should be made more accurate by the use of an iterative method.
    protected final double
    The square of eccentricity: ℯ² = (a²-b²)/a² where a is the semi-major axis length and b is the semi-minor axis length.
    private final AbstractMathTransform
    The inverse of this transform.
    private static final long
    Serial number for inter-operability with different versions.
    private boolean
    Whether calculation of φ should use an iterative method after the first φ approximation.
    (package private) final boolean
    true if ellipsoidal coordinates include an ellipsoidal height (i.e.

    Fields inherited from class org.apache.sis.referencing.operation.transform.AbstractMathTransform

    MAXIMUM_BUFFER_SIZE, MAXIMUM_FAILURES
  • Constructor Summary

    Constructors
    Constructor
    Description
    EllipsoidToCentricTransform(double semiMajor, double semiMinor, javax.measure.Unit<javax.measure.quantity.Length> unit, boolean withHeight, EllipsoidToCentricTransform.TargetType target)
    Creates a transform from angles in radians on ellipsoid having a semi-major axis length of 1.
  • Method Summary

    Modifier and Type
    Method
    Description
    (package private) final int
    beforeFormat(List<Object> transforms, int index, boolean inverse)
    Given a transformation chain to format in WKT, inserts a "Geographic 2D to 3D" pseudo-conversion before this transform (normally transforms.get(index)) if this conversion expects no height.
    protected int
    Computes a hash value for this transform.
    (package private) final EllipsoidToCentricTransform
    Creates a transform with the same parameters than this transform, but expecting two-dimensional inputs instead of three-dimensional.
    static org.opengis.referencing.operation.MathTransform
    createGeodeticConversion(org.opengis.referencing.operation.MathTransformFactory factory, double semiMajor, double semiMinor, javax.measure.Unit<javax.measure.quantity.Length> unit, boolean withHeight, EllipsoidToCentricTransform.TargetType target)
    Creates a transform from geographic to geocentric coordinates.
    static org.opengis.referencing.operation.MathTransform
    createGeodeticConversion(org.opengis.referencing.operation.MathTransformFactory factory, org.opengis.referencing.datum.Ellipsoid ellipsoid, boolean withHeight)
    Creates a transform from geographic to Cartesian geocentric coordinates (convenience method).
    org.opengis.referencing.operation.Matrix
    derivative(org.opengis.geometry.DirectPosition point)
    Computes the derivative at the given location.
    boolean
    equals(Object object, ComparisonMode mode)
    Compares the specified object with this math transform for equality.
    Returns the parameters used for creating the complete conversion.
    org.opengis.parameter.ParameterDescriptorGroup
    Returns a description of the internal parameters of this EllipsoidToCentricTransform transform.
    org.opengis.parameter.ParameterValueGroup
    Returns a copy of internal parameter values of this EllipsoidToCentricTransform transform.
    final int
    Gets the dimension of input points, which is 2 or 3.
    final int
    Gets the dimension of output points, which is 3.
    Returns whether the target coordinate system is Cartesian or Spherical.
    org.opengis.referencing.operation.MathTransform
    Returns the inverse of this transform.
    protected void
    inverseTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts)
    Converts Cartesian coordinates (X,Y,Z) to ellipsoidal coordinates (λ,φ) or (λ,φ,h).
    private void
    Restores transient fields after deserialization.
    org.opengis.referencing.operation.Matrix
    transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, boolean derivate)
    Converts the (λ,φ) or (λ,φ,h) geodetic coordinates to to (X,Y,Z) geocentric coordinates, and optionally returns the derivative at that location.
    void
    transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts)
    Converts the (λ,φ) or (λ,φ,h) geodetic coordinates to to (X,Y,Z) geocentric coordinates.
    private org.opengis.referencing.operation.Matrix
    transform(double λ, double φ, double h, double[] dstPts, int dstOff, boolean derivate, boolean wh)
    Implementation of transform(double[], int, double[], int, boolean) with possibility to override the withHeight value.
    protected org.opengis.referencing.operation.MathTransform
    tryConcatenate(boolean applyOtherFirst, org.opengis.referencing.operation.MathTransform other, org.opengis.referencing.operation.MathTransformFactory factory)
    If this transform expects three-dimensional inputs, and if the transform just before this one unconditionally sets the height to zero, then replaces this transform by a two-dimensional one.

    Methods inherited from class org.apache.sis.referencing.operation.transform.AbstractMathTransform

    equals, formatTo, getDomain, hashCode, isIdentity, isInverseEquals, mismatchedDimension, transform, transform, transform, transform

    Methods inherited from class org.apache.sis.io.wkt.FormattableObject

    print, toString, toString, toWKT

    Methods inherited from class java.lang.Object

    clone, finalize, getClass, notify, notifyAll, wait, wait, wait

    Methods inherited from interface org.opengis.referencing.operation.MathTransform

    toWKT
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      Serial number for inter-operability with different versions.
      See Also:
    • DESCRIPTOR

      @Debug private static org.opengis.parameter.ParameterDescriptorGroup DESCRIPTOR
      Internal parameter descriptor, used only for debugging purpose. Created only when first needed.
      See Also:
    • ECCENTRICITY_THRESHOLD

      private static final double ECCENTRICITY_THRESHOLD
      Minimal eccentricity value before to consider that the approximated φ value should be made more accurate by the use of an iterative method. The iterative method is not needed for a planet of Earth eccentricity, but become useful for planets of higher eccentricity.

      Actually the need for iteration is not just a matter of eccentricity. It is also a matter of h values. But empirical tests suggest that with Earth's eccentricity (about 0.082), the limit for h is quite high (close to 2000 km for a point at 30°N). This limit is reduced to about 200 km for an eccentricity of 0.16. It may be possible to find a formula for the limit of h as a function of ℯ and φ, but this has not been explored yet.

      See Also:
    • eccentricitySquared

      protected final double eccentricitySquared
      The square of eccentricity: ℯ² = (a²-b²)/a² where a is the semi-major axis length and b is the semi-minor axis length.
    • axisRatio

      private transient double axisRatio
      The b/a ratio where a is the semi-major axis length and b is the semi-minor axis length. Since the EllipsoidToCentricTransform class works on an ellipsoid where a = 1 (because of the work performed by the normalization matrices), we just drop a in the formulas - so this field could be written as just b.

      This value is related to eccentricitySquared and to the ε value used in EPSG guide by (assuming a=1):

      • ℯ² = 1 - b²
      • ε = ℯ²/b²

      Consider this field as final! It is not final only for the purpose of readObject(ObjectInputStream). This field is recomputed from eccentricitySquared on deserialization.

    • useIterations

      private transient boolean useIterations
      Whether calculation of φ should use an iterative method after the first φ approximation. The current implementation sets this field to true at construction time when the eccentricity value is greater than or equals to ECCENTRICITY_THRESHOLD, but this policy may change in any future SIS version (for example we do not take the h values in account yet).

      Consider this field as final! It is not final only for the purpose of readObject(ObjectInputStream). This field is not serialized because its value may depend on the version of this EllipsoidToCentricTransform class.

    • withHeight

      final boolean withHeight
      true if ellipsoidal coordinates include an ellipsoidal height (i.e. are 3-D). If false, then the input coordinates are expected to be two-dimensional and the ellipsoidal height is assumed to be 0.
    • context

      final ContextualParameters context
      The parameters used for creating this conversion. They are used for formatting Well Known Text (WKT) and error messages.
      See Also:
    • inverse

      private final AbstractMathTransform inverse
      The inverse of this transform.
      Note: creation of this object is not deferred to the first call to the inverse() method because this object is lightweight and typically needed soon anyway (may be as soon as ConcatenatedTransform construction time). In addition this field is part of serialization form in order to preserve the references graph.
  • Constructor Details

    • EllipsoidToCentricTransform

      public EllipsoidToCentricTransform(double semiMajor, double semiMinor, javax.measure.Unit<javax.measure.quantity.Length> unit, boolean withHeight, EllipsoidToCentricTransform.TargetType target)
      Creates a transform from angles in radians on ellipsoid having a semi-major axis length of 1. More specifically EllipsoidToCentricTransform instances expect input coordinates as below:
      1. longitudes in radians relative to the prime meridian (usually Greenwich),
      2. latitudes in radians,
      3. optionally heights above the ellipsoid, in units of an ellipsoid having a semi-major axis length of 1.
      Output coordinates are as below, in units of an ellipsoid having a semi-major axis length of 1:
      1. distance from Earth center on the X axis (toward the intersection of prime meridian and equator),
      2. distance from Earth center on the Y axis (toward the intersection of 90°E meridian and equator),
      3. distance from Earth center on the Z axis (toward North pole).

      Geographic to geocentric conversions

      For converting geographic coordinates to geocentric coordinates, EllipsoidToCentricTransform instances need to be concatenated with the following affine transforms:
      • Normalization before EllipsoidToCentricTransform:
        • Conversion of (λ,φ) from degrees to radians
        • Division of (h) by the semi-major axis length
      • Denormalization after EllipsoidToCentricTransform:
        • Multiplication of (X,Y,Z) by the semi-major axis length
      After EllipsoidToCentricTransform construction, the full conversion chain including the above affine transforms can be created by getContextualParameters().completeTransform(factory, this)}.
      Parameters:
      semiMajor - the semi-major axis length.
      semiMinor - the semi-minor axis length.
      unit - the unit of measurement for the semi-axes and the ellipsoidal height.
      withHeight - true if source geographic coordinates include an ellipsoidal height (i.e. are 3-D), or false if they are only 2-D.
      target - whether the target coordinate shall be Cartesian or Spherical.
      See Also:
  • Method Details

    • readObject

      private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
      Restores transient fields after deserialization.
      Parameters:
      in - the input stream from which to deserialize the transform.
      Throws:
      IOException - if an I/O error occurred while reading or if the stream contains invalid data.
      ClassNotFoundException - if the class serialized on the stream is not on the classpath.
    • createGeodeticConversion

      public static org.opengis.referencing.operation.MathTransform createGeodeticConversion(org.opengis.referencing.operation.MathTransformFactory factory, double semiMajor, double semiMinor, javax.measure.Unit<javax.measure.quantity.Length> unit, boolean withHeight, EllipsoidToCentricTransform.TargetType target) throws org.opengis.util.FactoryException
      Creates a transform from geographic to geocentric coordinates. This factory method combines the EllipsoidToCentricTransform instance with the steps needed for converting degrees to radians and expressing the results in units of the given ellipsoid.

      Input coordinates are expected to contain:

      1. longitudes in degrees relative to the prime meridian (usually Greenwich),
      2. latitudes in degrees,
      3. optionally heights above the ellipsoid, in units of the ellipsoid axis (usually metres).
      Output coordinates are as below, in units of the ellipsoid axis (usually metres):
      1. distance from Earth center on the X axis (toward the intersection of prime meridian and equator),
      2. distance from Earth center on the Y axis (toward the intersection of 90°E meridian and equator),
      3. distance from Earth center on the Z axis (toward North pole).
      Parameters:
      factory - the factory to use for creating and concatenating the affine transforms.
      semiMajor - the semi-major axis length.
      semiMinor - the semi-minor axis length.
      unit - the unit of measurement for the semi-axes and the ellipsoidal height.
      withHeight - true if source geographic coordinates include an ellipsoidal height (i.e. are 3-D), or false if they are only 2-D.
      target - whether the target coordinate shall be Cartesian or Spherical.
      Returns:
      the conversion from geographic to geocentric coordinates.
      Throws:
      org.opengis.util.FactoryException - if an error occurred while creating a transform.
    • createGeodeticConversion

      public static org.opengis.referencing.operation.MathTransform createGeodeticConversion(org.opengis.referencing.operation.MathTransformFactory factory, org.opengis.referencing.datum.Ellipsoid ellipsoid, boolean withHeight) throws org.opengis.util.FactoryException
      Creates a transform from geographic to Cartesian geocentric coordinates (convenience method). Invoking this method is equivalent to the following: The target type is assumed Cartesian because this is the most frequently used target.
      Parameters:
      factory - the factory to use for creating and concatenating the affine transforms.
      ellipsoid - the semi-major and semi-minor axis lengths with their unit of measurement.
      withHeight - true if source geographic coordinates include an ellipsoidal height (i.e. are 3-D), or false if they are only 2-D.
      Returns:
      the conversion from geographic to Cartesian geocentric coordinates.
      Throws:
      org.opengis.util.FactoryException - if an error occurred while creating a transform.
    • getContextualParameters

      protected ContextualParameters getContextualParameters()
      Returns the parameters used for creating the complete conversion. Those parameters describe a sequence of normalizethisdenormalize transforms, not including axis swapping. Those parameters are used for formatting Well Known Text (WKT) and error messages.
      Overrides:
      getContextualParameters in class AbstractMathTransform
      Returns:
      the parameter values for the sequence of normalizethisdenormalize transforms.
    • getParameterValues

      @Debug public org.opengis.parameter.ParameterValueGroup getParameterValues()
      Returns a copy of internal parameter values of this EllipsoidToCentricTransform transform. The returned group contains parameter values for the number of dimensions and the eccentricity.
      Note: this method is mostly for debugging purposes since the isolation of non-linear parameters in this class is highly implementation dependent. Most GIS applications will instead be interested in the contextual parameters.
      Specified by:
      getParameterValues in interface Parameterized
      Overrides:
      getParameterValues in class AbstractMathTransform
      Returns:
      a copy of the internal parameter values for this transform.
      See Also:
    • getParameterDescriptors

      @Debug public org.opengis.parameter.ParameterDescriptorGroup getParameterDescriptors()
      Returns a description of the internal parameters of this EllipsoidToCentricTransform transform. The returned group contains parameter descriptors for the number of dimensions and the eccentricity.
      Specified by:
      getParameterDescriptors in interface Parameterized
      Overrides:
      getParameterDescriptors in class AbstractMathTransform
      Returns:
      a description of the internal parameters.
      See Also:
    • getSourceDimensions

      public final int getSourceDimensions()
      Gets the dimension of input points, which is 2 or 3.
      Specified by:
      getSourceDimensions in interface org.opengis.referencing.operation.MathTransform
      Specified by:
      getSourceDimensions in class AbstractMathTransform
      Returns:
      2 or 3.
      See Also:
    • getTargetDimensions

      public final int getTargetDimensions()
      Gets the dimension of output points, which is 3.
      Specified by:
      getTargetDimensions in interface org.opengis.referencing.operation.MathTransform
      Specified by:
      getTargetDimensions in class AbstractMathTransform
      Returns:
      always 3.
      See Also:
    • getTargetType

      public final EllipsoidToCentricTransform.TargetType getTargetType()
      Returns whether the target coordinate system is Cartesian or Spherical.
      Returns:
      whether the target coordinate system is Cartesian or Spherical.
    • derivative

      public org.opengis.referencing.operation.Matrix derivative(org.opengis.geometry.DirectPosition point) throws org.opengis.referencing.operation.TransformException
      Computes the derivative at the given location. This method relaxes a little bit the MathTransform contract by accepting two- or three-dimensional points even if the number of dimensions does not match the getSourceDimensions() value.
      Rational: that flexibility on the number of dimensions is required for calculation of inverse transform derivative, because that calculation needs to inverse a square matrix with all terms in it before to drop the last row in the two-dimensional case.
      Specified by:
      derivative in interface org.opengis.referencing.operation.MathTransform
      Overrides:
      derivative in class AbstractMathTransform
      Parameters:
      point - the position where to evaluate the derivative.
      Returns:
      the derivative at the specified point (never null).
      Throws:
      org.opengis.referencing.operation.TransformException - if the derivative cannot be evaluated at the specified point.
    • transform

      public org.opengis.referencing.operation.Matrix transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, boolean derivate) throws org.opengis.referencing.operation.TransformException
      Converts the (λ,φ) or (λ,φ,h) geodetic coordinates to to (X,Y,Z) geocentric coordinates, and optionally returns the derivative at that location.
      Specified by:
      transform in class AbstractMathTransform
      Parameters:
      srcPts - the array containing the source coordinates (cannot be null).
      srcOff - the offset to the point to be transformed in the source array.
      dstPts - the array into which the transformed coordinates is returned. May be the same than srcPts. May be null if only the derivative matrix is desired.
      dstOff - the offset to the location of the transformed point that is stored in the destination array.
      derivate - true for computing the derivative, or false if not needed.
      Returns:
      the matrix of the transform derivative at the given source position, or null if the derivate argument is false.
      Throws:
      org.opengis.referencing.operation.TransformException - if the point cannot be transformed or if a problem occurred while calculating the derivative.
      See Also:
    • transform

      private org.opengis.referencing.operation.Matrix transform(double λ, double φ, double h, double[] dstPts, int dstOff, boolean derivate, boolean wh)
      Implementation of transform(double[], int, double[], int, boolean) with possibility to override the withHeight value.
      Parameters:
      \u03bb - longitude (radians).
      \u03c6 - latitude (radians).
      h - height above the ellipsoid divided by the length of semi-major axis.
      dstPts - the array into which the transformed coordinate is returned. May be null if only the derivative matrix is desired.
      dstOff - the offset to the location of the transformed point that is stored in the destination array.
      derivate - true for computing the derivative, or false if not needed.
      wh - true for a 3×3 matrix, or false for a 3×2 matrix excluding the height elements.
    • transform

      public void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) throws org.opengis.referencing.operation.TransformException
      Converts the (λ,φ) or (λ,φ,h) geodetic coordinates to to (X,Y,Z) geocentric coordinates. This method performs the same conversion than transform(double[], int, double[], int, boolean), but the formulas are repeated here for performance reasons.
      Specified by:
      transform in interface org.opengis.referencing.operation.MathTransform
      Overrides:
      transform in class AbstractMathTransform
      Parameters:
      srcPts - the array containing the source point coordinates.
      srcOff - the offset to the first point to be transformed in the source array.
      dstPts - the array into which the transformed point coordinates are returned. May be the same than srcPts.
      dstOff - the offset to the location of the first transformed point that is stored in the destination array.
      numPts - the number of point objects to be transformed.
      Throws:
      org.opengis.referencing.operation.TransformException - if a point cannot be transformed.
    • inverseTransform

      protected void inverseTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) throws org.opengis.referencing.operation.TransformException
      Converts Cartesian coordinates (X,Y,Z) to ellipsoidal coordinates (λ,φ) or (λ,φ,h). This method is invoked by the transform returned by inverse().
      Parameters:
      srcPts - the array containing the source point coordinates.
      srcOff - the offset to the first point to be transformed in the source array.
      dstPts - the array into which the transformed point coordinates are returned. May be the same than srcPts.
      dstOff - the offset to the location of the first transformed point that is stored in the destination array.
      numPts - the number of point objects to be transformed.
      Throws:
      org.opengis.referencing.operation.TransformException - if the calculation does not converge.
    • inverse

      public org.opengis.referencing.operation.MathTransform inverse()
      Returns the inverse of this transform. The default implementation returns a transform that will delegate its work to inverseTransform(double[], int, double[], int, int).
      Specified by:
      inverse in interface org.opengis.referencing.operation.MathTransform
      Overrides:
      inverse in class AbstractMathTransform
      Returns:
      the conversion from (geo)centric to ellipsoidal coordinates.
    • computeHashCode

      protected int computeHashCode()
      Computes a hash value for this transform. This method is invoked by AbstractMathTransform.hashCode() when first needed.
      Overrides:
      computeHashCode in class AbstractMathTransform
      Returns:
      the hash code value. This value may change between different execution of the Apache SIS library.
    • equals

      public boolean equals(Object object, ComparisonMode mode)
      Compares the specified object with this math transform for equality.
      Specified by:
      equals in interface LenientComparable
      Overrides:
      equals in class AbstractMathTransform
      Parameters:
      object - the object to compare with this transform.
      mode - the strictness level of the comparison. Default to STRICT.
      Returns:
      true if the given object is considered equals to this math transform.
      See Also:
    • beforeFormat

      final int beforeFormat(List<Object> transforms, int index, boolean inverse)
      Given a transformation chain to format in WKT, inserts a "Geographic 2D to 3D" pseudo-conversion before this transform (normally transforms.get(index)) if this conversion expects no height.
      Overrides:
      beforeFormat in class AbstractMathTransform
      Parameters:
      transforms - the full chain of concatenated transforms.
      index - the index of this transform in the transforms chain.
      inverse - always false, except if we are formatting the inverse transform.
      Returns:
      index of this transform in the transforms chain after processing.
      See Also:
    • tryConcatenate

      protected org.opengis.referencing.operation.MathTransform tryConcatenate(boolean applyOtherFirst, org.opengis.referencing.operation.MathTransform other, org.opengis.referencing.operation.MathTransformFactory factory) throws org.opengis.util.FactoryException
      If this transform expects three-dimensional inputs, and if the transform just before this one unconditionally sets the height to zero, then replaces this transform by a two-dimensional one. The intent is to handle the following sequence of operations defined in the EPSG database:
      1. Inverse of Geographic 3D to 2D conversion (EPSG:9659)
      2. Geographic/geocentric conversions (EPSG:9602)
      Replacing the above sequence by a two-dimensional EllipsoidToCentricTransform instance allow the following optimizations:
      • Avoid computation of h value.
      • Allow use of the more efficient AffineTransform before this transform instead of a transform based on a matrix of size 4×3.
      Overrides:
      tryConcatenate in class AbstractMathTransform
      Parameters:
      applyOtherFirst - true if the transformation order is other followed by this, or false if the transformation order is this followed by other.
      other - the other math transform to (pre-)concatenate with this transform.
      factory - the factory which is (indirectly) invoking this method, or null if none.
      Returns:
      the combined math transform, or null if no optimized combined transform is available.
      Throws:
      org.opengis.util.FactoryException - if an error occurred while combining the transforms.
      See Also:
    • create2D

      final EllipsoidToCentricTransform create2D()
      Creates a transform with the same parameters than this transform, but expecting two-dimensional inputs instead of three-dimensional.