You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2023/01/18 17:46:05 UTC

[sis] 02/02: Try to resolve ambiguity between "Polar Stereographic (variant A)" and "(variant B)" in GeoTIFF files.

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 610221887288ac6ea4ffe10331b869658fb31c51
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Wed Jan 18 17:50:52 2023 +0100

    Try to resolve ambiguity between "Polar Stereographic (variant A)" and "(variant B)" in GeoTIFF files.
---
 .../org/apache/sis/storage/geotiff/CRSBuilder.java | 29 ++++++++-
 .../org/apache/sis/storage/geotiff/GeoCodes.java   | 15 ++++-
 .../apache/sis/storage/geotiff/GeoCodesTest.java   | 68 ++++++++++++++++++++++
 .../apache/sis/test/suite/GeoTiffTestSuite.java    |  1 +
 4 files changed, 109 insertions(+), 4 deletions(-)

diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
index 58b39d3af4..cd2a2b459c 100644
--- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
+++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
@@ -63,6 +63,7 @@ import org.apache.sis.internal.referencing.WKTKeywords;
 import org.apache.sis.internal.referencing.NilReferencingObject;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.referencing.ReferencingFactoryContainer;
+import org.apache.sis.internal.referencing.provider.PolarStereographicB;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.internal.util.Strings;
 import org.apache.sis.internal.util.Numerics;
@@ -88,7 +89,7 @@ import static org.apache.sis.util.Utilities.equalsIgnoreMetadata;
  *
  * @author  Rémi Maréchal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.4
  *
  * @see GeoKeys
  * @see GeoKeysLoader
@@ -1253,6 +1254,29 @@ final class CRSBuilder extends ReferencingFactoryContainer {
         verify(projection, angularUnit, linearUnit);
     }
 
+    /**
+     * Returns the code of the operation method to request.
+     * This method tries to resolves some ambiguities in the way operation methods are defined.
+     * For example there is an ambiguity between Polar Stereographic (variant A) and (variant B).
+     */
+    private String methodCode() {
+        final String code = getMandatoryString(GeoKeys.CoordTrans);
+        try {
+            switch (Integer.parseInt(code)) {
+                case GeoCodes.PolarStereographic: {
+                    if (geoKeys.containsKey(GeoCodes.StdParallel1)) {
+                        return Constants.EPSG + ':' + PolarStereographicB.IDENTIFIER;
+                    }
+                    break;
+                }
+                // More cases may be added in the future.
+            }
+        } catch (NumberFormatException e) {
+            return code;
+        }
+        return Constants.GEOTIFF + ':' + code;
+    }
+
     /**
      * Creates a defining conversion from an EPSG code or from user-defined parameters.
      *
@@ -1275,8 +1299,7 @@ final class CRSBuilder extends ReferencingFactoryContainer {
             }
             case GeoCodes.userDefined: {
                 final Unit<Angle>         azimuthUnit = createUnit(GeoKeys.AzimuthUnits, (short) 0, Angle.class, Units.DEGREE);
-                final String              type        = getMandatoryString(GeoKeys.CoordTrans);
-                final OperationMethod     method      = getCoordinateOperationFactory().getOperationMethod(Constants.GEOTIFF + ':' + type);
+                final OperationMethod     method      = getCoordinateOperationFactory().getOperationMethod(methodCode());
                 final ParameterValueGroup parameters  = method.getParameters().createValue();
                 final Map<Integer,String> toNames     = ReferencingUtilities.identifierToName(parameters.getDescriptor(), Citations.GEOTIFF);
                 final Map<Object,Number>  paramValues = new HashMap<>();    // Keys: [String|Short] instances for [known|unknown] parameters.
diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoCodes.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoCodes.java
index 79b7a003bd..43e188814e 100644
--- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoCodes.java
+++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoCodes.java
@@ -23,7 +23,7 @@ package org.apache.sis.storage.geotiff;
  *
  * @author  Rémi Maréchal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.4
  * @since   0.8
  */
 final class GeoCodes {
@@ -81,4 +81,17 @@ final class GeoCodes {
      */
     public static final short RasterPixelIsArea  = 1;
     public static final short RasterPixelIsPoint = 2;
+
+    /**
+     * The code for polar stereographic map projection.
+     * This is handled as a special case for distinguishing between variants.
+     */
+    public static final short PolarStereographic = 15;
+
+    /**
+     * The code for standard parallel map projection parameters.
+     * This is used as a sentinel value for distinguishing between
+     * different variants of a map projection.
+     */
+    public static final short StdParallel1 = 3078;
 }
diff --git a/storage/sis-geotiff/src/test/java/org/apache/sis/storage/geotiff/GeoCodesTest.java b/storage/sis-geotiff/src/test/java/org/apache/sis/storage/geotiff/GeoCodesTest.java
new file mode 100644
index 0000000000..c97dd04686
--- /dev/null
+++ b/storage/sis-geotiff/src/test/java/org/apache/sis/storage/geotiff/GeoCodesTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.storage.geotiff;
+
+import org.opengis.util.FactoryException;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.referencing.IdentifiedObject;
+import org.opengis.referencing.operation.CoordinateOperationFactory;
+import org.apache.sis.internal.system.DefaultFactories;
+import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Verifies some {@link GeoCodes} values.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.4
+ * @since   1.4
+ */
+public final class GeoCodesTest extends TestCase {
+    /**
+     * Verifies the constants relative to the polar stereographic projection.
+     *
+     * @throws FactoryException if the operation method is not found.
+     */
+    @Test
+    public void verifyPolarStereographic() throws FactoryException {
+        ParameterDescriptorGroup parameters = parameters("Polar Stereographic (Variant A)");
+        assertEquals(GeoCodes.PolarStereographic, parseCode(parameters));
+
+        parameters = parameters("Polar Stereographic (Variant B)");
+        assertEquals(GeoCodes.StdParallel1, parseCode(parameters.descriptor("Latitude of standard parallel")));
+    }
+
+    /**
+     * Returns the parameters for the operation method of the given name.
+     */
+    private static ParameterDescriptorGroup parameters(final String method) throws FactoryException {
+        final CoordinateOperationFactory factory = DefaultFactories.forBuildin(CoordinateOperationFactory.class);
+        return factory.getOperationMethod(method).getParameters();
+    }
+
+    /**
+     * Returns the GeoTIFF code declared in the given object.
+     */
+    private static int parseCode(final IdentifiedObject object) {
+        return Integer.parseInt(IdentifiedObjects.getIdentifier(object, Citations.GEOTIFF).getCode());
+    }
+}
diff --git a/storage/sis-geotiff/src/test/java/org/apache/sis/test/suite/GeoTiffTestSuite.java b/storage/sis-geotiff/src/test/java/org/apache/sis/test/suite/GeoTiffTestSuite.java
index 3432eaa123..7a84be4b32 100644
--- a/storage/sis-geotiff/src/test/java/org/apache/sis/test/suite/GeoTiffTestSuite.java
+++ b/storage/sis-geotiff/src/test/java/org/apache/sis/test/suite/GeoTiffTestSuite.java
@@ -35,6 +35,7 @@ import org.junit.BeforeClass;
     org.apache.sis.storage.geotiff.TypeTest.class,
     org.apache.sis.storage.geotiff.TagsTest.class,
     org.apache.sis.storage.geotiff.GeoKeysTest.class,
+    org.apache.sis.storage.geotiff.GeoCodesTest.class,
     org.apache.sis.storage.geotiff.CRSBuilderTest.class,
     org.apache.sis.storage.geotiff.XMLMetadataTest.class,
     org.apache.sis.storage.geotiff.SelfConsistencyTest.class