sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1702008 - in /sis/branches/JDK8/core/sis-referencing/src: main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java test/java/org/apache/sis/referencing/operation/projection/TransverseMercatorTest.java
Date Wed, 09 Sep 2015 13:45:01 GMT
Author: desruisseaux
Date: Wed Sep  9 13:45:01 2015
New Revision: 1702008

URL: http://svn.apache.org/r1702008
Log:
Added the spherical implementation of TransverseMercator projection.

Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/TransverseMercatorTest.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java?rev=1702008&r1=1702007&r2=1702008&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java
[UTF-8] Wed Sep  9 13:45:01 2015
@@ -17,7 +17,10 @@
 package org.apache.sis.referencing.operation.projection;
 
 import java.util.EnumMap;
+import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.OperationMethod;
 import org.apache.sis.referencing.operation.matrix.Matrix2;
@@ -201,6 +204,42 @@ public class TransverseMercator extends
     }
 
     /**
+     * Creates a new projection initialized to the same parameters than the given one.
+     */
+    TransverseMercator(final TransverseMercator other) {
+        super(other);
+        h1  = other. h1;
+        h2  = other. h2;
+        h3  = other. h3;
+        h4  = other. h4;
+        ih1 = other.ih1;
+        ih2 = other.ih2;
+        ih3 = other.ih3;
+        ih4 = other.ih4;
+    }
+
+    /**
+     * Returns the sequence of <cite>normalization</cite> → {@code this} →
<cite>denormalization</cite> transforms
+     * as a whole. The transform returned by this method except (<var>longitude</var>,
<var>latitude</var>)
+     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>)
coordinates in <em>metres</em>.
+     *
+     * <p>The non-linear part of the returned transform will be {@code this} transform,
except if the ellipsoid
+     * is spherical. In the later case, {@code this} transform will be replaced by a simplified
implementation.</p>
+     *
+     * @param  factory The factory to use for creating the transform.
+     * @return The map projection from (λ,φ) to (<var>x</var>,<var>y</var>)
coordinates.
+     * @throws FactoryException if an error occurred while creating a transform.
+     */
+    @Override
+    public MathTransform createMapProjection(final MathTransformFactory factory) throws FactoryException
{
+        TransverseMercator kernel = this;
+        if (excentricity == 0) {
+            kernel = new Spherical(this);
+        }
+        return context.completeTransform(factory, kernel);
+    }
+
+    /**
      * Converts the specified (λ,φ) coordinate (units in radians) and stores the result
in {@code dstPts}.
      * In addition, opportunistically computes the projection derivative if {@code derivate}
is {@code true}.
      *
@@ -387,4 +426,83 @@ public class TransverseMercator extends
         }
         throw new ProjectionException(Errors.Keys.NoConvergence);
     }
+
+
+    /**
+     * Provides the transform equations for the spherical case of the Transverse Mercator
projection.
+     *
+     * @author  André Gosselin (MPO)
+     * @author  Martin Desruisseaux (IRD, Geomatys)
+     * @author  Rueben Schulz (UBC)
+     * @since   0.6
+     * @version 0.6
+     * @module
+     */
+    private static final class Spherical extends TransverseMercator {
+        /**
+         * For cross-version compatibility.
+         */
+        private static final long serialVersionUID = 8903592710452235162L;
+
+        /**
+         * Constructs a new map projection from the parameters of the given projection.
+         *
+         * @param other The other projection (usually ellipsoidal) from which to copy the
parameters.
+         */
+        protected Spherical(final TransverseMercator other) {
+            super(other);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public Matrix transform(final double[] srcPts, final int srcOff,
+                                final double[] dstPts, final int dstOff,
+                                final boolean derivate) throws ProjectionException
+        {
+            final double λ    = srcPts[srcOff];
+            final double φ    = srcPts[srcOff + 1];
+            final double sinλ = sin(λ);
+            final double cosλ = cos(λ);
+            final double sinφ = sin(φ);
+            final double cosφ = cos(φ);
+            final double tanφ = sinφ / cosφ;
+            final double B    = cosφ * sinλ;
+            /*
+             * Using Snyder's equation for calculating y, instead of the one used in Proj4.
+             * Potential problems when y and x = 90 degrees, but behaves ok in tests.
+             */
+            if (dstPts != null) {
+                dstPts[dstOff  ] = atanh(B);            // Snyder 8-1;
+                dstPts[dstOff+1] = atan2(tanφ, cosλ);   // Snyder 8-3;
+            }
+            if (!derivate) {
+                return null;
+            }
+            final double Bm  = B*B - 1;
+            final double sct = cosλ*cosλ + tanφ*tanφ;
+            return new Matrix2(-(cosφ * cosλ) / Bm,     // ∂x/∂λ
+                                (sinφ * sinλ) / Bm,     // ∂x/∂φ
+                                (tanφ * sinλ) / sct,    // ∂y/∂λ
+                         cosλ / (cosφ * cosφ * sct));   // ∂y/∂φ
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        protected void inverseTransform(final double[] srcPts, final int srcOff,
+                                        final double[] dstPts, final int dstOff)
+                throws ProjectionException
+        {
+            final double x = srcPts[srcOff  ];
+            final double y = srcPts[srcOff+1];
+            final double sinhx = sinh(x);
+            final double cosy  = cos(y);
+            // 'copySign' corrects for the fact that we made everything positive using sqrt(…)
+            dstPts[dstOff  ] = atan2(sinhx, cosy);
+            dstPts[dstOff+1] = copySign(asin(sqrt((1 - cosy*cosy) / (1 + sinhx*sinhx))),
y);
+        }
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/TransverseMercatorTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/TransverseMercatorTest.java?rev=1702008&r1=1702007&r2=1702008&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/TransverseMercatorTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/TransverseMercatorTest.java
[UTF-8] Wed Sep  9 13:45:01 2015
@@ -18,8 +18,11 @@ package org.apache.sis.referencing.opera
 
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.internal.referencing.Formulas;
 import org.apache.sis.internal.referencing.provider.TransverseMercatorSouth;
 import org.apache.sis.parameter.Parameters;
+import org.apache.sis.referencing.operation.transform.CoordinateDomain;
+import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.junit.Test;
 
@@ -36,7 +39,6 @@ import static java.lang.StrictMath.toRad
  */
 @DependsOn(NormalizedProjectionTest.class)
 public final strictfp class TransverseMercatorTest extends MapProjectionTestCase {
-    
     /**
      * Creates a new instance of {@link TransverseMercator}.
      *
@@ -76,11 +78,34 @@ public final strictfp class TransverseMe
      * @see org.opengis.test.referencing.ParameterizedTransformTest#testTransverseMercatorSouthOrientated()
      */
     @Test
+    @DependsOnMethod("testTransverseMercator")
     public void testTransverseMercatorSouthOrientated() throws FactoryException, TransformException
{
         createGeoApiTest(new TransverseMercatorSouth()).testTransverseMercatorSouthOrientated();
     }
 
     /**
+     * Verifies the consistency of elliptical formulas with the spherical formulas.
+     * This test compares the results of elliptical formulas with the spherical ones
+     * for some random points.
+     *
+     * @throws FactoryException if an error occurred while creating the map projection.
+     * @throws TransformException if an error occurred while projecting a coordinate.
+     */
+    @Test
+    @DependsOnMethod("testTransverseMercator")
+    public void compareEllipticalWithSpherical() throws FactoryException, TransformException
{
+        createCompleteProjection(new org.apache.sis.internal.referencing.provider.TransverseMercator(),
false,
+                  0.5,    // Central meridian
+                  2.5,    // Latitude of origin
+                  0,      // Standard parallel (none)
+                  0.997,  // Scale factor
+                200,      // False easting
+                100);     // False northing
+        tolerance = Formulas.LINEAR_TOLERANCE;
+        compareEllipticalWithSpherical(CoordinateDomain.RANGE_10, 0);
+    }
+
+    /**
      * Creates a projection and derivates a few points.
      *
      * @throws TransformException Should never happen.



Mime
View raw message