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 2026/05/02 16:34:01 UTC
(sis) 01/02: `EngineeringDatum` created by `GridGeometry.createGridCRS(…)` should have unique name. This is needed for avoiding that SIS thinks that two engineering CRSs are convertible while actually they are from unrelated grids.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
commit 0df8a4ce59617c126bd8f50c36347dd388b92ffa
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Sat May 2 13:47:34 2026 +0200
`EngineeringDatum` created by `GridGeometry.createGridCRS(…)` should have unique name.
This is needed for avoiding that SIS thinks that two engineering CRSs are convertible
while actually they are from unrelated grids.
---
.../apache/sis/coverage/grid/GridCRSBuilder.java | 28 ++++++++++++----------
.../org/apache/sis/coverage/grid/GridGeometry.java | 18 +++++++++++---
.../main/org/apache/sis/referencing/CommonCRS.java | 27 +++++++++++----------
.../referencing/factory/IdentifiedObjectSet.java | 2 +-
.../main/org/apache/sis/storage/DataStore.java | 10 ++++----
.../org/apache/sis/util/resources/Vocabulary.java | 10 ++++++++
.../sis/util/resources/Vocabulary.properties | 6 +++--
.../sis/util/resources/Vocabulary_fr.properties | 6 +++--
8 files changed, 68 insertions(+), 39 deletions(-)
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCRSBuilder.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCRSBuilder.java
index 8244d295a7..1f96d230e7 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCRSBuilder.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCRSBuilder.java
@@ -38,16 +38,15 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.CompoundCRS;
import org.opengis.referencing.crs.DerivedCRS;
import org.opengis.referencing.crs.EngineeringCRS;
+import org.opengis.referencing.datum.EngineeringDatum;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.operation.OperationMethod;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.apache.sis.metadata.iso.extent.DefaultExtent;
-import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.parameter.ParameterBuilder;
import org.apache.sis.referencing.CommonCRS;
-import org.apache.sis.referencing.NamedIdentifier;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.cs.AbstractCS;
import org.apache.sis.referencing.cs.CoordinateSystems;
@@ -106,14 +105,6 @@ final class GridCRSBuilder extends ReferencingFactoryContainer {
*/
private static final InternationalString SCOPE = Resources.formatInternational(Resources.Keys.CrsToGridConversion);
- /**
- * Name of the coordinate systems created by this class.
- * The current version uses the same name for all coordinate systems.
- * We do not create different names for different combination of axes.
- */
- private static final NamedIdentifier CS_NAME = new NamedIdentifier(
- Citations.SIS, Vocabulary.formatInternational(Vocabulary.Keys.GridExtent));
-
/**
* The extent of the grid geometry, or {@code null} if none.
*/
@@ -207,7 +198,8 @@ final class GridCRSBuilder extends ReferencingFactoryContainer {
dimensionNames = new DimensionNameType[dimension];
}
final CoordinateSystem cs = createCS(dimension, dimensionNames, directions(dimensionNames), 1, true);
- return getCRSFactory().createEngineeringCRS(properties(name), CommonCRS.Engineering.GRID.datum(), cs);
+ final EngineeringDatum datum = getDatumFactory().createEngineeringDatum(properties(name));
+ return getCRSFactory().createEngineeringCRS(properties(datum.getName()), datum, cs);
}
/**
@@ -341,6 +333,15 @@ toGrid: try {
return "Grid based on " + name;
}
+ /**
+ * Returns the coordinate reference system that we use as a template for object names.
+ * This template uses generic terms such as "Cell indices" for the <abbr>CRS</abbr> name
+ * and "Unknown grid" for the datum.
+ */
+ private static EngineeringCRS template() {
+ return CommonCRS.Engineering.GRID.crs();
+ }
+
/**
* Creates the coordinate system for the derived or engineering <abbr>CRS</abbr> of a grid.
*
@@ -412,7 +413,7 @@ toGrid: try {
* coordinate system type in last resort.
*/
@SuppressWarnings("LocalVariableHidesMemberVariable")
- final Map<String,?> properties = properties(CS_NAME);
+ final Map<String,?> properties = properties(template().getCoordinateSystem().getName());
final CoordinateSystemAxis axis = axes[0];
switch (dimension) {
case 1: {
@@ -533,6 +534,7 @@ toGrid: try {
if (cs == null) {
return Optional.empty();
}
- return Optional.of(getCRSFactory().createEngineeringCRS(properties(cs.getName()), CommonCRS.Engineering.GRID.datum(), cs));
+ final EngineeringCRS template = template();
+ return Optional.of(getCRSFactory().createEngineeringCRS(properties(template.getName()), template.getDatum(), cs));
}
}
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
index b1fb40ac4f..d575d101e8 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
@@ -94,6 +94,7 @@ import static org.apache.sis.referencing.CRS.SeparationMode;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
import org.opengis.coordinate.CoordinateMetadata;
import org.opengis.coordinate.MismatchedDimensionException;
+import org.opengis.referencing.crs.EngineeringCRS;
/**
@@ -1891,10 +1892,19 @@ public class GridGeometry implements LenientComparable, Serializable {
* by the {@linkplain #getGridToCRS grid to <abbr>CRS</abbr>} transform,
* then this method creates {@link DerivedCRS} instances derived from the
* {@link #getCoordinateReferenceSystem() <abbr>CRS</abbr> of this grid}.
- * This strategy makes possible to use the returned <abbr>CRS</abbr> in a chain of operations
- * with (for example) {@link org.apache.sis.referencing.CRS#findOperation CRS.findOperation(…)}.
+ * This strategy makes possible to use the returned <abbr>CRS</abbr> in a chain of coordinate operations
+ * created by (for example) {@link org.apache.sis.referencing.CRS#findOperation CRS.findOperation(…)}.
* Otherwise (if there is no grid to <abbr>CRS</abbr> transform or no real-world <abbr>CRS</abbr>),
- * this method creates {@link org.opengis.referencing.crs.EngineeringCRS} instances.
+ * then this method creates an {@link org.opengis.referencing.crs.EngineeringCRS} instance
+ * associated to an engineering datum identified by the given {@code name}.
+ *
+ * <h4>Recommendation about the name</h4>
+ * The {@code name} argument is not very important when this method creates {@link DerivedCRS} instances,
+ * because the datum is inherited from the real world <abbr>CRS</abbr>. However, if this method fallbacks
+ * on {@link EngineeringCRS}, then the {@code name} argument become the only way to determine whether
+ * a coordinate operation is possible between two such engineering <abbr>CRS</abbr>s.
+ * It is recommended to use an identifier which is unique for the grid. It may be, for example, derived
+ * from the {@linkplain org.apache.sis.storage.GridCoverageResource#getIdentifier() resource identifier}.
*
* <p><b>Alternative:</b> if the target grid geometry is known in advance,
* {@link #createTransformTo(GridGeometry, PixelInCell)} can provide a
@@ -1906,6 +1916,8 @@ public class GridGeometry implements LenientComparable, Serializable {
* @throws InvalidGeodeticParameterException if characteristics of this grid geometry disallow this operation.
* @throws FactoryException if another error occurred during the use of a referencing factory.
*
+ * @see #createTransformTo(GridGeometry, PixelInCell)
+ *
* @since 1.7
*/
public CoordinateReferenceSystem createGridCRS(final Identifier name, final PixelInCell anchor) throws FactoryException {
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
index 6b09decb55..c72d9fce98 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
@@ -51,7 +51,6 @@ import org.opengis.referencing.datum.TemporalDatum;
import org.opengis.referencing.datum.VerticalDatum;
import org.opengis.referencing.datum.EngineeringDatum;
import org.opengis.metadata.extent.GeographicBoundingBox;
-import static org.opengis.referencing.IdentifiedObject.NAME_KEY;
import org.apache.sis.referencing.datum.DatumOrEnsemble;
import org.apache.sis.referencing.datum.DefaultVerticalDatum;
import org.apache.sis.referencing.datum.DefaultTemporalDatum;
@@ -1915,7 +1914,7 @@ public enum CommonCRS {
* </table></blockquote>
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.7
* @since 1.1
*/
public enum Engineering {
@@ -1967,7 +1966,7 @@ public enum CommonCRS {
* <tr><th>Unit:</th> <td>{@link Units#UNITY}</td></tr>
* </table></blockquote>
*/
- GRID(new DefaultEngineeringDatum(Map.of(EngineeringDatum.NAME_KEY, "Cell indices"))),
+ GRID(new DefaultEngineeringDatum(properties(Vocabulary.Keys.UnknownGrid))),
/**
* A single-dimensional coordinate system for time in seconds since an unknown epoch.
@@ -1984,7 +1983,7 @@ public enum CommonCRS {
*
* @see Temporal
*/
- TIME(new DefaultEngineeringDatum(Map.of(EngineeringDatum.NAME_KEY, "Time")));
+ TIME(new DefaultEngineeringDatum(properties(Vocabulary.Keys.Time)));
/**
* The datum.
@@ -2006,20 +2005,20 @@ public enum CommonCRS {
/**
* Returns the coordinate reference system associated to this engineering object.
*
- * @return the CRS associated to this enum.
+ * @return the CRS associated to this enumeration value.
*/
public synchronized EngineeringCRS crs() {
if (crs == null) {
final String x, y;
final AxisDirection dx, dy;
- final Map<String,Object> pcs = Map.of(CartesianCS.NAME_KEY, datum.getName());
- final Map<String,Object> properties = new HashMap<>(pcs);
CoordinateSystem cs = null;
+ Map<String, ?> properties = Map.of(CartesianCS.NAME_KEY, datum.getName());
+ Map<String, ?> csName = properties;
switch (this) {
case GEODISPLAY: {
x = "i"; dx = AxisDirection.EAST;
y = "j"; dy = AxisDirection.SOUTH;
- properties.put(EngineeringCRS.NAME_KEY, new NamedIdentifier(Citations.WMS, "1"));
+ properties = Map.of(EngineeringCRS.NAME_KEY, new NamedIdentifier(Citations.WMS, "1"));
break;
}
case DISPLAY: {
@@ -2030,19 +2029,21 @@ public enum CommonCRS {
case GRID: {
x = "i"; dx = AxisDirection.COLUMN_POSITIVE;
y = "j"; dy = AxisDirection.ROW_POSITIVE;
+ properties = properties(Vocabulary.Keys.CellIndices);
+ csName = properties;
break;
}
case TIME: {
x = y = "t";
dx = dy = AxisDirection.FUTURE;
- cs = new DefaultTimeCS(pcs, new DefaultCoordinateSystemAxis(
- Map.of(TimeCS.NAME_KEY, x), x, dx, Units.SECOND));
+ cs = new DefaultTimeCS(properties,
+ new DefaultCoordinateSystemAxis(Map.of(TimeCS.NAME_KEY, x), x, dx, Units.SECOND));
break;
}
default: throw new AssertionError(this);
}
if (cs == null) {
- cs = new DefaultCartesianCS(pcs,
+ cs = new DefaultCartesianCS(csName,
new DefaultCoordinateSystemAxis(Map.of(CartesianCS.NAME_KEY, x), x, dx, Units.PIXEL),
new DefaultCoordinateSystemAxis(Map.of(CartesianCS.NAME_KEY, y), y, dy, Units.PIXEL));
}
@@ -2054,7 +2055,7 @@ public enum CommonCRS {
/**
* Returns the datum associated to this engineering object.
*
- * @return the datum associated to this enum.
+ * @return the datum associated to this enumeration value.
*/
public EngineeringDatum datum() {
return datum;
@@ -2101,7 +2102,7 @@ public enum CommonCRS {
* Puts the given name in a map of properties to be given to object constructors.
*/
private static Map<String,?> properties(final InternationalString name) {
- return Map.of(NAME_KEY, new NamedIdentifier(null, name));
+ return Map.of(IdentifiedObject.NAME_KEY, new NamedIdentifier(null, name));
}
/**
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectSet.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectSet.java
index c3c4f5c59f..58280eeb33 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectSet.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/IdentifiedObjectSet.java
@@ -317,7 +317,7 @@ public class IdentifiedObjectSet<T extends IdentifiedObject> extends AbstractSet
* Returns {@code true} if this collection contains the specified {@code IdentifiedObject}.
*
* @param object the {@code IdentifiedObject} to test for presence in this set.
- * @return {@code true} if the given object is presents in this set.
+ * @return {@code true} if the given object is present in this set.
* @throws ClassCastException if the given object is non-null and not an instance of {@code <T>}.
*/
@Override
diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/DataStore.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/DataStore.java
index 5317bc2658..c0ab806cbb 100644
--- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/DataStore.java
+++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/DataStore.java
@@ -289,12 +289,12 @@ public abstract class DataStore implements Resource, Localized, AutoCloseable {
* findResource(getIdentifier().toString()) == this
* }
*
- * Note that this identifier is not guaranteed to be unique between different {@code DataStore} instances;
- * it only needs to be unique among the resources provided by this data store instance.
+ * Note that this identifier is not guaranteed to be unique between different {@code DataStore} instances.
+ * It only needs to be unique among the resources provided by this data store instance.
*
* <h4>Default implementation</h4>
- * <p>The default implementation searches for an identifier in the metadata,
- * at the location shown below, provided that conditions are met:</p>
+ * The default implementation searches for an identifier in the metadata,
+ * at the locations shown below, provided that the following conditions are met:
*
* <blockquote>
* <p><b>Path:</b> {@link Resource#getMetadata() metadata} /
@@ -302,7 +302,7 @@ public abstract class DataStore implements Resource, Localized, AutoCloseable {
* {@link org.apache.sis.metadata.iso.identification.AbstractIdentification#getCitation() citation} /
* {@link org.apache.sis.metadata.iso.citation.DefaultCitation#getIdentifiers() identifier}</p>
*
- * <p><b>Condition:</b> in default implementation, the identifier is presents only if exactly one
+ * <p><b>Condition:</b> in default implementation, the identifier is present only if exactly one
* {@code citation} is found at above path. If two or more {@code citation} instances are found,
* the identification is considered ambiguous and an empty value is returned.</p>
*
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
index 9fea4b3345..5400228dde 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
@@ -179,6 +179,11 @@ public class Vocabulary extends IndexedResourceBundle {
*/
public static final short CellGeometry = 23;
+ /**
+ * Cell indices
+ */
+ public static final short CellIndices = 286;
+
/**
* Cells
*/
@@ -1359,6 +1364,11 @@ public class Vocabulary extends IndexedResourceBundle {
*/
public static final short Units = 206;
+ /**
+ * Unknown grid
+ */
+ public static final short UnknownGrid = 287;
+
/**
* Unnamed
*/
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
index b7e9cbf0e0..28348fe187 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
@@ -40,6 +40,7 @@ CausedBy_1 = Caused by {0}
Cells = Cells
CellCount_1 = {0} cells
CellGeometry = Cell geometry
+CellIndices = Cell indices
CharacterEncoding = Character encoding
Characteristics = Characteristics
Class = Class
@@ -275,12 +276,13 @@ True = True
Type = Type
TypeOfResource = Type of resource
Units = Units
+UnavailableContent = Unavailable content.
+UnknownGrid = Unknown grid
Unnamed = Unnamed
Unnamed_1 = Unnamed #{0}
Unspecified = Unspecified
-Untitled = Untitled
-UnavailableContent = Unavailable content.
UnspecifiedDatumChange = Unspecified datum change
+Untitled = Untitled
UpperBound = Upper bound
UserHome = User home directory
Value = Value
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
index 98b196c92d..d72a1e502d 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
@@ -47,6 +47,7 @@ CausedBy_1 = Caus\u00e9e par {0}
Cells = Cellules
CellCount_1 = {0} cellules
CellGeometry = G\u00e9om\u00e9trie des cellules
+CellIndices = Indices des cellules
CharacterEncoding = Encodage des caract\u00e8res
Characteristics = Caract\u00e9ristiques
Class = Classe
@@ -282,12 +283,13 @@ True = Vrai
Type = Type
TypeOfResource = Type de ressource
Units = Unit\u00e9s
+UnavailableContent = Contenu non-disponible.
+UnknownGrid = Grille inconnue
Unnamed = Sans nom
Unnamed_1 = Sans nom \u2116{0}
Unspecified = Non-sp\u00e9cifi\u00e9
-Untitled = Sans titre
-UnavailableContent = Contenu non-disponible.
UnspecifiedDatumChange = Changement de r\u00e9f\u00e9rentiel non sp\u00e9cifi\u00e9
+Untitled = Sans titre
UpperBound = Limite haute
UserHome = R\u00e9pertoire de l\u2019utilisateur
Value = Valeur