This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 02d0e99b52ba03cad63fe867e74a65fe9c7d35eb
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Fri Jul 29 15:38:45 2022 +0200

    Add a "Pseudo sinusoidal" projection similar to Pseudo Mercator:
    use spherical formulas but apply the result on WGS84 ellipsoid.
    
    https://issues.apache.org/jira/browse/SIS-553
---
 .../referencing/provider/PseudoSinusoidal.java     | 59 ++++++++++++++++++++
 .../internal/referencing/provider/Sinusoidal.java  | 22 +++++---
 .../referencing/operation/projection/Mercator.java |  2 +-
 .../operation/projection/Sinusoidal.java           | 64 ++++++++++++++++++++--
 .../operation/projection/package-info.java         |  2 +-
 ...g.opengis.referencing.operation.OperationMethod |  1 +
 .../referencing/provider/ProvidersTest.java        |  3 +-
 .../apache/sis/internal/earth/netcdf/GCOM_C.java   | 11 +---
 8 files changed, 139 insertions(+), 25 deletions(-)

diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PseudoSinusoidal.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PseudoSinusoidal.java
new file mode 100644
index 0000000000..bcf34efe4b
--- /dev/null
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PseudoSinusoidal.java
@@ -0,0 +1,59 @@
+/*
+ * 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.ParameterDescriptorGroup;
+
+
+/**
+ * The provider for <cite>"Pseudo sinusoidal equal-area"</cite> projection.
+ * This is similar to Pseudo-Mercator: uses spherical formulas but apply the 
result on an ellipsoid.
+ * This is sometime used with remote sensing data.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.3
+ * @since   1.3
+ * @module
+ */
+@XmlTransient
+public final class PseudoSinusoidal extends Sinusoidal {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 6523477856049963388L;
+
+    /**
+     * Name of this projection.
+     */
+    public static final String NAME = "Pseudo sinusoidal";
+
+    /**
+     * The group of all parameters expected by this coordinate operation.
+     */
+    private static ParameterDescriptorGroup parameters() {
+        return builder().addName(NAME)
+                
.createGroupForMapProjection(AbstractMercator.toArray(PARAMETERS.descriptors(), 
0));
+    }
+
+    /**
+     * Constructs a new provider.
+     */
+    public PseudoSinusoidal() {
+        super(parameters());
+    }
+}
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Sinusoidal.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Sinusoidal.java
index 3c3dfff3fd..81a249ae55 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Sinusoidal.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Sinusoidal.java
@@ -32,7 +32,7 @@ import 
org.apache.sis.referencing.operation.projection.NormalizedProjection;
  * This projection method has no associated EPSG code.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.3
  *
  * @see <a 
href="https://en.wikipedia.org/wiki/Sinusoidal_projection";>Sinusoidal 
projection on Wikipedia</a>
  * @see <a 
href="http://geotiff.maptools.org/proj_list/sinusoidal.html";>GeoTIFF parameters 
for Sinusoidal</a>
@@ -41,17 +41,12 @@ import 
org.apache.sis.referencing.operation.projection.NormalizedProjection;
  * @module
  */
 @XmlTransient
-public final class Sinusoidal extends MapProjection {
+public class Sinusoidal extends MapProjection {
     /**
      * For cross-version compatibility.
      */
     private static final long serialVersionUID = -3236247448683326299L;
 
-    /**
-     * Name of this projection.
-     */
-    public static final String NAME = "Sinusoidal";
-
     /**
      * The operation parameter descriptor for the <cite>Longitude of 
projection center</cite> (λ₀) parameter value.
      * Valid values range is [-180 … 180]° and default value is 0°.
@@ -97,10 +92,10 @@ public final class Sinusoidal extends MapProjection {
     /**
      * The group of all parameters expected by this coordinate operation.
      */
-    private static final ParameterDescriptorGroup PARAMETERS;
+    static final ParameterDescriptorGroup PARAMETERS;
     static {
         PARAMETERS = builder().setCodeSpace(Citations.OGC, Constants.OGC)
-                .addName      (NAME)
+                .addName      ("Sinusoidal")
                 .addName      ("Sanson-Flamsteed")
                 .addName      (Citations.GEOTIFF,  "CT_Sinusoidal")
                 .addIdentifier(Citations.GEOTIFF,  "24")
@@ -115,6 +110,15 @@ public final class Sinusoidal extends MapProjection {
         super(PARAMETERS);
     }
 
+    /**
+     * Constructs a math transform provider from a set of parameters.
+     *
+     * @param  parameters  the set of parameters (never {@code null}).
+     */
+    Sinusoidal(final ParameterDescriptorGroup parameters) {
+        super(parameters);
+    }
+
     /**
      * {@inheritDoc}
      *
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
index 90097ef0a1..6a669f5edc 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
@@ -381,7 +381,7 @@ public class Mercator extends ConformalProjection {
     @Override
     public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
         NormalizedProjection kernel = this;
-subst:  if ((variant.spherical || eccentricity == 0) && getClass() == 
Mercator.class) {
+subst:  if (variant.spherical || (eccentricity == 0 && getClass() == 
Mercator.class)) {
             if (variant == Variant.AUXILIARY && eccentricity != 0) {
                 final int type = 
context.getValue(MercatorAuxiliarySphere.AUXILIARY_SPHERE_TYPE);
                 if (type == AuthalicMercator.TYPE) {
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Sinusoidal.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Sinusoidal.java
index 808d9e439d..70283f04e3 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Sinusoidal.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Sinusoidal.java
@@ -17,6 +17,7 @@
 package org.apache.sis.referencing.operation.projection;
 
 import java.util.EnumMap;
+import java.util.regex.Pattern;
 import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.referencing.operation.Matrix;
@@ -41,7 +42,7 @@ import static 
org.apache.sis.internal.referencing.provider.Sinusoidal.*;
  * </ul>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.3
  * @since   1.0
  * @module
  */
@@ -51,17 +52,61 @@ public class Sinusoidal extends MeridianArcBased {
      */
     private static final long serialVersionUID = 7908925241331303236L;
 
+    /**
+     * Variants of Sinusoidal projection. Those variants modify the way the 
projections are constructed
+     * (e.g. in the way parameters are interpreted), but formulas are 
basically the same after construction.
+     *
+     * <p>We do not provide such codes in public API because they duplicate 
the functionality of
+     * {@link OperationMethod} instances. We use them only for constructors 
convenience.</p>
+     */
+    private enum Variant implements ProjectionVariant {
+        // Declaration order matter. Patterns are matched in that order.
+
+        /** The <cite>"Pseudo sinusoidal equal-area"</cite> projection. */
+        PSEUDO(".*\\bPseudo.*");
+
+        /** Name pattern for this variant. */
+        private final Pattern operationName;
+
+        /** Creates a new enumeration value.  */
+        private Variant(final String operationName) {
+            this.operationName = Pattern.compile(operationName, 
Pattern.CASE_INSENSITIVE);
+        }
+
+        /** The expected name pattern of an operation method for this variant. 
*/
+        @Override public Pattern getOperationNamePattern() {
+            return operationName;
+        }
+
+        /** EPSG identifier of an operation method for this variant. */
+        @Override public String getIdentifier() {
+            return null;
+        }
+    }
+
+    /**
+     * The type of sinusoidal projection. Possible values are:
+     * <ul>
+     *   <li>{@link Variant#PSEUDO} if this projection is the "Pseudo 
sinusoidal equal-area" case.</li>
+     *   <li>{@code null} for the standard case.</li>
+     * </ul>
+     *
+     * Other cases may be added in the future.
+     */
+    private final Variant variant;
+
     /**
      * 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.8")
     private static Initializer initializer(final OperationMethod method, final 
Parameters parameters) {
+        final Variant variant = variant(method, Variant.values(), null);
         final EnumMap<ParameterRole, ParameterDescriptor<Double>> roles = new 
EnumMap<>(ParameterRole.class);
         roles.put(ParameterRole.CENTRAL_MERIDIAN, CENTRAL_MERIDIAN);
         roles.put(ParameterRole.FALSE_EASTING,    FALSE_EASTING);
         roles.put(ParameterRole.FALSE_NORTHING,   FALSE_NORTHING);
-        return new Initializer(method, parameters, roles, null);
+        return new Initializer(method, parameters, roles, variant);
     }
 
     /**
@@ -76,7 +121,17 @@ public class Sinusoidal extends MeridianArcBased {
      * @param parameters  the parameter values of the projection to create.
      */
     public Sinusoidal(final OperationMethod method, final Parameters 
parameters) {
-        super(initializer(method, 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 Sinusoidal(final Initializer initializer) {
+        super(initializer);
+        variant = (Variant) initializer.variant;
     }
 
     /**
@@ -84,6 +139,7 @@ public class Sinusoidal extends MeridianArcBased {
      */
     Sinusoidal(final Sinusoidal other) {
         super(other);
+        variant = other.variant;
     }
 
     /**
@@ -101,7 +157,7 @@ public class Sinusoidal extends MeridianArcBased {
     @Override
     public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
         Sinusoidal kernel = this;
-        if (eccentricity == 0 && getClass() == Sinusoidal.class) {
+        if ((eccentricity == 0 && getClass() == Sinusoidal.class) || variant 
== Variant.PSEUDO) {
             kernel = new Spherical(this);
         }
         return context.completeTransform(factory, kernel);
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java
index f2ad34531e..0fa929c114 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java
@@ -160,7 +160,7 @@
  * @author  Rémi Maréchal (Geomatys)
  * @author  Adrian Custer (Geomatys)
  * @author  Matthieu Bastianelli (Geomatys)
- * @version 1.2
+ * @version 1.3
  *
  * @see <a href="https://mathworld.wolfram.com/MapProjection.html";>Map 
projections on MathWorld</a>
  *
diff --git 
a/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
 
b/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
index 52f61edf69..a1ac1bfbf8 100644
--- 
a/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
+++ 
b/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
@@ -64,6 +64,7 @@ 
org.apache.sis.internal.referencing.provider.ModifiedAzimuthalEquidistant
 org.apache.sis.internal.referencing.provider.AzimuthalEquidistantSpherical
 org.apache.sis.internal.referencing.provider.ZonedTransverseMercator
 org.apache.sis.internal.referencing.provider.Sinusoidal
+org.apache.sis.internal.referencing.provider.PseudoSinusoidal
 org.apache.sis.internal.referencing.provider.Polyconic
 org.apache.sis.internal.referencing.provider.Mollweide
 org.apache.sis.internal.referencing.provider.SouthPoleRotation
diff --git 
a/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java
 
b/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java
index fb24e65e70..f13cda4040 100644
--- 
a/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java
+++ 
b/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java
@@ -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 1.2
+ * @version 1.3
  * @since   0.6
  * @module
  */
@@ -114,6 +114,7 @@ public final strictfp class ProvidersTest extends TestCase {
             ZonedTransverseMercator.class,
             SatelliteTracking.class,
             Sinusoidal.class,
+            PseudoSinusoidal.class,
             Polyconic.class,
             Mollweide.class,
             SouthPoleRotation.class,
diff --git 
a/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/GCOM_C.java
 
b/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/GCOM_C.java
index d21d264952..8ec93cd0b7 100644
--- 
a/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/GCOM_C.java
+++ 
b/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/GCOM_C.java
@@ -37,7 +37,7 @@ import org.apache.sis.internal.netcdf.Variable;
 import org.apache.sis.internal.netcdf.VariableRole;
 import org.apache.sis.internal.netcdf.Linearizer;
 import org.apache.sis.internal.netcdf.Node;
-import org.apache.sis.internal.referencing.provider.Sinusoidal;
+import org.apache.sis.internal.referencing.provider.PseudoSinusoidal;
 import org.apache.sis.internal.referencing.provider.Equirectangular;
 import org.apache.sis.internal.referencing.provider.PolarStereographicA;
 import org.apache.sis.referencing.operation.transform.TransferFunction;
@@ -361,13 +361,11 @@ public final class GCOM_C extends Convention {
         if (name == null) {
             return super.projection(node);
         }
-        Number radius = null;
         final String method;
         final int s = name.indexOf(' ');
         final String code = (s >= 0) ? name.substring(0, s) : name;
         if (code.equalsIgnoreCase("EQA")) {
-            method = Sinusoidal.NAME;
-            radius = 6371000;           // "Not specified (based on Authalic 
Sphere)" datum (EPSG:6035).
+            method = PseudoSinusoidal.NAME;
         } else if (code.equalsIgnoreCase("EQR")) {
             method = Equirectangular.NAME;
         } else if (code.equalsIgnoreCase("PS")) {
@@ -378,11 +376,6 @@ public final class GCOM_C extends Convention {
         final Map<String,Object> definition = new HashMap<>(4);
         definition.put(CF.GRID_MAPPING_NAME, method);
         definition.put(CONVERSION_NAME, name);
-        if (radius != null) {
-            definition.put(CF.SEMI_MAJOR_AXIS, radius);
-            definition.put(CF.SEMI_MINOR_AXIS, radius);
-            definition.put(ELLIPSOID_NAME, "Authalic sphere");
-        }
         return definition;
     }
 

Reply via email to