sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1673961 [1/2] - in /sis/branches/JDK8/core: sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ sis-referencing/src/test/java/org/apache...
Date Wed, 15 Apr 2015 21:35:22 GMT
Author: desruisseaux
Date: Wed Apr 15 21:35:21 2015
New Revision: 1673961

URL: http://svn.apache.org/r1673961
Log:
Referencing: initial port of Lambert Conformal map projection formulas.
As a side effect of this port, tuned again parameters handling.

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConformal.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java   (with props)
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractLambert.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.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/internal/referencing/provider/LambertConformal1SP.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal2SP.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformalBelgium.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MercatorSpherical.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MillerCylindrical.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PseudoMercator.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/RegionalMercator.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/EquirectangularTest.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/test/suite/ReferencingTestSuite.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractLambert.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractLambert.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractLambert.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractLambert.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -20,6 +20,7 @@ import org.opengis.parameter.ParameterDe
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.referencing.operation.ConicProjection;
 import org.apache.sis.parameter.Parameters;
+import org.apache.sis.referencing.operation.projection.LambertConformal;
 import org.apache.sis.referencing.operation.projection.NormalizedProjection;
 
 
@@ -73,6 +74,6 @@ class AbstractLambert extends MapProject
      */
     @Override
     protected final NormalizedProjection createProjection(final Parameters parameters) {
-        return null; // TODO
+        return new LambertConformal(this, parameters);
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -121,6 +121,18 @@ abstract class AbstractProvider extends
     }
 
     /**
+     * Creates a descriptor for a latitude parameter in degrees without default value.
+     * This method is used for latitude of origin that can not be zero, of for standard parallels
+     * where the default value should be the value of another parameter instead than 0°.
+     */
+    static ParameterDescriptor<Double> createMandatoryLatitude(final ParameterBuilder builder) {
+        return builder.createBounded(MeasurementRange.create(
+                Latitude.MIN_VALUE, true,
+                Latitude.MAX_VALUE, true,
+                NonSI.DEGREE_ANGLE), null);
+    }
+
+    /**
      * Creates a descriptor for a latitude parameter in degrees with a default value of 0°.
      */
     static ParameterDescriptor<Double> createLatitude(final ParameterBuilder builder, final boolean includePoles) {

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=1673961&r1=1673960&r2=1673961&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] Wed Apr 15 21:35:21 2015
@@ -37,12 +37,18 @@ import static java.lang.Math.*;
 
 
 /**
- * The provider for "<cite>Equidistant Cylindrical (Spherical)</cite>" projection
+ * The provider for <cite>"Equidistant Cylindrical (Spherical)"</cite> projection
  * (EPSG:1029, <span class="deprecated">EPSG:9823</span>).
+ * In the particular case where the longitude of origin and the standard parallel are 0°,
+ * this projection is also known as <cite>"Plate Carrée"</cite>.
  *
- * At the difference of most other map projection providers, this class does not extend {@link MapProjection}
+ * <p>At the difference of most other map projection providers, this class does not extend {@link MapProjection}
  * because it does not create non-liner kernel. Instead, the projection created by this class is implemented
- * by an affine transform.
+ * by an affine transform.</p>
+ *
+ * <p>We do not provide <cite>"Pseudo Plate Carrée"</cite> projection (EPSG:9825) at this time because that
+ * pseudo-projection is only the identity transform. Even the semi-major and semi-minor axis lengths are set
+ * to 1.</p>
  *
  * <p>This provider is <strong>not</strong> suitable for the <cite>Equidistant Cylindrical</cite> projection
  * (EPSG:1028, <span class="deprecated">EPSG:9842</span>). EPSG defines Equidistant Cylindrical projection as
@@ -174,6 +180,7 @@ public final class Equirectangular exten
             .addName(                   "Equidistant Cylindrical (Spherical)")
             .addName(                   "Plate Carrée")  // Not formally defined by EPSG, but cited in documentation.
             .addName(Citations.OGC,     "Equirectangular")
+            .addName(Citations.ESRI,    "Plate_Carree")
             .addName(Citations.GEOTIFF, "CT_Equirectangular")
             .addName(Citations.PROJ4,   "eqc")
             .addIdentifier(Citations.GEOTIFF, "17")
@@ -203,6 +210,26 @@ public final class Equirectangular exten
     }
 
     /**
+     * Gets a parameter value identified by the given descriptor and stores it only if different than zero.
+     *
+     * @param  source     The parameters from which to read the value.
+     * @param  target     Where to store the parameter values.
+     * @param  descriptor The descriptor that specify the parameter names and desired units.
+     * @return The parameter value in the units given by the descriptor.
+     * @throws IllegalArgumentException if the given value is out of bounds.
+     */
+    private static double getAndStore(final Parameters source, final ParameterValueGroup target,
+            final ParameterDescriptor<Double> descriptor) throws IllegalArgumentException
+    {
+        final double value = source.doubleValue(descriptor);    // Apply a unit conversion if needed.
+        MapProjection.validate(descriptor, value);              // Unconditional validation for semi-axes.
+        if (value != 0) {                                       // All default values in this class are zero.
+            target.parameter(descriptor.getName().getCode()).setValue(value);
+        }
+        return value;
+    }
+
+    /**
      * Creates an Equirectangular projection from the specified group of parameter values. This method is an
      * adaptation of {@link org.apache.sis.referencing.operation.projection.NormalizedProjection} constructor,
      * reproduced in this method because we will create an affine transform instead than the usual projection
@@ -219,13 +246,13 @@ public final class Equirectangular exten
     {
         final Parameters p = Parameters.castOrWrap(parameters);
         final ContextualParameters context = new ContextualParameters(this);
-        double a  = MapProjection.getAndStore(p, context, MapProjection.SEMI_MAJOR);
-        double b  = MapProjection.getAndStore(p, context, MapProjection.SEMI_MINOR);
-        double λ0 = MapProjection.getAndStore(p, context, CENTRAL_MERIDIAN);
-        double φ0 = MapProjection.getAndStore(p, context, LATITUDE_OF_ORIGIN);
-        double φ1 = MapProjection.getAndStore(p, context, STANDARD_PARALLEL);
-        double fe = MapProjection.getAndStore(p, context, FALSE_EASTING);
-        double fn = MapProjection.getAndStore(p, context, FALSE_NORTHING);
+        double a  = getAndStore(p, context, MapProjection.SEMI_MAJOR);
+        double b  = getAndStore(p, context, MapProjection.SEMI_MINOR);
+        double λ0 = getAndStore(p, context, CENTRAL_MERIDIAN);
+        double φ0 = getAndStore(p, context, LATITUDE_OF_ORIGIN);
+        double φ1 = getAndStore(p, context, STANDARD_PARALLEL);
+        double fe = getAndStore(p, context, FALSE_EASTING);
+        double fn = getAndStore(p, context, FALSE_NORTHING);
         /*
          * Perform following transformation, in that order. Note that following
          * AffineTransform convention, the Java code appears in reverse order:

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal1SP.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal1SP.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal1SP.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal1SP.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -40,10 +40,15 @@ public final class LambertConformal1SP e
     private static final long serialVersionUID = -4243116402872545772L;
 
     /**
+     * The EPSG identifier, to be preferred to the name when available.
+     */
+    public static final String IDENTIFIER = "9801";
+
+    /**
      * The operation parameter descriptor for the <cite>Latitude of natural origin</cite> (φ₀) parameter value.
      * Valid values range is [-90 … 90]° and default value is 0°.
      */
-    public static final ParameterDescriptor<Double> LATITUDE_OF_ORIGIN = Mercator1SP.LATITUDE_OF_ORIGIN;
+    public static final ParameterDescriptor<Double> LATITUDE_OF_ORIGIN;
 
     /**
      * The operation parameter descriptor for the <cite>Longitude of natural origin</cite> (λ₀) parameter value.
@@ -63,8 +68,12 @@ public final class LambertConformal1SP e
     static final ParameterDescriptorGroup PARAMETERS;
     static {
         final ParameterBuilder builder = builder();
+
+        LATITUDE_OF_ORIGIN = createMandatoryLatitude(builder
+                .addNamesAndIdentifiers(Mercator1SP.LATITUDE_OF_ORIGIN));
+
         PARAMETERS = builder
-            .addIdentifier(              "9801")
+            .addIdentifier(IDENTIFIER)
             .addName(                    "Lambert Conic Conformal (1SP)")
             .addName(Citations.OGC,      "Lambert_Conformal_Conic_1SP")
             .addName(Citations.GEOTIFF,  "CT_LambertConfConic_1SP")

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal2SP.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal2SP.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal2SP.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformal2SP.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -41,6 +41,11 @@ public final class LambertConformal2SP e
     private static final long serialVersionUID = 3240860802816724947L;
 
     /**
+     * The EPSG identifier, to be preferred to the name when available.
+     */
+    public static final String IDENTIFIER = "9802";
+
+    /**
      * The operation parameter descriptor for the <cite>Latitude of false origin</cite> (φf) parameter value.
      * Valid values range is [-90 … 90]° and default value is 0°.
      */
@@ -92,7 +97,7 @@ public final class LambertConformal2SP e
     /**
      * The group of all parameters expected by this coordinate operation.
      */
-    public static final ParameterDescriptorGroup PARAMETERS;
+    static final ParameterDescriptorGroup PARAMETERS;
     static {
         final ParameterBuilder builder = builder();
         /*
@@ -122,23 +127,27 @@ public final class LambertConformal2SP e
          * ESRI:    Standard_Parallel_1
          * NetCDF:  standard_parallel
          * GeoTIFF: StdParallel1
+         *
+         * Special case: default value shall be the value of LATITUDE_OF_FALSE_ORIGIN.
          */
-        STANDARD_PARALLEL_1 = createLatitude(builder
-                .addNamesAndIdentifiers(Mercator2SP.STANDARD_PARALLEL), true);  // TODO: default value should be NaN
+        STANDARD_PARALLEL_1 = createMandatoryLatitude(builder
+                .addNamesAndIdentifiers(Mercator2SP.STANDARD_PARALLEL));
         /*
          * EPSG:    Latitude of 2nd standard parallel
          * OGC:     standard_parallel_2
          * ESRI:    Standard_Parallel_2
          * NetCDF:  standard_parallel
          * GeoTIFF: StdParallel2
+         *
+         * Special case: default value shall be the value of STANDARD_PARALLEL_1.
          */
-        STANDARD_PARALLEL_2 = createLatitude(builder
+        STANDARD_PARALLEL_2 = createMandatoryLatitude(builder
                 .addIdentifier("8824")
                 .addName("Latitude of 2nd standard parallel")
                 .addName(Citations.OGC,     Constants.STANDARD_PARALLEL_2)
                 .addName(Citations.ESRI,    "Standard_Parallel_2")
                 .addName(Citations.GEOTIFF, "StdParallel2")
-                .addName(Citations.PROJ4,   "lat_2"), true);  // TODO: default value should be NaN
+                .addName(Citations.PROJ4,   "lat_2"));
         /*
          * Remove the EPSG name and identifier at least for the scale factor, because its meaning does not fit well
          * in this context. The EPSG name is "Scale factor at natural origin" while actually the scale factor applied
@@ -149,7 +158,7 @@ public final class LambertConformal2SP e
                 .setRemarks(notFormalParameter("Lambert Conic Conformal (1SP)")).setDeprecated(true));
 
         PARAMETERS = builder
-            .addIdentifier(              "9802")
+            .addIdentifier(IDENTIFIER)
             .addName(                    "Lambert Conic Conformal (2SP)")
             .addName(Citations.OGC,      "Lambert_Conformal_Conic_2SP")
             .addName(Citations.ESRI,     "Lambert_Conformal_Conic")

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformalBelgium.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformalBelgium.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformalBelgium.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LambertConformalBelgium.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -39,14 +39,19 @@ public final class LambertConformalBelgi
     private static final long serialVersionUID = -6388030784088639876L;
 
     /**
+     * The EPSG identifier, to be preferred to the name when available.
+     */
+    public static final String IDENTIFIER = "9803";
+
+    /**
      * The group of all parameters expected by this coordinate operation.
      */
-    public static final ParameterDescriptorGroup PARAMETERS;
+    static final ParameterDescriptorGroup PARAMETERS;
     static {
         final ParameterBuilder builder = builder();
 
         PARAMETERS = builder
-            .addIdentifier(              "9803")
+            .addIdentifier(IDENTIFIER)
             .addName(                    "Lambert Conic Conformal (2SP Belgium)")
             .addName(Citations.OGC,      "Lambert_Conformal_Conic_2SP_Belgium")
             .addName(Citations.ESRI,     "Lambert_Conformal_Conic_2SP_Belgium")

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MapProjection.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -127,28 +127,15 @@ public abstract class MapProjection exte
     }
 
     /**
-     * Gets a parameter value identified by the given descriptor and stores it in the {@code context}.
-     * This method performs the following actions:
+     * Validates the given parameter value.
      *
-     * <ul>
-     *   <li>Convert the value to the units specified by the descriptor.</li>
-     *   <li>Ensure that the value is contained in the range specified by the descriptor.</li>
-     *   <li>Store the value only if different than the default value.</li>
-     * </ul>
-     *
-     * This method should be invoked at {@link #createMathTransform(MathTransformFactory, ParameterValueGroup)}
-     * execution time only.
-     *
-     * @param  source     The parameters from which to read the value.
-     * @param  target     Where to store the parameter values.
-     * @param  descriptor The descriptor that specify the parameter names and desired units.
-     * @return The parameter value in the units given by the descriptor.
+     * @param  descriptor The descriptor that specify the parameter to validate.
+     * @param  value The parameter value in the units given by the descriptor.
      * @throws IllegalArgumentException if the given value is out of bounds.
      */
-    public static double getAndStore(final Parameters source, final ParameterValueGroup target,
-            final ParameterDescriptor<Double> descriptor) throws IllegalArgumentException
+    public static void validate(final ParameterDescriptor<Double> descriptor, final double value)
+            throws IllegalArgumentException
     {
-        final double value = source.doubleValue(descriptor);    // Apply a unit conversion if needed.
         if (Double.isNaN(value) || Double.isInfinite(value)) {
             throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalParameterValue_2,
                     descriptor.getName(), value));
@@ -170,11 +157,6 @@ public abstract class MapProjection exte
                         descriptor.getName(), min, max, value));
             }
         }
-        final Double defaultValue = descriptor.getDefaultValue();
-        if (defaultValue == null || !defaultValue.equals(value)) {
-            target.parameter(descriptor.getName().getCode()).setValue(value);
-        }
-        return value;
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MercatorSpherical.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MercatorSpherical.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MercatorSpherical.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MercatorSpherical.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -38,11 +38,6 @@ public final class MercatorSpherical ext
     private static final long serialVersionUID = 4761755206841656129L;
 
     /**
-     * The name of this projection method.
-     */
-    public static final String NAME = "Mercator (Spherical)";
-
-    /**
      * The EPSG identifier, to be preferred to the name when available.
      */
     public static final String IDENTIFIER = "1026";
@@ -56,8 +51,8 @@ public final class MercatorSpherical ext
         PARAMETERS = builder
             .addIdentifier(IDENTIFIER)
             .addDeprecatedIdentifier("9841", IDENTIFIER)
-            .addName(NAME)                                          // Starting from EPSG version 7.6
-            .addDeprecatedName("Mercator (1SP) (Spherical)", NAME)  // Prior to EPSG version 7.6
+            .addName("Mercator (Spherical)")                                          // Starting from EPSG version 7.6
+            .addDeprecatedName("Mercator (1SP) (Spherical)", "Mercator (Spherical)")  // Prior to EPSG version 7.6
             .createGroupForMapProjection(
                     Mercator1SP.LATITUDE_OF_ORIGIN,
                     Mercator1SP.CENTRAL_MERIDIAN,

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MillerCylindrical.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MillerCylindrical.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MillerCylindrical.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MillerCylindrical.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -58,18 +58,13 @@ public final class MillerCylindrical ext
     private static final long serialVersionUID = -7682370461334391883L;
 
     /**
-     * The name of this operation method.
-     */
-    public static final String NAME = "Miller_Cylindrical";
-
-    /**
      * The group of all parameters expected by this coordinate operation.
      */
     private static final ParameterDescriptorGroup PARAMETERS;
     static {
         final ParameterBuilder builder = builder().setCodeSpace(Citations.OGC, Constants.OGC);
         PARAMETERS = builder
-            .addName      (NAME)
+            .addName      ("Miller_Cylindrical")
             .addName      (Citations.GEOTIFF,  "CT_MillerCylindrical")
             .addIdentifier(Citations.GEOTIFF,  "20")
             .addName      (Citations.PROJ4,    "mill")

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PseudoMercator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PseudoMercator.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PseudoMercator.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PseudoMercator.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -37,11 +37,6 @@ public final class PseudoMercator extend
     private static final long serialVersionUID = -8126827491349984471L;
 
     /**
-     * The name of this operation method.
-     */
-    public static final String NAME = "Popular Visualisation Pseudo Mercator";
-
-    /**
      * The EPSG identifier, to be preferred to the name when available.
      */
     public static final String IDENTIFIER = "1024";
@@ -54,7 +49,7 @@ public final class PseudoMercator extend
         final ParameterBuilder builder = builder();
         PARAMETERS = builder
             .addIdentifier(IDENTIFIER)
-            .addName(NAME)
+            .addName("Popular Visualisation Pseudo Mercator")
             .createGroupForMapProjection(toArray(MercatorSpherical.PARAMETERS.descriptors()));
     }
 

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/RegionalMercator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/RegionalMercator.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/RegionalMercator.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/RegionalMercator.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -43,11 +43,6 @@ public class RegionalMercator extends Ab
     private static final long serialVersionUID = 5957081563587752477L;
 
     /**
-     * The name of this projection method.
-     */
-    public static final String NAME = "Mercator (variant C)";
-
-    /**
      * The EPSG identifier, to be preferred to the name when available.
      */
     public static final String IDENTIFIER = "1044";
@@ -94,7 +89,7 @@ public class RegionalMercator extends Ab
 
         PARAMETERS = builder
             .addIdentifier(IDENTIFIER)
-            .addName(NAME)
+            .addName("Mercator (variant C)")
             .createGroupForMapProjection(
                     Mercator2SP.STANDARD_PARALLEL,
                     Mercator1SP.CENTRAL_MERIDIAN,

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConformal.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConformal.java?rev=1673961&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConformal.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConformal.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -0,0 +1,466 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.referencing.operation.projection;
+
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.referencing.operation.Matrix;
+import org.apache.sis.measure.Latitude;
+import org.apache.sis.parameter.Parameters;
+import org.apache.sis.referencing.operation.matrix.Matrix2;
+import org.apache.sis.referencing.operation.matrix.MatrixSIS;
+import org.apache.sis.internal.referencing.provider.LambertConformal1SP;
+import org.apache.sis.internal.referencing.provider.LambertConformal2SP;
+import org.apache.sis.internal.referencing.provider.LambertConformalBelgium;
+import org.apache.sis.internal.referencing.Formulas;
+import org.apache.sis.internal.util.DoubleDouble;
+import org.apache.sis.internal.util.Constants;
+import org.apache.sis.internal.util.Numerics;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.util.Workaround;
+import org.apache.sis.util.Debug;
+
+import static java.lang.Math.*;
+import static java.lang.Double.*;
+
+
+/**
+ * <cite>Lambert Conical Conformal</cite> projection (EPSG codes 9801, 9802, 9803).
+ * See the <a href="http://mathworld.wolfram.com/LambertConformalConicProjection.html">Lambert conformal
+ * conic projection on MathWorld</a> for an overview.
+ *
+ * <div class="section">Description</div>
+ * Areas and shapes are deformed as one moves away from standard parallels.
+ * The angles are true in a limited area.
+ * This projection is used for the charts of North America and some European countries.
+ *
+ * @author  Martin Desruisseaux (MPO, IRD, Geomatys)
+ * @author  André Gosselin (MPO)
+ * @author  Rueben Schulz (UBC)
+ * @author  Rémi Maréchal (Geomatys)
+ * @since   0.6
+ * @version 0.6
+ * @module
+ */
+public class LambertConformal extends NormalizedProjection {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 2067358524298002016L;
+
+    /**
+     * Codes for special kinds of Lambert 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.
+     *
+     * @see #getType(ParameterDescriptorGroup)
+     */
+    static final byte SP1 = 1, SP2 = 2, BELGIUM = 3;
+
+    /**
+     * Constant for the Belgium 2SP case. This is 29.2985 seconds, given here in radians.
+     */
+    private static final double BELGE_A = 0.00014204313635987700;
+
+    /**
+     * Internal coefficients for computation, depending only on values of standards parallels.
+     */
+    final double n;
+
+    /**
+     * Creates a Lambert projection from the given parameters.
+     * The {@code method} argument can be the description of one of the following:
+     *
+     * <ul>
+     *   <li><cite>"Lambert Conic Conformal (1SP)"</cite>.</li>
+     *   <li><cite>"Lambert Conic Conformal (2SP)"</cite>.</li>
+     *   <li><cite>"Lambert Conic Conformal (2SP Belgium)"</cite>.</li>
+     * </ul>
+     *
+     * @param method     Description of the projection parameters.
+     * @param parameters The parameter values of the projection to create.
+     */
+    public LambertConformal(final OperationMethod method, final Parameters parameters) {
+        this(method, parameters, getType(parameters.getDescriptor()));
+    }
+
+    /**
+     * Work around for RFE #4093999 in Sun's bug database
+     * ("Relax constraint on placement of this()/super() call in constructors").
+     */
+    @Workaround(library="JDK", version="1.7")
+    private LambertConformal(final OperationMethod method, final Parameters parameters, final byte type) {
+        super(method, parameters, null,
+                (type == SP1) ? LambertConformal1SP.FALSE_EASTING  : LambertConformal2SP.EASTING_AT_FALSE_ORIGIN,
+                (type == SP1) ? LambertConformal1SP.FALSE_NORTHING : LambertConformal2SP.NORTHING_AT_FALSE_ORIGIN);
+        double φ0 = getAndStore(parameters,
+                (type == SP1) ? LambertConformal1SP.LATITUDE_OF_ORIGIN : LambertConformal2SP.LATITUDE_OF_FALSE_ORIGIN);
+        /*
+         * Standard parallels (SP) are defined only for the 2SP case, but we look for them unconditionally
+         * in case the user gave us non-standard parameters. For the 1SP case, or for the 2SP case left to
+         * their default values, EPSG says that we shall use the latitude of origin as the SP.
+         */
+        double φ1 = getAndStore(parameters, LambertConformal2SP.STANDARD_PARALLEL_1, φ0);
+        double φ2 = getAndStore(parameters, LambertConformal2SP.STANDARD_PARALLEL_2, φ1);
+        if (abs(φ1 + φ2) < Formulas.ANGULAR_TOLERANCE) {
+            throw new IllegalArgumentException(Errors.format(Errors.Keys.LatitudesAreOpposite_2,
+                    new Latitude(φ1), new Latitude(φ2)));
+        }
+        φ0 = toRadians(φ0);
+        φ1 = toRadians(φ1);
+        φ2 = toRadians(φ2);
+        /*
+         * Computes constants.
+         */
+        final double  ρ0, F;
+        final double  cosφ1  = cos(φ1);
+        final double  sinφ1  = sin(φ1);
+        final boolean secant = abs(φ1 - φ2) > ANGULAR_TOLERANCE;    // Should be 'true' for 2SP case.
+        if (excentricity == 0) {
+            if (secant) {
+                n = log(cosφ1 / cos(φ2)) /
+                    log(tan(PI/4 + 0.5*φ2) / tan(PI/4 + 0.5*φ1));
+            } else {
+                n = sinφ1;
+            }
+            F = cosφ1 * pow(tan(PI/4 + 0.5*φ1), n) / n;
+            if (abs(abs(φ0) - PI/2) >= ANGULAR_TOLERANCE) {
+                ρ0 = F * pow(tan(PI/4 + 0.5*φ0), -n);
+            } else {
+                ρ0 = 0.0;
+            }
+        } else {
+            final double m1 = cosφ1 / rν(sinφ1);
+            final double t1 = expOfNorthing(-φ1, -excentricity * sinφ1);
+            if (secant) {
+                final double sinφ2 = sin(φ2);
+                final double m2 = cos(φ2) / rν(sinφ2);
+                final double t2 = expOfNorthing(-φ2, -excentricity * sinφ2);
+                n = log(m1/m2) / log(t1/t2);
+            } else {
+                n = sinφ1;
+            }
+            F = m1 * pow(t1, -n) / n;
+            if (abs(abs(φ0) - PI/2) >= ANGULAR_TOLERANCE) {
+                ρ0 = F * pow(expOfNorthing(-φ0, -excentricity * sin(φ0)), n);
+            } else {
+                ρ0 = 0.0;
+            }
+        }
+        /*
+         * At this point, all parameters have been processed. Now store
+         * the linear operations in the (de)normalize affine transforms:
+         *
+         * Normalization:
+         *   - Subtract central meridian to longitudes.
+         *   - Convert longitudes and latitudes from degrees to radians
+         *   - Multiply longitude by 'n'.
+         *   - In the Belgium case only, subtract BELGE_A to the scaled longitude.
+         *
+         * Denormalization
+         *   - Revert the sign of y.
+         *   - Scale x and y by F.
+         *   - Translate y by ρ0.
+         *   - Multiply by the scale factor.
+         *   - Add false easting and fasle northing (done by the super-class constructor).
+         */
+        context.getMatrix(true).concatenate(0, new DoubleDouble(n),       // Multiplication factor for longitudes.
+                (type == BELGIUM) ? new DoubleDouble(-BELGE_A) : null);   // Longitude translation for Belgium.
+        context.normalizeGeographicInputs(getAndStore(parameters,
+                (type == SP1) ? LambertConformal1SP.CENTRAL_MERIDIAN : LambertConformal2SP.LONGITUDE_OF_FALSE_ORIGIN));
+
+        final MatrixSIS denormalize = context.scaleAndTranslate2D(false,
+                getAndStore(parameters, LambertConformal1SP.SCALE_FACTOR), 0, 0);
+
+        denormalize.concatenate(0, new DoubleDouble(F), null);
+        denormalize.concatenate(1, new DoubleDouble(-F), new DoubleDouble(ρ0));
+    }
+
+    /**
+     * Creates a new projection initialized to the same parameters than the given one.
+     */
+    LambertConformal(final LambertConformal other) {
+        super(other);
+        n = other.n;
+    }
+
+    /**
+     * Returns the type of the projection based on the name and identifier of the given parameter group.
+     * If this method can not identify the type, then the parameters should be considered as a 2SP case.
+     */
+    private static byte getType(final ParameterDescriptorGroup parameters) {
+        if (identMatch(parameters, "(?i).*\\bBelgium\\b.*", LambertConformalBelgium.IDENTIFIER)) return BELGIUM;
+        if (identMatch(parameters, "(?i).*\\b2SP\\b.*",     LambertConformal2SP    .IDENTIFIER)) return SP2;
+        if (identMatch(parameters, "(?i).*\\b1SP\\b.*",     LambertConformal1SP    .IDENTIFIER)) return SP1;
+        return 0; // Unidentified case, to be considered as 2SP.
+    }
+
+    /**
+     * Returns a copy of the parameter values for this projection.
+     * This method supplies a value only for the following parameters:
+     *
+     * <ul>
+     *   <li>Semi-major axis length of 1</li>
+     *   <li>Semi-minor axis length of <code>sqrt(1 - {@linkplain #excentricitySquared ℯ²})</code></li>
+     *   <li>Only one of the following:
+     *     <ul>
+     *       <li>Natural origin (1SP case)</li>
+     *     </ul>
+     *     or, in the 2SP case:
+     *     <ul>
+     *       <li>Standard parallel 1</li>
+     *       <li>Standard parallel 2</li>
+     *     </ul>
+     *   </li>
+     * </ul>
+     *
+     * No other parameters are set because only the above-cited ones are significant for the non-linear part
+     * of this projection.
+     *
+     * <div class="note"><b>Note:</b>
+     * This method is mostly for {@linkplain org.apache.sis.io.wkt.Convention#INTERNAL debugging purposes}
+     * since the isolation of non-linear parameters in this class is highly implementation dependent.
+     * Most GIS applications will instead be interested in the {@linkplain #getContextualParameters()
+     * contextual parameters}.</div>
+     *
+     * @return A copy of the parameter values for this normalized projection.
+     */
+    @Debug
+    @Override
+    public ParameterValueGroup getParameterValues() {
+        return getParameterValues(new String[] {
+            Constants.SEMI_MAJOR,
+            Constants.SEMI_MINOR,
+            Constants.STANDARD_PARALLEL_1,
+            Constants.STANDARD_PARALLEL_2,
+            "latitude_of_origin"
+        });
+    }
+
+    /**
+     * Converts the specified (λ,φ) coordinate (units in radians) and stores the result in {@code dstPts}
+     * (linear distance on a unit sphere). In addition, opportunistically computes the projection derivative
+     * if {@code derivate} is {@code true}.
+     *
+     * @return The matrix of the projection derivative at the given source position,
+     *         or {@code null} if the {@code derivate} argument is {@code false}.
+     * @throws ProjectionException if the coordinate can not be converted.
+     */
+    @Override
+    public Matrix transform(final double[] srcPts, final int srcOff,
+                            final double[] dstPts, final int dstOff,
+                            final boolean derivate) throws ProjectionException
+    {
+        /*
+         * NOTE: If some equation terms seem missing, this is because the linear operations applied before
+         * the first non-linear one moved to the "normalize" affine transform, and the linear operations
+         * applied after the last non-linear one moved to the "denormalize" affine transform.
+         */
+        final double λ    = srcPts[srcOff];
+        final double φ    = srcPts[srcOff + 1];
+        final double absφ = abs(φ);
+        final double sinλ = sin(λ);
+        final double cosλ = cos(λ);
+        final double sinφ;
+        final double ρ;     // Snyder p. 108
+        if (absφ < PI/2) {
+            sinφ = sin(φ);
+            ρ = pow(expOfNorthing(-φ, -excentricity * sinφ), n);
+        } else if (absφ < PI/2 + ANGULAR_TOLERANCE) {
+            sinφ = 1;
+            ρ = (φ*n <= 0) ? POSITIVE_INFINITY : 0;
+        } else {
+            ρ = sinφ = NaN;
+        }
+        final double x = ρ * sinλ;
+        final double y = ρ * cosλ;
+        if (dstPts != null) {
+            dstPts[dstOff]   = x;
+            dstPts[dstOff+1] = y;
+        }
+        if (!derivate) {
+            return null;
+        }
+        //
+        // End of map projection. Now compute the derivative.
+        //
+        final double dρ;
+        if (sinφ != 1) {
+            dρ = n * -dy_dφ(sinφ, cos(φ)) * ρ;
+        } else {
+            dρ = ρ;
+        }
+        return new Matrix2(y, dρ*sinλ,      // ∂x/∂λ , ∂x/∂φ
+                          -x, dρ*cosλ);     // ∂y/∂λ , ∂y/∂φ
+    }
+
+    /**
+     * Transforms the specified (<var>x</var>,<var>y</var>) coordinates
+     * and stores the result in {@code dstPts} (angles in radians).
+     *
+     * @throws ProjectionException if the point can not be converted.
+     */
+    @Override
+    protected void inverseTransform(final double[] srcPts, final int srcOff,
+                                    final double[] dstPts, final int dstOff)
+            throws ProjectionException
+    {
+        final double x = srcPts[srcOff  ];
+        final double y = srcPts[srcOff+1];
+        /*
+         * NOTE: If some equation terms seem missing (e.g. "y = ρ0 - y"), this is because the linear operations
+         * applied before the first non-linear one moved to the inverse of the "denormalize" transform, and the
+         * linear operations applied after the last non-linear one moved to the inverse of the "normalize" transform.
+         */
+        dstPts[dstOff  ] = atan2(x, y);  // Really (x,y), not (y,x)
+        dstPts[dstOff+1] = φ(pow(hypot(x, y), 1/n));
+    }
+
+
+    /**
+     * Provides the transform equations for the spherical case of the Lambert Conformal projection.
+     *
+     * <div class="note"><b>Implementation note:</b>
+     * this class contains explicit checks for latitude values at poles.
+     * See the discussion in the {@link Mercator.Spherical} javadoc for an explanation.
+     * The following is specific to the Lambert Conformal projection.
+     *
+     * <p>Comparison of observed behavior at poles between the spherical and ellipsoidal cases,
+     * if no special checks are applied:</p>
+     *
+     * {@preformat text
+     *     ┌───────┬─────────────────────────────┬───────────────────────────┐
+     *     │       │ Spherical                   │ Ellipsoidal               │
+     *     ├───────┼─────────────────────────────┼───────────────────────────┤
+     *     │ North │ Approximative (y = small)   │ Exact answer  (y = 0.0)   │
+     *     │ South │ Exact answer  (y = +∞)      │ Approximative (y = big)   │
+     *     └───────┴─────────────────────────────┴───────────────────────────┘
+     * }
+     * </div>
+     *
+     * @author  Martin Desruisseaux (MPO, IRD, Geomatys)
+     * @author  André Gosselin (MPO)
+     * @author  Rueben Schulz (UBC)
+     * @since   0.6
+     * @version 0.6
+     * @module
+     */
+    static final class Spherical extends LambertConformal {
+        /**
+         * For cross-version compatibility.
+         */
+        private static final long serialVersionUID = -7005092237343502956L;
+
+        /**
+         * Constructs a new map projection from the parameters of the given projection.
+         *
+         * @param other The other projection (usually ellipsoidal) from which to copy the parameters.
+         */
+        protected Spherical(final LambertConformal other) {
+            super(other);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public Matrix transform(final double[] srcPts, final int srcOff,
+                                final double[] dstPts, final int dstOff,
+                                final boolean derivate) throws ProjectionException
+        {
+            final double λ    = srcPts[srcOff];
+            final double φ    = srcPts[srcOff + 1];
+            final double absφ = abs(φ);
+            final double sinλ = sin(λ);
+            final double cosλ = cos(λ);
+            final double ρ;
+            if (absφ < PI/2) {
+                ρ = pow(tan(PI/4 + 0.5*φ), -n);
+            } else if (absφ < PI/2 + ANGULAR_TOLERANCE) {
+                ρ = (φ*n <= 0) ? POSITIVE_INFINITY : 0;
+            } else {
+                ρ = NaN;
+            }
+            final double x = ρ * sinλ;
+            final double y = ρ * cosλ;
+            Matrix derivative = null;
+            if (derivate) {
+                final double dρ;
+                if (absφ < PI/2) {
+                    dρ = -n*ρ / cos(φ);
+                } else {
+                    dρ = NaN;
+                }
+                derivative = new Matrix2(y, dρ*sinλ,    // ∂x/∂λ , ∂x/∂φ
+                                        -x, dρ*cosλ);   // ∂y/∂λ , ∂y/∂φ
+            }
+            // Following part is common to all spherical projections: verify, store and return.
+            assert Assertions.checkDerivative(derivative, super.transform(srcPts, srcOff, dstPts, dstOff, derivate))
+                && Assertions.checkTransform(dstPts, dstOff, x, y);     // dstPts = result from ellipsoidal formulas.
+            if (dstPts != null) {
+                dstPts[dstOff  ] = x;
+                dstPts[dstOff+1] = y;
+            }
+            return derivative;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        protected void inverseTransform(final double[] srcPts, final int srcOff,
+                                        final double[] dstPts, final int dstOff)
+                throws ProjectionException
+        {
+            double x = srcPts[srcOff  ];
+            double y = srcPts[srcOff+1];
+            final double ρ = hypot(x, y);
+            x = atan2(x, y);  // Really (x,y), not (y,x)
+            y = 2 * atan(pow(1/ρ, 1/n)) - PI/2;
+            assert 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, λ, φ);
+        }
+    }
+
+    /**
+     * Compares the given object with this transform for equivalence.
+     *
+     * @return {@code true} if the given object is equivalent to this map projection.
+     */
+    @Override
+    public boolean equals(final Object object, final ComparisonMode mode) {
+        if (super.equals(object, mode)) {
+            return Numerics.epsilonEqual(n, ((LambertConformal) object).n, mode);
+        }
+        return false;
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConformal.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConformal.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -27,7 +27,6 @@ import org.apache.sis.internal.referenci
 import org.apache.sis.internal.referencing.provider.Mercator2SP;
 import org.apache.sis.internal.referencing.provider.MercatorSpherical;
 import org.apache.sis.internal.referencing.provider.RegionalMercator;
-import org.apache.sis.internal.referencing.provider.MillerCylindrical;
 import org.apache.sis.internal.referencing.provider.PseudoMercator;
 import org.apache.sis.internal.util.DoubleDouble;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
@@ -85,6 +84,8 @@ public class Mercator extends Normalized
      *
      * <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>
+     *
+     * @see #getType(ParameterDescriptorGroup)
      */
     static final byte SPHERICAL = 1, PSEUDO = 3,    // Must be odd and SPHERICAL must be 1.
                       REGIONAL  = 2, MILLER = 4;    // Must be even.
@@ -216,10 +217,10 @@ public class Mercator extends Normalized
      * 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, RegionalMercator .NAME, RegionalMercator .IDENTIFIER)) return REGIONAL;
-        if (identMatch(parameters, MercatorSpherical.NAME, MercatorSpherical.IDENTIFIER)) return SPHERICAL;
-        if (identMatch(parameters, PseudoMercator   .NAME, PseudoMercator   .IDENTIFIER)) return PSEUDO;
-        if (identMatch(parameters, MillerCylindrical.NAME, null))                         return MILLER;
+        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;
     }
 
@@ -245,9 +246,9 @@ public class Mercator extends Normalized
     }
 
     /**
-     * Converts the specified (<var>λ</var>,<var>φ</var>) coordinate (units in radians)
-     * and stores the result in {@code dstPts} (linear distance on a unit sphere). In addition,
-     * opportunistically computes the projection derivative if {@code derivate} is {@code true}.
+     * Converts the specified (λ,φ) coordinate (units in radians) and stores the result in {@code dstPts}
+     * (linear distance on a unit sphere). In addition, opportunistically computes the projection derivative
+     * if {@code derivate} is {@code true}.
      *
      * @return The matrix of the projection derivative at the given source position,
      *         or {@code null} if the {@code derivate} argument is {@code false}.
@@ -362,8 +363,10 @@ public class Mercator extends Normalized
      * </ul>
      * </div>
      *
-     * @author Martin Desruisseaux (MPO, IRD, Geomatys)
-     * @author Rueben Schulz (UBC)
+     * @author  Martin Desruisseaux (MPO, IRD, Geomatys)
+     * @author  Rueben Schulz (UBC)
+     * @since   0.6
+     * @version 0.6
      * @module
      */
     static final class Spherical extends Mercator {
@@ -375,7 +378,7 @@ public class Mercator extends Normalized
         /**
          * Constructs a new map projection from the parameters of the given projection.
          *
-         * @param other  The other projection (usually ellipsoidal) from which to copy the parameters.
+         * @param other The other projection (usually ellipsoidal) from which to copy the parameters.
          */
         Spherical(final Mercator other) {
             super(other);

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -20,6 +20,7 @@ import java.util.List;
 import java.util.ArrayList;
 import java.io.Serializable;
 import org.opengis.metadata.Identifier;
+import org.opengis.parameter.ParameterValue;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
@@ -330,23 +331,30 @@ public abstract class NormalizedProjecti
     }
 
     /**
-     * Returns {@code true} if the projection specified by the given parameters has the given name or identifier.
-     * If non-null, the given identifier is presumed in the EPSG namespace and has precedence over the name.
+     * Returns {@code true} if the projection specified by the given parameters 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>
+     * Since callers usually give a constant string for the {@code regex} argument, it would be more efficient to
+     * compile the {@link java.util.regex.Pattern} once for all. However the regular expression is used only as a
+     * fallback if the descriptor does not contain EPSG identifier, which should be rare. Usually, the regular
+     * expression will never be compiled.</div>
      *
      * @param  parameters The user-specified parameters.
-     * @param  name       The name to compare against the parameter group name.
+     * @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 has a name or EPSG identifier matching the given ones.
+     * @return {@code true} if the given parameter group name contains the given keyword
+     *         or has an EPSG identifier equals to the given identifier.
      */
-    static boolean identMatch(final ParameterDescriptorGroup parameters, final String name, final String identifier) {
+    static boolean identMatch(final ParameterDescriptorGroup parameters, final String regex, final String identifier) {
         if (identifier != null) {
             for (final Identifier id : parameters.getIdentifiers()) {
-                if (identifier.equals(id.getCode()) && Constants.EPSG.equals(id.getCodeSpace())) {
-                    return true;
+                if (Constants.EPSG.equals(id.getCodeSpace())) {
+                    return identifier.equals(id.getCode());
                 }
             }
         }
-        return IdentifiedObjects.isHeuristicMatchForName(parameters, name);
+        return parameters.getName().getCode().matches(regex);
     }
 
     /**
@@ -354,10 +362,40 @@ public abstract class NormalizedProjecti
      * A "contextual parameter" is a parameter that apply to the normalize → {@code this} → denormalize
      * chain as a whole. It does not really apply to this {@code NormalizedProjection} instance when taken alone.
      *
-     * <p>This method shall be invoked at construction time only.</p>
+     * <p>This method performs the following actions:</p>
+     * <ul>
+     *   <li>Convert the value to the units specified by the descriptor.</li>
+     *   <li>Ensure that the value is contained in the range specified by the descriptor.</li>
+     *   <li>Store the value only if different than the default value.</li>
+     * </ul>
+     *
+     * This method shall be invoked at construction time only.
      */
     final double getAndStore(final Parameters parameters, final ParameterDescriptor<Double> descriptor) {
-        return MapProjection.getAndStore(parameters, context, descriptor);
+        final double value = parameters.doubleValue(descriptor);    // Apply a unit conversion if needed.
+        final Double defaultValue = descriptor.getDefaultValue();
+        if (defaultValue == null || !defaultValue.equals(value)) {
+            MapProjection.validate(descriptor, value);
+            context.parameter(descriptor.getName().getCode()).setValue(value);
+        }
+        return value;
+    }
+
+    /**
+     * Same as {@link #getAndStore(Parameters, ParameterDescriptor)}, but returns the given default value
+     * if the parameter is not specified.  This method shall be used only for parameters having a default
+     * value more complex than what we can represent in {@link ParameterDescriptor#getDefaultValue()}.
+     */
+    final double getAndStore(final Parameters parameters, final ParameterDescriptor<Double> descriptor,
+            final double defaultValue)
+    {
+        final Double value = parameters.getValue(descriptor);   // Apply a unit conversion if needed.
+        if (value == null) {
+            return defaultValue;
+        }
+        MapProjection.validate(descriptor, value);
+        context.parameter(descriptor.getName().getCode()).setValue(value);
+        return value;
     }
 
     /**
@@ -427,30 +465,51 @@ public abstract class NormalizedProjecti
     @Debug
     @Override
     public ParameterValueGroup getParameterValues() {
-        final ParameterDescriptorGroup descriptor = filter(getParameterDescriptors());
-        final ParameterValueGroup values = descriptor.createValue();
-        values.parameter(Constants.SEMI_MAJOR).setValue(1.0);
-        values.parameter(Constants.SEMI_MINOR).setValue(sqrt(1 - excentricitySquared));
-        return values;
+        return getParameterValues(new String[] {
+            Constants.SEMI_MAJOR,
+            Constants.SEMI_MINOR
+        });
     }
 
     /**
-     * Filter the given parameter descriptor in order to retain only the semi-major and semi-minor axis lengths.
-     * This filtered version is used for displaying the parameter values of this non-linear kernel only, not for
-     * displaying the {@linkplain #getContextualParameters() contextual parameters}. Since displaying the kernel
-     * parameter values is for debugging purpose only, it is not worth to cache this descriptor.
+     * Filters the parameter descriptor in order to retain only the parameters of the given names, and
+     * sets the semi-major and semi-minor axis lengths. The specified parameters list should contains at
+     * least the {@code "semi_major"} and {@code "semi_minor"} strings.
+     *
+     * <p>This filtered descriptor is used for displaying the parameter values of this non-linear kernel only,
+     * not for displaying the {@linkplain #getContextualParameters() contextual parameters}. Since displaying
+     * the kernel parameter values is for debugging purpose only, it is not worth to cache this descriptor.</p>
      */
-    private static ParameterDescriptorGroup filter(final ParameterDescriptorGroup descriptor) {
-        final List<GeneralParameterDescriptor> filtered = new ArrayList<>(5);
+    @Debug
+    final ParameterValueGroup getParameterValues(final String[] nonLinearParameters) {
+        ParameterDescriptorGroup descriptor = getParameterDescriptors();
+        final List<GeneralParameterDescriptor> filtered = new ArrayList<>(nonLinearParameters.length);
         for (final GeneralParameterDescriptor p : descriptor.descriptors()) {
-            if (IdentifiedObjects.isHeuristicMatchForName(p, Constants.SEMI_MAJOR) ||
-                IdentifiedObjects.isHeuristicMatchForName(p, Constants.SEMI_MINOR))
-            {
-                filtered.add(p);
+            for (final String name : nonLinearParameters) {
+                if (IdentifiedObjects.isHeuristicMatchForName(p, name)) {
+                    filtered.add(p);
+                    break;
+                }
             }
         }
-        return new DefaultParameterDescriptorGroup(IdentifiedObjects.getProperties(descriptor),
+        descriptor = new DefaultParameterDescriptorGroup(IdentifiedObjects.getProperties(descriptor),
                 1, 1, filtered.toArray(new GeneralParameterDescriptor[filtered.size()]));
+        /*
+         * Parameter values for the ellipsoid semi-major and semi-minor axis lengths are 1 and <= 1
+         * respectively because the denormalization (e.g. multiplication by a scale factor) will be
+         * applied by an affine transform after this NormalizedProjection.
+         */
+        final ParameterValueGroup values = descriptor.createValue();
+        for (final GeneralParameterDescriptor desc : filtered) {
+            final String name = desc.getName().getCode();
+            final ParameterValue<?> p = values.parameter(name);
+            switch (name) {
+                case Constants.SEMI_MAJOR: p.setValue(1.0); break;
+                case Constants.SEMI_MINOR: p.setValue(sqrt(1 - excentricitySquared)); break;
+                default: p.setValue(context.parameter(name).getValue());
+            }
+        }
+        return values;
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/EquirectangularTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/EquirectangularTest.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/EquirectangularTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/EquirectangularTest.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -118,7 +118,7 @@ public final strictfp class Equirectangu
      */
     @Test
     public void testRandomPoints() throws FactoryException, TransformException {
-        initialize(new Equirectangular(), true, true, false);
+        initialize(new Equirectangular(), true, false, true, false);
         tolerance = Formulas.LINEAR_TOLERANCE;  // Not NORMALIZED_TOLERANCE since this is not a NormalizedProjection.
         derivativeDeltas = new double[] {100, 100};
         verifyInDomain(CoordinateDomain.GEOGRAPHIC, 0);

Added: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java?rev=1673961&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.referencing.operation.projection;
+
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.internal.referencing.Formulas;
+import org.apache.sis.internal.referencing.provider.LambertConformal1SP;
+import org.apache.sis.internal.referencing.provider.LambertConformal2SP;
+import org.apache.sis.internal.referencing.provider.LambertConformalBelgium;
+import org.apache.sis.referencing.operation.transform.CoordinateDomain;
+import org.apache.sis.parameter.Parameters;
+import org.apache.sis.test.DependsOnMethod;
+import org.apache.sis.test.DependsOn;
+import org.junit.Test;
+
+import static java.lang.StrictMath.*;
+import static java.lang.Double.*;
+import static org.junit.Assert.*;
+
+
+/**
+ * Tests the {@link LambertConformal} class. We test using various values of the latitude of origin.
+ * We do not test with various values of standard parallels, because it is just an other way to set
+ * the value of the <var>n</var> field in {@code LambertConformal}. As long as we make this value varying,
+ * the latitude of origin is the simplest approach.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @author  Rémi Maréchal (Geomatys)
+ * @since   0.6
+ * @version 0.6
+ * @module
+ */
+@DependsOn(NormalizedProjectionTest.class)
+public final strictfp class LambertConformalTest extends MapProjectionTestCase {
+    /**
+     * Creates a new instance of {@link LambertConformal}. See the class javadoc for an explanation
+     * about why we ask only for the latitude of origin and not the standard parallels.
+     *
+     * @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) {
+        final LambertConformal1SP method = new LambertConformal1SP();
+        final Parameters parameters = parameters(method, ellipse);
+        parameters.getOrCreate(LambertConformal1SP.LATITUDE_OF_ORIGIN).setValue(latitudeOfOrigin);
+        transform = new LambertConformal(method, parameters);
+        if (!ellipse) {
+            transform = new LambertConformal.Spherical((LambertConformal) transform);
+        }
+        tolerance = NORMALIZED_TOLERANCE;
+        validate();
+    }
+
+    /**
+     * Tests the WKT formatting of {@link NormalizedProjection}. For the Lambert Conformal projection, we expect
+     * the standard parallels or the latitude of origin in addition to the semi-major and semi-minor axis length.
+     */
+    @Test
+    public void testNormalizedWKT() {
+        initialize(true, 40);
+        assertWktEquals(
+                "PARAM_MT[“Lambert_Conformal_Conic_1SP”,\n" +
+                "  PARAMETER[“semi_major”, 1.0],\n" +
+                "  PARAMETER[“semi_minor”, 0.9966471893352525],\n" +
+                "  PARAMETER[“latitude_of_origin”, 40.0]]");
+    }
+
+    /**
+     * Tests the projection at some special latitudes (0, ±π/2, NaN and others).
+     *
+     * @throws ProjectionException Should never happen.
+     */
+    @Test
+    public void testSpecialLatitudes() throws ProjectionException {
+        if (transform == null) {    // May have been initialized by 'testSphericalCase'.
+            initialize(true, 40);   // Elliptical case
+        }
+        final double INF = POSITIVE_INFINITY;
+        assertEquals ("Not a number",     NaN, transform(NaN),            NORMALIZED_TOLERANCE);
+        assertEquals ("Out of range",     NaN, transform(+2),             NORMALIZED_TOLERANCE);
+        assertEquals ("Out of range",     NaN, transform(-2),             NORMALIZED_TOLERANCE);
+        assertEquals ("Forward 0°N",      1,   transform(0),              NORMALIZED_TOLERANCE);
+        assertEquals ("Forward 90°N",     0,   transform(+PI/2),          NORMALIZED_TOLERANCE);
+        assertEquals ("Forward 90°S",     INF, transform(-PI/2),          NORMALIZED_TOLERANCE);
+        assertEquals ("Forward (90+ε)°N", 0,   transform(+nextUp(+PI/2)), NORMALIZED_TOLERANCE);
+        assertEquals ("Forward (90+ε)°S", INF, transform(-nextUp( PI/2)), NORMALIZED_TOLERANCE);
+        assertEquals ("Forward (90-ε)°N", 0,   transform(-nextUp(-PI/2)), 1E-10);
+
+        assertEquals ("Not a number", NaN, inverseTransform(NaN),  NORMALIZED_TOLERANCE);
+        assertEquals ("Inverse 0",  +PI/2, inverseTransform( 0),   NORMALIZED_TOLERANCE);
+        assertEquals ("Inverse +1",     0, inverseTransform(+1),   NORMALIZED_TOLERANCE);
+        assertEquals ("Inverse -1",     0, inverseTransform(-1),   NORMALIZED_TOLERANCE);
+        assertEquals ("Inverse +∞", -PI/2, inverseTransform(INF),  NORMALIZED_TOLERANCE);
+        assertEquals ("Inverse -∞", -PI/2, inverseTransform(-INF), NORMALIZED_TOLERANCE);
+
+        // Like the north case, but with sign inversed.
+        initialize(((LambertConformal) transform).excentricity != 0, -40);
+        validate();
+
+        assertEquals ("Not a number",     NaN, transform(NaN),            NORMALIZED_TOLERANCE);
+        assertEquals ("Out of range",     NaN, transform(+2),             NORMALIZED_TOLERANCE);
+        assertEquals ("Out of range",     NaN, transform(-2),             NORMALIZED_TOLERANCE);
+        assertEquals ("Forward 0°N",      1,   transform(0),              NORMALIZED_TOLERANCE);
+        assertEquals ("Forward 90°N",     INF, transform(+PI/2),          NORMALIZED_TOLERANCE);
+        assertEquals ("Forward 90°S",     0,   transform(-PI/2),          NORMALIZED_TOLERANCE);
+        assertEquals ("Forward (90+ε)°N", INF, transform(+nextUp(+PI/2)), NORMALIZED_TOLERANCE);
+        assertEquals ("Forward (90+ε)°S", 0,   transform(-nextUp( PI/2)), NORMALIZED_TOLERANCE);
+        assertEquals ("Forward (90-ε)°S", 0,   transform( nextUp(-PI/2)), 1E-10);
+
+        assertEquals ("Not a number", NaN, inverseTransform(NaN),  NORMALIZED_TOLERANCE);
+        assertEquals ("Inverse 0",  -PI/2, inverseTransform( 0),   NORMALIZED_TOLERANCE);
+        assertEquals ("Inverse +∞", +PI/2, inverseTransform(INF),  NORMALIZED_TOLERANCE);
+        assertEquals ("Inverse -∞", +PI/2, inverseTransform(-INF), NORMALIZED_TOLERANCE);
+    }
+
+    /**
+     * Tests the derivatives at a few points. This method compares the derivatives computed by
+     * the projection with an estimation of derivatives computed by the finite differences method.
+     *
+     * @throws TransformException Should never happen.
+     */
+    @Test
+    @DependsOnMethod("testSpecialLatitudes")
+    public void testDerivative() throws TransformException {
+        if (transform == null) {    // May have been initialized by 'testSphericalCase'.
+            initialize(true, 40);   // Elliptical case
+        }
+        final double delta = toRadians(100.0 / 60) / 1852; // Approximatively 100 metres.
+        derivativeDeltas = new double[] {delta, delta};
+        tolerance = 1E-9;
+        verifyDerivative(toRadians( 0), toRadians( 0));
+        verifyDerivative(toRadians(15), toRadians(30));
+        verifyDerivative(toRadians(10), toRadians(60));
+    }
+
+    /**
+     * Tests the <cite>"Lambert Conic Conformal (1SP)"</cite> case (EPSG:9801).
+     * This test is defined in GeoAPI conformance test suite.
+     *
+     * @throws FactoryException if an error occurred while creating the map projection.
+     * @throws TransformException if an error occurred while projecting a coordinate.
+     *
+     * @see org.opengis.test.referencing.ParameterizedTransformTest#testLambertConicConformal1SP()
+     */
+    @Test
+    @DependsOnMethod({"testSpecialLatitudes", "testDerivative"})
+    public void testLambertConicConformal1SP() throws FactoryException, TransformException {
+        createGeoApiTest(new LambertConformal1SP()).testLambertConicConformal1SP();
+    }
+
+    /**
+     * Tests the <cite>"Lambert Conic Conformal (2SP)"</cite> case (EPSG:9802).
+     * This test is defined in GeoAPI conformance test suite.
+     *
+     * @throws FactoryException if an error occurred while creating the map projection.
+     * @throws TransformException if an error occurred while projecting a coordinate.
+     *
+     * @see org.opengis.test.referencing.ParameterizedTransformTest#testLambertConicConformal1SP()
+     */
+    @Test
+    @DependsOnMethod("testLambertConicConformal1SP")
+    public void testLambertConicConformal2SP() throws FactoryException, TransformException {
+        createGeoApiTest(new LambertConformal2SP()).testLambertConicConformal2SP();
+    }
+
+    /**
+     * Tests the <cite>"Lambert Conic Conformal (2SP Belgium)"</cite> case (EPSG:9803).
+     * This test is defined in GeoAPI conformance test suite.
+     *
+     * @throws FactoryException if an error occurred while creating the map projection.
+     * @throws TransformException if an error occurred while projecting a coordinate.
+     *
+     * @see org.opengis.test.referencing.ParameterizedTransformTest#testLambertConicConformal1SP()
+     */
+    @Test
+    @DependsOnMethod("testLambertConicConformal2SP")
+    public void testLambertConicConformalBelgium() throws FactoryException, TransformException {
+        createGeoApiTest(new LambertConformalBelgium()).testLambertConicConformalBelgium();
+    }
+
+    /**
+     * Verifies the consistency of spherical formulas with the elliptical 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")
+    public void testSphericalCase() throws FactoryException, TransformException {
+        initialize(false, 40); // Spherical case
+        testSpecialLatitudes();
+        testDerivative();
+        /*
+         * Make sure that the above methods did not changed the 'transform' field type.
+         */
+        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, true, false, true);
+        tolerance = Formulas.LINEAR_TOLERANCE;
+        verifyInDomain(CoordinateDomain.GEOGRAPHIC_SAFE, 268617081);
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConformalTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

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=1673961&r1=1673960&r2=1673961&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] Wed Apr 15 21:35:21 2015
@@ -28,6 +28,9 @@ import org.apache.sis.referencing.operat
 import org.apache.sis.test.mock.MathTransformFactoryMock;
 import org.apache.sis.test.mock.GeodeticDatumMock;
 
+import static java.lang.StrictMath.*;
+import static org.junit.Assert.*;
+
 
 /**
  * Base class of map projection tests.
@@ -80,13 +83,18 @@ strictfp class MapProjectionTestCase ext
      * the chances to detect a mismatch.
      */
     final void initialize(final DefaultOperationMethod provider, final boolean ellipse,
-            final boolean hasStandardParallel, final boolean hasScaleFactor)
+            final boolean hasLatitudeOfOrigin,
+            final boolean hasStandardParallel,
+            final boolean hasScaleFactor)
             throws FactoryException
     {
         final Parameters parameters = parameters(provider, ellipse);
         parameters.parameter(Constants.CENTRAL_MERIDIAN).setValue(0.5, NonSI.DEGREE_ANGLE);
         parameters.parameter(Constants.FALSE_EASTING)   .setValue(200);
         parameters.parameter(Constants.FALSE_NORTHING)  .setValue(100);
+        if (hasLatitudeOfOrigin) {
+            parameters.parameter("latitude_of_origin").setValue(40);
+        }
         if (hasStandardParallel) {
             parameters.parameter(Constants.STANDARD_PARALLEL_1).setValue(20);
         }
@@ -96,4 +104,52 @@ strictfp class MapProjectionTestCase ext
         transform = new MathTransformFactoryMock(provider).createParameterizedTransform(parameters);
         validate();
     }
+
+    /**
+     * Projects the given latitude value. The longitude is fixed to zero.
+     * This method is useful for testing the behavior close to poles in a simple case.
+     *
+     * @param  φ The latitude.
+     * @return The northing.
+     * @throws ProjectionException if the projection failed.
+     */
+    final double transform(final double φ) throws ProjectionException {
+        final double[] coordinate = new double[2];
+        coordinate[1] = φ;
+        ((NormalizedProjection) transform).transform(coordinate, 0, coordinate, 0, false);
+        final double y = coordinate[1];
+        if (!Double.isNaN(y) && !Double.isInfinite(y)) {
+            assertEquals(0, coordinate[0], tolerance);
+        }
+        return y;
+    }
+
+    /**
+     * Inverse projects the given northing value. The easting is fixed to zero.
+     * This method is useful for testing the behavior close to poles in a simple case.
+     *
+     * @param  y The northing.
+     * @return The latitude.
+     * @throws ProjectionException if the projection failed.
+     */
+    final double inverseTransform(final double y) throws ProjectionException {
+        final double[] coordinate = new double[2];
+        coordinate[1] = y;
+        ((NormalizedProjection) transform).inverseTransform(coordinate, 0, coordinate, 0);
+        final double φ = coordinate[1];
+        if (!Double.isNaN(φ)) {
+            /*
+             * Opportunistically verify that the longitude is still zero. However the longitude value is meaningless
+             * at poles. We can not always use coordinate[0] for testing if we are at a pole because its calculation
+             * is not finished (the denormalization matrix has not yet been applied).  In the particular case of SIS
+             * implementation, we observe sometime a ±180° rotation, which we ignore below. Such empirical hack is
+             * not rigorous, but it is not the purpose of this test to check the longitude value - we are doing only
+             * an opportunist check, other test methods will test longitude more accurately.
+             */
+            double λ = coordinate[0];
+            λ -= rint(λ / PI) * PI;
+            assertEquals(0, λ, tolerance);
+        }
+        return φ;
+    }
 }

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=1673961&r1=1673960&r2=1673961&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] Wed Apr 15 21:35:21 2015
@@ -78,45 +78,6 @@ public final strictfp class MercatorTest
     }
 
     /**
-     * Projects the given latitude value. The longitude is fixed to zero.
-     * This method is useful for testing the behavior close to poles in a simple case.
-     *
-     * @param  φ The latitude.
-     * @return The northing.
-     * @throws ProjectionException if the projection failed.
-     */
-    private double transform(final double φ) throws ProjectionException {
-        final double[] coordinate = new double[2];
-        coordinate[1] = φ;
-        ((NormalizedProjection) transform).transform(coordinate, 0, coordinate, 0, false);
-        final double y = coordinate[1];
-        if (!Double.isNaN(y) && !Double.isInfinite(y)) {
-            assertEquals(0, coordinate[0], tolerance);
-        }
-        return y;
-    }
-
-    /**
-     * Inverse projects the given northing value. The longitude is fixed to zero.
-     * This method is useful for testing the behavior close to poles in a simple case.
-     *
-     * @param  y The northing.
-     * @return The latitude.
-     * @throws ProjectionException if the projection failed.
-     */
-    private double inverseTransform(final double y) throws ProjectionException {
-        final double[] coordinate = new double[2];
-        coordinate[1] = y;
-        ((NormalizedProjection) transform).inverseTransform(coordinate, 0, coordinate, 0);
-        final double φ = coordinate[1];
-        if (!Double.isNaN(φ)) {
-            final double λ = coordinate[0];
-            assertEquals(0, λ, tolerance);
-        }
-        return φ;
-    }
-
-    /**
      * Tests the projection at some special latitudes (0, ±π/2, NaN).
      *
      * @throws ProjectionException Should never happen.
@@ -273,7 +234,7 @@ public final strictfp class MercatorTest
         /*
          * For some random points, compare the result of spherical formulas with the ellipsoidal ones.
          */
-        initialize(new Mercator1SP(), false, false, true);
+        initialize(new Mercator1SP(), false, false, false, true);
         tolerance = Formulas.LINEAR_TOLERANCE;
         verifyInDomain(CoordinateDomain.GEOGRAPHIC_SAFE, 84018710);
     }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -102,6 +102,7 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.operation.projection.NormalizedProjectionTest.class,
     org.apache.sis.referencing.operation.projection.EquirectangularTest.class,
     org.apache.sis.referencing.operation.projection.MercatorTest.class,
+    org.apache.sis.referencing.operation.projection.LambertConformalTest.class,
 
     // Coordinate Reference System components.
     org.apache.sis.referencing.datum.BursaWolfParametersTest.class,

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Wed Apr 15 21:35:21 2015
@@ -459,6 +459,11 @@ public final class Errors extends Indexe
         public static final short KeyCollision_1 = 54;
 
         /**
+         * Latitudes {0} and {1} are opposite.
+         */
+        public static final short LatitudesAreOpposite_2 = 183;
+
+        /**
          * Attribute “{0}” is mandatory for an object of type ‘{1}’.
          */
         public static final short MandatoryAttribute_2 = 55;

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1673961&r1=1673960&r2=1673961&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Wed Apr 15 21:35:21 2015
@@ -102,6 +102,7 @@ InfiniteArgumentValue_1           = Argu
 InseparableTransform              = Inseparable transform.
 InsufficientArgumentSize_3        = Argument \u2018{0}\u2019 shall contain at least {1} elements. A number of {2} is insufficient.
 KeyCollision_1                    = A different value is already associated to the \u201c{0}\u201d key.
+LatitudesAreOpposite_2            = Latitudes {0} and {1} are opposite.
 MandatoryAttribute_2              = Attribute \u201c{0}\u201d is mandatory for an object of type \u2018{1}\u2019.
 MismatchedArrayLengths            = Mismatched array lengths.
 MismatchedCRS                     = The coordinate reference system must be the same for all objects.



Mime
View raw message