sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1828642 - in /sis/branches/JDK8/core/sis-referencing/src: main/java/org/apache/sis/internal/referencing/provider/ main/java/org/apache/sis/parameter/ main/java/org/apache/sis/referencing/operation/projection/ test/java/org/apache/sis/inter...
Date Sun, 08 Apr 2018 15:19:39 GMT
Author: desruisseaux
Date: Sun Apr  8 15:19:39 2018
New Revision: 1828642

URL: http://svn.apache.org/viewvc?rev=1828642&view=rev
Log:
Add Oblique Mercator projection (EPSG:9812, EPSG:9815).
https://issues.apache.org/jira/browse/SIS-221

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercator.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorCenter.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorTwoPoints.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorTwoPointsCenter.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueMercator.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ObliqueMercatorTest.java   (with props)
Modified:
    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/Mercator1SP.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/package-info.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueStereographic.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java

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=1828642&r1=1828641&r2=1828642&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] Sun Apr  8 15:19:39 2018
@@ -95,7 +95,7 @@ public final class Equirectangular exten
      * Valid values range is (-90 … 90)° and default value is 0°.
      *
      * <p>In theory, this parameter should not be used and its value should be 0 in all cases.
-     * This parameter is included for completeness in CRS labelling only, and is declared optional.</p>
+     * This parameter is included for completeness in CRS labeling only, and is declared optional.</p>
      */
     static final ParameterDescriptor<Double> LATITUDE_OF_ORIGIN;
 

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java?rev=1828642&r1=1828641&r2=1828642&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java [UTF-8] Sun Apr  8 15:19:39 2018
@@ -47,7 +47,7 @@ public final class Mercator1SP extends A
     /**
      * The operation parameter descriptor for the <cite>Latitude of natural origin</cite> (φ₀) parameter value.
      * In theory, this parameter should not be used and its value should be 0 in all cases.
-     * This parameter is included in the EPSG dataset for completeness in CRS labelling only.
+     * This parameter is included in the EPSG dataset for completeness in CRS labeling only.
      */
     public static final ParameterDescriptor<Double> LATITUDE_OF_ORIGIN;
 

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercator.java?rev=1828642&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercator.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercator.java [UTF-8] Sun Apr  8 15:19:39 2018
@@ -0,0 +1,172 @@
+/*
+ * 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.internal.referencing.provider;
+
+import javax.xml.bind.annotation.XmlTransient;
+import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.apache.sis.parameter.Parameters;
+import org.apache.sis.parameter.ParameterBuilder;
+import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.referencing.operation.projection.NormalizedProjection;
+import org.apache.sis.measure.Units;
+
+
+
+/**
+ * The provider for <cite>"Hotine Oblique Mercator (variant A)"</cite> projection (EPSG:9812).
+ * Also the parent class for all variants.
+ *
+ * @author  Rueben Schulz (UBC)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+@XmlTransient
+public class ObliqueMercator extends AbstractMercator {
+    /**
+     * For compatibility with different versions during deserialization.
+     */
+    private static final long serialVersionUID = 9100327311220773612L;
+
+    /**
+     * The {@value} EPSG identifier for <cite>"Hotine Oblique Mercator (variant A)"</cite>.
+     * Should be preferred to the name when available.
+     */
+    public static final String IDENTIFIER_A = "9812";
+
+    /**
+     * The operation parameter descriptor for the <cite>Latitude of projection centre</cite> (φc) parameter value.
+     * Valid values range is [-90 … 90]° and default value is 0°.
+     */
+    public static final ParameterDescriptor<Double> LATITUDE_OF_CENTRE;
+
+    /**
+     * The operation parameter descriptor for the <cite>Longitude of projection centre</cite> (λc) parameter value.
+     * Valid values range is [-180 … 180]° and default value is 0°.
+     */
+    public static final ParameterDescriptor<Double> LONGITUDE_OF_CENTRE;
+
+    /**
+     * The operation parameter descriptor for the <cite>Azimuth of initial line</cite> (α) parameter value.
+     * Valid values ranges are [-360 … -270]°, [-90 … 90]° and [270 … 360]°. There is no default value.
+     */
+    public static final ParameterDescriptor<Double> AZIMUTH;
+
+    /**
+     * The operation parameter descriptor for the <cite>Angle from rectified to skew grid</cite> (γ) parameter value.
+     * Valid values range is [-360 … 360]° and default value is the value given to the {@link #AZIMUTH} parameter.
+     */
+    public static final ParameterDescriptor<Double> RECTIFIED_GRID_ANGLE;
+
+    /**
+     * The operation parameter descriptor for the <cite>Scale factor on initial line</cite> (k) parameter value.
+     * Valid values range is (0 … ∞) and default value is 1.
+     */
+    public static final ParameterDescriptor<Double> SCALE_FACTOR;
+
+    /**
+     * The group of all parameters expected by this coordinate operation.
+     */
+    private static final ParameterDescriptorGroup PARAMETERS;
+    static {
+        final ParameterBuilder builder = builder();
+
+        LATITUDE_OF_CENTRE = createLatitude(builder.addNamesAndIdentifiers(AlbersEqualArea.LATITUDE_OF_FALSE_ORIGIN)
+                .reidentify(Citations.EPSG, "8811")
+                .rename    (Citations.EPSG, "Latitude of projection centre")
+                .addName   (Citations.ESRI, "Latitude_Of_Center")
+                .rename    (Citations.NETCDF), false);                  // Remove the netCDF name.
+
+        LONGITUDE_OF_CENTRE = createLongitude(builder.addNamesAndIdentifiers(AlbersEqualArea.LONGITUDE_OF_FALSE_ORIGIN)
+                .reidentify(Citations.EPSG, "8812")
+                .rename    (Citations.EPSG, "Longitude of projection centre")
+                .addName   (Citations.ESRI, "Longitude_Of_Center")
+                .rename    (Citations.NETCDF));                         // Remove the netCDF name.
+
+        AZIMUTH = builder
+                .addIdentifier("8813")
+                .addIdentifier(Citations.GEOTIFF, "3094")
+                .addName("Azimuth of initial line")
+                .addName(Citations.OGC,     "azimuth")
+                .addName(Citations.ESRI,    "Azimuth")
+                .addName(Citations.GEOTIFF, "AzimuthAngle")
+                .addName(Citations.PROJ4,   "alpha")
+                .createBounded(-360, 360, Double.NaN, Units.DEGREE);
+
+        RECTIFIED_GRID_ANGLE = builder
+                .addIdentifier("8814")
+                .addName("Angle from Rectified to Skew Grid")
+                .addName(Citations.OGC,     "rectified_grid_angle")
+                .addName(Citations.ESRI,    "XY_Plane_Rotation")
+                .addName(Citations.GEOTIFF, "RectifiedGridAngle")
+                .createBounded(-360, 360, Double.NaN, Units.DEGREE);
+
+        SCALE_FACTOR = createScale(builder
+                .addNamesAndIdentifiers(Mercator1SP.SCALE_FACTOR)
+                .reidentify(Citations.EPSG,    "8815")
+                .reidentify(Citations.GEOTIFF, "3093")
+                .rename    (Citations.EPSG,    "Scale factor on initial line")
+                .rename    (Citations.GEOTIFF, "ScaleAtCenter")
+                .rename    (Citations.NETCDF));                                 // Remove the netCDF name.
+
+        PARAMETERS = builder
+                .addIdentifier(IDENTIFIER_A)
+                .addName("Hotine Oblique Mercator (variant A)")                 // Starting from EPSG version 7.6
+                .addName("Hotine Oblique Mercator")                             // Prior to EPSG version 7.6
+                .addName      (Citations.OGC,     "Hotine_Oblique_Mercator")
+                .addName      (Citations.ESRI,    "Hotine_Oblique_Mercator_Azimuth_Natural_Origin")
+                .addName      (Citations.ESRI,    "Rectified_Skew_Orthomorphic_Natural_Origin")
+                .addName      (Citations.S57,     "Hotine Oblique Mercator")
+                .addName      (Citations.S57,     "HOM")
+                .addIdentifier(Citations.S57,     "5")
+                .addName      (Citations.GEOTIFF, "CT_ObliqueMercator_Hotine")
+                .createGroupForMapProjection(
+                        LATITUDE_OF_CENTRE,
+                        LONGITUDE_OF_CENTRE,
+                        AZIMUTH,
+                        RECTIFIED_GRID_ANGLE,
+                        SCALE_FACTOR,
+                        FALSE_EASTING,
+                        FALSE_NORTHING);
+    }
+
+    /**
+     * Constructs a new provider.
+     */
+    public ObliqueMercator() {
+        super(PARAMETERS);
+    }
+
+    /**
+     * For subclass constructors only.
+     */
+    ObliqueMercator(final ParameterDescriptorGroup parameters) {
+        super(parameters);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @return the map projection created from the given parameter values.
+     */
+    @Override
+    protected final NormalizedProjection createProjection(final Parameters parameters) {
+        return new org.apache.sis.referencing.operation.projection.ObliqueMercator(this, parameters);
+   }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercator.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorCenter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorCenter.java?rev=1828642&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorCenter.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorCenter.java [UTF-8] Sun Apr  8 15:19:39 2018
@@ -0,0 +1,113 @@
+/*
+ * 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.internal.referencing.provider;
+
+import javax.xml.bind.annotation.XmlTransient;
+import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.apache.sis.parameter.ParameterBuilder;
+import org.apache.sis.metadata.iso.citation.Citations;
+
+
+/**
+ * The provider for <cite>"Hotine Oblique Mercator (variant B)"</cite> projection (EPSG:9815).
+ *
+ * @author  Rueben Schulz (UBC)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+@XmlTransient
+public final class ObliqueMercatorCenter extends ObliqueMercator {
+    /**
+     * For compatibility with different versions during deserialization.
+     */
+    private static final long serialVersionUID = 1404490143062736127L;
+
+    /**
+     * The {@value} EPSG identifier for <cite>"Hotine Oblique Mercator (variant B)"</cite>.
+     * Should be preferred to the name when available.
+     */
+    public static final String IDENTIFIER = "9815";
+
+    /**
+     * The operation parameter descriptor for the <cite>Easting at projection centre</cite> (Ec) parameter value.
+     * Valid values range is unrestricted and default value is 0 metre.
+     */
+    public static final ParameterDescriptor<Double> EASTING_AT_CENTRE;
+
+    /**
+     * The operation parameter descriptor for the <cite>Northing at projection centre</cite> (Nc) parameter value.
+     * Valid values range is unrestricted and default value is 0 metre.
+     */
+    public static final ParameterDescriptor<Double> NORTHING_AT_CENTRE;
+
+    /**
+     * The group of all parameters expected by this coordinate operation.
+     */
+    private static final ParameterDescriptorGroup PARAMETERS;
+    static {
+        final ParameterBuilder builder = builder();
+
+        EASTING_AT_CENTRE = createShift(builder
+                .addNamesAndIdentifiers(FALSE_EASTING)
+                .reidentify(Citations.EPSG,    "8816")
+                .reidentify(Citations.GEOTIFF, "3090")
+                .rename(Citations.EPSG, "Easting at projection centre")
+                .rename(Citations.GEOTIFF, "ProjCenterEastingGeoKey")
+                .rename(Citations.NETCDF));                                 // Delete the netCDF name.
+
+        NORTHING_AT_CENTRE = createShift(builder
+                .addNamesAndIdentifiers(FALSE_NORTHING)
+                .reidentify(Citations.EPSG,    "8817")
+                .reidentify(Citations.GEOTIFF, "3091")
+                .rename(Citations.EPSG, "Northing at projection centre")
+                .rename(Citations.GEOTIFF, "ProjCenterNorthingGeoKey")
+                .rename(Citations.NETCDF));                                 // Delete the netCDF name.
+
+        PARAMETERS = builder
+                .addIdentifier(IDENTIFIER)
+                .addName("Hotine Oblique Mercator (variant B)")             // Starting from EPSG version 7.6
+                .addName("Rectified Skew Orthomorphic (RSO)")               // Alias
+                .addName("Oblique Mercator")                                // Prior to EPSG version 7.6
+                .addName      (Citations.OGC,     "Oblique_Mercator")
+                .addName      (Citations.ESRI,    "Hotine_Oblique_Mercator_Azimuth_Center")
+                .addName      (Citations.ESRI,    "Rectified_Skew_Orthomorphic_Center")
+                .addName      (Citations.S57,     "Oblique Mercator")
+                .addName      (Citations.S57,     "OME")
+                .addIdentifier(Citations.S57,     "9")
+                .addName      (Citations.GEOTIFF, "CT_ObliqueMercator")
+                .addIdentifier(Citations.GEOTIFF, "3")
+                .addName      (Citations.PROJ4,   "omerc")
+                .createGroupForMapProjection(
+                        LATITUDE_OF_CENTRE,
+                        LONGITUDE_OF_CENTRE,
+                        AZIMUTH,
+                        RECTIFIED_GRID_ANGLE,
+                        SCALE_FACTOR,
+                        EASTING_AT_CENTRE,
+                        NORTHING_AT_CENTRE);
+    }
+
+    /**
+     * Constructs a new provider.
+     */
+    public ObliqueMercatorCenter() {
+        super(PARAMETERS);
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorCenter.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorTwoPoints.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorTwoPoints.java?rev=1828642&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorTwoPoints.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorTwoPoints.java [UTF-8] Sun Apr  8 15:19:39 2018
@@ -0,0 +1,79 @@
+/*
+ * 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.internal.referencing.provider;
+
+import javax.xml.bind.annotation.XmlTransient;
+import org.opengis.parameter.ParameterDescriptor;
+import org.apache.sis.parameter.ParameterBuilder;
+import org.apache.sis.metadata.iso.citation.Citations;
+
+
+/**
+ * The provider for "<cite>Oblique Mercator</cite>" projection specified by two points on the central line.
+ * This is different than the classical {@linkplain ObliqueMercator Oblique Mercator}, which uses a central
+ * point and azimuth. This projection is specific to ESRI software.
+ *
+ * @author  Rueben Schulz (UBC)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+@XmlTransient
+public class ObliqueMercatorTwoPoints extends ObliqueMercator {
+    /**
+     * For compatibility with different versions during deserialization.
+     */
+    private static final long serialVersionUID = 7202109026784761711L;
+
+    /**
+     * The operation parameter descriptor for the latitude / longitude of one of the two points.
+     */
+    public static final ParameterDescriptor<Double> LAT_OF_1ST_POINT, LONG_OF_1ST_POINT,
+                                                    LAT_OF_2ND_POINT, LONG_OF_2ND_POINT;
+
+    static {
+        final ParameterBuilder builder = builder().setCodeSpace(Citations.ESRI, "ESRI");
+        LAT_OF_1ST_POINT  = createLatitude (builder.addName("Latitude_Of_1st_Point"), false);
+        LAT_OF_2ND_POINT  = createLatitude (builder.addName("Latitude_Of_2nd_Point"), false);
+        LONG_OF_1ST_POINT = createLongitude(builder.addName("Longitude_Of_1st_Point"));
+        LONG_OF_2ND_POINT = createLongitude(builder.addName("Longitude_Of_2nd_Point"));
+    }
+
+    /**
+     * Constructs a new provider for a projection with false easting/northing at coordinate system natural origin.
+     */
+    public ObliqueMercatorTwoPoints() {
+        this("Hotine_Oblique_Mercator_Two_Point_Natural_Origin", FALSE_EASTING, FALSE_NORTHING);
+    }
+
+    /**
+     * Constructs a new provider for a projection of the given name. Used for the two variants:
+     * with easting/northing values at coordinate system natural origin or at projection center.
+     */
+    ObliqueMercatorTwoPoints(final String name,
+                             final ParameterDescriptor<Double> easting,
+                             final ParameterDescriptor<Double> northing)
+    {
+        super(builder().setCodeSpace(Citations.ESRI, "ESRI").addName(name)
+                .createGroupForMapProjection(
+                        LAT_OF_1ST_POINT,    LONG_OF_1ST_POINT,
+                        LAT_OF_2ND_POINT,    LONG_OF_2ND_POINT,
+                        LATITUDE_OF_CENTRE,  SCALE_FACTOR,
+                        easting, northing));
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorTwoPoints.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorTwoPointsCenter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorTwoPointsCenter.java?rev=1828642&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorTwoPointsCenter.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorTwoPointsCenter.java [UTF-8] Sun Apr  8 15:19:39 2018
@@ -0,0 +1,48 @@
+/*
+ * 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.internal.referencing.provider;
+
+import javax.xml.bind.annotation.XmlTransient;
+
+
+/**
+ * The provider for "<cite>Oblique Mercator</cite>" projection specified by two points on the central line,
+ * with easting/northing specified at projection center instead than coordinate system natural origin.
+ * This projection is specific to ESRI software.
+ *
+ * @author  Rueben Schulz (UBC)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+@XmlTransient
+public final class ObliqueMercatorTwoPointsCenter extends ObliqueMercatorTwoPoints {
+    /**
+     * For compatibility with different versions during deserialization.
+     */
+    private static final long serialVersionUID = -4386924772861986539L;
+
+    /**
+     * Constructs a new provider.
+     */
+    public ObliqueMercatorTwoPointsCenter() {
+        super("Hotine_Oblique_Mercator_Two_Point_Center",
+              ObliqueMercatorCenter.EASTING_AT_CENTRE,
+              ObliqueMercatorCenter.NORTHING_AT_CENTRE);
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ObliqueMercatorTwoPointsCenter.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/package-info.java?rev=1828642&r1=1828641&r2=1828642&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/package-info.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/package-info.java [UTF-8] Sun Apr  8 15:19:39 2018
@@ -21,7 +21,7 @@
  * discussion of parameters.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.0
  *
  * @see org.apache.sis.referencing.operation.transform.MathTransformProvider
  *

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java?rev=1828642&r1=1828641&r2=1828642&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterValue.java [UTF-8] Sun Apr  8 15:19:39 2018
@@ -413,7 +413,7 @@ public class DefaultParameterValue<T> ex
      */
     @Override
     public double doubleValue(final Unit<?> unit) throws IllegalArgumentException, IllegalStateException {
-        final double value = doubleValue(); // Invoke first in case it throws an exception.
+        final double value = doubleValue();                 // Invoke first in case it throws an exception.
         return getConverterTo(unit).convert(value);
     }
 

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java?rev=1828642&r1=1828641&r2=1828642&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java [UTF-8] Sun Apr  8 15:19:39 2018
@@ -114,7 +114,7 @@ final class Initializer {
      * @param roles       parameters to look for <cite>central meridian</cite>, <cite>scale factor</cite>,
      *                    <cite>false easting</cite>, <cite>false northing</cite> and other values.
      * @param variant     convenience field left at the discretion of {@link NormalizedProjection} subclasses.
-     *                    Values equal to greater than 128 are special values recognized by this constructor
+     *                    Values equal or greater than 128 are special values recognized by this constructor
      *                    (see {@link #AUTHALIC_RADIUS}).
      */
     Initializer(final OperationMethod method, final Parameters parameters,
@@ -246,7 +246,7 @@ final class Initializer {
      */
     final double getAndStore(final ParameterDescriptor<? extends Number> descriptor) {
         if (descriptor == null) {
-            return 0;                           // Default value for all parameters except scale factor.
+            return 0;                           // Default value for most parameters except scale factor.
         }
         /*
          * Get the parameter value, or its default value if the parameter was not set. That default value
@@ -314,7 +314,7 @@ final class Initializer {
      * @return reciprocal squared of the radius of curvature of the ellipsoid
      *         perpendicular to the meridian at latitude φ.
      */
-    private DoubleDouble rν2(final double sinφ) {
+    final DoubleDouble rν2(final double sinφ) {
         if (DoubleDouble.DISABLED) {
             return verbatim(1 - eccentricitySquared.value * (sinφ*sinφ));
         }

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=1828642&r1=1828641&r2=1828642&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] Sun Apr  8 15:19:39 2018
@@ -73,6 +73,7 @@ import static org.apache.sis.internal.ut
  * @version 0.8
  *
  * @see TransverseMercator
+ * @see ObliqueMercator
  *
  * @since 0.6
  * @module

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueMercator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueMercator.java?rev=1828642&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueMercator.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueMercator.java [UTF-8] Sun Apr  8 15:19:39 2018
@@ -0,0 +1,418 @@
+/*
+ * 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 java.util.EnumMap;
+import java.awt.geom.AffineTransform;
+import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.parameter.InvalidParameterValueException;
+import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.referencing.operation.Matrix;
+import org.apache.sis.measure.Angle;
+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.referencing.operation.matrix.AffineTransforms2D;
+import org.apache.sis.referencing.operation.transform.ContextualParameters.MatrixRole;
+import org.apache.sis.internal.referencing.provider.ObliqueMercatorTwoPoints;
+import org.apache.sis.internal.referencing.Resources;
+import org.apache.sis.util.Workaround;
+
+import static java.lang.Math.*;
+import static org.apache.sis.math.MathFunctions.atanh;
+import static org.apache.sis.internal.referencing.provider.ObliqueMercatorCenter.*;
+
+
+/**
+ * <cite>Oblique Mercator</cite> projection (EPSG codes 9812, 9815).
+ * The Oblique Mercator projection can be seen as a generalization of {@link Mercator} and {@link TransverseMercator}
+ * projections when the central line is not along the equator or a meridian, respectively.
+ * This class covers also the <cite>Rectified Skew Orthomorphic</cite> (RSO) case.
+ *
+ * <p>There is different ways to specify the projection parameters:</p>
+ * <ul>
+ *   <li>Variant A (EPSG:9812) uses false easting/northing defined at the natural origin of the coordinate system.</li>
+ *   <li>Variant B (EPSG:9815) uses false easting/northing defined at the projection center.</li>
+ *   <li>ESRI "Two Points" variant defines the central line with two points instead than with an azimuth angle.</li>
+ * </ul>
+ *
+ * Azimuth values of 0 and ±90 degrees are allowed, but for such cases the {@link Mercator} and
+ * {@link TransverseMercator} projections should be preferred, both for performance and accuracy reasons.
+ *
+ * @author  Rueben Schulz (UBC)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @author  Rémi Maréchal (Geomatys)
+ * @version 1.0
+ *
+ * @see Mercator
+ * @see TransverseMercator
+ *
+ * @since 1.0
+ * @module
+ */
+public class ObliqueMercator extends ConformalProjection {
+    /**
+     * For compatibility with different versions during deserialization.
+     */
+    private static final long serialVersionUID = -5289761492678147674L;
+
+    /**
+     * Bitmask for projections having easting/northing values defined at projection center
+     * instead than at coordinate system natural origin.
+     * This bit is unset for <cite>Hotine Oblique Mercator (variant A)</cite> (EPSG:9812)
+     * and is set for        <cite>Hotine Oblique Mercator (variant B)</cite> (EPSG:9815).
+     */
+    private static final byte CENTER = 1;
+
+    /**
+     * Bitmask for projections having their central line defined by two points instead than an azimuth angle.
+     * The two points variants are used by ESRI.
+     */
+    private static final byte TWO_POINTS = 2;
+
+    /**
+     * Returns the type of the projection based on the name and identifier of the given operation method.
+     */
+    private static byte getVariant(final OperationMethod method) {
+        if (identMatch(method, "(?i).*\\bvariant\\s*A\\b.*", IDENTIFIER_A))        return 0;
+        if (identMatch(method, "(?i).*\\bvariant\\s*B\\b.*", IDENTIFIER  ))        return CENTER;
+        if (identMatch(method, "(?i).*\\bTwo[_\\s]Point[_\\s]Natural\\b.*", null)) return TWO_POINTS;
+        if (identMatch(method, "(?i).*\\bTwo[_\\s]Point[_\\s]Center\\b.*",  null)) return TWO_POINTS | CENTER;
+        return 0;       // Unidentified case, to be considered as variant A.
+    }
+
+    /**
+     * Constants used in the transformation.
+     * Those coefficients depend only on the latitude of center.
+     */
+    private final double B, H;
+
+    /**
+     * Sine and Cosine values for {@code γ0} (the angle between the meridian and central line
+     * at the intersection between the central line and the Earth equator on aposphere).
+     */
+    private final double sinγ0, cosγ0;
+
+    /**
+     * Creates an Oblique Mercator projection from the given parameters.
+     * The {@code method} argument can be the description of one of the following:
+     *
+     * <ul>
+     *   <li><cite>"Hotine Oblique Mercator (variant A)"</cite>.</li>
+     *   <li><cite>"Hotine Oblique Mercator (variant B)"</cite>.</li>
+     *   <li><cite>"Hotine Oblique Mercator two point center"</cite> (from ESRI).</li>
+     *   <li><cite>"Hotine Oblique Mercator two point natural origin"</cite> (from ESRI).</li>
+     *   <li><cite>"Rectified Skew Orthomorphic"</cite>.</li>
+     * </ul>
+     *
+     * @param  method      description of the projection parameters.
+     * @param  parameters  the parameter values of the projection to create.
+     */
+    public ObliqueMercator(final OperationMethod method, final Parameters parameters) {
+        this(initializer(method, parameters));
+    }
+
+    /**
+     * 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 static Initializer initializer(final OperationMethod method, final Parameters parameters) {
+        final byte variant = getVariant(method);
+        final boolean isCenter = (variant & CENTER) != 0;
+        final EnumMap<ParameterRole, ParameterDescriptor<Double>> roles = new EnumMap<>(ParameterRole.class);
+//      ParameterRole.CENTRAL_MERIDIAN intentionally excluded. It will be handled in the constructor instead.
+        roles.put(ParameterRole.SCALE_FACTOR,   SCALE_FACTOR);
+        roles.put(ParameterRole.FALSE_EASTING,  isCenter ? EASTING_AT_CENTRE  : FALSE_EASTING);
+        roles.put(ParameterRole.FALSE_NORTHING, isCenter ? NORTHING_AT_CENTRE : FALSE_NORTHING);
+        return new Initializer(method, parameters, roles, variant);
+    }
+
+    /**
+     * Work around for RFE #4093999 in Sun's bug database
+     * ("Relax constraint on placement of this()/super() call in constructors").
+     */
+    private ObliqueMercator(final Initializer initializer) {
+        super(initializer);
+        super.computeCoefficients();
+        final double λc = toRadians(initializer.getAndStore(LONGITUDE_OF_CENTRE));
+        final double φc = toRadians(initializer.getAndStore(LATITUDE_OF_CENTRE));
+        final double sinφ  = sin(φc);
+        final double cosφ  = cos(φc);
+        final double cos2φ = cosφ * cosφ;
+        /*
+         * From EPSG guidance notes:
+         *
+         *      B  =  √{1+[ℯ²cos⁴φc / (1 – ℯ²)]}
+         *      A  =  a⋅B⋅kc⋅√(1–ℯ²) / (1 – ℯ²sin²φc)
+         *      t₀ =  tan(π/4 – φc/2) / [(1 – ℯsinφc) / (1 + ℯ⋅sinφc)]^(e/2)
+         *      D  =  B⋅√(1–ℯ²) / [cos(φc)⋅√(1 – ℯ²sin²φc)]
+         *      F  =  D + √(D² – 1)⋅SIGN(φc)                        — if D<1 use D²=1
+         *      H  =  F⋅(t₀^B)
+         *      G  =  (F – 1/F) / 2
+         *      γ₀ =  asin[sin(αc) / D]
+         *      λ₀ =  λc – [asin(G⋅tan(γ₀))] / B
+         */
+        B = sqrt(1 + eccentricitySquared*(cos2φ*cos2φ) / (1 - eccentricitySquared));
+        final double Br  = B * initializer.axisLengthRatio().value;                     // Br = B⋅√(1 - ℯ²)
+        final double rν2 = initializer.rν2(sinφ).value;                                 // rν² = (1 - ℯ²⋅sin²φc)
+        final double A   = Br / rν2;                                                    // a and kc handled later.
+        final double D   = Br / (cosφ * sqrt(rν2));
+        final double F   = D + copySign(sqrt(Math.max(D*D - 1, 0)), φc);
+        H = F * pow(expOfNorthing(φc, eccentricity*sinφ), -B);                          // expOfNorthing(…) = 1/t
+        /*
+         * Next coefficients depend on whether the user specified azimuth or two points.
+         * Only the azimuth case is described in EPSG guidance notes.
+         */
+        double αc, γc, γ0, λ0;
+        if ((initializer.variant & TWO_POINTS) == 0) {
+            αc = initializer.getAndStore(AZIMUTH);                                      // Convert to radians later.
+            γc = toRadians(initializer.getAndStore(RECTIFIED_GRID_ANGLE, αc));
+            αc = toRadians(αc);
+            γ0 = asin(sin(αc) / D);
+            double Gt = (F - 1/F) * 0.5 * tan(γ0);                                      // G⋅tan(γ₀)
+            final double aGt = abs(Gt);
+            if (aGt > 1 && aGt <= 1 + ANGULAR_TOLERANCE) {                              // Accept asin(±1.000…1)
+                Gt = copySign(1, Gt);
+            }
+            λ0 = λc - asin(Gt) / B;
+            if (Double.isNaN(λ0)) {
+                final String name = AZIMUTH.getName().getCode();
+                final Angle value = new Angle(toDegrees(αc));
+                throw new InvalidParameterValueException(Resources.format(
+                        Resources.Keys.IllegalParameterValue_2, name, value), name, value);
+            }
+        } else {
+            /*
+             * From Snyder equations 9-16 to 9-24 (pages 72-73):
+             *
+             *      E  =  [D ± √(D² - 1)]⋅(t₀^B)        — =H in EPSG formulas
+             *      H  =  t₁^B                          — where t is the tsfn function with φ = φ₁
+             *      L  =  t₂^B                          — where t is the tsfn function with φ = φ₂
+             *      F  =  E/H                           — not the same F than from EPSG guidance notes.
+             *      G  = (F - 1/F) / 2
+             *      J  = (E² - L⋅H) / (E² + L⋅H)
+             *      P  = (L - H) / (L + H)
+             *      λ₀ = (λ₁ + λ₂)/2 + atan[J⋅tan(B⋅(λ₁ - λ₂)/2) / P] / B
+             *      γ₀ = atan(sin[B⋅(λ₁ - λ₀)] / G)     —  Snyder warns to not use atan2(…) here.
+             *      αc = asin(D⋅sin(γ₀))
+             */
+            final double φ1 = toRadians(initializer.getAndStore(ObliqueMercatorTwoPoints.LAT_OF_1ST_POINT));
+            final double φ2 = toRadians(initializer.getAndStore(ObliqueMercatorTwoPoints.LAT_OF_2ND_POINT));
+            final double λ1 = toRadians(initializer.getAndStore(ObliqueMercatorTwoPoints.LONG_OF_1ST_POINT));
+                  double λ2 = toRadians(initializer.getAndStore(ObliqueMercatorTwoPoints.LONG_OF_2ND_POINT));
+            final double H1 = pow(expOfNorthing(φ1, sin(eccentricity*φ1)), -B);
+            final double L  = pow(expOfNorthing(φ2, sin(eccentricity*φ2)), -B);
+            final double E2 = H * H;
+            final double LH = L * H1;
+            final double J  = (E2 - LH) / (E2 + LH);
+            final double P  = (L - H1) / (L + H1);
+            double Δλ = λ1 - λ2;
+            if (abs(Δλ) > PI) {
+                λ2 += copySign(2*Math.PI, Δλ);                      // Adjustment recommended by Snyder.
+                Δλ = λ1 - λ2;
+            }
+            λ0 = (λ1 + λ2)/2 - atan(J * tan(B*Δλ/2) / P) / B;
+            Δλ = λ1 - λ0;
+            if (abs(Δλ) > PI) {
+                λ0 += copySign(2*Math.PI, Δλ);                      // Adjustment recommended by Snyder.
+                Δλ = λ1 - λ0;
+            }
+            γ0 = atan(2 * sin(B * Δλ) / (H/H1 - H1/H));             // Do not use atan2(…) here.
+            αc = γc = asin(D * sin(γ0));
+        }
+        sinγ0 = sin(γ0);
+        cosγ0 = cos(γ0);
+        /*
+         * At this point, all parameters have been processed. Now process to their
+         * validation and the initialization of (de)normalize affine transforms.
+         */
+        getContextualParameters().getMatrix(MatrixRole.NORMALIZATION).convertAfter(0, null, -λ0);
+        final MatrixSIS denormalize = getContextualParameters().getMatrix(MatrixRole.DENORMALIZATION);
+        if (γc != 0) {
+            // TODO: This complicated code is only a workaround for the absence of "rotate" method in MatrixSIS.
+            // We should provide a "rotate" method in a future SIS version instead.
+            final AffineTransform tmp = AffineTransforms2D.castOrCopy(denormalize);
+            tmp.rotate(-γc);
+            final Matrix m = AffineTransforms2D.toMatrix(tmp);
+            for (int i=0; i<3; i++) {
+                for (int j=0; j<3; j++) {
+                    denormalize.setElement(j, i, m.getElement(j, i));
+                }
+            }
+        }
+        /*
+         * For variant B only, an additional (uc, vc) translation is applied here.
+         * Note that the general form of uc works even in  αc = 90°  special case,
+         * so we could omit the later. But we find a difference varying from zero
+         * to 0.2 metres between the two forms; we assume they are rounding errors.
+         *
+         *      vc = 0
+         *      uc = (A / B)⋅atan[√(D² – 1) / cos(αc)]⋅SIGN(φc)
+         *         = A⋅(λc – λ₀)  if  αc = 90°.
+         */
+        final double ArB = A / B;
+        if ((initializer.variant & CENTER) != 0) {
+            final double uc;
+            if (abs(abs(αc) - PI/2) < ANGULAR_TOLERANCE) {
+                uc = A * (λc - λ0);
+            } else {
+                uc = ArB * atan2(sqrt(D*D - 1), cos(αc));
+            }
+            denormalize.convertBefore(1, null, -copySign(uc, φc));
+        }
+        denormalize.convertBefore(0, ArB, null);
+        denormalize.convertBefore(1, ArB, null);
+    }
+
+    /**
+     * Returns the names of additional internal parameters which need to be taken in account when
+     * comparing two {@code ObliqueMercator} projections or formatting them in debug mode.
+     */
+    @Override
+    final String[] getInternalParameterNames() {
+        return new String[] {"B", "H", "γ₀"};
+    }
+
+    /**
+     * Returns the values of additional internal parameters which need to be taken in account when
+     * comparing two {@code ObliqueMercator} projections or formatting them in debug mode.
+     */
+    @Override
+    final double[] getInternalParameterValues() {
+        return new double[] {B, H, γ0()};
+    }
+
+    /**
+     * Returns the value used for computing {@link #sinγ0} and {@link #cosγ0}.
+     * We did not stored that value because it is not used often.
+     */
+    private double γ0() {
+        return (abs(sinγ0) < abs(cosγ0)) ? asin(sinγ0) : acos(cosγ0);
+    }
+
+    /**
+     * Converts the specified (λ,φ) coordinate (units in radians) and stores the result in {@code dstPts}.
+     * 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
+    {
+        final double λ = srcPts[srcOff];
+        final double φ = srcPts[srcOff + 1];
+        /*
+         * From EPSG guidance notes:
+         *
+         *      t  =  tan(π/4 – φ/2) / [(1 – ℯ⋅sinφ) / (1 + ℯ⋅sinφ)]^(ℯ/2)
+         *      Q  =  H / t^B                                                   — note: t = 1/expOfNorthing
+         *      S  =  (Q – 1/Q) / 2
+         *      T  =  (Q + 1/Q) / 2
+         *      V  =  sin(B⋅(λ – λ₀))
+         *      U  =  (–V⋅cos(γ₀) + S⋅sin(γ₀)) / T
+         *      v  =  A⋅ln[(1 – U) / (1 + U)] / (2⋅B)
+         *      u  =  A⋅atan{(S⋅cos(γ₀) + V⋅sin(γ₀)) / cos[B⋅(λ – λ₀)]} / B
+         *
+         * Code below computes (x,y) instead of (v,u) because A, B and λ₀ constants are factored out.
+         *
+         *      x  =  v⋅A/(2⋅B)
+         *      y  =  u/A
+         */
+        final double sinφ  = sin(φ);
+        final double Q     = H * pow(expOfNorthing(φ, eccentricity*sinφ), B);
+        final double iQ    = 1 / Q;
+        final double S     = (Q - iQ) * 0.5;
+        final double T     = (Q + iQ) * 0.5;
+        final double V     = sin(B * λ);
+        final double U     = (S*sinγ0 - V*cosγ0) / T;
+        final double dV_dλ = cos(B * λ);
+        if (dstPts != null) {
+            dstPts[dstOff  ] = atanh(-U);                           // = 0.5 * log((1-U) / (1+U));;
+            dstPts[dstOff+1] = atan2((S*cosγ0 + V*sinγ0), dV_dλ);
+        }
+        if (!derivate) {
+            return null;
+        }
+        /*                   ┌              ┐
+         *                   │ ∂x/∂λ, ∂x/∂φ │
+         * Jacobian        = │              │
+         *    (Proj(λ,φ))    │ ∂y/∂λ, ∂y/∂φ │
+         *                   └              ┘
+         */
+        final double dQ_dφ =  B * Q * dy_dφ(sinφ, cos(φ));
+        final double dU_dλ = -B * (cosγ0 / T) * dV_dλ;
+        final double dU_dφ = dQ_dφ * (sinγ0 + (sinγ0 + U)/(Q*Q) - U) / (2*T);
+        final double dS_dφ = 0.5*dQ_dφ * (1 + 1/(Q*Q));
+        final double M = (S*cosγ0 + V*sinγ0);
+        final double L = hypot(dV_dλ, M);
+        final double P = L + dV_dλ;
+        final double D = (P*P + M*M);
+        final double dy_dλ = 2 * B * (dV_dλ * (sinγ0*P + (V - sinγ0*M) * M/L) + V*M) / D;      // Y = atan2(M, T)
+        final double dy_dφ = 2 * cosγ0 * dS_dφ * (P - M*M/L) / D;
+        final double R = U*U - 1;
+        return new Matrix2(dU_dλ/R, dU_dφ/R,
+                           dy_dλ,   dy_dφ);
+    }
+
+    /**
+     * Converts 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
+    {
+        /*
+         * From EPSG guidance notes:
+         *
+         *      Q′ =  exp(-(B⋅v′/A))
+         *      S′ =  (Q′ – 1/Q′) / 2
+         *      T′ =  (Q′ + 1/Q′) / 2
+         *      V′ =  sin(Bu′/A)
+         *      U′ = (V′⋅cos(γ₀) + S′⋅sin(γ₀)) / T′
+         *      t′ = {H / √[(1+U′) / (1–U′)]} ^ (1/B)
+         *      χ  = π/2 – 2⋅atan(t′)
+         *      λ  = λ₀ – atan[(S′⋅cos(γ₀) – V′⋅sin(γ₀)) / cos(B⋅u′/A)] / B
+         *      φ  = χ + sin(2χ)⋅(e⁸⋅13/360     + e⁶⋅1/12   + e⁴⋅5/24 + e²⋅1/2)
+         *             + sin(4χ)⋅(e⁸⋅811/11520  + e⁶⋅29/240 + e⁴⋅7/48)
+         *             + sin(6χ)⋅(e⁸⋅81/1120    + e⁶⋅7/120)
+         *             + sin(8χ)⋅(e⁸⋅4279/161280)
+         *
+         * The calculation of χ and its use in serie expansion is performed by the φ(t) function.
+         */
+        final double x  = srcPts[srcOff  ];
+        final double y  = srcPts[srcOff+1];
+        final double Q  = exp(-x);
+        final double Qi = 1 / Q;
+        final double S  = (Q - Qi) * 0.5;
+        final double T  = (Q + Qi) * 0.5;
+        final double V  = sin(y);
+        final double U  = (V*cosγ0 + S*sinγ0) / T;
+        final double λ  = -atan2((S*cosγ0 - V*sinγ0), cos(y)) / B;
+        final double φ  = φ(pow(H / sqrt((1 + U) / (1 - U)), 1/B));
+        dstPts[dstOff  ] = λ;
+        dstPts[dstOff+1] = φ;
+    }
+}

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

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueMercator.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/ObliqueStereographic.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueStereographic.java?rev=1828642&r1=1828641&r2=1828642&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueStereographic.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueStereographic.java [UTF-8] Sun Apr  8 15:19:39 2018
@@ -192,7 +192,7 @@ public class ObliqueStereographic extend
      *
      * <p>We could report any of the internal parameters. But since they are all derived from φ₀ and
      * the {@linkplain #eccentricity eccentricity} and since the eccentricity is already reported by
-     * the super-class, we report only χ₀ is a representative of the internal parameters.</p>
+     * the super-class, we report only χ₀ as a representative of the internal parameters.</p>
      */
     @Override
     final String[] getInternalParameterNames() {

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java?rev=1828642&r1=1828641&r2=1828642&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java [UTF-8] Sun Apr  8 15:19:39 2018
@@ -62,6 +62,7 @@ import static org.apache.sis.internal.re
  * @version 0.8
  *
  * @see Mercator
+ * @see ObliqueMercator
  *
  * @since 0.6
  * @module

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java?rev=1828642&r1=1828641&r2=1828642&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java [UTF-8] Sun Apr  8 15:19:39 2018
@@ -36,7 +36,7 @@ import static org.junit.Assert.*;
  * Tests {@link Providers} and some consistency rules of all providers defined in this package.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.0
  * @since   0.6
  * @module
  */
@@ -92,6 +92,10 @@ public final strictfp class ProvidersTes
             AlbersEqualArea.class,
             TransverseMercator.class,
             TransverseMercatorSouth.class,
+            ObliqueMercator.class,
+            ObliqueMercatorCenter.class,
+            ObliqueMercatorTwoPoints.class,
+            ObliqueMercatorTwoPointsCenter.class,
             PolarStereographicA.class,
             PolarStereographicB.class,
             PolarStereographicC.class,

Added: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ObliqueMercatorTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ObliqueMercatorTest.java?rev=1828642&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ObliqueMercatorTest.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ObliqueMercatorTest.java [UTF-8] Sun Apr  8 15:19:39 2018
@@ -0,0 +1,115 @@
+/*
+ * 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.parameter.ParameterValueGroup;
+import org.opengis.referencing.datum.Ellipsoid;
+import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.internal.referencing.provider.ObliqueMercatorCenter;
+import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.parameter.Parameters;
+import org.apache.sis.test.DependsOn;
+import org.junit.*;
+
+import static java.lang.StrictMath.*;
+
+
+/**
+ * Tests the {@link ObliqueMercator} class.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @author  Rémi Maréchal (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+@DependsOn(MercatorTest.class)
+public final strictfp class ObliqueMercatorTest extends MapProjectionTestCase {
+    /**
+     * Returns a new instance of {@link ObliqueMercator}.
+     *
+     * @param  cx       the longitude of projection center.
+     * @param  cy       the latitude of projection center.
+     * @param  azimuth  the azimuth.
+     * @return newly created projection.
+     */
+    private static ObliqueMercator create(final double cx, final double cy, final double azimuth) {
+        final ObliqueMercatorCenter method = new ObliqueMercatorCenter();
+        final ParameterValueGroup values = method.getParameters().createValue();
+        final Ellipsoid ellipsoid = CommonCRS.WGS84.ellipsoid();
+        values.parameter("semi_major")         .setValue(ellipsoid.getSemiMajorAxis());
+        values.parameter("semi_minor")         .setValue(ellipsoid.getSemiMinorAxis());
+        values.parameter("azimuth")            .setValue(azimuth);
+        values.parameter("rectified_grid_angle").setValue(azimuth);
+        values.parameter("longitude_of_center").setValue(cx);
+        values.parameter("latitude_of_center") .setValue(cy);
+        return new ObliqueMercator(method, Parameters.castOrWrap(values));
+    }
+
+    // TODO: supprimer rectified_grid_angle. Nécessite de modifier Parameters.getValue(),
+    // ce qui peut rendre inutile Molodensky.optional(…).
+
+    /**
+     * Creates a projection and derivates a few points.
+     *
+     * @throws TransformException if an error occurred while converting a point.
+     */
+    @Test
+    public void testEllipsoidalDerivative() throws TransformException {
+        tolerance = 1E-9;
+        transform = create(0, 0, 0);
+        validate();
+
+        final double delta = toRadians(100.0 / 60) / 1852;      // Approximatively 100 metres.
+        derivativeDeltas = new double[] {delta, delta};
+        verifyDerivative(toRadians( 0), toRadians( 0));
+        verifyDerivative(toRadians(15), toRadians(30));
+        verifyDerivative(toRadians(15), toRadians(40));
+        verifyDerivative(toRadians(10), toRadians(60));
+    }
+
+    /**
+     * Tests with an azimuth of 90°.
+     *
+     * @throws TransformException if an error occurred while converting a point.
+     */
+    @Test
+    public void testAzimuth90() throws TransformException {
+        tolerance = 1E-9;
+        transform = create(10, 20, 90);
+        validate();
+
+        final double delta = toRadians(100.0 / 60) / 1852;      // Approximatively 100 metres.
+        derivativeDeltas = new double[] {delta, delta};
+        verifyInverse(0.15, 0.2);
+    }
+
+    /**
+     * Tests the <cite>"Hotine Oblique Mercator (variant B)"</cite> (EPSG:9815) projection method.
+     * 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#testHotineObliqueMercator()
+     */
+    @Test
+    public void runGeoapiTest() throws FactoryException, TransformException {
+        createGeoApiTest(new ObliqueMercatorCenter()).testHotineObliqueMercator();
+    }
+}

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

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

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=1828642&r1=1828641&r2=1828642&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] Sun Apr  8 15:19:39 2018
@@ -168,6 +168,7 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.operation.projection.ZonedGridSystemTest.class,
     org.apache.sis.referencing.operation.projection.PolarStereographicTest.class,
     org.apache.sis.referencing.operation.projection.ObliqueStereographicTest.class,
+    org.apache.sis.referencing.operation.projection.ObliqueMercatorTest.class,
     org.apache.sis.referencing.operation.projection.CylindricalEqualAreaTest.class,
     org.apache.sis.referencing.operation.projection.AlbersEqualAreaTest.class,
 



Mime
View raw message