sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1693658 - in /sis/branches/JDK8/core: sis-referencing/src/main/java/org/apache/sis/internal/referencing/ sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ sis-referencing/src/main/java/org/apache/sis/parameter/ si...
Date Fri, 31 Jul 2015 21:59:39 GMT
Author: desruisseaux
Date: Fri Jul 31 21:59:39 2015
New Revision: 1693658

URL: http://svn.apache.org/r1693658
Log:
Allow NormalizedProjection constructors to know whether the second defining parameter of the
Ellipsoid
is the semi-major axis length or the inverse flattening factor, and in the later case allow
constructors
to get the definitive flattening factor in order to compute the excentricity more accuratly.

The intend is not to get more accurate map projection. Instead, we do that because some code
sometime
compute back the original semi-minor axis length (for example) from the excentricity. Our
goal is to
allow (if possible) such code to get a value closer to the original value (idealy the exact
same value).

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/Equirectangular.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.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/parameter/ParameterBuilder.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/LambertConicConformal.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestCase.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=1693658&r1=1693657&r2=1693658&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 21:59:39 2015
@@ -106,9 +106,7 @@ public final class Formulas extends Stat
 
     /**
      * Returns the radius of a hypothetical sphere having the same surface than the ellipsoid
-     * specified by the given axis length. This method does not verify if {@code a == b}
-     * (in which case {@code a} could be returned directly); it is up to the caller to perform
-     * such optimization if desired.
+     * specified by the given axis length.
      *
      * @param  a The semi-major axis length.
      * @param  b The semi-minor axis length.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -126,7 +126,7 @@ public final class Equirectangular exten
                 .addName("Latitude of 1st standard parallel")
                 .addName(Citations.OGC,     Constants.STANDARD_PARALLEL_1)
                 .addName(Citations.ESRI,    "Standard_Parallel_1")
-                .addName(Citations.NETCDF,  "standard_parallel")
+                .addName(Citations.NETCDF,  Constants.STANDARD_PARALLEL)
                 .addName(Citations.GEOTIFF, "ProjStdParallel1")
                 .addName(Citations.PROJ4,   "lat_ts"), false);
 
@@ -144,7 +144,7 @@ public final class Equirectangular exten
                 .addName("False easting")
                 .addName(Citations.OGC,     Constants.FALSE_EASTING)
                 .addName(Citations.ESRI,    "False_Easting")
-                .addName(Citations.NETCDF,  "false_easting")
+                .addName(Citations.NETCDF,  Constants.FALSE_EASTING)
                 .addName(Citations.GEOTIFF, "FalseEasting")
                 .addName(Citations.PROJ4,   "x_0"));
 
@@ -153,7 +153,7 @@ public final class Equirectangular exten
                 .addName("False northing")
                 .addName(Citations.OGC,     Constants.FALSE_NORTHING)
                 .addName(Citations.ESRI,    "False_Northing")
-                .addName(Citations.NETCDF,  "false_northing")
+                .addName(Citations.NETCDF,  Constants.FALSE_NORTHING)
                 .addName(Citations.GEOTIFF, "FalseNorthing")
                 .addName(Citations.PROJ4,   "y_0"));
         /*

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -58,30 +58,6 @@ final class MapProjectionDescriptor exte
     private static final long serialVersionUID = -9142116135803309453L;
 
     /**
-     * The NetCDF parameter name for the Earth radius.
-     *
-     * @see Constants#SEMI_MAJOR
-     * @see Constants#SEMI_MINOR
-     */
-    static final String EARTH_RADIUS = "earth_radius";
-
-    /**
-     * The NetCDF parameter name for inverse flattening.
-     *
-     * @see Constants#SEMI_MAJOR
-     * @see Constants#SEMI_MINOR
-     */
-    static final String INVERSE_FLATTENING = "inverse_flattening";
-
-    /**
-     * The NetCDF parameter name for the standard parallels.
-     *
-     * @see Constants#STANDARD_PARALLEL_1
-     * @see Constants#STANDARD_PARALLEL_2
-     */
-    static final String STANDARD_PARALLEL = "standard_parallel";
-
-    /**
      * {@code true} if the {@link #STANDARD_PARALLEL} parameter can be added.
      */
     final boolean hasStandardParallels;
@@ -146,14 +122,17 @@ final class MapProjectionDescriptor exte
      */
     @Override
     public GeneralParameterDescriptor descriptor(final String name) throws ParameterNotFoundException
{
-        if (isHeuristicMatchForName(name, EARTH_RADIUS)) {
+        if (isHeuristicMatchForName(name, Constants.EARTH_RADIUS)) {
             return MapProjectionParameters.EarthRadius.DESCRIPTOR;
         }
-        if (isHeuristicMatchForName(name, INVERSE_FLATTENING)) {
+        if (isHeuristicMatchForName(name, Constants.INVERSE_FLATTENING)) {
             return MapProjectionParameters.InverseFlattening.DESCRIPTOR;
         }
+        if (isHeuristicMatchForName(name, Constants.IS_IVF_DEFINITIVE)) {
+            return MapProjectionParameters.IsIvfDefinitive.DESCRIPTOR;
+        }
         if (hasStandardParallels) {
-            if (isHeuristicMatchForName(name, STANDARD_PARALLEL)) {
+            if (isHeuristicMatchForName(name, Constants.STANDARD_PARALLEL)) {
                 return MapProjectionParameters.StandardParallel.DESCRIPTOR;
             }
         }

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=1693658&r1=1693657&r2=1693658&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 21:59:39 2015
@@ -33,6 +33,9 @@ import org.apache.sis.util.ArraysExt;
 import static org.opengis.referencing.IdentifiedObject.NAME_KEY;
 import static org.apache.sis.metadata.iso.citation.Citations.NETCDF;
 
+// Branch-specific imports
+import java.util.Objects;
+
 
 /**
  * Map projection parameters, with special processing for alternative ways to express the
ellipsoid axis length
@@ -60,7 +63,7 @@ final class MapProjectionParameters exte
      * The {@link InverseFlattening} parameter instance, created when first needed.
      * This is an "invisible" parameter, never shown in the {@link #values()} list.
      */
-    private transient ParameterValue<Double> inverseFlattening;
+    private transient InverseFlattening inverseFlattening;
 
     /**
      * The {@link StandardParallel} parameter instance, created when first needed.
@@ -69,6 +72,12 @@ final class MapProjectionParameters exte
     private transient ParameterValue<double[]> standardParallel;
 
     /**
+     * The {@link IsIvfDefinitive} parameter instance, created when first needed.
+     * This is an "invisible" parameter, never shown in the {@link #values()} list.
+     */
+    private transient ParameterValue<Boolean> isIvfDefinitive;
+
+    /**
      * Creates a new parameter value group. An instance of {@link MapProjectionDescriptor}
      * is mandatory, because some method in this class will need to cast the descriptor.
      */
@@ -97,38 +106,46 @@ final class MapProjectionParameters exte
      */
     @Override
     ParameterValue<?> parameterIfExist(final String name) throws ParameterNotFoundException
{
-        if (MapProjectionDescriptor.isHeuristicMatchForName(name, MapProjectionDescriptor.EARTH_RADIUS))
{
-            ParameterValue<?> value = earthRadius;
-            if (value == null) {
-                value = earthRadius = new EarthRadius(
-                        parameter(Constants.SEMI_MAJOR),
-                        parameter(Constants.SEMI_MINOR));
+        if (MapProjectionDescriptor.isHeuristicMatchForName(name, Constants.EARTH_RADIUS))
{
+            if (earthRadius == null) {
+                earthRadius = new EarthRadius(parameter(Constants.SEMI_MAJOR),
+                                              parameter(Constants.SEMI_MINOR));
             }
-            return value;
+            return earthRadius;
+        }
+        if (MapProjectionDescriptor.isHeuristicMatchForName(name, Constants.INVERSE_FLATTENING))
{
+            return getInverseFlattening();
         }
-        if (MapProjectionDescriptor.isHeuristicMatchForName(name, MapProjectionDescriptor.INVERSE_FLATTENING))
{
-            ParameterValue<?> value = inverseFlattening;
-            if (value == null) {
-                value = inverseFlattening = new InverseFlattening(
-                        parameter(Constants.SEMI_MAJOR),
-                        parameter(Constants.SEMI_MINOR));
+        if (MapProjectionDescriptor.isHeuristicMatchForName(name, Constants.IS_IVF_DEFINITIVE))
{
+            if (isIvfDefinitive == null) {
+                isIvfDefinitive = new IsIvfDefinitive(getInverseFlattening());
             }
-            return value;
+            return isIvfDefinitive;
         }
         if (((MapProjectionDescriptor) getDescriptor()).hasStandardParallels) {
-            if (MapProjectionDescriptor.isHeuristicMatchForName(name, MapProjectionDescriptor.STANDARD_PARALLEL))
{
-                ParameterValue<?> value = standardParallel;
-                if (value == null) {
-                    value = standardParallel = new StandardParallel(
-                            parameter(Constants.STANDARD_PARALLEL_1),
-                            parameter(Constants.STANDARD_PARALLEL_2));
+            if (MapProjectionDescriptor.isHeuristicMatchForName(name, Constants.STANDARD_PARALLEL))
{
+                if (standardParallel == null) {
+                    standardParallel = new StandardParallel(parameter(Constants.STANDARD_PARALLEL_1),
+                                                            parameter(Constants.STANDARD_PARALLEL_2));
                 }
-                return value;
+                return standardParallel;
             }
         }
         return super.parameterIfExist(name);
     }
 
+    /**
+     * Returns the {@link InverseFlattening} instance, creating it when first needed.
+     * This parameter is used also by {@link IsIvfDefinitive}.
+     */
+    private InverseFlattening getInverseFlattening() {
+        if (inverseFlattening == null) {
+            inverseFlattening = new InverseFlattening(parameter(Constants.SEMI_MAJOR),
+                                                      parameter(Constants.SEMI_MINOR));
+        }
+        return inverseFlattening;
+    }
+
 
 
 
@@ -152,17 +169,10 @@ final class MapProjectionParameters exte
          * This is not a standard parameter.
          */
         static final ParameterDescriptor<Double> DESCRIPTOR = new DefaultParameterDescriptor<>(
-                toMap(MapProjectionDescriptor.EARTH_RADIUS), 0, 1, Double.class,
+                InverseFlattening.toMap(Constants.EARTH_RADIUS), 0, 1, Double.class,
                 MeasurementRange.createGreaterThan(0.0, SI.METRE), null, null);
 
         /**
-         * Helper method for {@link #DESCRIPTOR} constructions.
-         */
-        static Map<String,?> toMap(final String name) {
-            return Collections.singletonMap(NAME_KEY, new NamedIdentifier(NETCDF, name));
-        }
-
-        /**
          * The parameters for the semi-major and semi-minor axis length.
          */
         private final ParameterValue<?> semiMajor, semiMinor;
@@ -181,8 +191,8 @@ final class MapProjectionParameters exte
          */
         @Override
         protected void setValue(final Object value, final Unit<?> unit) {
-            super.setValue(value, unit);   // Perform argument check.
-            final double r = (Double) value;
+            super.setValue(value, unit);        // Perform argument check.
+            final double r = (Double) value;    // At this point, can not be anything else
than Double.
             semiMajor.setValue(r, unit);
             semiMinor.setValue(r, unit);
         }
@@ -243,21 +253,60 @@ final class MapProjectionParameters exte
          * This is not a standard parameter.
          */
         static final ParameterDescriptor<Double> DESCRIPTOR = new DefaultParameterDescriptor<>(
-                EarthRadius.toMap(MapProjectionDescriptor.INVERSE_FLATTENING), 0, 1, Double.class,
+                toMap(Constants.INVERSE_FLATTENING), 0, 1, Double.class,
                 MeasurementRange.createGreaterThan(0.0, Unit.ONE), null, null);
 
         /**
+         * Helper method for {@link #DESCRIPTOR} constructions.
+         */
+        static Map<String,?> toMap(final String name) {
+            return Collections.singletonMap(NAME_KEY, new NamedIdentifier(NETCDF, name));
+        }
+
+        /**
          * The parameters for the semi-major and semi-minor axis length.
          */
         private final ParameterValue<?> semiMajor, semiMinor;
 
         /**
+         * The declared inverse flattening values, together with a snapshot of axis lengths
+         * at the time the inverse flattening has been set.
+         */
+        private double inverseFlattening, a, b;
+
+        /**
          * Creates a new parameter.
          */
         InverseFlattening(final ParameterValue<?> semiMajor, final ParameterValue<?>
semiMinor) {
             super(DESCRIPTOR);
             this.semiMajor = semiMajor;
             this.semiMinor = semiMinor;
+            invalidate();
+        }
+
+        /**
+         * Declares that the inverse flattening factor is not definitive.
+         * We use the fact that the {@code ==} operator gives {@code false} if a value is
NaN.
+         */
+        void invalidate() {
+            a = b = Double.NaN;
+        }
+
+        /**
+         * Returns {@code true} if the inverse flattening factor has been explicitely specified
+         * and seems to still valid.
+         */
+        boolean isIvfDefinitive() {
+            if (inverseFlattening > 0) {
+                final Number ca = (Number) semiMajor.getValue();
+                if (ca != null && ca.doubleValue() == a) {
+                    final Number cb = (Number) semiMinor.getValue();
+                    if (cb != null && cb.doubleValue() == b) {
+                        return Objects.equals(semiMajor.getUnit(), semiMinor.getUnit());
+                    }
+                }
+            }
+            return false;
         }
 
         /**
@@ -266,27 +315,31 @@ final class MapProjectionParameters exte
          */
         @Override
         protected void setValue(final Object value, final Unit<?> unit) {
-            super.setValue(value, unit);   // Perform argument check.
-            final double ivf = (Double) value;
-            if (!Double.isNaN(ivf)) {
-                final Double a = (Double) semiMajor.getValue();
-                if (a != null) {
-                    semiMinor.setValue(Formulas.getSemiMinor(a, ivf), semiMajor.getUnit());
-                }
+            super.setValue(value, unit);        // Perform argument check.
+            final double ivf = (Double) value;  // At this point, can not be anything else
than Double.
+            final Number ca = (Number) semiMajor.getValue();
+            if (ca != null) {
+                a = ca.doubleValue();
+                b = Formulas.getSemiMinor(a, ivf);
+                semiMinor.setValue(b, semiMajor.getUnit());
+            } else {
+                invalidate();
             }
+            inverseFlattening = ivf;
         }
 
         /**
-         * Invoked when the parameter value is requested.
-         * Unconditionally computes the inverse flattening factor from the axis lengths.
+         * Invoked when the parameter value is requested. Computes the inverse flattening
factor
+         * from the axis lengths if the currently stored value does not seem to be valid
anymore.
          */
         @Override
         public double doubleValue() {
-            final Double a = (Double) semiMajor.getValue();
-            if (a != null && semiMinor.getValue() != null) {
-                return Formulas.getInverseFlattening(a, semiMinor.doubleValue(semiMajor.getUnit()));
+            final double ca = semiMajor.doubleValue();
+            final double cb = semiMinor.doubleValue(semiMajor.getUnit());
+            if (ca == a && cb == b && inverseFlattening > 0) {
+                return inverseFlattening;
             }
-            return Double.NaN;
+            return Formulas.getInverseFlattening(ca, cb);
         }
 
         /**
@@ -302,6 +355,69 @@ final class MapProjectionParameters exte
 
 
     /**
+     * Whether the inverse flattening parameter is definitive.
+     *
+     * @see org.apache.sis.referencing.datum.DefaultEllipsoid#isIvfDefinitive()
+     */
+    static final class IsIvfDefinitive extends DefaultParameterValue<Boolean> {
+        /**
+         * For cross-version compatibility. Actually instances of this class
+         * are not expected to be serialized, but we try to be a bit safer here.
+         */
+        private static final long serialVersionUID = 5988883252321358629L;
+
+        /**
+         * All names known to Apache SIS for the "is IVF definitive" parameter.
+         * This is not a standard parameter.
+         */
+        static final ParameterDescriptor<Boolean> DESCRIPTOR = new DefaultParameterDescriptor<>(
+                InverseFlattening.toMap(Constants.IS_IVF_DEFINITIVE), 0, 1, Boolean.class,
null, null, null);
+
+        /**
+         * The parameters for the inverse flattening factor.
+         */
+        private final InverseFlattening inverseFlattening;
+
+        /**
+         * Creates a new parameter.
+         */
+        IsIvfDefinitive(final InverseFlattening inverseFlattening) {
+            super(DESCRIPTOR);
+            this.inverseFlattening = inverseFlattening;
+        }
+
+        /**
+         * Invoked when a new parameter value is set.
+         */
+        @Override
+        protected void setValue(final Object value, final Unit<?> unit) {
+            super.setValue(value, unit);   // Perform argument check.
+            if (!(Boolean) value) {
+                inverseFlattening.invalidate();
+            }
+        }
+
+        /**
+         * Invoked when the parameter value is requested.
+         */
+        @Override
+        public boolean booleanValue() {
+            return inverseFlattening.isIvfDefinitive();
+        }
+
+        /**
+         * Getters other than the above {@code booleanValue()} delegate to this method.
+         */
+        @Override
+        public Boolean getValue() {
+            return booleanValue();
+        }
+    }
+
+
+
+
+    /**
      * The standard parallels parameter as an array of {@code double}. This parameter is
computed automatically
      * from the {@code "standard_parallel_1"} and {@code "standard_parallel_1"} standard
parameters. When this
      * non-standard parameter is explicitely set, the array elements are given to the above-cited
standard parameters.
@@ -319,7 +435,7 @@ final class MapProjectionParameters exte
          * {@link #STANDARD_PARALLEL_2}. This is not a standard parameter.
          */
         static final ParameterDescriptor<double[]> DESCRIPTOR = new DefaultParameterDescriptor<>(
-                EarthRadius.toMap(MapProjectionDescriptor.STANDARD_PARALLEL),
+                InverseFlattening.toMap(Constants.STANDARD_PARALLEL),
                 0, 1, double[].class, null, null, null);
 
         /**
@@ -368,15 +484,15 @@ final class MapProjectionParameters exte
          */
         @Override
         public double[] getValue() {
-            final Double p1 = (Double) standardParallel1.getValue();
-            final Double p2 = (Double) standardParallel2.getValue();
+            final Number p1 = (Number) standardParallel1.getValue();
+            final Number p2 = (Number) standardParallel2.getValue();
             if (p2 == null) {
                 if (p1 == null) {
                     return ArraysExt.EMPTY_DOUBLE;
                 }
-                return new double[] {p1};
+                return new double[] {p1.doubleValue()};
             }
-            return new double[] {(p1 != null) ? p1 : Double.NaN, p2};
+            return new double[] {(p1 != null) ? p1.doubleValue() : Double.NaN, p2.doubleValue()};
         }
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -385,7 +385,7 @@ public class ParameterBuilder extends Bu
      *   <tr><td>{@code "semi_major"}</td>         <td>Always</td>
    <td>Standard parameter defined by WKT 1.</td></tr>
      *   <tr><td>{@code "semi_minor"}</td>         <td>Always</td>
    <td>Standard parameter defined by WKT 1.</td></tr>
      *   <tr><td>{@code "earth_radius"}</td>       <td>Hidden</td>
    <td>Mapped to {@code "semi_major"} and {@code "semi_minor"} parameters.</td></tr>
-     *   <tr><td>{@code "inverse_flattening"}</td> <td>Hidden</td>
    <td>Mapped to {@code "semi_major"} and {@code "semi_minor"} parameters.</td></tr>
+     *   <tr><td>{@code "inverse_flattening"}</td> <td>Hidden</td>
    <td>Computed from the {@code "semi_major"} and {@code "semi_minor"} parameters.</td></tr>
      *   <tr><td>{@code "standard_parallel"}</td>  <td>Hidden</td>
      *     <td>Array of 1 or 2 elements mapped to {@code "standard_parallel_1"} and
{@code "standard_parallel_2"}.</td></tr>
      * </table>

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=1693658&r1=1693657&r2=1693658&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 21:59:39 2015
@@ -18,8 +18,10 @@ package org.apache.sis.referencing.opera
 
 import java.util.Map;
 import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.parameter.ParameterNotFoundException;
 import org.opengis.referencing.operation.OperationMethod;
 import org.apache.sis.internal.referencing.provider.MapProjection;
+import org.apache.sis.internal.util.Constants;
 import org.apache.sis.parameter.Parameters;
 import org.apache.sis.internal.util.DoubleDouble;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
@@ -67,6 +69,11 @@ final class Initializer {
      * <var>ℯ</var> is the {@linkplain #excentricity excentricity},
      * <var>a</var> is the <cite>semi-major</cite> axis length and
      * <var>b</var> is the <cite>semi-minor</cite> axis length.
+     *
+     * <p>This is stored as a double-double value because this parameter is sometime
used for computing back
+     * the semi-minor axis length or the inverse flattening factor. In such case we wish
to find the original
+     * {@code double} parameter value without rounding errors. This wish usually do not apply
to other internal
+     * {@link NormalizedProjection} parameters.</p>
      */
     final DoubleDouble excentricitySquared;
 
@@ -117,13 +124,31 @@ final class Initializer {
         DoubleDouble k = new DoubleDouble(a);  // The value by which to multiply all results
of normalized projection.
         if (a != b) {
             /*
-             * ℯ² = 1 - (b/a)²
+             * (1) Using axis lengths:  ℯ² = 1 - (b/a)²
+             * (2) Using flattening;    ℯ² = 2f - f²     where f is the (NOT inverse)
flattening factor.
              *
-             * Double-double arithmetic here makes a difference in the 3 last digits for
WGS84 ellipsoid.
+             * If the inverse flattening factor is the definitive factor for the ellipsoid,
we use (2).
+             * Otherwise use (1). With double-double arithmetic, this makes a difference
in the 3 last
+             * digits for the WGS84 ellipsoid.
              */
-            if (DoubleDouble.DISABLED) {
-                final double rs = b / a;
-                excentricitySquared.value = 1 - (rs * rs);
+            boolean isIvfDefinitive;
+            try {
+                isIvfDefinitive = parameters.parameter(Constants.IS_IVF_DEFINITIVE).booleanValue();
+            } catch (ParameterNotFoundException e) {
+                /*
+                 * Should never happen with Apache SIS implementation, but may happen if
the given parameters come
+                 * from another implementation. We can safely abandon our attempt to get
the inverse flattening value,
+                 * since it was redundant with semi-minor axis length.
+                 */
+                isIvfDefinitive = false;
+            }
+            if (isIvfDefinitive) {
+                final DoubleDouble f = new DoubleDouble(parameters.parameter(Constants.INVERSE_FLATTENING).doubleValue());
+                f.inverseDivide(1,0);
+                excentricitySquared.setFrom(f);
+                excentricitySquared.multiply(2,0);
+                f.multiply(f);
+                excentricitySquared.subtract(f);
             } else {
                 final DoubleDouble rs = new DoubleDouble(b);
                 rs.divide(k);    // rs = b/a

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -96,7 +96,10 @@ public class LambertConicConformal exten
     }
 
     /**
-     * Constant for the Belgium 2SP case. This is 29.2985 seconds, given here in radians.
+     * Constant for the Belgium 2SP case. Defined as 29.2985 seconds, given here in radians.
+     * Use double-double arithmetic not for map projection accuracy, but for consistency
with
+     * the normalization matrix which use that precision for "degrees to radians" conversion.
+     * The goal is to have cleaner results after matrix inversions and multiplications.
      *
      * <div class="note"><b>Tip:</b> how to verify the value:
      * {@preformat java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -36,6 +36,7 @@ import org.opengis.parameter.ParameterVa
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.ParameterNotFoundException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.datum.Ellipsoid;
@@ -535,12 +536,34 @@ public class DefaultMathTransformFactory
                  */
                 failure = e;
             }
+            final boolean isIvfDefinitive;
             if (mismatchedParam != null) {
                 final LogRecord record = Messages.getResources((Locale) null).getLogRecord(Level.WARNING,
                         Messages.Keys.MismatchedEllipsoidAxisLength_3, ellipsoid.getName().getCode(),
                         mismatchedParam.getDescriptor().getName().getCode(), mismatchedValue);
                 record.setLoggerName(Loggers.COORDINATE_OPERATION);
                 Logging.log(DefaultMathTransformFactory.class, "createBaseToDerived", record);
+                isIvfDefinitive = false;
+            } else {
+                isIvfDefinitive = ellipsoid.isIvfDefinitive();
+            }
+            /*
+             * Following is specific to Apache SIS. We use this non-standard API for allowing
the
+             * NormalizedProjection class (our base class for all map projection implementations)
+             * to known that the ellipsoid definitive parameter is the inverse flattening
factor
+             * instead than the semi-major axis length. It makes a small difference in the
accuracy
+             * of the excentricity parameter.
+             */
+            if (isIvfDefinitive) try {
+                parameters.parameter(Constants.INVERSE_FLATTENING).setValue(ellipsoid.getInverseFlattening());
+            } catch (ParameterNotFoundException e) {
+                /*
+                 * Should never happen with Apache SIS implementation, but may happen if
the given parameters come
+                 * from another implementation. We can safely abandon our attempt to set
the inverse flattening value,
+                 * since it was redundant with semi-minor axis length.
+                 */
+                Logging.recoverableException(Logging.getLogger(Loggers.COORDINATE_OPERATION),
+                        DefaultMathTransformFactory.class, "createBaseToDerived", e);
             }
         }
         MathTransform baseToDerived;

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -28,12 +28,13 @@ import org.junit.Test;
 import static org.junit.Assert.*;
 import static org.apache.sis.internal.util.Constants.SEMI_MAJOR;
 import static org.apache.sis.internal.util.Constants.SEMI_MINOR;
+import static org.apache.sis.internal.util.Constants.EARTH_RADIUS;
+import static org.apache.sis.internal.util.Constants.INVERSE_FLATTENING;
+import static org.apache.sis.internal.util.Constants.IS_IVF_DEFINITIVE;
 import static org.apache.sis.internal.util.Constants.CENTRAL_MERIDIAN;
+import static org.apache.sis.internal.util.Constants.STANDARD_PARALLEL;
 import static org.apache.sis.internal.util.Constants.STANDARD_PARALLEL_1;
 import static org.apache.sis.internal.util.Constants.STANDARD_PARALLEL_2;
-import static org.apache.sis.parameter.MapProjectionDescriptor.EARTH_RADIUS;
-import static org.apache.sis.parameter.MapProjectionDescriptor.INVERSE_FLATTENING;
-import static org.apache.sis.parameter.MapProjectionDescriptor.STANDARD_PARALLEL;
 
 
 /**
@@ -103,17 +104,24 @@ public final strictfp class MapProjectio
         final MapProjectionDescriptor descriptor = createDescriptor(0);
         final ParameterValueGroup parameters = descriptor.createValue();
 
-        parameters.parameter(SEMI_MAJOR).setValue(6378206.4); // Clarke 1866
+        parameters.parameter(SEMI_MAJOR).setValue(6378206.4);  // Clarke 1866
         parameters.parameter(SEMI_MINOR).setValue(6356583.8);
         assertEquals(294.97870, parameters.parameter(INVERSE_FLATTENING).doubleValue(), 0.00001);
         assertEquals(6378206.4, parameters.parameter(SEMI_MAJOR)        .doubleValue(), 0.5);
         assertEquals(6356583.8, parameters.parameter(SEMI_MINOR)        .doubleValue(), 0.5);
+        assertFalse("isIvfDefinitive", parameters.parameter(IS_IVF_DEFINITIVE).booleanValue());
 
-        parameters.parameter(SEMI_MAJOR).setValue(6378137.000); // WGS84
+        parameters.parameter(SEMI_MAJOR).setValue(6378137.0);  // WGS84
         parameters.parameter(INVERSE_FLATTENING).setValue(298.257223563);
         assertEquals(298.257, parameters.parameter(INVERSE_FLATTENING).doubleValue(), 0.001);
         assertEquals(6378137, parameters.parameter(SEMI_MAJOR)        .doubleValue(), 0.5);
         assertEquals(6356752, parameters.parameter(SEMI_MINOR)        .doubleValue(), 0.5);
+        assertTrue("isIvfDefinitive", parameters.parameter(IS_IVF_DEFINITIVE).booleanValue());
+
+        parameters.parameter(SEMI_MAJOR).setValue(6378350.9);  // Clarke 1858 (approximative)
+        parameters.parameter(SEMI_MINOR).setValue(6356675.0);
+        assertEquals(294.26, parameters.parameter(INVERSE_FLATTENING).doubleValue(), 0.001);
+        assertFalse("isIvfDefinitive", parameters.parameter(IS_IVF_DEFINITIVE).booleanValue());
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -105,7 +105,7 @@ public final strictfp class LambertConic
         createNormalizedProjection(true, 40);
         assertWktEqualsRegex("\\Q" +
                 "PARAM_MT[“Lambert conic conformal”,\n" +
-                "  PARAMETER[“excentricity”, 0.08181919084262244],\n" +
+                "  PARAMETER[“excentricity”, 0.0818191908426215],\n" +
                 "  PARAMETER[“n”, 0.64278760968653\\E\\d*\\]\\]");  // 0.6427876096865393
in the original test.
     }
 

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -66,6 +66,9 @@ strictfp class MapProjectionTestCase ext
         final Ellipsoid ellipsoid = (ellipse ? GeodeticDatumMock.WGS84 : GeodeticDatumMock.SPHERE).getEllipsoid();
         parameters.parameter(Constants.SEMI_MAJOR).setValue(ellipsoid.getSemiMajorAxis());
         parameters.parameter(Constants.SEMI_MINOR).setValue(ellipsoid.getSemiMinorAxis());
+        if (ellipse) {
+            parameters.parameter(Constants.INVERSE_FLATTENING).setValue(ellipsoid.getInverseFlattening());
+        }
         return parameters;
     }
 

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -75,7 +75,7 @@ public final strictfp class MercatorTest
         createNormalizedProjection(true);
         assertWktEquals(
                 "PARAM_MT[“Mercator”,\n" +
-                "  PARAMETER[“excentricity”, 0.08181919084262244]]");
+                "  PARAMETER[“excentricity”, 0.0818191908426215]]");
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -45,7 +45,17 @@ final strictfp class NoOp extends Confor
      * @param ellipsoidal {@code true} for an ellipsoidal case, or {@code false} for a spherical
case.
      */
     NoOp(final boolean ellipsoidal) {
-        this(parameters((ellipsoidal ? GeodeticDatumMock.WGS84 : GeodeticDatumMock.SPHERE).getEllipsoid()));
+        this(ellipsoidal, ellipsoidal);
+    }
+
+    /**
+     * Creates a new "no-operation".
+     *
+     * @param ellipsoidal {@code true} for an ellipsoidal case, or {@code false} for a spherical
case.
+     * @param declareIvf  {@code true} for declaring the inverse flattening factor.
+     */
+    NoOp(final boolean ellipsoidal, final boolean declareIvf) {
+        this(parameters((ellipsoidal ? GeodeticDatumMock.WGS84 : GeodeticDatumMock.SPHERE).getEllipsoid(),
declareIvf));
     }
 
     /**
@@ -71,9 +81,14 @@ final strictfp class NoOp extends Confor
      * ("Relax constraint on placement of this()/super() call in constructors").
      */
     @Workaround(library="JDK", version="1.7")
-    private static Parameters parameters(final Ellipsoid ellipsoid) {
-        return parameters(ellipsoid.getSemiMajorAxis(),
-                          ellipsoid.getSemiMinorAxis());
+    private static Parameters parameters(final Ellipsoid ellipsoid, final boolean declareIvf)
{
+        final Parameters parameters = parameters(
+                ellipsoid.getSemiMajorAxis(),
+                ellipsoid.getSemiMinorAxis());
+        if (declareIvf) {
+            parameters.parameter(Constants.INVERSE_FLATTENING).setValue(ellipsoid.getInverseFlattening());
+        }
+        return parameters;
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -65,8 +65,17 @@ public final strictfp class NormalizedPr
         NormalizedProjection projection;
         transform = projection = new NoOp(false);
         assertEquals("excentricity", 0.0, projection.excentricity, 0.0);
+        /*
+         * Tested methods. Note the similarity between (1) and (3).
+         *
+         *  (1) Using double        arithmetic and axis lengths:  0.08181919084262157
+         *  (2) Using double-double arithmetic and axis lengths:  0.08181919084262244
+         *  (3) Using double-double arithmetic and flattening:    0.0818191908426215
+         */
+        transform = projection = new NoOp(true, false);
+        assertEquals("excentricity", 0.08181919084262244, projection.excentricity, 0.0);
 
-        transform = projection = new NoOp(true);
-        assertEquals("excentricity", 0.08181919084262157, projection.excentricity, TOLERANCE);
+        transform = projection = new NoOp(true, true);
+        assertEquals("excentricity", 0.0818191908426215, projection.excentricity, 0.0);
     }
 }

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -78,17 +78,34 @@ public final class Constants extends Sta
     public static final byte CRS84 = 84;
 
     /**
+     * The NetCDF parameter name for the Earth radius.
+     */
+    public static final String EARTH_RADIUS = "earth_radius";
+
+    /**
      * Name of the {@value} projection parameter, which is handled specially during WKT formatting.
      */
     public static final String SEMI_MAJOR = "semi_major",
                                SEMI_MINOR = "semi_minor";
 
     /**
+     * The NetCDF parameter name for inverse flattening, and whether that parameter is definitive.
+     * The later is specific to SIS.
+     */
+    public static final String INVERSE_FLATTENING = "inverse_flattening",
+                               IS_IVF_DEFINITIVE  = "is_ivf_definitive";
+
+    /**
      * The OGC parameter name for the central meridian.
      */
     public static final String CENTRAL_MERIDIAN = "central_meridian";
 
     /**
+     * The NetCDF parameter name for the standard parallels.
+     */
+    public static final String STANDARD_PARALLEL = "standard_parallel";
+
+    /**
      * The OGC parameter name for the standard parallels.
      */
     public static final String STANDARD_PARALLEL_1 = "standard_parallel_1",
@@ -125,6 +142,7 @@ public final class Constants extends Sta
      */
     public static final String FALSE_EASTING  = "false_easting",
                                FALSE_NORTHING = "false_northing";
+
     /**
      * Name of the {@value} matrix parameters.
      */

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestCase.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestCase.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestCase.java [UTF-8]
(original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestCase.java [UTF-8]
Fri Jul 31 21:59:39 2015
@@ -24,7 +24,6 @@ import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.io.OutputStreamWriter;
 import java.io.UnsupportedEncodingException;
-import org.apache.sis.internal.system.Modules;
 import org.apache.sis.util.logging.Logging;
 import org.junit.runner.RunWith;
 
@@ -182,6 +181,7 @@ public abstract strictfp class TestCase
      *
      * @param success {@code true} if this method is invoked on build success,
      */
+    @SuppressWarnings("UseOfSystemOutOrSystemErr")
     static void flushOutput() {
         System.out.flush();
         System.err.flush();



Mime
View raw message