Class ConformalProjection

All Implemented Interfaces:
Serializable, Parameterized, LenientComparable, org.opengis.referencing.operation.MathTransform, org.opengis.referencing.operation.MathTransform2D
Direct Known Subclasses:
LambertConicConformal, Mercator, ObliqueMercator, PolarStereographic

abstract class ConformalProjection extends NormalizedProjection
Base class of LambertConicConformal, Mercator and PolarStereographic projections. Those projections have in common the property of being conformal, i.e. they preserve angles locally. However, we do not put this base class in public API because not all conformal projections extend this base class. For example, the TransverseMercator projection, despite being conformal, uses very different formulas.

Note that no projection can be both conformal and equal-area. So the formulas in this class are usually mutually exclusive with formulas in AuthalicConversion class (used for equal-area projections).

This base class can be seen as a generalization of Lambert Conic Conformal projection, which includes some other projections like Mercator and Polar Stereographic as special cases. For this base class, the Mercator projection is considered as "a special limiting case of the Lambert Conic Conformal map projection with the equator as the single standard parallel." (Source: §1.3.3 in IOGP Publication 373-7-2 – Geomatics Guidance Note number 7, part 2 – April 2015). Indeed, those two projections have some equation in commons which are provided in this base class.

The Polar Stereographic projection is not documented as a special case of Lambert Conic Conformal, but the equations in the PolarStereographic.transform(…) and inverseTransform(…) methods appear to be the same with the n factor fixed to 1 or -1, so we leverage the code provided by this base class. This class hierarchy is only an implementation convenience and not part of public API.

The Transverse Mercator projection is also conformal, but does not use the formulas provided in this class. It will instead compute the coefficients itself and use its own, more complex, formulas with those coefficients. However, the formulas provided in this ConformalProjection class can be seen as a special case of Transverse Mercator formulas for x = 0.

Reference: “Lambert developed the regular Conformal Conic as the oblique aspect of a family containing the previously known polar Stereographic and regular Mercator projections. (…) If the standard parallels are symmetrical about the Equator, the regular Mercator results (although formulas must be revised). If the only standard parallel is a pole, the polar Stereographic results.” (Snyder, page 105)
Since:
0.6
Version:
1.0
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      For cross-version compatibility.
      See Also:
    • ECCENTRICITY_THRESHOLD

      static final double ECCENTRICITY_THRESHOLD
      The threshold value of NormalizedProjection.eccentricity at which we consider the accuracy of the series expansion insufficient. This threshold is determined empirically with the help of the MercatorMethodComparison class in the test directory. We choose the value where:
      See Also:
    • useIterations

      private final boolean useIterations
      true if the NormalizedProjection.eccentricity value is greater than or equals to ECCENTRICITY_THRESHOLD, in which case the φ(double) method will need to use an iterative method.
    • c2χ

      private final double c2χ
      Coefficients of the first terms in the series expansion of the reverse projection. Values of those coefficients depend only on eccentricity value. The series expansion is published under the following form, where χ is the conformal latitude:
      c₂⋅sin(2χ) + c₄⋅sin(4χ) + c₆⋅sin(6χ) + c₈⋅sin(8χ)
      However, we rewrite above series expansion for taking advantage of trigonometric identities. The equation become (with different c values):
      sin(2χ)⋅(c₂ + cos(2χ)⋅(c₄ + cos(2χ)⋅(c₆ + cos(2χ)⋅c₈)))
      Serialization note: we do not strictly need to serialize those fields since they could be computed after deserialization. Bu we serialize them anyway in order to simplify a little bit this class (it allows us to keep those fields final) and because values computed after deserialization could be slightly different than the ones computed after construction if a future version of the constructor uses the double-double values provided by Initializer.
    • c4χ

      private final double c4χ
      Coefficients of the first terms in the series expansion of the reverse projection. Values of those coefficients depend only on eccentricity value. The series expansion is published under the following form, where χ is the conformal latitude:
      c₂⋅sin(2χ) + c₄⋅sin(4χ) + c₆⋅sin(6χ) + c₈⋅sin(8χ)
      However, we rewrite above series expansion for taking advantage of trigonometric identities. The equation become (with different c values):
      sin(2χ)⋅(c₂ + cos(2χ)⋅(c₄ + cos(2χ)⋅(c₆ + cos(2χ)⋅c₈)))
      Serialization note: we do not strictly need to serialize those fields since they could be computed after deserialization. Bu we serialize them anyway in order to simplify a little bit this class (it allows us to keep those fields final) and because values computed after deserialization could be slightly different than the ones computed after construction if a future version of the constructor uses the double-double values provided by Initializer.
    • c6χ

      private final double c6χ
      Coefficients of the first terms in the series expansion of the reverse projection. Values of those coefficients depend only on eccentricity value. The series expansion is published under the following form, where χ is the conformal latitude:
      c₂⋅sin(2χ) + c₄⋅sin(4χ) + c₆⋅sin(6χ) + c₈⋅sin(8χ)
      However, we rewrite above series expansion for taking advantage of trigonometric identities. The equation become (with different c values):
      sin(2χ)⋅(c₂ + cos(2χ)⋅(c₄ + cos(2χ)⋅(c₆ + cos(2χ)⋅c₈)))
      Serialization note: we do not strictly need to serialize those fields since they could be computed after deserialization. Bu we serialize them anyway in order to simplify a little bit this class (it allows us to keep those fields final) and because values computed after deserialization could be slightly different than the ones computed after construction if a future version of the constructor uses the double-double values provided by Initializer.
    • c8χ

      private final double c8χ
      Coefficients of the first terms in the series expansion of the reverse projection. Values of those coefficients depend only on eccentricity value. The series expansion is published under the following form, where χ is the conformal latitude:
      c₂⋅sin(2χ) + c₄⋅sin(4χ) + c₆⋅sin(6χ) + c₈⋅sin(8χ)
      However, we rewrite above series expansion for taking advantage of trigonometric identities. The equation become (with different c values):
      sin(2χ)⋅(c₂ + cos(2χ)⋅(c₄ + cos(2χ)⋅(c₆ + cos(2χ)⋅c₈)))
      Serialization note: we do not strictly need to serialize those fields since they could be computed after deserialization. Bu we serialize them anyway in order to simplify a little bit this class (it allows us to keep those fields final) and because values computed after deserialization could be slightly different than the ones computed after construction if a future version of the constructor uses the double-double values provided by Initializer.
  • Constructor Details

    • ConformalProjection

      ConformalProjection(Initializer initializer)
      Creates a new normalized projection from the parameters computed by the given initializer. This constructor computes the coefficients in the series expansion from the NormalizedProjection.eccentricitySquared value.
      Parameters:
      initializer - the initializer for computing map projection internal parameters.
    • ConformalProjection

      ConformalProjection(ConformalProjection other)
      Creates a new projection initialized to the values of the given one. This constructor may be invoked after we determined that the default implementation can be replaced by another one, for example using spherical formulas instead of the ellipsoidal ones. This constructor allows to transfer all parameters to the new instance without recomputing them.
  • Method Details

    • φ

      final double φ(double rexpΨ) throws ProjectionException
      Computes the latitude for a value closely related to the y value of a Mercator projection. This formula is also part of other projections, since Mercator can be considered as a special case of Lambert Conic Conformal for instance.

      This function is almost the converse of the expΨ(double, double) function. In a Mercator reverse projection, the value of the rexpΨ argument is exp(-Ψ).

      The input should be a positive number, otherwise the result will be either outside the [-π/2 … π/2] range, or will be NaN. Its behavior at some particular points is:

      • φ(0) = π/2
      • φ(1) = 0
      • φ(∞) = -π/2
      Note: §1.3.3 in Geomatics Guidance Note number 7 part 2 (April 2015) uses a series expansion while USGS used an iterative method. The series expansion is twice faster than the iterative method for the same precision, but this precision is achieved "only" for relatively small eccentricity like the Earth's one. See the MercatorMethodComparison class in the test package for more discussion.
      Parameters:
      rexpΨ - the reciprocal of the value returned by expΨ(double, double).
      Returns:
      the latitude in radians.
      Throws:
      ProjectionException - if the iteration does not converge.
      See Also:
    • expΨ

      final double expΨ(double φ, double ℯsinφ)
      Computes exp(Ψ) where Ψ is the isometric latitude. This is part of the Mercator projection for the given latitude. This formula is also part of Lambert Conic Conformal projection, since Mercator can be considered as a special case of that Lambert projection with the equator as the single standard parallel.

      The isometric latitude is given by the natural logarithm of the value returned by this method. The reciprocal of this function 1/expΨ(φ) is the converse of φ(double). Isometric latitude Ψ is related to conformal latitude χ by χ(φ) = gd(Ψ(φ)) where gd(x) is the Gudermannian function. There is many representations of that function, e.g. gd(Ψ) = 2⋅atan(expΨ) - π/2.

      In IOGP Publication 373-7-2 – Geomatics Guidance Note number 7, part 2 – April 2015, a function closely related to this method has the letter t.

      Properties

      This function is used with φ values in the [-π/2 … π/2] range and has a periodicity of 2π. The result is always a positive number when the φ argument is inside the above-cited range. If, after removal of any 2π periodicity, φ is still outside the [-π/2 … π/2] range, then the result is a negative number. In a Mercator projection, such negative number will result in NaN.

      Some values are:

      • expΨ(NaN) = NaN
      • expΨ(±∞) = NaN
      • expΨ(-π/2) = 0
      • expΨ( 0 ) = 1
      • expΨ(+π/2) → ∞ (actually some large value like 1.633E+16)
      • expΨ(-φ) = 1 / expΨ(φ)

      The π/2 special case

      The value at Math.PI/2 is not exactly infinity because there is no exact representation of π/2. However, since the conversion of 90° to radians gives Math.PI/2, we can presume that the user was expecting infinity. The caller should check for the PI/2 special case himself if desired, as this method does nothing special about it.

      Note that the result for the φ value after Math.PI/2 (as given by Math.nextUp(double)) is still positive, maybe because PI/2 < π/2 < nextUp(PI/2). Only the nextUp(nextUp(PI/2)) value become negative. Callers may need to take this behavior in account: special check for Math.PI/2 is not sufficient, the check needs to include at least the nextUp(Math.PI/2) case.

      Relationship with Snyder

      This function is related to the following functions from Snyder:
      • (7-7) in the Mercator projection chapter.
      • Reciprocal of (9-13) in the Oblique Mercator projection chapter.
      • Reciprocal of (15-9) in the Lambert Conformal Conic projection chapter.
      Parameters:
      φ - the latitude in radians.
      ℯsinφ - the sine of the φ argument multiplied by NormalizedProjection.eccentricity.
      Returns:
      Math.exp(Ψ) where Ψ is the isometric latitude.
      See Also:
    • dy_dφ

      final double dy_dφ(double sinφ, double cosφ)
      Computes the partial derivative of a Mercator projection at the given latitude. This formula is also part of other projections, since Mercator can be considered as a special case of Lambert Conic Conformal for instance.

      In order to get the derivative of the expΨ(double, double) function, caller can multiply the returned value by expΨ.

      Parameters:
      sinφ - the sine of latitude.
      cosφ - the cosine of latitude.
      Returns:
      the partial derivative of a Mercator projection at the given latitude.
      See Also: