Class LongitudeWraparound

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

final class LongitudeWraparound extends AbstractMathTransform2D implements Serializable
If the scaled longitude θ=n⋅λ is outside the [−n⋅π … n⋅π] range, maybe shifts θ to that range. This transform intentionally does not force θ to be inside that range in all cases. We avoid explicit wraparounds as much as possible (as opposed to implicit wraparounds performed by trigonometric functions) because they tend to introduce discontinuities. We perform wraparounds only when necessary for the problem of area crossing the anti-meridian (±180°).
Example: a CRS for Alaska may have the central meridian at λ₀=−154° of longitude. If the point to project is at λ=177° of longitude, calculations will be performed with Δλ=331° while the correct value that we need to use is Δλ=−29°.
In order to avoid wraparound operations as much as possible, we test only the bound where anti-meridian problem may happen; no wraparound will be applied for the opposite bound. Furthermore, we add or subtract 360° only once. Even if the point did many turns around the Earth, the 360° shift will still be applied at most once. The desire to apply the minimal amount of shifts is the reason why we do not use Math.IEEEremainder(double, double).

When to use

Many map projections implicitly wraparound longitude values through the use of trigonometric functions (sin(λ), cos(λ), etc). For those map projections, the wraparound is unconditional and this LongitudeWraparound class is not needed. This class is used only when the wraparound is not implicitly done and the central meridian is not zero. The latter condition is because subtraction of central meridian may cause longitude values to go outside the −180° … +180° range.

This transform is hidden in WKT (it does not appear as a concatenation).

Since:
1.3
Version:
1.3
See Also:
  • Field Details

    • serialVersionUID

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

      final NormalizedProjection projection
      The actual map projection to execute after the longitude wraparound.
    • bound

      final double bound
      A bound of the [−n⋅π … n⋅π] range which, if exceeded, should cause wraparound. Some (not all) θ = n⋅λ values need to be shifted inside that range before to use them in trigonometric functions.

      The sign is significant. A negative value means that the wraparound is applied only on longitudes less than −180°. A positive value means that the wraparound is applied only on longitudes greater than +180°.

    • negative

      final boolean negative
      Whether the bound is on the side of negative longitudes. This is bound < 0. This field is trivial in LongitudeWraparound case, but more important in LongitudeWraparound.Inverse case because rotation - bound may cancel to zero.
    • inverse

      private final LongitudeWraparound.Inverse inverse
      The inverse of this operation.
      See Also:
  • Constructor Details

    • LongitudeWraparound

      LongitudeWraparound(NormalizedProjection projection, double bound, double rotation)
      Creates a new transform for wrapping around the longitude values before a map projection.
      Parameters:
      projection - the actual map projection to execute after the longitude wraparound.
      bound - one bound of the [−n⋅π … n⋅π] range, on the side where wraparound needs to be applied.
      rotation - longitude rotation applied by the normalization matrix after conversion to projection domain.
  • Method Details

    • boundOfScaledLongitude

      static double boundOfScaledLongitude(MatrixSIS normalize, boolean negative)
      Returns a bound of the [−n⋅π … n⋅π] domain where n is a map projection dependent factor. The factor is inferred from the NormalizedProjection.context.
      Parameters:
      normalize - the normalization matrix of the projection for which to get a bound.
      negative - true for the −180° bound, or false for the +180° bound.
      Returns:
      a bound of the [−n⋅π … n⋅π] range.
    • getDomain

      public Optional<org.opengis.geometry.Envelope> getDomain(DomainDefinition criteria) throws org.opengis.referencing.operation.TransformException
      Returns the ranges of coordinate values which can be used as inputs. The projection domain is used verbatim, without wraparound adjustment.
      Overrides:
      getDomain in class AbstractMathTransform
      Parameters:
      criteria - controls the definition of transform domain.
      Returns:
      estimation of a domain where this transform is considered numerically applicable.
      Throws:
      org.opengis.referencing.operation.TransformException - if the domain cannot be estimated.
      See Also:
    • getParameterDescriptors

      public org.opengis.parameter.ParameterDescriptorGroup getParameterDescriptors()
      Returns the parameter descriptors for this math transform, or null if unknown. Delegates to projection since this LongitudeWraparound is hidden. This is used by WKT formatting.
      Specified by:
      getParameterDescriptors in interface Parameterized
      Overrides:
      getParameterDescriptors in class AbstractMathTransform
      Returns:
      the parameter descriptors for this math transform, or null if unspecified.
      See Also:
    • getParameterValues

      public org.opengis.parameter.ParameterValueGroup getParameterValues()
      Returns the parameter values for this math transform, or null if unknown. Delegates to projection since this LongitudeWraparound is hidden. This is used by WKT formatting.
      Specified by:
      getParameterValues in interface Parameterized
      Overrides:
      getParameterValues in class AbstractMathTransform
      Returns:
      the parameter values for this math transform, or null if unspecified. Note that those parameters may be normalized (e.g. represent a transformation of an ellipsoid of semi-major axis length of 1).
      See Also:
    • getContextualParameters

      protected ContextualParameters getContextualParameters()
      Returns the parameters for a sequence of normalizethisdenormalize. Delegates to projection since this LongitudeWraparound is hidden. This is used by WKT formatting.
      Overrides:
      getContextualParameters in class AbstractMathTransform
      Returns:
      the parameter values for the sequence of normalizethisdenormalize transforms, or null if unspecified. Callers should not modify the returned parameters, since modifications (if allowed) will generally not be reflected back in this MathTransform.
    • transform

      public org.opengis.referencing.operation.Matrix transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, boolean derivate) throws org.opengis.referencing.operation.TransformException
      Transforms a single coordinate tuple in an array, and optionally computes the transform derivative. The wraparound is applied, if needed, on the longitude value before to delegate to projection.
      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

      public void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) throws org.opengis.referencing.operation.TransformException
      Transforms a list of coordinate tuples. This method is provided for efficiently transforming many points. Wraparound is applied on all longitude values before to delegate to projection.
      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. Some implementations will stop at the first failure, wile some other implementations will fill the untransformable points with Double.NaN values, continue and throw the exception only at end. Implementations that fall in the latter case should set the last completed transform to this.
    • inverse

      public org.opengis.referencing.operation.MathTransform2D inverse() throws org.opengis.referencing.operation.NoninvertibleTransformException
      Returns the inverse transform of this object.
      Specified by:
      inverse in interface org.opengis.referencing.operation.MathTransform
      Specified by:
      inverse in interface org.opengis.referencing.operation.MathTransform2D
      Overrides:
      inverse in class AbstractMathTransform2D
      Throws:
      org.opengis.referencing.operation.NoninvertibleTransformException
    • computeHashCode

      protected int computeHashCode()
      Computes a hash value for this transform.
      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: