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
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new b2facbdd8f Assign GeoTIFF projection 15 to Polar Stereographic variant
B instead of A. It requires a special case for handling existing GeoTIFF files
with wrong parameters.
b2facbdd8f is described below
commit b2facbdd8f658ba112ecd17cf397f55ea5dd7396
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Thu Jan 19 18:50:31 2023 +0100
Assign GeoTIFF projection 15 to Polar Stereographic variant B instead of A.
It requires a special case for handling existing GeoTIFF files with wrong
parameters.
https://issues.apache.org/jira/browse/SIS-572
---
.../apache/sis/internal/referencing/Resources.java | 5 +++
.../sis/internal/referencing/Resources.properties | 1 +
.../internal/referencing/Resources_fr.properties | 1 +
.../referencing/provider/PolarStereographicA.java | 21 +++++-----
.../referencing/provider/PolarStereographicB.java | 26 ++++++++----
.../org/apache/sis/internal/geotiff/Resources.java | 6 +++
.../sis/internal/geotiff/Resources.properties | 1 +
.../sis/internal/geotiff/Resources_fr.properties | 1 +
.../org/apache/sis/storage/geotiff/CRSBuilder.java | 47 +++++++++++++++++++++-
.../org/apache/sis/storage/geotiff/GeoCodes.java | 7 ----
.../apache/sis/storage/geotiff/GeoCodesTest.java | 11 +++--
11 files changed, 98 insertions(+), 29 deletions(-)
diff --git
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
index 0b79c2e4be..6799a2c5ed 100644
---
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
+++
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
@@ -525,6 +525,11 @@ public final class Resources extends IndexedResourceBundle
{
*/
public static final short RecursiveCreateCallForCode_2 = 62;
+ /**
+ * The only valid entries are ±90° or equivalent in alternative angle
units.
+ */
+ public static final short RestrictedToPoleLatitudes = 104;
+
/**
* Matrix is singular.
*/
diff --git
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
index 8ad76eb3a2..8455a965a4 100644
---
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
+++
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
@@ -40,6 +40,7 @@ NotFormalProjectionParameter_1 = This parameter borrowed
from the \u201c{0}\u
NonConformAxes_2 = The coordinate system axes in the given
\u201c{0}\u201d description do not conform to the expected axes according
\u201c{1}\u201d authoritative description.
NonConformCRS_3 = The given \u201c{0}\u201d description does
not conform to the \u201c{1}\u201d authoritative description. \
Differences are found in
{2,choice,0#conversion method|1#conversion description|2#coordinate
system|3#datum|4#prime meridian|5#CRS}.
+RestrictedToPoleLatitudes = The only valid entries are \u00b190\u00b0
or equivalent in alternative angle units.
#
# Error messages (to be used in exceptions)
diff --git
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
index 9d82487e4a..6bb9bd8016 100644
---
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
+++
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
@@ -45,6 +45,7 @@ NotFormalProjectionParameter_1 = Ce param\u00e8tre
emprunt\u00e9 \u00e0 la pr
NonConformAxes_2 = Les axes du syst\u00e8me de
coordonn\u00e9es d\u00e9finis dans \u00ab\u202f{0}\u202f\u00bb ne sont pas
conformes aux axes attendus d\u2019apr\u00e8s la description officielle de
\u00ab\u202f{1}\u202f\u00bb.
NonConformCRS_3 = La description donn\u00e9e pour
\u00ab\u202f{0}\u202f\u00bb n\u2019est pas conforme \u00e0 la description
officielle de \u00ab\u202f{1}\u202f\u00bb. \
Des diff\u00e9rences ont \u00e9t\u00e9
trouv\u00e9es dans {2,choice,0#la m\u00e9thode de conversion|1#la description
de la conversion|2#le syst\u00e8me de coordonn\u00e9es|3#le
r\u00e9f\u00e9rentiel|4#le m\u00e9ridien d\u2019origine|5#le CRS}.
+RestrictedToPoleLatitudes = Les seules valeurs valides sont
\u00b190\u00b0 ou \u00e9quivalent dans d\u2019autres unit\u00e9s.
#
# Error messages (to be used in exceptions)
diff --git
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PolarStereographicA.java
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PolarStereographicA.java
index f6e680027e..d947a7d7b2 100644
---
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PolarStereographicA.java
+++
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PolarStereographicA.java
@@ -23,6 +23,7 @@ import org.opengis.parameter.ParameterDescriptorGroup;
import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.parameter.ParameterBuilder;
import org.apache.sis.internal.referencing.Formulas;
+import org.apache.sis.internal.referencing.Resources;
import org.apache.sis.internal.util.Constants;
import org.apache.sis.internal.util.Numerics;
import org.apache.sis.measure.Latitude;
@@ -30,14 +31,14 @@ import org.apache.sis.measure.Units;
/**
- * The provider for <cite>"Polar Stereographic (Variant A)"</cite> projection
(EPSG:9810).
+ * The provider for <cite>"Polar Stereographic (variant A)"</cite> projection
(EPSG:9810).
* Also used for the definition of Universal Polar Stereographic (UPS)
projection.
*
* @author Rueben Schulz (UBC)
* @author Martin Desruisseaux (Geomatys)
* @version 1.0
*
- * @see <a
href="http://geotiff.maptools.org/proj_list/polar_stereographic.html">GeoTIFF
parameters for Polar Stereographic</a>
+ * @see <a href="https://issues.apache.org/jira/browse/SIS-572">SIS-512</a>
*
* @since 0.6
*/
@@ -77,7 +78,7 @@ public final class PolarStereographicA extends
AbstractStereographic {
* <li>No default value</li>
* </ul>
*/
- public static final ParameterDescriptor<Double> LATITUDE_OF_ORIGIN =
LambertConformal1SP.LATITUDE_OF_ORIGIN;
+ public static final ParameterDescriptor<Double> LATITUDE_OF_ORIGIN;
/**
* The operation parameter descriptor for the <cite>Longitude of natural
origin</cite> (λ₀) parameter value.
@@ -119,18 +120,20 @@ public final class PolarStereographicA extends
AbstractStereographic {
static final ParameterDescriptorGroup PARAMETERS;
static {
final ParameterBuilder builder = builder();
+ LATITUDE_OF_ORIGIN = createMandatoryLatitude(builder
+ .addNamesAndIdentifiers(LambertConformal1SP.LATITUDE_OF_ORIGIN)
+
.setRemarks(Resources.formatInternational(Resources.Keys.RestrictedToPoleLatitudes)));
+
LONGITUDE_OF_ORIGIN = createLongitude(builder
.addNamesAndIdentifiers(ObliqueStereographic.LONGITUDE_OF_ORIGIN)
.reidentify(Citations.GEOTIFF, "3095")
.rename(Citations.GEOTIFF, "StraightVertPoleLong"));
PARAMETERS = builder
- .addIdentifier( IDENTIFIER)
- .addName( NAME)
- .addName(Citations.OGC, "Polar_Stereographic")
- .addName(Citations.GEOTIFF, "CT_PolarStereographic")
- .addName(Citations.PROJ4, "stere")
- .addIdentifier(Citations.GEOTIFF, "15")
+ .addIdentifier(IDENTIFIER)
+ .addName(NAME)
+ .addName(Citations.OGC, "Polar_Stereographic")
+ .addName(Citations.PROJ4, "stere")
.createGroupForMapProjection(
LATITUDE_OF_ORIGIN, // Can be only ±90°
LONGITUDE_OF_ORIGIN,
diff --git
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PolarStereographicB.java
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PolarStereographicB.java
index a1e94ce593..383bcb6875 100644
---
a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PolarStereographicB.java
+++
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PolarStereographicB.java
@@ -24,14 +24,18 @@ import org.apache.sis.parameter.ParameterBuilder;
/**
- * The provider for <cite>"Polar Stereographic (Variant B)"</cite> projection
(EPSG:9829).
+ * The provider for <cite>"Polar Stereographic (variant B)"</cite> projection
(EPSG:9829).
* This provider includes a <cite>"Latitude of standard parallel"</cite>
parameter and
* determines the hemisphere of the projection from that parameter value.
*
* @author Rueben Schulz (UBC)
* @author Martin Desruisseaux (Geomatys)
- * @version 1.0
- * @since 0.6
+ * @version 1.4
+ *
+ * @see <a
href="http://geotiff.maptools.org/proj_list/polar_stereographic.html">GeoTIFF
parameters for Polar Stereographic</a>
+ * @see <a href="https://issues.apache.org/jira/browse/SIS-572">SIS-512</a>
+ *
+ * @since 0.6
*/
@XmlTransient
public final class PolarStereographicB extends AbstractStereographic {
@@ -40,6 +44,11 @@ public final class PolarStereographicB extends
AbstractStereographic {
*/
private static final long serialVersionUID = 5188231050523249971L;
+ /**
+ * The EPSG name for this projection.
+ */
+ public static final String NAME = "Polar Stereographic (variant B)";
+
/**
* The EPSG identifier, to be preferred to the name when available.
*/
@@ -128,11 +137,12 @@ public final class PolarStereographicB extends
AbstractStereographic {
PARAMETERS = builder
.addIdentifier(IDENTIFIER)
- .addName("Polar Stereographic (variant B)")
- .addName(Citations.S57, "Polar stereographic")
- .addName(Citations.S57, "PST")
- .addIdentifier(Citations.S57, "11")
- .addNameAndIdentifier(Citations.PROJ4,
PolarStereographicA.PARAMETERS)
+ .addName(NAME)
+ .addName (Citations.S57, "Polar stereographic")
+ .addName (Citations.S57, "PST")
+ .addIdentifier(Citations.S57, "11")
+ .addName (Citations.GEOTIFF, "CT_PolarStereographic")
+ .addIdentifier(Citations.GEOTIFF, "15")
.createGroupForMapProjection(
STANDARD_PARALLEL,
LONGITUDE_OF_ORIGIN,
diff --git
a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.java
b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.java
index 5e1897f5e9..ac6264953b 100644
---
a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.java
+++
b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.java
@@ -151,6 +151,12 @@ public final class Resources extends IndexedResourceBundle
{
*/
public static final short RandomizedProcessApplied = 15;
+ /**
+ * Interpreted parameter “{0}” as “{1}” because the former is invalid
for the “{2}” map
+ * projection.
+ */
+ public static final short ReassignedParameter_3 = 32;
+
/**
* The “{0}” GeoTIFF file does not specify the values format.
*/
diff --git
a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.properties
b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.properties
index 3eb87da2a6..5c320a471e 100644
---
a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.properties
+++
b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources.properties
@@ -37,6 +37,7 @@ MissingGeoValue_1 = No value has been found
for the \u201c{0}\u2
MissingValue_2 = Cannot read TIFF image from
\u201c{0}\u201d because the \u201c{1}\u201d tag is missing.
NotTheEpsgValue_5 = The file defines \u201c{2}\u201d with
value {3}{4}, but that value should be {1}{4} according parent definition ({0}).
RandomizedProcessApplied = A randomized process such as error
diffusion has been applied to the image data.
+ReassignedParameter_3 = Interpreted parameter \u201c{0}\u201d as
\u201c{1}\u201d because the former is invalid for the \u201c{2}\u201d map
projection.
UndefinedDataFormat_1 = The \u201c{0}\u201d GeoTIFF file does not
specify the values format.
UnexpectedListOfValues_2 = A single value was expected for the
\u201c{0}\u201d key but {1} values have been found.
UnexpectedParameter_2 = The \u201c{1}\u201d parameter was not
expected for the \u201c{0}\u201d projection method.
diff --git
a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources_fr.properties
b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources_fr.properties
index f668385c12..3193a52fd0 100644
---
a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources_fr.properties
+++
b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/Resources_fr.properties
@@ -42,6 +42,7 @@ MissingGeoValue_1 = Aucune valeur n\u2019a
\u00e9t\u00e9 trouv\u
MissingValue_2 = Ne peut pas lire l\u2019image TIFF
provenant de \u00ab\u202f{0}\u202f\u00bb car le tag \u00ab\u202f{1}\u202f\u00bb
est manquant.
NotTheEpsgValue_5 = Le fichier d\u00e9finit
\u00ab\u202f{2}\u202f\u00bb avec la valeur {3}{4}, mais cette valeur devrait
\u00eatre {1}{4} pour \u00eatre en accord avec la d\u00e9finition du parent {0}.
RandomizedProcessApplied = Un processus randomis\u00e9 comme la
diffusion d\u2019erreur a \u00e9t\u00e9 appliqu\u00e9.
+ReassignedParameter_3 = Le param\u00e8tre
\u00ab\u202f{0}\u202f\u00bb a \u00e9t\u00e9 interpr\u00e9t\u00e9 comme
\u00ab\u202f{1}\u202f\u00bb parce que le premier est invalide pour la
projection \u00ab\u202f{2}\u202f\u00bb.
UndefinedDataFormat_1 = Le fichier GeoTIFF
\u00ab\u202f{0}\u202f\u00bb ne sp\u00e9cifie pas le format de ses valeurs.
UnexpectedListOfValues_2 = Une seule valeur \u00e9tait attendue pour
la cl\u00e9 \u00ab\u202f{0}\u202f\u00bb, mais on en a trouv\u00e9es {1}.
UnexpectedParameter_2 = Le param\u00e8tre
\u00ab\u202f{1}\u202f\u00bb est inattendu pour la m\u00e9thode de projection
\u00ab\u202f{0}\u202f\u00bb.
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 cd2a2b459c..2a700e0c6d 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.PolarStereographicA;
import org.apache.sis.internal.referencing.provider.PolarStereographicB;
import org.apache.sis.internal.util.Constants;
import org.apache.sis.internal.util.Strings;
@@ -76,6 +77,7 @@ import org.apache.sis.referencing.cs.AxesConvention;
import org.apache.sis.referencing.cs.CoordinateSystems;
import org.apache.sis.referencing.crs.DefaultGeographicCRS;
import org.apache.sis.io.TableAppender;
+import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.Characters;
@@ -381,6 +383,31 @@ final class CRSBuilder extends ReferencingFactoryContainer
{
warning(Resources.Keys.InvalidGeoValue_2, GeoKeys.name(key), value);
}
+ /**
+ * Moves the value of a projection parameter to a new GeoKey.
+ * This is used for handling erroneous map projection definitions.
+ * A warning is emitted.
+ *
+ * @param projection name of the map projection to report in the warning.
+ * @param oldKey old map projection key.
+ * @param newKey new map projection key, or 0 if none.
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/SIS-572">SIS-572</a>
+ */
+ private void moveParameter(final String projection, final short oldKey,
final short newKey) {
+ final Object value = geoKeys.remove(oldKey);
+ if (value != null) {
+ final Object name;
+ if (newKey != 0) {
+ geoKeys.put(newKey, value);
+ name = GeoKeys.name(newKey);
+ } else {
+ name = Vocabulary.formatInternational(Vocabulary.Keys.None);
+ }
+ warning(Resources.Keys.ReassignedParameter_3,
GeoKeys.name(oldKey), name, projection);
+ }
+ }
+
/**
* Verifies that a value found in the GeoTIFF file is approximately equal
to the expected value.
* This method is invoked when a CRS component is defined both explicitly
and by EPSG code,
@@ -1264,9 +1291,25 @@ final class CRSBuilder extends
ReferencingFactoryContainer {
try {
switch (Integer.parseInt(code)) {
case GeoCodes.PolarStereographic: {
- if (geoKeys.containsKey(GeoCodes.StdParallel1)) {
- return Constants.EPSG + ':' +
PolarStereographicB.IDENTIFIER;
+ /*
+ * Some GeoTIFF producers wrongly interpreted GeoTIFF
projection #15
+ * as "Polar Stereographic (Variant A)" while it should be
variant B.
+ * In those files, the "Latitude of true scale" parameter
is wrongly
+ * named "Latitude of natural origin" because the former
is a member
+ * of variant A while the latter is a member of variant B.
This code
+ * does the substitution.
+ *
+ * https://issues.apache.org/jira/browse/SIS-572
+ */
+ if (geoKeys.containsKey(GeoKeys.StdParallel1)) {
+ break; // Assume a valid map projection.
+ }
+ Object value = geoKeys.get(GeoKeys.ScaleAtNatOrigin);
+ if (value instanceof Number && ((Number)
value).doubleValue() != 1) {
+ return Constants.EPSG + ':' +
PolarStereographicA.IDENTIFIER;
}
+ moveParameter(PolarStereographicB.NAME,
GeoKeys.NatOriginLat, GeoKeys.StdParallel1);
+ moveParameter(PolarStereographicB.NAME,
GeoKeys.ScaleAtNatOrigin, (short) 0);
break;
}
// More cases may be added in the future.
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 43e188814e..9c977545ee 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
@@ -87,11 +87,4 @@ final class GeoCodes {
* 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
index c97dd04686..95cfdb46c5 100644
---
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
@@ -44,11 +44,16 @@ public final class GeoCodesTest extends TestCase {
*/
@Test
public void verifyPolarStereographic() throws FactoryException {
- ParameterDescriptorGroup parameters = parameters("Polar Stereographic
(Variant A)");
+ ParameterDescriptorGroup parameters = parameters("Polar Stereographic
(Variant B)");
assertEquals(GeoCodes.PolarStereographic, parseCode(parameters));
+ /*
+ * Following are testing `GeoKeys` rather than `GeoCodes`,
+ * but we do that as an additional consistency check.
+ */
+ ParameterDescriptorGroup alternative = parameters("Polar Stereographic
(Variant A)");
+ assertEquals(GeoKeys.StdParallel1, parseCode(parameters
.descriptor("Latitude of standard parallel")));
+ assertEquals(GeoKeys.NatOriginLat,
parseCode(alternative.descriptor("Latitude of natural origin")));
- parameters = parameters("Polar Stereographic (Variant B)");
- assertEquals(GeoCodes.StdParallel1,
parseCode(parameters.descriptor("Latitude of standard parallel")));
}
/**