sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1541686 - in /sis/branches/JDK7/core/sis-referencing/src: main/java/org/apache/sis/referencing/datum/ test/java/org/apache/sis/referencing/datum/ test/java/org/apache/sis/test/suite/
Date Wed, 13 Nov 2013 20:06:09 GMT
Author: desruisseaux
Date: Wed Nov 13 20:06:09 2013
New Revision: 1541686

URL: http://svn.apache.org/r1541686
Log:
Added DefaultEllipsoidTest.

Added:
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java
  (with props)
Modified:
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/Sphere.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java?rev=1541686&r1=1541685&r2=1541686&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
[UTF-8] Wed Nov 13 20:06:09 2013
@@ -543,24 +543,25 @@ public class DefaultEllipsoid extends Ab
 
     /**
      * Returns the orthodromic distance between two geographic coordinates.
-     * The orthodromic distance is the shortest distance between two points on a sphere's
surface.
+     * The orthodromic distance is the shortest distance between two points on a ellipsoid's
surface.
      * The orthodromic path is always on a great circle.
-     * This is different from the <cite>loxodromic distance</cite>, which is
a
-     * longer distance on a path with a constant direction on the compass.
      *
-     * @param  x1 Longitude of first  point (in decimal degrees).
-     * @param  y1 Latitude  of first  point (in decimal degrees).
-     * @param  x2 Longitude of second point (in decimal degrees).
-     * @param  y2 Latitude  of second point (in decimal degrees).
+     * {@note Orthodromic distances anre different than the <cite>loxodromic distance</cite>.
+     *        The later is a longer distance on a path with a constant direction on the compass.}
+     *
+     * @param  λ1 Longitude of first  point (in decimal degrees).
+     * @param  φ1 Latitude  of first  point (in decimal degrees).
+     * @param  λ2 Longitude of second point (in decimal degrees).
+     * @param  φ2 Latitude  of second point (in decimal degrees).
      * @return The orthodromic distance (in the units of this ellipsoid's axis).
      *
      * @see org.apache.sis.referencing.GeodeticCalculator
      */
-    public double orthodromicDistance(double x1, double y1, double x2, double y2) {
-        x1 = toRadians(x1);
-        y1 = toRadians(y1);
-        x2 = toRadians(x2);
-        y2 = toRadians(y2);
+    public double orthodromicDistance(double λ1, double φ1, double λ2, double φ2) {
+        λ1 = toRadians(λ1);
+        φ1 = toRadians(φ1);
+        λ2 = toRadians(λ2);
+        φ2 = toRadians(φ2);
         /*
          * Solution of the geodetic inverse problem after T.Vincenty.
          * Modified Rainsford's method with Helmert's elliptical terms.
@@ -579,15 +580,15 @@ public class DefaultEllipsoid extends Ab
         final double F = 1 / getInverseFlattening();
         final double R = 1 - F;
 
-        double tu1 = R * tan(y1);
-        double tu2 = R * tan(y2);
+        double tu1 = R * tan(φ1);
+        double tu2 = R * tan(φ2);
         double cu1 = 1 / sqrt(tu1*tu1 + 1);
         double cu2 = 1 / sqrt(tu2*tu2 + 1);
         double su1 = cu1 * tu1;
         double s   = cu1 * cu2;
         double baz =   s * tu2;
         double faz = baz * tu1;
-        double x   =  x2 - x1;
+        double x   =  λ2 - λ1;
         for (int i=0; i<MAX_ITERATIONS; i++) {
             final double sx = sin(x);
             final double cx = cos(x);
@@ -606,7 +607,7 @@ public class DefaultEllipsoid extends Ab
             double c = ((-3*c2a+4)*F + 4) * c2a * F/16;
             double d = x;
             x = ((e*cy*c+cz)*sy*c + y) * SA;
-            x = (1-c)*x*F + x2-x1;
+            x = (1-c)*x*F + λ2-λ1;
 
             if (abs(d-x) <= EPS) {
                 x = sqrt((1/(R*R) - 1) * c2a + 1) + 1;
@@ -622,20 +623,20 @@ public class DefaultEllipsoid extends Ab
         }
         // No convergence. It may be because coordinate points
         // are equals or because they are at antipodes.
-        if (abs(x1-x2) <= COMPARISON_THRESHOLD && abs(y1-y2) <= COMPARISON_THRESHOLD)
{
+        if (abs(λ1-λ2) <= COMPARISON_THRESHOLD && abs(φ1-φ2) <= COMPARISON_THRESHOLD)
{
             return 0; // Coordinate points are equals
         }
-        if (abs(y1) <= COMPARISON_THRESHOLD && abs(y2) <= COMPARISON_THRESHOLD)
{
-            return abs(x1-x2) * getSemiMajorAxis(); // Points are on the equator.
+        if (abs(φ1) <= COMPARISON_THRESHOLD && abs(φ2) <= COMPARISON_THRESHOLD)
{
+            return abs(λ1-λ2) * getSemiMajorAxis(); // Points are on the equator.
         }
         // At least one input ordinate is NaN.
-        if (isNaN(x1) || isNaN(y1) || isNaN(x2) || isNaN(y2)) {
+        if (isNaN(λ1) || isNaN(φ1) || isNaN(λ2) || isNaN(φ2)) {
             return NaN;
         }
         // Other cases: no solution for this algorithm.
         throw new ArithmeticException(Errors.format(Errors.Keys.NoConvergenceForPoints_2,
-                  new DirectPosition2D(toDegrees(x1), toDegrees(y1)),
-                  new DirectPosition2D(toDegrees(x2), toDegrees(y2))));
+                  new DirectPosition2D(toDegrees(λ1), toDegrees(φ1)),
+                  new DirectPosition2D(toDegrees(λ2), toDegrees(φ2))));
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java?rev=1541686&r1=1541685&r2=1541686&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
[UTF-8] Wed Nov 13 20:06:09 2013
@@ -168,7 +168,7 @@ public class DefaultGeodeticDatum extend
      *   </tr>
      *   <tr>
      *     <td>{@value #BURSA_WOLF_KEY}</td>
-     *     <td>{@link BursaWolfParameters} or {@code BursaWolfParameters[]}</td>
+     *     <td>{@link BursaWolfParameters} (optionally as array)</td>
      *     <td>{@link #getBursaWolfParameters()}</td>
      *   </tr>
      *   <tr>

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/Sphere.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/Sphere.java?rev=1541686&r1=1541685&r2=1541686&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/Sphere.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/Sphere.java
[UTF-8] Wed Nov 13 20:06:09 2013
@@ -83,27 +83,18 @@ final class Sphere extends DefaultEllips
      * The orthodromic distance is the shortest distance between two points
      * on a sphere's surface. The orthodromic path is always on a great circle.
      *
-     * @param  x1 Longitude of first point (in decimal degrees).
-     * @param  y1 Latitude of first point (in decimal degrees).
-     * @param  x2 Longitude of second point (in decimal degrees).
-     * @param  y2 Latitude of second point (in decimal degrees).
+     * @param  λ1 Longitude of first point (in decimal degrees).
+     * @param  φ1 Latitude of first point (in decimal degrees).
+     * @param  λ2 Longitude of second point (in decimal degrees).
+     * @param  φ2 Latitude of second point (in decimal degrees).
      * @return The orthodromic distance (in the units of this ellipsoid's axis).
      */
     @Override
-    public double orthodromicDistance(double x1, double y1, double x2, double y2) {
-        /*
-         * The calculation of orthodromic distance on an ellipsoidal surface is complex,
-         * subject to rounding errors and has no solution near the poles. In some situation
-         * we use a calculation based on a spherical shape of the earth.  A Fortran program
-         * which calculates orthodromic distances on an ellipsoidal surface can be downloaded
-         * from the NOAA site:
-         *
-         *            ftp://ftp.ngs.noaa.gov/pub/pcsoft/for_inv.3d/source/
-         */
-        y1 = toRadians(y1);
-        y2 = toRadians(y2);
-        final double dx = toRadians(abs(x2-x1) % 360);
-        double rho = sin(y1)*sin(y2) + cos(y1)*cos(y2)*cos(dx);
+    public double orthodromicDistance(double λ1, double φ1, double λ2, double φ2) {
+        φ1 = toRadians(φ1);
+        φ2 = toRadians(φ2);
+        final double dx = toRadians(abs(λ2-λ1) % 360);
+        double rho = sin(φ1)*sin(φ2) + cos(φ1)*cos(φ2)*cos(dx);
         assert abs(rho) < 1.0000001 : rho;
         if (rho > +1) rho = +1; // Catch rounding error.
         if (rho < -1) rho = -1; // Catch rounding error.

Added: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java?rev=1541686&view=auto
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java
(added)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java
[UTF-8] Wed Nov 13 20:06:09 2013
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.referencing.datum;
+
+import java.util.Random;
+import org.apache.sis.measure.Latitude;
+import org.apache.sis.measure.Longitude;
+import org.apache.sis.referencing.GeodeticObjects;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.test.TestCase;
+import org.apache.sis.test.TestUtilities;
+import org.apache.sis.test.DependsOn;
+import org.apache.sis.test.DependsOnMethod;
+import org.junit.Test;
+
+import static java.lang.StrictMath.*;
+import static org.opengis.test.Assert.*;
+
+
+/**
+ * Tests the {@link DefaultEllipsoid} class.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.4 (derived from geotk-2.1)
+ * @version 0.4
+ * @module
+ */
+@DependsOn(org.apache.sis.internal.referencing.FormulasTest.class)
+public final strictfp class DefaultEllipsoidTest extends TestCase {
+    /**
+     * Half of a minute of angle, in degrees.
+     */
+    private static final double HM = 0.5 / 60;
+
+    /**
+     * Tolerances in metres for the tests using on spheres.
+     * Those tests are usually more accurate than the tests on ellipsoid.
+     */
+    private static final double SPHERICAL_TOLERANCE = 0.001;
+
+    /**
+     * Returns a random longitude (in degrees) using the given random number generator.
+     */
+    private static double nextLongitude(final Random random) {
+        return (Longitude.MAX_VALUE - Longitude.MIN_VALUE) * random.nextDouble() + Longitude.MIN_VALUE;
+    }
+
+    /**
+     * Tests the orthodromic distances computed by {@link DefaultEllipsoid}. There is actually
two algorithms:
+     * one for the ellipsoidal model, and a simpler one for spherical model. This method
tests the ellipsoidal
+     * model using known values of nautical mile at different latitude.
+     *
+     * <p>This method performs the test on the Clark 1866 ellipsoid, which was the
basis for the Imperial and
+     * U.S. definitions prior the First International Extraordinary Hydrographic Conference
in Monaco (1929).</p>
+     */
+    @Test
+    public void testOrthodromicDistance() {
+        final DefaultEllipsoid e = (DefaultEllipsoid) GeodeticObjects.NAD27.ellipsoid();
// Clark 1866
+        assertEquals("Nautical mile at equator",    1842.78, e.orthodromicDistance(0,   
-HM,   0,    +HM), 0.01);
+        assertEquals("Nautical mile at North pole", 1861.67, e.orthodromicDistance(0,  90-HM*2,
0,  90   ), 0.02);
+        assertEquals("Nautical mile at South pole", 1861.67, e.orthodromicDistance(0, -90+HM*2,
0, -90   ), 0.02);
+        assertEquals("International nautical mile", 1852.00, e.orthodromicDistance(0,  45-HM,
  0,  45+HM), 0.20);
+        /*
+         * Test parallel segments of increasing length at random positions on the equator.
+         */
+        final Random random = TestUtilities.createRandomNumberGenerator();
+        final double semiMajor = e.getSemiMajorAxis();
+        for (double length = 0; length <= Longitude.MAX_VALUE; length += 0.5) {
+            final double λ = nextLongitude(random);
+            assertEquals(semiMajor * toRadians(length), e.orthodromicDistance(λ, 0, λ+length,
0), 0.2);
+        }
+    }
+
+    /**
+     * Tests the orthodromic distances computed by {@link DefaultEllipsoid} on a sphere,
+     * and compares them with the distances computed by {@link Sphere}.
+     */
+    @Test
+    @DependsOnMethod("testOrthodromicDistance")
+    public void testOrthodromicDistanceOnSphere() {
+        final DefaultEllipsoid s = (DefaultEllipsoid) GeodeticObjects.SPHERE.ellipsoid();
+        assertInstanceOf("SPHERE", Sphere.class, s);
+        /*
+         * Creates an instance of DefaultEllipsoid with the same properties than s.
+         * The 's' and 'e' instances will use different formulas for orthodromic distances,
which we will compare.
+         */
+        final double radius = s.getSemiMajorAxis();
+        final DefaultEllipsoid e = new DefaultEllipsoid(IdentifiedObjects.getProperties(s),
+                radius, radius, Double.POSITIVE_INFINITY, false, s.getAxisUnit());
+        /*
+         * Test parallel segments of increasing length at random positions on the equator.
+         */
+        final Random random = TestUtilities.createRandomNumberGenerator();
+        for (double length = 0; length <= Longitude.MAX_VALUE; length += 0.5) {
+            final double λ = nextLongitude(random);
+            final double distance = radius * toRadians(length);
+            assertEquals(distance, s.orthodromicDistance(λ, 0, λ+length, 0), SPHERICAL_TOLERANCE);
+            assertEquals(distance, e.orthodromicDistance(λ, 0, λ+length, 0), SPHERICAL_TOLERANCE);
+        }
+        /*
+         * Test meridian segments from equator to increasing latitudes.
+         */
+        for (double φ = Latitude.MIN_VALUE; φ <= Latitude.MAX_VALUE; φ += 0.5) {
+            final double λ = nextLongitude(random);
+            final double distance = radius * toRadians(abs(φ));
+            assertEquals(distance, s.orthodromicDistance(λ, 0, λ, φ), SPHERICAL_TOLERANCE);
+            assertEquals(distance, e.orthodromicDistance(λ, 0, λ, φ), SPHERICAL_TOLERANCE);
+        }
+        /*
+         * Tests random segments.
+         */
+        final double circumference = (radius * (1 + 1E-8)) * (2*PI);
+        for (int i=0; i<100; i++) {
+            final double φ1 =  -90 + 180*random.nextDouble();
+            final double φ2 =  -90 + 180*random.nextDouble();
+            final double λ1 = -180 + 360*random.nextDouble();
+            final double λ2 = -180 + 360*random.nextDouble();
+            final double distance = s.orthodromicDistance(λ1, φ1, λ2, φ2);
+            assertTrue(distance >= 0 && distance <= circumference);
+            assertEquals(distance, e.orthodromicDistance(λ1, φ1, λ2, φ2), SPHERICAL_TOLERANCE);
+        }
+    }
+
+    /**
+     * Tests the {@link DefaultEllipsoid#getAuthalicRadius()} method on the GRS 1980 ellipsoid
(EPSG:7019).
+     * The expected result is the radius of the sphere defined by EPSG:7048.
+     */
+    @Test
+    public void testAuthalicRadius() {
+        assertEquals("SPHERE", 6371007, ((DefaultEllipsoid) GeodeticObjects.SPHERE.ellipsoid()).getAuthalicRadius(),
0.0);
+        assertEquals("NAD83",  6371007, ((DefaultEllipsoid) GeodeticObjects.NAD83 .ellipsoid()).getAuthalicRadius(),
0.2);
+    }
+}

Propchange: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1541686&r1=1541685&r2=1541686&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
[UTF-8] Wed Nov 13 20:06:09 2013
@@ -50,6 +50,7 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.AbstractReferenceSystemTest.class,
     org.apache.sis.referencing.datum.BursaWolfParametersTest.class,
     org.apache.sis.referencing.datum.TimeDependentBWPTest.class,
+    org.apache.sis.referencing.datum.DefaultEllipsoidTest.class,
 
     org.apache.sis.geometry.AbstractDirectPositionTest.class,
     org.apache.sis.geometry.GeneralDirectPositionTest.class,



Mime
View raw message