sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1692168 [2/3] - in /sis/branches/JDK6: ./ application/sis-console/src/main/java/org/apache/sis/console/ core/sis-feature/src/main/java/org/apache/sis/feature/ core/sis-feature/src/test/java/org/apache/sis/feature/ core/sis-metadata/src/mai...
Date Tue, 21 Jul 2015 16:41:14 GMT
Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -20,7 +20,6 @@ import java.util.Map;
 import java.util.EnumMap;
 import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterDescriptor;
-import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
@@ -76,23 +75,38 @@ import static org.apache.sis.math.MathFu
  * @see TransverseMercator
  * @see ObliqueMercator
  */
-public class Mercator extends AbstractLambertConformal {
+public class Mercator extends ConformalProjection {
     /**
      * For cross-version compatibility.
      */
     private static final long serialVersionUID = 2564172914329253286L;
 
     /**
-     * Codes for special kinds of Mercator projection. We do not provide such codes in public API because
-     * they duplicate the functionality of {@link OperationMethod} instances. We use them only for convenience.
+     * Codes for variants of Mercator projection. Those variants modify the way the projections are constructed
+     * (e.g. in the way parameters are interpreted), but formulas are basically the same after construction.
+     * Those variants are not exactly the same than variants A, B and C used by EPSG, but they are related.
      *
-     * <p><b>CONVENTION:</b> Spherical cases must be odd, all other cases must be even. This allow us to perform
-     * quick checks for all spherical cases using {@code if ((type & SPHERICAL) != 0)}.</p>
+     * <p>We do not provide such codes in public API because they duplicate the functionality of
+     * {@link OperationMethod} instances. We use them only for constructors convenience.</p>
      *
-     * @see #getType(ParameterDescriptorGroup)
+     * <p><b>CONVENTION:</b> <strong>Spherical cases must be odd, all other cases must be even.</strong>
+     * This allow us to perform quick checks for all spherical cases using {@code if ((type & SPHERICAL) != 0)}.</p>
+     *
+     * @see #getVariant(OperationMethod)
+     */
+    private static final byte SPHERICAL = 1, PSEUDO = 3,    // Must be odd and SPHERICAL must be 1.
+                              REGIONAL  = 2, MILLER = 4;    // Must be even.
+
+    /**
+     * Returns the variant of the projection based on the name and identifier of the given operation method.
      */
-    static final byte SPHERICAL = 1, PSEUDO = 3,    // Must be odd and SPHERICAL must be 1.
-                      REGIONAL  = 2, MILLER = 4;    // Must be even.
+    private static byte getVariant(final OperationMethod method) {
+        if (identMatch(method, "(?i).*\\bvariant\\s*C\\b.*", RegionalMercator .IDENTIFIER)) return REGIONAL;
+        if (identMatch(method, "(?i).*\\bSpherical\\b.*",    MercatorSpherical.IDENTIFIER)) return SPHERICAL;
+        if (identMatch(method, "(?i).*\\bPseudo.*",          PseudoMercator   .IDENTIFIER)) return PSEUDO;
+        if (identMatch(method, "(?i).*\\bMiller.*",          null))                         return MILLER;
+        return 0;
+    }
 
     /**
      * The type of Mercator projection. Possible values are:
@@ -106,18 +120,18 @@ public class Mercator extends AbstractLa
      *
      * Other cases may be added in the future.
      *
-     * @see #getType(ParameterDescriptorGroup)
+     * @see #getVariant(OperationMethod)
      */
-    final byte type;
+    private final byte variant;
 
     /**
-     * Returns the (<var>role</var> → <var>parameter</var>) associations for a Mercator projection of the given type.
+     * Returns the (<var>role</var> → <var>parameter</var>) associations for a Mercator projection of the given variant.
      *
-     * @param  type One of {@link #REGIONAL}, {@link #SPHERICAL}, {@link #PSEUDO} or {@link #MILLER} constants.
+     * @param  variant One of {@link #REGIONAL}, {@link #SPHERICAL}, {@link #PSEUDO} or {@link #MILLER} constants.
      * @return The roles map to give to super-class constructor.
      */
     @SuppressWarnings("fallthrough")
-    private static Map<ParameterRole, ParameterDescriptor<Double>> roles(final byte type) {
+    private static Map<ParameterRole, ParameterDescriptor<Double>> roles(final byte variant) {
         final EnumMap<ParameterRole, ParameterDescriptor<Double>> roles =
                 new EnumMap<ParameterRole, ParameterDescriptor<Double>>(ParameterRole.class);
         /*
@@ -127,7 +141,7 @@ public class Mercator extends AbstractLa
          * since it may be used in some Well Known Text (WKT).
          */
         roles.put(ParameterRole.SCALE_FACTOR, Mercator1SP.SCALE_FACTOR);
-        switch (type) {
+        switch (variant) {
             case REGIONAL: {
                 roles.put(ParameterRole.FALSE_EASTING,  RegionalMercator.EASTING_AT_FALSE_ORIGIN);
                 roles.put(ParameterRole.FALSE_NORTHING, RegionalMercator.NORTHING_AT_FALSE_ORIGIN);
@@ -178,7 +192,7 @@ public class Mercator extends AbstractLa
      * @param parameters The parameter values of the projection to create.
      */
     public Mercator(final OperationMethod method, final Parameters parameters) {
-        this(method, parameters, getType(parameters.getDescriptor()));
+        this(method, parameters, getVariant(method));
     }
 
     /**
@@ -186,15 +200,15 @@ public class Mercator extends AbstractLa
      * ("Relax constraint on placement of this()/super() call in constructors").
      */
     @Workaround(library="JDK", version="1.7")
-    private Mercator(final OperationMethod method, final Parameters parameters, final byte type) {
-        super(method, parameters, roles(type));
-        this.type = type;
+    private Mercator(final OperationMethod method, final Parameters parameters, final byte variant) {
+        super(method, parameters, roles(variant));
+        this.variant = variant;
         /*
          * The "Longitude of natural origin" parameter is found in all Mercator projections and is mandatory.
          * Since this is usually the Greenwich meridian, the default value is 0°. We keep the value in degrees
          * for now; it will be converted to radians later.
          */
-        final double λ0 = getAndStore(parameters, Mercator1SP.CENTRAL_MERIDIAN);
+        final double λ0 = getAndStore(parameters, Mercator1SP.LONGITUDE_OF_ORIGIN);
         /*
          * The "Latitude of natural origin" is not formally a parameter of Mercator projection. But the parameter
          * is included for completeness in CRS labelling, with the restriction (specified in EPSG documentation)
@@ -207,7 +221,7 @@ public class Mercator extends AbstractLa
          * "Latitude of origin" can not have a non-zero value, if it still have non-zero value we will process as
          * for "Latitude of false origin".
          */
-        final double φ0 = toRadians(getAndStore(parameters, (type == REGIONAL)
+        final double φ0 = toRadians(getAndStore(parameters, (variant == REGIONAL)
                 ? RegionalMercator.LATITUDE_OF_FALSE_ORIGIN : Mercator1SP.LATITUDE_OF_ORIGIN));
         /*
          * In theory, the "Latitude of 1st standard parallel" and the "Scale factor at natural origin" parameters
@@ -241,7 +255,7 @@ public class Mercator extends AbstractLa
         if (φ0 != 0) {
             denormalize.convertBefore(1, null, new DoubleDouble(-log(expOfNorthing(φ0, excentricity * sin(φ0)))));
         }
-        if (type == MILLER) {
+        if (variant == MILLER) {
               normalize.convertBefore(1, new DoubleDouble(0.80), null);
             denormalize.convertBefore(1, new DoubleDouble(1.25), null);
         }
@@ -280,18 +294,7 @@ public class Mercator extends AbstractLa
      */
     Mercator(final Mercator other) {
         super(other);
-        type = other.type;
-    }
-
-    /**
-     * Returns the type of the projection based on the name and identifier of the given parameter group.
-     */
-    private static byte getType(final ParameterDescriptorGroup parameters) {
-        if (identMatch(parameters, "(?i).*\\bvariant\\s*C\\b.*", RegionalMercator .IDENTIFIER)) return REGIONAL;
-        if (identMatch(parameters, "(?i).*\\bSpherical\\b.*",    MercatorSpherical.IDENTIFIER)) return SPHERICAL;
-        if (identMatch(parameters, "(?i).*\\bPseudo.*",          PseudoMercator   .IDENTIFIER)) return PSEUDO;
-        if (identMatch(parameters, "(?i).*\\bMiller.*",          null))                         return MILLER;
-        return 0;
+        variant = other.variant;
     }
 
     /**
@@ -309,7 +312,7 @@ public class Mercator extends AbstractLa
     @Override
     public MathTransform createMapProjection(final MathTransformFactory factory) throws FactoryException {
         Mercator kernel = this;
-        if ((type & SPHERICAL) != 0 || excentricity == 0) {
+        if ((variant & SPHERICAL) != 0 || excentricity == 0) {
             kernel = new Spherical(this);
         }
         return context.completeTransform(factory, kernel);
@@ -329,29 +332,28 @@ public class Mercator extends AbstractLa
                             final double[] dstPts, final int dstOff,
                             final boolean derivate) throws ProjectionException
     {
-        final double λ    = srcPts[srcOff];
-        final double φ    = srcPts[srcOff + 1];
+        final double φ    = srcPts[srcOff+1];
         final double sinφ = sin(φ);
-        /*
-         * Projection of zero is zero. However the formulas below have a slight rounding error
-         * which produce values close to 1E-10, so we will avoid them when y=0. In addition of
-         * avoiding rounding error, this also preserve the sign (positive vs negative zero).
-         */
-        final double y;
-        if (φ == 0) {
-            y = φ;
-        } else {
-            // See the javadoc of the Spherical inner class for a note
-            // about why we perform explicit checks for the pole cases.
-            final double a = abs(φ);
-            if (a < PI/2) {
-                y = log(expOfNorthing(φ, excentricity * sinφ));     // Snyder (7-7)
+        if (dstPts != null) {
+            /*
+             * Projection of zero is zero. However the formulas below have a slight rounding error
+             * which produce values close to 1E-10, so we will avoid them when y=0. In addition of
+             * avoiding rounding error, this also preserve the sign (positive vs negative zero).
+             */
+            final double y;
+            if (φ == 0) {
+                y = φ;
             } else {
-                y = copySign(a <= (PI/2 + ANGULAR_TOLERANCE) ? POSITIVE_INFINITY : NaN, φ);
+                // See the javadoc of the Spherical inner class for a note
+                // about why we perform explicit checks for the pole cases.
+                final double a = abs(φ);
+                if (a < PI/2) {
+                    y = log(expOfNorthing(φ, excentricity * sinφ));     // Snyder (7-7)
+                } else {
+                    y = copySign(a <= (PI/2 + ANGULAR_TOLERANCE) ? POSITIVE_INFINITY : NaN, φ);
+                }
             }
-        }
-        if (dstPts != null) {
-            dstPts[dstOff]   = λ;
+            dstPts[dstOff  ] = srcPts[srcOff];   // Scale will be applied by the denormalization matrix.
             dstPts[dstOff+1] = y;
         }
         /*
@@ -462,40 +464,29 @@ public class Mercator extends AbstractLa
                                 final double[] dstPts, final int dstOff,
                                 final boolean derivate) throws ProjectionException
         {
-            final double λ = srcPts[srcOff  ];
             final double φ = srcPts[srcOff+1];
-            /*
-             * Projection of zero is zero. However the formulas below have a slight rounding error
-             * which produce values close to 1E-10, so we will avoid them when y=0. In addition of
-             * avoiding rounding error, this also preserve the sign (positive vs negative zero).
-             */
-            final double y;
-            if (φ == 0) {
-                y = φ;
-            } else {
-                // See class javadoc for a note about explicit check for poles.
-                final double a = abs(φ);
-                if (a < PI/2) {
-                    y = log(tan(PI/4 + 0.5*φ));    // Part of Snyder (7-2)
+            if (dstPts != null) {
+                /*
+                 * Projection of zero is zero. However the formulas below have a slight rounding error
+                 * which produce values close to 1E-10, so we will avoid them when y=0. In addition of
+                 * avoiding rounding error, this also preserve the sign (positive vs negative zero).
+                 */
+                final double y;
+                if (φ == 0) {
+                    y = φ;
                 } else {
-                    y = copySign(a <= (PI/2 + ANGULAR_TOLERANCE) ? POSITIVE_INFINITY : NaN, φ);
+                    // See class javadoc for a note about explicit check for poles.
+                    final double a = abs(φ);
+                    if (a < PI/2) {
+                        y = log(tan(PI/4 + 0.5*φ));    // Part of Snyder (7-2)
+                    } else {
+                        y = copySign(a <= (PI/2 + ANGULAR_TOLERANCE) ? POSITIVE_INFINITY : NaN, φ);
+                    }
                 }
-            }
-            Matrix derivative = null;
-            if (derivate) {
-                derivative = new Matrix2(1, 0, 0, 1/cos(φ));
-            }
-            /*
-             * Following part is common to all spherical projections: verify, store and return.
-             */
-            assert (excentricity != 0)  // Can not perform the following assertions if excentricity is not zero.
-                   || (Assertions.checkDerivative(derivative, super.transform(srcPts, srcOff, dstPts, dstOff, derivate))
-                   && Assertions.checkTransform(dstPts, dstOff, λ, y)); // dstPts = result from ellipsoidal formulas.
-            if (dstPts != null) {
-                dstPts[dstOff  ] = λ;
+                dstPts[dstOff  ] = srcPts[srcOff];
                 dstPts[dstOff+1] = y;
             }
-            return derivative;
+            return derivate ? new Matrix2(1, 0, 0, 1/cos(φ)) : null;
         }
 
         /**
@@ -539,26 +530,9 @@ public class Mercator extends AbstractLa
                                         final double[] dstPts, final int dstOff)
                 throws ProjectionException
         {
-            double x = srcPts[srcOff  ];
-            double y = srcPts[srcOff+1];
-            y = PI/2 - 2 * atan(exp(-y));     // Part of Snyder (7-4)
-            assert (excentricity != 0)  // Can not perform the following assertion if excentricity is not zero.
-                   || checkInverseTransform(srcPts, srcOff, dstPts, dstOff, x, y);
-            dstPts[dstOff  ] = x;
-            dstPts[dstOff+1] = y;
-        }
-
-        /**
-         * Computes using ellipsoidal formulas and compare with the
-         * result from spherical formulas. Used in assertions only.
-         */
-        private boolean checkInverseTransform(final double[] srcPts, final int srcOff,
-                                              final double[] dstPts, final int dstOff,
-                                              final double λ, final double φ)
-                throws ProjectionException
-        {
-            super.inverseTransform(srcPts, srcOff, dstPts, dstOff);
-            return Assertions.checkInverseTransform(dstPts, dstOff, λ, φ);
+            final double y = srcPts[srcOff+1];           // Must be before writing x.
+            dstPts[dstOff  ] = srcPts[srcOff];           // Must be before writing y.
+            dstPts[dstOff+1] = PI/2 - 2*atan(exp(-y));  // Part of Snyder (7-4);
         }
     }
 }

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -143,7 +143,7 @@ public abstract class NormalizedProjecti
 
     /**
      * Desired accuracy for the result of iterative computations, in radians.
-     * This constant defines the desired accuracy of methods like {@link AbstractLambertConformal#φ(double)}.
+     * This constant defines the desired accuracy of methods like {@link ConformalProjection#φ(double)}.
      *
      * <p>The current value is 0.25 time the accuracy derived from {@link Formulas#LINEAR_TOLERANCE}.
      * So if the linear tolerance is 1 cm, then the accuracy that we will seek for is 0.25 cm (about
@@ -453,7 +453,7 @@ public abstract class NormalizedProjecti
     }
 
     /**
-     * Returns {@code true} if the projection specified by the given parameters has the given keyword or identifier.
+     * Returns {@code true} if the projection specified by the given method has the given keyword or identifier.
      * If non-null, the given identifier is presumed in the EPSG namespace and has precedence over the keyword.
      *
      * <div class="note"><b>Implementation note:</b>
@@ -464,19 +464,19 @@ public abstract class NormalizedProjecti
      *
      * @param  parameters The user-specified parameters.
      * @param  regex      The regular expression to use when using the operation name as the criterion.
-     * @param  identifier The identifier to compare against the parameter group name.
-     * @return {@code true} if the given parameter group name contains the given keyword
+     * @param  identifier The identifier to compare against the operation method name.
+     * @return {@code true} if the name of the given operation method contains the given keyword
      *         or has an EPSG identifier equals to the given identifier.
      */
-    static boolean identMatch(final ParameterDescriptorGroup parameters, final String regex, final String identifier) {
+    static boolean identMatch(final OperationMethod method, final String regex, final String identifier) {
         if (identifier != null) {
-            for (final Identifier id : parameters.getIdentifiers()) {
+            for (final Identifier id : method.getIdentifiers()) {
                 if (Constants.EPSG.equals(id.getCodeSpace())) {
                     return identifier.equals(id.getCode());
                 }
             }
         }
-        return parameters.getName().getCode().matches(regex);
+        return method.getName().getCode().replace('_',' ').matches(regex);
     }
 
     /**
@@ -501,7 +501,7 @@ public abstract class NormalizedProjecti
         final Double defaultValue = descriptor.getDefaultValue();
         if (defaultValue == null || !defaultValue.equals(value)) {
             MapProjection.validate(descriptor, value);
-            context.parameter(descriptor.getName().getCode()).setValue(value);
+            context.getOrCreate(descriptor).setValue(value);
         }
         return value;
     }
@@ -861,91 +861,4 @@ public abstract class NormalizedProjecti
     final double rν(final double sinφ) {
         return sqrt(1 - excentricitySquared * (sinφ*sinφ));
     }
-
-    /**
-     * Computes part of the Mercator projection for the given latitude. This formula is also part of
-     * Lambert Conic Conformal projection, since Mercator can be considered as a special case of that
-     * Lambert projection with the equator as the single standard parallel.
-     *
-     * <p>The Mercator projection is given by the {@linkplain Math#log(double) natural logarithm}
-     * of the value returned by this method. This function is <em>almost</em> the converse of
-     * {@link AbstractLambertConformal#φ(double)}.
-     *
-     * <p>In IOGP Publication 373-7-2 – Geomatics Guidance Note number 7, part 2 – April 2015,
-     * a function closely related to this one has the letter <var>t</var>.</p>
-     *
-     *
-     * <div class="section">Properties</div>
-     * This function is used with φ values in the [-π/2 … π/2] range and has a periodicity of 2π.
-     * The result is always a positive number when the φ argument is inside the above-cited range.
-     * If, after removal of any 2π periodicity, φ is still outside the [-π/2 … π/2] range, then the
-     * result is a negative number. In a Mercator projection, such negative number will result in NaN.
-     *
-     * <p>Some values are:</p>
-     * <ul>
-     *   <li>expOfNorthing(NaN)    =  NaN</li>
-     *   <li>expOfNorthing(±∞)     =  NaN</li>
-     *   <li>expOfNorthing(-π/2)   =   0</li>
-     *   <li>expOfNorthing( 0  )   =   1</li>
-     *   <li>expOfNorthing(+π/2)   →   ∞  (actually some large value like 1.633E+16)</li>
-     *   <li>expOfNorthing(-φ)     =  1 / expOfNorthing(φ)</li>
-     * </ul>
-     *
-     *
-     * <div class="section">The π/2 special case</div>
-     * The value at {@code Math.PI/2} is not exactly infinity because there is no exact representation of π/2.
-     * However since the conversion of 90° to radians gives {@code Math.PI/2}, we can presume that the user was
-     * expecting infinity. The caller should check for the PI/2 special case himself if desired, as this method
-     * does nothing special about it.
-     *
-     * <p>Note that the result for the φ value after {@code Math.PI/2} (as given by {@link Math#nextUp(double)})
-     * is still positive, maybe because {@literal PI/2 < π/2 < nextUp(PI/2)}. Only the {@code nextUp(nextUp(PI/2))}
-     * value become negative. Callers may need to take this behavior in account: special check for {@code Math.PI/2}
-     * is not sufficient, the check needs to include at least the {@code nextUp(Math.PI/2)} case.</p>
-     *
-     *
-     * <div class="section">Relationship with Snyder</div>
-     * This function is related to the following functions from Snyder:
-     *
-     * <ul>
-     *   <li>(7-7) in the <cite>Mercator projection</cite> chapter.</li>
-     *   <li>Reciprocal of (9-13) in the <cite>Oblique Mercator projection</cite> chapter.</li>
-     *   <li>Reciprocal of (15-9) in the <cite>Lambert Conformal Conic projection</cite> chapter.</li>
-     * </ul>
-     *
-     * @param  φ     The latitude in radians.
-     * @param  ℯsinφ The sine of the φ argument multiplied by {@link #excentricity}.
-     * @return {@code Math.exp} of the Mercator projection of the given latitude.
-     *
-     * @see AbstractLambertConformal#φ(double)
-     * @see #dy_dφ(double, double)
-     */
-    final double expOfNorthing(final double φ, final double ℯsinφ) {
-        /*
-         * Note:   tan(π/4 - φ/2)  =  1 / tan(π/4 + φ/2)
-         *
-         * A + sign in the equation favorises slightly the accuracy in South hemisphere, while a - sign
-         * favorises slightly the North hemisphere (but the differences are very small). In Apache SIS,
-         * we handle that by changing the sign of some terms in the (de)normalisation matrices.
-         */
-        return tan(PI/4 + 0.5*φ) * pow((1 - ℯsinφ) / (1 + ℯsinφ), 0.5*excentricity);
-    }
-
-    /**
-     * Computes the partial derivative of a Mercator projection at the given latitude. This formula is also part of
-     * other projections, since Mercator can be considered as a special case of Lambert Conic Conformal for instance.
-     *
-     * <p>In order to get the derivative of the {@link #expOfNorthing(double, double)} function, call can multiply
-     * the returned value by by {@code expOfNorthing}.</p>
-     *
-     * @param  sinφ the sine of latitude.
-     * @param  cosφ The cosine of latitude.
-     * @return The partial derivative of a Mercator projection at the given latitude.
-     *
-     * @see #expOfNorthing(double, double)
-     * @see AbstractLambertConformal#φ(double)
-     */
-    final double dy_dφ(final double sinφ, final double cosφ) {
-        return (1 / cosφ)  -  excentricitySquared * cosφ / (1 - excentricitySquared * (sinφ*sinφ));
-    }
 }

Copied: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java (from r1692163, sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java?p2=sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java&p1=sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java&r1=1692163&r2=1692168&rev=1692168&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -91,7 +91,8 @@ public class PolarStereographic extends
      * @return The roles map to give to super-class constructor.
      */
     private static Map<ParameterRole, ParameterDescriptor<Double>> roles(final byte variant) {
-        final EnumMap<ParameterRole, ParameterDescriptor<Double>> roles = new EnumMap<>(ParameterRole.class);
+        final EnumMap<ParameterRole, ParameterDescriptor<Double>> roles =
+                new EnumMap<ParameterRole, ParameterDescriptor<Double>>(ParameterRole.class);
         ParameterDescriptor<Double> falseEasting  = PolarStereographicA.FALSE_EASTING;
         ParameterDescriptor<Double> falseNorthing = PolarStereographicA.FALSE_NORTHING;
         if (variant == C) {

Copied: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java (from r1692163, sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java?p2=sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java&p1=sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java&r1=1692163&r2=1692168&rev=1692168&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -77,7 +77,8 @@ public class TransverseMercator extends
      * @return The roles map to give to super-class constructor.
      */
     private static Map<ParameterRole, ParameterDescriptor<Double>> roles(final boolean isSouth) {
-        final EnumMap<ParameterRole, ParameterDescriptor<Double>> roles = new EnumMap<>(ParameterRole.class);
+        final EnumMap<ParameterRole, ParameterDescriptor<Double>> roles =
+                new EnumMap<ParameterRole, ParameterDescriptor<Double>>(ParameterRole.class);
         ParameterRole xOffset = ParameterRole.FALSE_EASTING;
         ParameterRole yOffset = ParameterRole.FALSE_NORTHING;
         if (isSouth) {

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -40,6 +40,7 @@ import org.apache.sis.util.resources.Err
  * @version 0.6
  * @module
  */
+@SuppressWarnings("CloneInNonCloneableClass")
 abstract class AbstractLinearTransform extends AbstractMathTransform
         implements LinearTransform, Matrix // Not Cloneable, despite the clone() method.
 {

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -99,6 +99,7 @@ class ConcatenatedTransform extends Abst
      * @param transform1 The first math transform.
      * @param transform2 The second math transform.
      */
+    @SuppressWarnings("OverridableMethodCallDuringObjectConstruction")
     protected ConcatenatedTransform(final MathTransform transform1,
                                     final MathTransform transform2)
     {

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -370,6 +370,7 @@ public class ContextualParameters extend
      *
      * @see org.apache.sis.referencing.operation.projection.NormalizedProjection#createMapProjection(MathTransformFactory)
      */
+    @SuppressWarnings("AssignmentToForLoopParameter")
     public MathTransform completeTransform(final MathTransformFactory factory, final MathTransform kernel)
             throws FactoryException
     {

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -26,7 +26,6 @@ import org.apache.sis.referencing.operat
 import org.apache.sis.referencing.operation.matrix.Matrices;
 
 
-
 /**
  * A transform which copy the ordinates in the source array to different locations in the target array.
  * This is a special case of {@link ProjectiveTransform} where the matrix coefficients are zero everywhere,

Modified: sis/branches/JDK6/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod [UTF-8] Tue Jul 21 16:41:12 2015
@@ -14,3 +14,8 @@ org.apache.sis.internal.referencing.prov
 org.apache.sis.internal.referencing.provider.LambertConformalWest
 org.apache.sis.internal.referencing.provider.LambertConformalBelgium
 org.apache.sis.internal.referencing.provider.LambertConformalMichigan
+org.apache.sis.internal.referencing.provider.PolarStereographicA
+org.apache.sis.internal.referencing.provider.PolarStereographicB
+org.apache.sis.internal.referencing.provider.PolarStereographicC
+org.apache.sis.internal.referencing.provider.PolarStereographicNorth
+org.apache.sis.internal.referencing.provider.PolarStereographicSouth

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/MapProjectionTest.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -141,7 +141,7 @@ public final strictfp class MapProjectio
      * This test is mostly for {@link Equirectangular#LATITUDE_OF_ORIGIN}.
      */
     private static void assertIsForcedToZero(final ParameterDescriptor<?> parameter) {
-        final Double zero = Double.valueOf(0);
+        final Double zero = 0.0;
         assertEquals("minimumValue", zero, parameter.getMinimumValue());
         assertEquals("maximumValue", zero, parameter.getMaximumValue());
     }

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/EquirectangularTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/EquirectangularTest.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/EquirectangularTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/EquirectangularTest.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -44,11 +44,11 @@ import static org.apache.sis.internal.me
 public final strictfp class EquirectangularTest extends MapProjectionTestCase {
     /**
      * Initializes a simple Equirectangular projection on sphere. This method is different than the
-     * {@code initialize(boolean)} method in all other test classes,  because it does not create an
-     * instance of {@link NormalizedProjection}. Instead, it creates an affine transform for the
-     * whole projection (not only the normalized part).
+     * {@code createNormalizedProjection(boolean)} method in all other test classes, because it does
+     * not create an instance of {@link NormalizedProjection}. Instead, it creates an affine transform
+     * for the whole projection (not only the normalized part).
      */
-    private void initialize() throws FactoryException {
+    private void createCompleteProjection() throws FactoryException {
         final Equirectangular provider = new Equirectangular();
         final Parameters parameters = parameters(provider, false);
         transform = new MathTransformFactoryMock(provider).createParameterizedTransform(parameters);
@@ -65,7 +65,7 @@ public final strictfp class Equirectangu
      */
     @Test
     public void testWKT() throws FactoryException {
-        initialize();
+        createCompleteProjection();
         assertWktEquals(
                 "PARAM_MT[“Equirectangular”,\n" +
                 "  PARAMETER[“semi_major”, 6371007.0],\n" +
@@ -95,7 +95,7 @@ public final strictfp class Equirectangu
      */
     @Test
     public void testSimpleTransform() throws FactoryException, TransformException {
-        initialize();
+        createCompleteProjection();
         verifyTransform(
                 new double[] {  // (λ,φ) coordinates in degrees to project.
                     0, 0,
@@ -118,7 +118,7 @@ public final strictfp class Equirectangu
      */
     @Test
     public void testRandomPoints() throws FactoryException, TransformException {
-        initialize(new Equirectangular(), true,
+        createCompleteProjection(new Equirectangular(), true,
                   0.5,  // Central meridian
                   0,    // Latitude of origin (none)
                  20,    // Standard parallel

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -50,7 +50,7 @@ import static org.junit.Assert.*;
  * @version 0.6
  * @module
  */
-@DependsOn(AbstractLambertConformalTest.class)
+@DependsOn(ConformalProjectionTest.class)
 public final strictfp class LambertConformalTest extends MapProjectionTestCase {
     /**
      * Creates a new instance of {@link LambertConformal}. See the class javadoc for an explanation
@@ -59,7 +59,7 @@ public final strictfp class LambertConfo
      * @param ellipse {@code false} for a sphere, or {@code true} for WGS84 ellipsoid.
      * @param latitudeOfOrigin The latitude of origin, in decimal degrees.
      */
-    private void initialize(final boolean ellipse, final double latitudeOfOrigin) {
+    private void createNormalizedProjection(final boolean ellipse, final double latitudeOfOrigin) {
         final LambertConformal1SP method = new LambertConformal1SP();
         final Parameters parameters = parameters(method, ellipse);
         parameters.getOrCreate(LambertConformal1SP.LATITUDE_OF_ORIGIN).setValue(latitudeOfOrigin);
@@ -77,7 +77,7 @@ public final strictfp class LambertConfo
      */
     @Test
     public void testNormalizedWKT() {
-        initialize(true, 40);
+        createNormalizedProjection(true, 40);
         assertWktEquals(
                 "PARAM_MT[“Lambert_Conformal_Conic_1SP”,\n" +
                 "  PARAMETER[“semi_major”, 1.0],\n" +
@@ -93,7 +93,7 @@ public final strictfp class LambertConfo
     @Test
     public void testSpecialLatitudes() throws ProjectionException {
         if (transform == null) {    // May have been initialized by 'testSphericalCase'.
-            initialize(true, 40);  // Elliptical case
+            createNormalizedProjection(true, 40);  // Elliptical case
         }
         final double INF = POSITIVE_INFINITY;
         assertEquals ("Not a number",     NaN, transform(NaN),            NORMALIZED_TOLERANCE);
@@ -114,7 +114,7 @@ public final strictfp class LambertConfo
         assertEquals ("Inverse -∞", +PI/2, inverseTransform(-INF), NORMALIZED_TOLERANCE);
 
         // Like the north case, but with sign inversed.
-        initialize(((LambertConformal) transform).excentricity != 0, -40);
+        createNormalizedProjection(((LambertConformal) transform).excentricity != 0, -40);
         validate();
 
         assertEquals ("Not a number",     NaN, transform(NaN),            NORMALIZED_TOLERANCE);
@@ -143,7 +143,7 @@ public final strictfp class LambertConfo
     @DependsOnMethod("testSpecialLatitudes")
     public void testDerivative() throws TransformException {
         if (transform == null) {    // May have been initialized by 'testSphericalCase'.
-            initialize(true, 40);   // Elliptical case
+            createNormalizedProjection(true, 40);   // Elliptical case
         }
         final double delta = toRadians(100.0 / 60) / 1852; // Approximatively 100 metres.
         derivativeDeltas = new double[] {delta, delta};
@@ -222,7 +222,7 @@ public final strictfp class LambertConfo
     @Test
     @DependsOnMethod("testLambertConicConformal1SP")
     public void testLambertConicConformalWestOrientated() throws FactoryException, TransformException {
-        initialize(new LambertConformal1SP(), false,
+        createCompleteProjection(new LambertConformal1SP(), false,
                   0.5,    // Central meridian
                  40,      // Latitude of origin
                   0,      // Standard parallel (none)
@@ -231,7 +231,7 @@ public final strictfp class LambertConfo
                 100);     // False northing
         final MathTransform reference = transform;
 
-        initialize(new LambertConformalWest(), false,
+        createCompleteProjection(new LambertConformalWest(), false,
                   0.5,    // Central meridian
                  40,      // Latitude of origin
                   0,      // Standard parallel (none)
@@ -274,25 +274,35 @@ public final strictfp class LambertConfo
     }
 
     /**
-     * Verifies the consistency of spherical formulas with the elliptical formulas.
+     * Performs the same tests than {@link #testSpecialLatitudes()} and {@link #testDerivative()},
+     * but using spherical formulas.
      *
      * @throws FactoryException if an error occurred while creating the map projection.
      * @throws TransformException if an error occurred while projecting a coordinate.
      */
     @Test
-    @DependsOnMethod("testSpecialLatitudes")
+    @DependsOnMethod({"testSpecialLatitudes", "testDerivative"})
     public void testSphericalCase() throws FactoryException, TransformException {
-        initialize(false, 40); // Spherical case
+        createNormalizedProjection(false, 40); // Spherical case
         testSpecialLatitudes();
         testDerivative();
-        /*
-         * Make sure that the above methods did not changed the 'transform' field type.
-         */
+
+        // Make sure that the above methods did not overwrote the 'transform' field.
         assertEquals("transform.class", LambertConformal.Spherical.class, transform.getClass());
-        /*
-         * For some random points, compare the result of spherical formulas with the ellipsoidal ones.
-         */
-        initialize(new LambertConformal1SP(), false,
+    }
+
+    /**
+     * 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("testSphericalCase")
+    public void compareEllipticalWithSpherical() throws FactoryException, TransformException {
+        createCompleteProjection(new LambertConformal1SP(), false,
                   0.5,    // Central meridian
                  40,      // Latitude of origin
                   0,      // Standard parallel (none)
@@ -300,6 +310,6 @@ public final strictfp class LambertConfo
                 200,      // False easting
                 100);     // False northing
         tolerance = Formulas.LINEAR_TOLERANCE;
-        verifyInDomain(CoordinateDomain.GEOGRAPHIC_SAFE, 268617081);
+        compareEllipticalWithSpherical(CoordinateDomain.GEOGRAPHIC_SAFE, 0);
     }
 }

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -19,11 +19,13 @@ package org.apache.sis.referencing.opera
 import javax.measure.unit.NonSI;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.datum.Ellipsoid;
+import org.opengis.referencing.operation.TransformException;
 import org.opengis.test.referencing.ParameterizedTransformTest;
 import org.apache.sis.parameter.Parameters;
-import org.apache.sis.internal.referencing.provider.MapProjection;
 import org.apache.sis.internal.util.Constants;
+import org.apache.sis.internal.referencing.provider.MapProjection;
 import org.apache.sis.referencing.operation.DefaultOperationMethod;
+import org.apache.sis.referencing.operation.transform.CoordinateDomain;
 import org.apache.sis.referencing.operation.transform.MathTransformTestCase;
 import org.apache.sis.test.mock.MathTransformFactoryMock;
 import org.apache.sis.test.mock.GeodeticDatumMock;
@@ -80,9 +82,9 @@ strictfp class MapProjectionTestCase ext
     /**
      * Initializes a complete projection (including conversion from degrees to radians) for the given provider.
      * This method uses arbitrary central meridian, scale factor, false easting and false northing for increasing
-     * the chances to detect a mismatch.
+     * the chances to detect a mismatch. The result is stored in the {@link #transform} field.
      */
-    final void initialize(final DefaultOperationMethod provider, final boolean ellipse,
+    final void createCompleteProjection(final DefaultOperationMethod provider, final boolean ellipse,
             final double centralMeridian,
             final double latitudeOfOrigin,
             final double standardParallel,
@@ -148,4 +150,24 @@ strictfp class MapProjectionTestCase ext
         }
         return φ;
     }
+
+    /**
+     * Compares the elliptical formulas with the spherical formulas for random points in the given domain.
+     * The spherical formulas are arbitrarily selected as the reference implementation because they are simpler,
+     * so less bug-prone, than the elliptical formulas.
+     *
+     * @param  domain The domain of the numbers to be generated.
+     * @param  randomSeed The seed for the random number generator, or 0 for choosing a random seed.
+     * @throws TransformException If a conversion, transformation or derivative failed.
+     */
+    final void compareEllipticalWithSpherical(final CoordinateDomain domain, final long randomSeed)
+            throws TransformException
+    {
+        transform = ProjectionResultComparator.sphericalAndEllipsoidal(transform);
+        if (derivativeDeltas == null) {
+            final double delta = toRadians(100.0 / 60) / 1852;    // Approximatively 100 metres.
+            derivativeDeltas = new double[] {delta, delta};
+        }
+        verifyInDomain(domain, randomSeed);
+    }
 }

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -61,6 +61,7 @@ public final class MercatorMethodCompari
     /**
      * Where to print the outputs of this class.
      */
+    @SuppressWarnings("UseOfSystemOutOrSystemErr")
     private static final PrintStream out = System.out;
 
     /**
@@ -112,7 +113,7 @@ public final class MercatorMethodCompari
 
     /**
      * Computes φ using the series expansion given by Geomatics Guidance Note number 7, part 2.
-     * This is the first part of the {@link AbstractLambertConformal#φ(double)} method.
+     * This is the first part of the {@link ConformalProjection#φ(double)} method.
      *
      * @param  t The {@code expOfSouthing} parameter value.
      * @return The latitude (in radians) for the given parameter.
@@ -126,8 +127,32 @@ public final class MercatorMethodCompari
     }
 
     /**
+     * Same formula than {@link #bySeriesExpansion(double)}, but replacing some sine by trigonometric identities.
+     * The identities used are:
+     *
+     * <ul>
+     *   <li>sin(2⋅x) = 2⋅sin(x)⋅cos(x)</li>
+     *   <li>sin(3⋅x) = (3 - 4⋅sin²(x))⋅sin(x)</li>
+     *   <li>sin(4⋅x) = (4 - 8⋅sin²(x))⋅sin(x)⋅cos(x)</li>
+     * </ul>
+     *
+     * @param  t The {@code expOfSouthing} parameter value.
+     * @return The latitude (in radians) for the given parameter.
+     */
+    public double usingTrigonometricIdentities(final double t) {
+        final double χ = PI/2 - 2*atan(t);
+        final double sin2χ     = sin(2*χ);
+        final double sin_cos2χ = cos(2*χ) * sin2χ;
+        final double sin_sin2χ = sin2χ * sin2χ;
+        return c8χ * (4 - 8*sin_sin2χ)*sin_cos2χ
+             + c6χ * (3 - 4*sin_sin2χ)*sin2χ
+             + c4χ * 2*sin_cos2χ
+             + c2χ * sin2χ + χ;
+    }
+
+    /**
      * Computes φ using the iterative method used by USGS.
-     * This is the second part of the {@link AbstractLambertConformal#φ(double)} method.
+     * This is the second part of the {@link ConformalProjection#φ(double)} method.
      *
      * @param  t The {@code expOfSouthing} parameter value.
      * @return The latitude (in radians) for the given parameter.
@@ -150,7 +175,7 @@ public final class MercatorMethodCompari
     }
 
     /**
-     * Basically a copy of {@link AbstractLambertConformal#expOfNorthing(double, double)}.
+     * Basically a copy of {@link ConformalProjection#expOfNorthing(double, double)}.
      */
     final double expOfNorthing(final double φ) {
         final double ℯsinφ = excentricity * sin(φ);
@@ -171,23 +196,26 @@ public final class MercatorMethodCompari
 
     /**
      * Implementation of {@link #printAccuracyComparison(int)} and {@link #printErrorForExcentricities(double,double)},
-     * optionally with a comparison with {@link AbstractLambertConformal}.
+     * optionally with a comparison with {@link ConformalProjection}.
      */
-    private void compare(final AbstractLambertConformal projection, final int numSamples, final TableAppender summarize)
+    private void compare(final ConformalProjection projection, final int numSamples, final TableAppender summarize)
             throws ProjectionException
     {
         final Statistics iterativeMethodErrors = new Statistics("Iterative method error");
         final Statistics seriesExpansionErrors = new Statistics("Series expansion error");
-        final Statistics abstractLambertErrors  = new Statistics("'AbstractLambertConformal' error");
+        final Statistics usingTrigoIdentErrors = new Statistics("Using trigonometric identities");
+        final Statistics abstractLambertErrors = new Statistics("'ConformalProjection' error");
         final Random random = new Random();
         for (int i=0; i<numSamples; i++) {
             final double φ = random.nextDouble() * PI - PI/2;
             final double t = 1 / expOfNorthing(φ);
             final double byIterativeMethod = byIterativeMethod(t);
             final double bySeriesExpansion = bySeriesExpansion(t);
+            final double usingTrigoIdent = usingTrigonometricIdentities(t);
 
             iterativeMethodErrors.accept(abs(φ - byIterativeMethod) / NormalizedProjection.ITERATION_TOLERANCE);
             seriesExpansionErrors.accept(abs(φ - bySeriesExpansion) / NormalizedProjection.ITERATION_TOLERANCE);
+            usingTrigoIdentErrors.accept(abs(φ - usingTrigoIdent)   / NormalizedProjection.ITERATION_TOLERANCE);
             if (projection != null) {
                 abstractLambertErrors.accept(abs(φ - projection.φ(t)) / NormalizedProjection.ITERATION_TOLERANCE);
             }
@@ -208,6 +236,7 @@ public final class MercatorMethodCompari
             Statistics[] stats = new Statistics[] {
                 iterativeMethodErrors,
                 seriesExpansionErrors,
+                usingTrigoIdentErrors,
                 abstractLambertErrors
             };
             if (projection == null) {
@@ -232,7 +261,7 @@ public final class MercatorMethodCompari
      * Prints the error of the two methods for various excentricity values.
      * The intend of this method is to find an excentricity threshold value where we consider the errors too high.
      *
-     * <p>This method is used for determining empirically a value for {@link AbstractLambertConformal#EXCENTRICITY_THRESHOLD}.
+     * <p>This method is used for determining empirically a value for {@link ConformalProjection#EXCENTRICITY_THRESHOLD}.
      * The current threshold value is shown by inserting a horizontal line separator in the table when that threshold
      * is crossed.</p>
      *
@@ -253,7 +282,7 @@ public final class MercatorMethodCompari
         final double step = 0.01;
         double excentricity;
         for (int i=0; (excentricity = min + step*i) < max; i++) {
-            if (!crossThreshold && excentricity >= AbstractLambertConformal.EXCENTRICITY_THRESHOLD) {
+            if (!crossThreshold && excentricity >= ConformalProjection.EXCENTRICITY_THRESHOLD) {
                 crossThreshold = true;
                 table.appendHorizontalSeparator();
             }
@@ -269,12 +298,47 @@ public final class MercatorMethodCompari
     }
 
     /**
+     * Compares the performance of the 3 methods.
+     *
+     * @throws ProjectionException if an error occurred in {@link #φ(double)}.
+     */
+    private void benchmark() throws ProjectionException {
+        final Random random = new Random();
+        final double[] t = new double[1000000];
+        for (int i=0; i<t.length; i++) {
+            t[i] = random.nextGaussian() * 3;
+        }
+        double s0 = 0, s1 = 0, s2 = 0;
+        final long t0 = System.nanoTime();
+        for (int i=0; i<t.length; i++) {
+            s0 += byIterativeMethod(t[i]);
+        }
+        final long t1 = System.nanoTime();
+        for (int i=0; i<t.length; i++) {
+            s1 += bySeriesExpansion(t[i]);
+        }
+        final long t2 = System.nanoTime();
+        for (int i=0; i<t.length; i++) {
+            s2 += usingTrigonometricIdentities(t[i]);
+        }
+        final long t3 = System.nanoTime();
+        final float c = (t1 - t0) / 100f;
+        out.println("Iterative method:         " + ((t1 - t0) / 1E9f) + " seconds (" + round((t1 - t0) / c) + "%).");
+        out.println("Series expansion:         " + ((t2 - t1) / 1E9f) + " seconds (" + round((t2 - t1) / c) + "%).");
+        out.println("Trigonometric identities: " + ((t3 - t2) / 1E9f) + " seconds (" + round((t3 - t2) / c) + "%).");
+        out.println("Mean φ values: " + (s0 / t.length) + ", "
+                                      + (s1 / t.length) + " and "
+                                      + (s2 / t.length) + ".");
+    }
+
+    /**
      * The result is printed to the standard output stream.
      *
      * @param  args ignored.
      * @throws ProjectionException if an error occurred in {@link #φ(double)}.
+     * @throws InterruptedException if the thread has been interrupted between two benchmarks.
      */
-    public static void main(String[] args) throws ProjectionException {
+    public static void main(String[] args) throws ProjectionException, InterruptedException {
         out.println("Comparison of the errors of series expension and iterative method for various excentricity values.");
         printErrorForExcentricities(0.08, 0.3);
 
@@ -282,24 +346,35 @@ public final class MercatorMethodCompari
         out.println("Comparison of the errors for a sphere.");
         out.println("The errors should be almost zero:");
         out.println();
-        AbstractLambertConformal projection = new NoOp(false);
-        MercatorMethodComparison alt = new MercatorMethodComparison(projection);
-        alt.compare(projection, 10000, null);
+        ConformalProjection projection = new NoOp(false);
+        MercatorMethodComparison c = new MercatorMethodComparison(projection);
+        c.compare(projection, 10000, null);
 
         out.println();
         out.println("Comparison of the errors for the WGS84 excentricity.");
-        out.println("The 'AbstractLambertConformal' errors should be the same than the series expansion errors:");
+        out.println("The 'ConformalProjection' errors should be the same than the series expansion errors:");
         out.println();
         projection = new NoOp(true);
-        alt = new MercatorMethodComparison(projection);
-        alt.compare(projection, 1000000, null);
+        c = new MercatorMethodComparison(projection);
+        c.compare(projection, 1000000, null);
 
         out.println();
         out.println("Comparison of the errors for the excentricity of an imaginary ellipsoid.");
-        out.println("The 'AbstractLambertConformal' errors should be the close to the iterative method errors:");
+        out.println("The 'ConformalProjection' errors should be the close to the iterative method errors:");
         out.println();
         projection = new NoOp(100, 95);
-        alt = new MercatorMethodComparison(projection);
-        alt.compare(projection, 1000000, null);
+        c = new MercatorMethodComparison(projection);
+        c.compare(projection, 1000000, null);
+
+        out.println();
+        out.println("Benchmarks");
+        c = new MercatorMethodComparison();
+        for (int i=0; i<4; i++) {
+            System.gc();
+            Thread.sleep(1000);
+            c.benchmark();
+            out.println();
+        }
+        out.flush();
     }
 }

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -33,7 +33,7 @@ import org.junit.Test;
 import static java.lang.Double.*;
 import static java.lang.StrictMath.*;
 import static org.opengis.test.Assert.*;
-import static org.apache.sis.referencing.operation.projection.NormalizedProjectionTest.LN_INFINITY;
+import static org.apache.sis.referencing.operation.projection.ConformalProjectionTest.LN_INFINITY;
 
 
 /**
@@ -46,14 +46,14 @@ import static org.apache.sis.referencing
  * @version 0.6
  * @module
  */
-@DependsOn(AbstractLambertConformalTest.class)
+@DependsOn(ConformalProjectionTest.class)
 public final strictfp class MercatorTest extends MapProjectionTestCase {
     /**
      * Creates a new instance of {@link Mercator} for a sphere or an ellipsoid.
      *
      * @param ellipse {@code false} for a sphere, or {@code true} for WGS84 ellipsoid.
      */
-    private void initialize(final boolean ellipse) {
+    private void createNormalizedProjection(final boolean ellipse) {
         final Mercator2SP method = new Mercator2SP();
         transform = new Mercator(method, parameters(method, ellipse));
         if (!ellipse) {
@@ -70,7 +70,7 @@ public final strictfp class MercatorTest
      */
     @Test
     public void testNormalizedWKT() {
-        initialize(true);
+        createNormalizedProjection(true);
         assertWktEquals(
                 "PARAM_MT[“Mercator_2SP”,\n" +
                 "  PARAMETER[“semi_major”, 1.0],\n" +
@@ -85,7 +85,7 @@ public final strictfp class MercatorTest
     @Test
     public void testSpecialLatitudes() throws ProjectionException {
         if (transform == null) {    // May have been initialized by 'testSphericalCase'.
-            initialize(true);       // Elliptical case
+            createNormalizedProjection(true);       // Elliptical case
         }
         assertEquals ("Not a number",     NaN,                    transform(NaN),           tolerance);
         assertEquals ("Out of range",     NaN,                    transform(+2),            tolerance);
@@ -116,11 +116,11 @@ public final strictfp class MercatorTest
     @DependsOnMethod("testSpecialLatitudes")
     public void testDerivative() throws TransformException {
         if (transform == null) {    // May have been initialized by 'testSphericalCase'.
-            initialize(true);       // Elliptical case
+            createNormalizedProjection(true);       // Elliptical case
         }
-        final double delta = toRadians(100.0 / 60) / 1852; // Approximatively 100 metres.
+        final double delta = toRadians(100.0 / 60) / 1852;    // Approximatively 100 metres.
         derivativeDeltas = new double[] {delta, delta};
-        tolerance = 1E-9;
+        tolerance = 1E-9;    // More severe than Formulas.LINEAR_TOLERANCE.
         verifyDerivative(toRadians(15), toRadians( 30));
         verifyDerivative(toRadians(10), toRadians(-60));
     }
@@ -216,25 +216,35 @@ public final strictfp class MercatorTest
     }
 
     /**
-     * Verifies the consistency of spherical formulas with the elliptical formulas.
+     * Performs the same tests than {@link #testSpecialLatitudes()} and {@link #testDerivative()},
+     * but using spherical formulas.
      *
      * @throws FactoryException if an error occurred while creating the map projection.
      * @throws TransformException if an error occurred while projecting a coordinate.
      */
     @Test
-    @DependsOnMethod("testSpecialLatitudes")
+    @DependsOnMethod({"testSpecialLatitudes", "testDerivative"})
     public void testSphericalCase() throws FactoryException, TransformException {
-        initialize(false); // Spherical case
+        createNormalizedProjection(false); // Spherical case
         testSpecialLatitudes();
         testDerivative();
-        /*
-         * Make sure that the above methods did not overwrote the 'transform' field.
-         */
+
+        // Make sure that the above methods did not overwrote the 'transform' field.
         assertEquals("transform.class", Mercator.Spherical.class, transform.getClass());
-        /*
-         * For some random points, compare the result of spherical formulas with the ellipsoidal ones.
-         */
-        initialize(new Mercator1SP(), false,
+    }
+
+    /**
+     * 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("testSphericalCase")
+    public void compareEllipticalWithSpherical() throws FactoryException, TransformException {
+        createCompleteProjection(new Mercator1SP(), false,
                   0.5,    // Central meridian
                   0,      // Latitude of origin (none)
                   0,      // Standard parallel (none)
@@ -242,6 +252,6 @@ public final strictfp class MercatorTest
                 200,      // False easting
                 100);     // False northing
         tolerance = Formulas.LINEAR_TOLERANCE;
-        verifyInDomain(CoordinateDomain.GEOGRAPHIC_SAFE, 84018710);
+        compareEllipticalWithSpherical(CoordinateDomain.GEOGRAPHIC_SAFE, 0);
     }
 }

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -39,7 +39,7 @@ import org.apache.sis.util.Workaround;
  * @module
  */
 @SuppressWarnings("serial")
-final strictfp class NoOp extends AbstractLambertConformal {
+final strictfp class NoOp extends ConformalProjection {
     /**
      * Creates a new "no-operation".
      *

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -16,16 +16,10 @@
  */
 package org.apache.sis.referencing.operation.projection;
 
-import org.opengis.referencing.operation.TransformException;
 import org.opengis.test.referencing.TransformTestCase;
-import org.apache.sis.referencing.operation.transform.AbstractMathTransform1D;
-import org.apache.sis.internal.util.DoubleDouble;
-import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
-import org.apache.sis.test.TestUtilities;
 import org.junit.Test;
 
-import static java.lang.Double.*;
 import static java.lang.StrictMath.*;
 import static org.apache.sis.internal.metadata.ReferencingServices.NAUTICAL_MILE;
 import static org.junit.Assert.*;
@@ -44,7 +38,7 @@ import static org.apache.sis.internal.jd
  */
 @DependsOn({
     // Following dependency is where the basic parameters (e.g. SEMI_MAJOR) are tested.
-    // Those parameters are needed by NoOp pseudo-projection, which is used in this class.
+    // Those parameters are needed by NoOp pseudo-projection, which is used in this package.
     org.apache.sis.internal.referencing.provider.MapProjectionTest.class
 })
 public final strictfp class NormalizedProjectionTest extends TransformTestCase {
@@ -54,34 +48,6 @@ public final strictfp class NormalizedPr
     static final double TOLERANCE = 1E-12;
 
     /**
-     * Natural logarithm of the pseudo-infinity as returned by Mercator formulas in the spherical
-     * case, truncated to nearest integer. This is not a real infinity because there is no exact
-     * representation of π/2 in base 2, so tan(π/2) is not positive infinity.
-     */
-    static final int LN_INFINITY = 37;
-
-    /**
-     * Computes {@link NormalizedProjection#expOfNorthing(double, double)} for the given latitude.
-     *
-     * @param  projection The projection on which to invoke {@code expOfNorthing(…)}.
-     * @param  φ The latitude in radians.
-     * @return {@code Math.exp} of the Mercator projection of the given latitude.
-     */
-    static double expOfNorthing(final NormalizedProjection projection, final double φ) {
-        return projection.expOfNorthing(φ, projection.excentricity * sin(φ));
-    }
-
-    /**
-     * Computes {@link NormalizedProjection#expOfNorthing(double, double)} for the given latitude.
-     *
-     * @param  φ The latitude in radians.
-     * @return {@code Math.exp} of the Mercator projection of the given latitude.
-     */
-    private double expOfNorthing(final double φ) {
-        return expOfNorthing((NormalizedProjection) transform, φ);
-    }
-
-    /**
      * Tests the value documented in the javadoc. Those value may be freely changed;
      * those tests exist only to increase the chances that the documented values are right.
      */
@@ -106,148 +72,4 @@ public final strictfp class NormalizedPr
         transform = projection = new NoOp(true);
         assertEquals("excentricity", 0.08181919084262157, projection.excentricity, TOLERANCE);
     }
-
-    /**
-     * Tests a few formulas used by the Mercator projection in the spherical case.
-     * This is a little bit more a Java test than an Apache SIS test (or to be more
-     * accurate, a test of our understanding of the {@code java.lang.Math} library).
-     *
-     * {@preformat text
-     *   Forward:  y = log(tan(π/4 + φ/2))
-     *   Inverse:  φ = π/2 - 2*atan(exp(-y))
-     * }
-     */
-    @Test
-    public void testMath() {
-        assertEquals("Forward 0°N",      0, log(tan(PI/4)),                   TOLERANCE);
-        assertEquals("Inverse 0 m",      0, PI/2 - 2*atan(exp(0)),            TOLERANCE);
-        assertEquals("Forward 90°S",     NEGATIVE_INFINITY, log(tan(0)),      TOLERANCE);
-        assertEquals("Forward (90+ε)°S", NaN,  log(tan(-nextUp(0))),          TOLERANCE);
-        assertEquals("Inverse -∞",       PI/2, atan(exp(-NEGATIVE_INFINITY)), TOLERANCE);
-        assertEquals("Inverse -∞ appr.", PI/2, atan(exp(LN_INFINITY + 1)),    TOLERANCE);
-        /*
-         * tan(PI/2) do not produces positive infinity as we would expect, because there is no
-         * exact representation of PI in base 2.  Experiments show that we get some high value
-         * instead (1.633E+16 on my machine, having a logarithm of 37.332).
-         */
-        assertTrue  ("Forward 90°N",     1E+16 < tan(PI/2));
-        assertTrue  ("Forward 90°N",     LN_INFINITY < log(tan(PI/2)));
-        assertEquals("Forward (90+ε)°N", NaN, log(tan(nextUp(PI/2))),      TOLERANCE);
-        assertEquals("Inverse +∞",       0, atan(exp(NEGATIVE_INFINITY)),  TOLERANCE);
-        assertEquals("Inverse +∞ appr.", 0, atan(exp(-(LN_INFINITY + 1))), TOLERANCE);
-        /*
-         * Some checks performed in our projection implementations assume that
-         * conversion of 90° to radians give exactly Math.PI/2.
-         */
-        final DoubleDouble dd = DoubleDouble.createDegreesToRadians();
-        dd.multiply(90);
-        assertEquals(PI/2, dd.value, 0.0);
-        assertEquals(PI/2, toRadians(90), 0.0);
-    }
-
-    /**
-     * Tests the {@link NormalizedProjection#expOfNorthing(double, double)} function.
-     *
-     * {@preformat text
-     *   Forward:  y = -log(t(φ))
-     *   Inverse:  φ = φ(exp(-y))
-     * }
-     */
-    @Test
-    public void testExpOfNorthing() {
-        transform = new NoOp(false);   // Spherical case
-        tolerance = TOLERANCE;
-        doTestExpOfNorthing();
-        transform = new NoOp(true);    // Ellipsoidal case
-        doTestExpOfNorthing();
-    }
-
-    /**
-     * Implementation of {@link #testExpOfNorthing()}.
-     * The {@link #projection} field must have been set before this method is called.
-     */
-    private void doTestExpOfNorthing() {
-        assertEquals("f(NaN) = NaN",       NaN, expOfNorthing(NaN),               tolerance);
-        assertEquals("f( ±∞) = NaN",       NaN, expOfNorthing(NEGATIVE_INFINITY), tolerance);
-        assertEquals("f( ±∞) = NaN",       NaN, expOfNorthing(POSITIVE_INFINITY), tolerance);
-        assertEquals("f(  0°) = 1",          1, expOfNorthing(0),                 tolerance);
-        assertEquals("f(-90°) = 0",          0, expOfNorthing(-PI/2),             tolerance);
-        assertTrue  ("f(< -90°) < 0",           expOfNorthing(-PI/2 - 0.1)        < 0);
-        assertTrue  ("f(< -90°) < 0",           expOfNorthing(nextDown(-PI/2))    < 0);
-        /*
-         * Values around π/2 are a special case. Theoretically the result should be positive infinity.
-         * But since we do not have an exact representatation of π/2, we instead get a high number.
-         * Furthermore the value does not become negative immediately after π/2; we have to skip an
-         * other IEEE 754 double value. This is because the real π/2 value is actually between PI/2
-         * and nextUp(PI/2):
-         *
-         *      PI/2          =   1.570796326794896558…
-         *      π/2           =   1.570796326794896619…
-         *      nextUp(PI/2)  =   1.570796326794896780…
-         */
-        assertTrue("f(+90°) → ∞",   expOfNorthing(+PI/2) > exp(LN_INFINITY));
-        assertTrue("f(> +90°) < 0", expOfNorthing(+PI/2 + 0.1) < 0);
-        assertTrue("f(> +90°) < 0", expOfNorthing(nextUp(nextUp(+PI/2))) < 0);
-        /*
-         * Test function periodicity. This is not a strong requirement for the expOfNorthing(…) function,
-         * but we nevertheless try to ensure that the method behaves correctly with unexpected values.
-         */
-        assertEquals("f(+360°)",  1, expOfNorthing(+2*PI),   tolerance);
-        assertEquals("f(+270°)",  0, expOfNorthing(+PI*3/2), tolerance);
-        assertEquals("f(+180°)", -1, expOfNorthing(+PI),     tolerance);
-        assertEquals("f(-180°)", -1, expOfNorthing(-PI),     tolerance);
-        assertTrue  ("f(-270°) → ∞", expOfNorthing(-PI*3/2)  < exp(-LN_INFINITY));
-        assertEquals("f(-360°)",  1, expOfNorthing(-2*PI),   tolerance);
-        assertEquals("f(-450°)",  0, expOfNorthing(-PI*5/2), tolerance);
-        /*
-         * Use in a way close to (but not identical)
-         * to the way the Mercator projection need it.
-         */
-        assertEquals("Mercator(0°)",   0,                 log(expOfNorthing(0)),     tolerance);
-        assertEquals("Mercator(90°S)", NEGATIVE_INFINITY, log(expOfNorthing(-PI/2)), tolerance);
-        assertTrue  ("Mercator(90°N)", LN_INFINITY <      log(expOfNorthing(+PI/2)));
-    }
-
-    /**
-     * Tests the {@link NormalizedProjection#dy_dφ(double, double)} method.
-     *
-     * @throws TransformException Should never happen.
-     */
-    @Test
-    @DependsOnMethod("testExpOfNorthing")
-    public void test_dy_dφ() throws TransformException {
-        tolerance = 1E-7;
-        doTest_dy_dφ(new NoOp(false));      // Spherical case
-        doTest_dy_dφ(new NoOp(true));       // Ellipsoidal case
-    }
-
-    /**
-     * Implementation of {@link #test_dy_dφ()}.
-     * The {@link #projection} field must have been set before this method is called.
-     */
-    private void doTest_dy_dφ(final NoOp projection) throws TransformException {
-        transform = new AbstractMathTransform1D() {
-            @Override public double transform(final double φ) {
-                return expOfNorthing(projection, φ);
-            }
-            @Override public double derivative(final double φ) {
-                final double sinφ = sin(φ);
-                return projection.dy_dφ(sinφ, cos(φ)) * expOfNorthing(projection, φ);
-            }
-        };
-        verifyInDomain(-89 * (PI/180), 89 * (PI/180));  // Verify from 85°S to 85°N.
-    }
-
-    /**
-     * Convenience method invoking {@link TransformTestCase#verifyInDomain} for an 1D transform.
-     */
-    private void verifyInDomain(final double min, final double max) throws TransformException {
-        derivativeDeltas = new double[] {2E-8};
-        isInverseTransformSupported = false;
-        verifyInDomain(
-                new double[] {min},     // Minimal value to test.
-                new double[] {max},     // Maximal value to test.
-                new int[]    {100},     // Number of points to test.
-                TestUtilities.createRandomNumberGenerator());
-    }
 }

Copied: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ProjectionResultComparator.java (from r1692163, sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ProjectionResultComparator.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ProjectionResultComparator.java?p2=sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ProjectionResultComparator.java&p1=sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ProjectionResultComparator.java&r1=1692163&r2=1692168&rev=1692168&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ProjectionResultComparator.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ProjectionResultComparator.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -112,7 +112,7 @@ final strictfp class ProjectionResultCom
                 final Object elliptical;
                 try {
                     elliptical = ellipticalClass.getDeclaredConstructor(ellipticalClass).newInstance(spherical);
-                } catch (ReflectiveOperationException e) {
+                } catch (Exception e) {  // ReflectiveOperationException on the JDK7 branch.
                     throw new AssertionError(e);    // Considered as a test failure.
                 }
                 /*

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomain.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomain.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomain.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomain.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -19,6 +19,7 @@ package org.apache.sis.referencing.opera
 import java.util.Random;
 import org.apache.sis.measure.Latitude;
 import org.apache.sis.measure.Longitude;
+
 import static java.lang.StrictMath.*;
 import static org.apache.sis.internal.metadata.ReferencingServices.AUTHALIC_RADIUS;
 
@@ -100,7 +101,7 @@ public strictfp class CoordinateDomain {
     public static final CoordinateDomain GEOGRAPHIC_POLES = new CoordinateDomain(
             Longitude.MIN_VALUE, Longitude.MAX_VALUE,
             Latitude .MIN_VALUE, Latitude .MAX_VALUE,
-                  -0*5 * HEIGHT,        0.5 * HEIGHT)
+                        -HEIGHT,              HEIGHT)
     {
         @Override
         public double[] generateRandomInput(final Random random, final int dimension, final int numPts) {
@@ -119,6 +120,24 @@ public strictfp class CoordinateDomain {
     };
 
     /**
+     * Geographic input coordinates close to the north pole.
+     * Ordinates are in (<var>longitude</var>, <var>latitude</var>, <var>height</var>) order.
+     */
+    public static final CoordinateDomain GEOGRAPHIC_NORTH_POLE = new CoordinateDomain(
+            Longitude.MIN_VALUE, Longitude.MAX_VALUE,
+                 ARTICLE_CIRCLE, Latitude .MAX_VALUE,
+                        -HEIGHT,              HEIGHT);
+
+    /**
+     * Geographic input coordinates close to the south pole.
+     * Ordinates are in (<var>longitude</var>, <var>latitude</var>, <var>height</var>) order.
+     */
+    public static final CoordinateDomain GEOGRAPHIC_SOUTH_POLE = new CoordinateDomain(
+            Longitude.MIN_VALUE, Longitude.MAX_VALUE,
+            Latitude .MIN_VALUE,     -ARTICLE_CIRCLE,
+                        -HEIGHT,              HEIGHT);
+
+    /**
      * Geographic input coordinates with angles in radians.
      * Ordinates are in (<var>lambda</var>, <var>phi</var>, <var>height</var>) order.
      */

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomainTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomainTest.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomainTest.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomainTest.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -107,15 +107,45 @@ public class CoordinateDomainTest extend
     public void testGeographicPole() {
         assertArrayEquals(new double[] {
             // ……λ   …………φ   ………………H
-            -136.6,  -74.3,   2467.5,
-             -17.9,   74.7,   2338.4,
-              98.2,   66.9,   2078.0,
-             151.9,   73.8,   2799.3,
-             -90.5,  -86.4,    585.3
+            -136.6,  -74.3,   -130.1,
+             -17.9,   74.7,   -646.5,
+              98.2,   66.9,  -1687.9,
+             151.9,   73.8,   1197.0,
+             -90.5,  -86.4,  -7658.8
         }, CoordinateDomain.GEOGRAPHIC_POLES.generateRandomInput(new Random(6784869539382621964L), 3, 5), TOLERANCE);
     }
 
     /**
+     * Tests {@link CoordinateDomain#GEOGRAPHIC_NORTH_POLE}.
+     */
+    @Test
+    public void testGeographicNorthPole() {
+        assertArrayEquals(new double[] {
+            // ……λ   …………φ   ………………H
+             -41.7,   72.6,   9605.3,
+            -107.7,   68.2,    388.5,
+              32.9,   69.3,   2553.6,
+             106.5,   81.0,  -7334.3,
+             135.2,   87.6,  -3518.9
+        }, CoordinateDomain.GEOGRAPHIC_NORTH_POLE.generateRandomInput(new Random(2141713460614422218L), 3, 5), TOLERANCE);
+    }
+
+    /**
+     * Tests {@link CoordinateDomain#GEOGRAPHIC_SOUTH_POLE}.
+     */
+    @Test
+    public void testGeographicSouthPole() {
+        assertArrayEquals(new double[] {
+            // ……λ   …………φ   ………………H
+            -106.2,  -71.9, -2202.6,
+            -172.6,  -89.5,  2428.1,
+              33.2,  -84.3,  6068.1,
+             -64.3,  -76.3, -3436.7,
+             -97.6,  -72.5,  8702.2
+        }, CoordinateDomain.GEOGRAPHIC_SOUTH_POLE.generateRandomInput(new Random(5769644852151897296L), 3, 5), TOLERANCE);
+    }
+
+    /**
      * Tests {@link CoordinateDomain#GEOGRAPHIC_RADIANS}.
      */
     @Test

Modified: sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -101,9 +101,11 @@ import org.junit.BeforeClass;
     // Test map projections. Those tests need the providers tested above.
     org.apache.sis.referencing.operation.projection.NormalizedProjectionTest.class,
     org.apache.sis.referencing.operation.projection.EquirectangularTest.class,
-    org.apache.sis.referencing.operation.projection.AbstractLambertConformalTest.class,
+    org.apache.sis.referencing.operation.projection.ConformalProjectionTest.class,
     org.apache.sis.referencing.operation.projection.MercatorTest.class,
     org.apache.sis.referencing.operation.projection.LambertConformalTest.class,
+    org.apache.sis.referencing.operation.projection.TransverseMercatorTest.class,
+    org.apache.sis.referencing.operation.projection.PolarStereographicTest.class,
 
     // Coordinate Reference System components.
     org.apache.sis.referencing.datum.BursaWolfParametersTest.class,

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/converter/StringConverter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/converter/StringConverter.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/converter/StringConverter.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/converter/StringConverter.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -83,6 +83,7 @@ abstract class StringConverter<T> extend
      * @param targetClass The {@linkplain #getTargetClass() target class}.
      * @param inverse The inverse converter from the target to the source class.
      */
+    @SuppressWarnings("OverridableMethodCallDuringObjectConstruction")
     StringConverter(final Class<T> targetClass) {
         super(String.class, targetClass);
         inverse = createInverse();

Modified: sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/converter/SystemConverter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/converter/SystemConverter.java?rev=1692168&r1=1692167&r2=1692168&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/converter/SystemConverter.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-utility/src/main/java/org/apache/sis/internal/converter/SystemConverter.java [UTF-8] Tue Jul 21 16:41:12 2015
@@ -57,6 +57,8 @@ abstract class SystemConverter<S,T> exte
 
     /**
      * Returns the source class given at construction time.
+     *
+     * @return The type of objects to convert.
      */
     @Override
     public final Class<S> getSourceClass() {
@@ -65,6 +67,8 @@ abstract class SystemConverter<S,T> exte
 
     /**
      * Returns the target class given at construction time.
+     *
+     * @return The type of converted objects.
      */
     @Override
     public final Class<T> getTargetClass() {
@@ -82,6 +86,8 @@ abstract class SystemConverter<S,T> exte
 
     /**
      * Default to non-invertible conversion. Must be overridden by subclasses that support inversions.
+     *
+     * @return A converter for converting instances of <var>T</var> back to instances of <var>S</var>.
      */
     @Override
     public ObjectConverter<T,S> inverse() throws UnsupportedOperationException {



Mime
View raw message