Author: desruisseaux
Date: Fri Jul 31 14:09:09 2015
New Revision: 1693603

URL: http://svn.apache.org/r1693603
Log:
Minor consolidation: factor out the computation of semi-minor axis length and 
inverse flattening factor, provide some analysis in the comment about the 
accuracy.

Modified:
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/FormulasTest.java

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java?rev=1693603&r1=1693602&r2=1693603&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java
 [UTF-8] Fri Jul 31 14:09:09 2015
@@ -125,4 +125,36 @@ public final class Formulas extends Stat
             return a;
         }
     }
+
+    /**
+     * Computes the semi-minor axis length from the given semi-major axis and 
inverse flattening factor.
+     *
+     * @param  semiMajorAxis     The semi-major axis length.
+     * @param  inverseFlattening The inverse flattening factor.
+     * @return The semi-minor axis length.
+     */
+    public static double getSemiMinor(final double semiMajorAxis, final double 
inverseFlattening) {
+        /*
+         * Note: double-double arithmetic does not increase the accuracy here, 
unless the inverse flattening
+         * factor given to this method is very high (i.e. the planet is very 
close to a perfect sphere).
+         */
+        return semiMajorAxis * (1 - 1/inverseFlattening);
+    }
+
+    /**
+     * Computes the inverse flattening factor from the given axis lengths.
+     *
+     * @param  semiMajorAxis The semi-major axis length.
+     * @param  semiMinorAxis The semi-minor axis length.
+     * @return The inverse flattening factor.
+     */
+    public static double getInverseFlattening(final double semiMajorAxis, 
final double semiMinorAxis) {
+        /*
+         * Note: double-double arithmetic here sometime change the last digit. 
We ignore for now.
+         * We may consider using double-double arithmetic in a future SIS 
version, not for more
+         * accurate map projection but rather for being able to find back the 
original value after
+         * we convert back and forward betwen inverse flattening and 
semi-minor axis length.
+         */
+        return semiMajorAxis / (semiMajorAxis - semiMinorAxis);
+    }
 }

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java?rev=1693603&r1=1693602&r2=1693603&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
 [UTF-8] Fri Jul 31 14:09:09 2015
@@ -135,15 +135,15 @@ public abstract class MapProjection exte
      *
      * @see #createConstant(ParameterBuilder, Double)
      */
-    public static void validate(final ParameterDescriptor<Double> descriptor, 
final double value)
+    public static void validate(final ParameterDescriptor<? extends Number> 
descriptor, final double value)
             throws IllegalArgumentException
     {
         if (Double.isNaN(value) || Double.isInfinite(value)) {
             throw new 
IllegalArgumentException(Errors.format(Errors.Keys.IllegalParameterValue_2,
                     descriptor.getName(), value));
         }
-        final Comparable<Double> min = descriptor.getMinimumValue();
-        final Comparable<Double> max = descriptor.getMaximumValue();
+        final Comparable<? extends Number> min = descriptor.getMinimumValue();
+        final Comparable<? extends Number> max = descriptor.getMaximumValue();
         if (!Objects.equals(min, max)) {
             /*
              * RATIONAL: why we do not check the bounds if (min == max):

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java?rev=1693603&r1=1693602&r2=1693603&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptor.java
 [UTF-8] Fri Jul 31 14:09:09 2015
@@ -322,8 +322,9 @@ public class DefaultParameterDescriptor<
      *         or {@code null} if it does not apply or if there is no 
restriction.
      */
     @Override
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
     public Set<T> getValidValues() {
-        return validValues;
+        return validValues;   // Null or unmodifiable
     }
 
     /**

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java?rev=1693603&r1=1693602&r2=1693603&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java
 [UTF-8] Fri Jul 31 14:09:09 2015
@@ -271,7 +271,7 @@ final class MapProjectionParameters exte
             if (!Double.isNaN(ivf)) {
                 final Double a = (Double) semiMajor.getValue();
                 if (a != null) {
-                    semiMinor.setValue(a * (1 - 1/ivf), semiMajor.getUnit());
+                    semiMinor.setValue(Formulas.getSemiMinor(a, ivf), 
semiMajor.getUnit());
                 }
             }
         }
@@ -284,8 +284,7 @@ final class MapProjectionParameters exte
         public double doubleValue() {
             final Double a = (Double) semiMajor.getValue();
             if (a != null && semiMinor.getValue() != null) {
-                final double b = semiMinor.doubleValue(semiMajor.getUnit());
-                return a / (a - b);
+                return Formulas.getInverseFlattening(a, 
semiMinor.doubleValue(semiMajor.getUnit()));
             }
             return Double.NaN;
         }

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java?rev=1693603&r1=1693602&r2=1693603&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
 [UTF-8] Fri Jul 31 14:09:09 2015
@@ -296,7 +296,7 @@ public class DefaultEllipsoid extends Ab
             return new Sphere(properties, semiMajorAxis, false, unit);
         } else {
             return new DefaultEllipsoid(properties, semiMajorAxis, 
semiMinorAxis,
-                       semiMajorAxis / (semiMajorAxis - semiMinorAxis), false, 
unit);
+                       Formulas.getInverseFlattening(semiMajorAxis, 
semiMinorAxis), false, unit);
         }
     }
 
@@ -320,7 +320,8 @@ public class DefaultEllipsoid extends Ab
             return new Sphere(properties, semiMajorAxis, true, unit);
         } else {
             return new DefaultEllipsoid(properties, semiMajorAxis,
-                    semiMajorAxis * (1 - 1/inverseFlattening), 
inverseFlattening, true, unit);
+                    Formulas.getSemiMinor(semiMajorAxis, inverseFlattening),
+                    inverseFlattening, true, unit);
         }
     }
 
@@ -358,11 +359,11 @@ public class DefaultEllipsoid extends Ab
     private void afterUnmarshal() {
         if (ivfDefinitive) {
             if (semiMinorAxis == 0) {
-                semiMinorAxis = semiMajorAxis * (1 - 1/inverseFlattening);
+                semiMinorAxis = Formulas.getSemiMinor(semiMajorAxis, 
inverseFlattening);
             }
         } else {
             if (inverseFlattening == 0) {
-                inverseFlattening = semiMajorAxis / (semiMajorAxis - 
semiMinorAxis);
+                inverseFlattening = 
Formulas.getInverseFlattening(semiMajorAxis, semiMinorAxis);
             }
         }
         if (unit == null) {

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java?rev=1693603&r1=1693602&r2=1693603&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
 [UTF-8] Fri Jul 31 14:09:09 2015
@@ -86,7 +86,7 @@ final class Initializer {
      *        <cite>false easting</cite>, <cite>false northing</cite> and 
other values.
      */
     Initializer(final OperationMethod method, final Parameters parameters,
-            final Map<ParameterRole, ? extends ParameterDescriptor<Double>> 
roles,
+            final Map<ParameterRole, ? extends ParameterDescriptor<? extends 
Number>> roles,
             final byte variant)
     {
         ensureNonNull("method",     method);
@@ -100,8 +100,8 @@ final class Initializer {
          * a null value to keys (we are paranoiac...) and because it conflicts 
with the "? extends" part of
          * in this constructor signature.
          */
-        ParameterDescriptor<Double> semiMajor = 
roles.get(ParameterRole.SEMI_MAJOR);
-        ParameterDescriptor<Double> semiMinor = 
roles.get(ParameterRole.SEMI_MINOR);
+        ParameterDescriptor<? extends Number> semiMajor = 
roles.get(ParameterRole.SEMI_MAJOR);
+        ParameterDescriptor<? extends Number> semiMinor = 
roles.get(ParameterRole.SEMI_MINOR);
         if (semiMajor == null) semiMajor = MapProjection.SEMI_MAJOR;
         if (semiMinor == null) semiMinor = MapProjection.SEMI_MINOR;
 
@@ -131,7 +131,7 @@ final class Initializer {
                 excentricitySquared.value = 1;
                 excentricitySquared.subtract(rs);
             }
-            final ParameterDescriptor<Double> radius = 
roles.get(ParameterRole.LATITUDE_OF_CONFORMAL_SPHERE_RADIUS);
+            final ParameterDescriptor<? extends Number> radius = 
roles.get(ParameterRole.LATITUDE_OF_CONFORMAL_SPHERE_RADIUS);
             if (radius != null) {
                 /*
                  * EPSG said: R is the radius of the sphere and will normally 
be one of the CRS parameters.
@@ -154,7 +154,7 @@ final class Initializer {
             }
         }
         context.normalizeGeographicInputs(λ0);
-        final ParameterDescriptor<Double> scaleFactor = 
roles.get(ParameterRole.SCALE_FACTOR);
+        final ParameterDescriptor<? extends Number> scaleFactor = 
roles.get(ParameterRole.SCALE_FACTOR);
         if (scaleFactor != null) {
             k.multiply(getAndStore(scaleFactor));
         }
@@ -166,7 +166,7 @@ final class Initializer {
     /**
      * Gets a parameter value identified by the given descriptor and stores it 
in the {@link #context}.
      * A "contextual parameter" is a parameter that apply to the normalize → 
{@code this} → denormalize
-     * chain as a whole. It does not really apply to this {@code 
NormalizedProjection} instance when taken alone.
+     * chain as a whole. It does not really apply to a {@code 
NormalizedProjection} instance taken alone.
      *
      * <p>This method performs the following actions:</p>
      * <ul>
@@ -175,12 +175,12 @@ final class Initializer {
      *   <li>Store the value only if different than the default value.</li>
      * </ul>
      */
-    final double getAndStore(final ParameterDescriptor<Double> descriptor) {
+    final double getAndStore(final ParameterDescriptor<? extends Number> 
descriptor) {
         if (descriptor == null) {
             return 0;   // Default value for all parameters except scale 
factor.
         }
         final double value = parameters.doubleValue(descriptor);    // Apply a 
unit conversion if needed.
-        final Double defaultValue = descriptor.getDefaultValue();
+        final Number defaultValue = descriptor.getDefaultValue();
         if (defaultValue == null || !defaultValue.equals(value)) {
             MapProjection.validate(descriptor, value);
             context.getOrCreate(descriptor).setValue(value);
@@ -236,15 +236,10 @@ final class Initializer {
         t.multiply(t);
         t.multiply(excentricitySquared);
 
-        // Save result of ℯ²⋅sin²φ
-        final double value = t.value;
-        final double error = t.error;
-
-        // Compute 1 - above. Since above may be small, this
-        // is where double-double arithmetic has more value.
-        t.clear();
-        t.value = 1;
-        t.subtract(value, error);
+        // Compute 1 - ℯ²⋅sin²φ.  Since  ℯ²⋅sin²φ  may be small,
+        // this is where double-double arithmetic has more value.
+        t.negate();
+        t.add(1,0);
         return t;
     }
 

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java?rev=1693603&r1=1693602&r2=1693603&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
 [UTF-8] Fri Jul 31 14:09:09 2015
@@ -397,7 +397,7 @@ public abstract class NormalizedProjecti
      *        <cite>false easting</cite>, <cite>false northing</cite> and 
other values.
      */
     protected NormalizedProjection(final OperationMethod method, final 
Parameters parameters,
-            final Map<ParameterRole, ? extends ParameterDescriptor<Double>> 
roles)
+            final Map<ParameterRole, ? extends ParameterDescriptor<? extends 
Number>> roles)
     {
         this(new Initializer(method, parameters, roles, (byte) 0));
     }

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/FormulasTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/FormulasTest.java?rev=1693603&r1=1693602&r2=1693603&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/FormulasTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/FormulasTest.java
 [UTF-8] Fri Jul 31 14:09:09 2015
@@ -78,4 +78,25 @@ public final strictfp class FormulasTest
     public void testGetAuthalicRadius() {
         assertEquals(ReferencingServices.AUTHALIC_RADIUS, 
Formulas.getAuthalicRadius(6378137, 6356752), 0.5);
     }
+
+    /**
+     * Tests {@link Formulas#getSemiMinor(double, double)}.
+     */
+    @Test
+    public void testGetSemiMinor() {
+        assertEquals("WGS 84",             6356752.314245179,  
Formulas.getSemiMinor(6378137, 298.257223563), 1E-9);
+        assertEquals("International 1924", 6356911.9461279465, 
Formulas.getSemiMinor(6378388, 297), 1E-9);
+        assertEquals("Clarke 1858",        20855233, // Unit in feet. Is the 
definitive parameter for this ellipsoid.
+                Formulas.getSemiMinor(20926348, 294.26067636926103), 1E-8);
+    }
+
+    /**
+     * Tests {@link Formulas#getInverseFlattening(double, double)}.
+     */
+    @Test
+    public void testGetInverseFlattening() {
+        assertEquals("WGS 84", 298.2572235629972, 
Formulas.getInverseFlattening(6378137, 6356752.314245179), 1E-11);
+        assertEquals("International 1924", 297, 
Formulas.getInverseFlattening(6378388, 6356911.9461279465), 1E-11);
+        assertEquals("Clarke 1858", 294.26067636926103, 
Formulas.getInverseFlattening(20926348, 20855233), 1E-11);
+    }
 }


Reply via email to