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 2024/01/14 21:12:12 UTC
(sis) branch geoapi-4.0 updated: Better management of change of axis order: - Share cache, for avoiding to redo the same operation. - Make possible to get back the original definition. - Always sort time dimension last in "normalized" CS.
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 2a816a05e5 Better management of change of axis order: - Share cache, for avoiding to redo the same operation. - Make possible to get back the original definition. - Always sort time dimension last in "normalized" CS.
2a816a05e5 is described below
commit 2a816a05e50503c04669614ec3fcee6f34c45e49
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Sun Jan 14 21:46:03 2024 +0100
Better management of change of axis order:
- Share cache, for avoiding to redo the same operation.
- Make possible to get back the original definition.
- Always sort time dimension last in "normalized" CS.
---
.../apache/sis/coverage/grid/GridOrientation.java | 2 +-
.../apache/sis/referencing/crs/AbstractCRS.java | 116 +++++++------
.../sis/referencing/crs/AbstractDerivedCRS.java | 16 +-
.../sis/referencing/crs/DefaultCompoundCRS.java | 126 +++++++-------
.../sis/referencing/crs/DefaultDerivedCRS.java | 73 +++++---
.../sis/referencing/crs/DefaultEngineeringCRS.java | 22 ++-
.../sis/referencing/crs/DefaultGeocentricCRS.java | 29 ++--
.../sis/referencing/crs/DefaultGeodeticCRS.java | 20 ++-
.../sis/referencing/crs/DefaultGeographicCRS.java | 25 ++-
.../sis/referencing/crs/DefaultImageCRS.java | 19 ++-
.../sis/referencing/crs/DefaultParametricCRS.java | 21 ++-
.../sis/referencing/crs/DefaultProjectedCRS.java | 17 +-
.../sis/referencing/crs/DefaultTemporalCRS.java | 20 ++-
.../sis/referencing/crs/DefaultVerticalCRS.java | 17 +-
.../apache/sis/referencing/crs/package-info.java | 2 +-
.../org/apache/sis/referencing/cs/AbstractCS.java | 185 +++++++++++++--------
.../apache/sis/referencing/cs/AxesConvention.java | 14 +-
.../apache/sis/referencing/cs/DefaultAffineCS.java | 33 ++--
.../sis/referencing/cs/DefaultCartesianCS.java | 71 +++++---
.../sis/referencing/cs/DefaultCompoundCS.java | 44 ++++-
.../sis/referencing/cs/DefaultCylindricalCS.java | 36 ++--
.../sis/referencing/cs/DefaultEllipsoidalCS.java | 43 ++---
.../apache/sis/referencing/cs/DefaultLinearCS.java | 34 ++--
.../sis/referencing/cs/DefaultParametricCS.java | 34 ++--
.../apache/sis/referencing/cs/DefaultPolarCS.java | 34 ++--
.../sis/referencing/cs/DefaultSphericalCS.java | 41 ++---
.../apache/sis/referencing/cs/DefaultTimeCS.java | 34 ++--
.../sis/referencing/cs/DefaultUserDefinedCS.java | 34 ++--
.../sis/referencing/cs/DefaultVerticalCS.java | 34 ++--
.../org/apache/sis/referencing/cs/Normalizer.java | 16 +-
.../org/apache/sis/referencing/cs/SubTypes.java | 31 ++++
.../apache/sis/referencing/cs/package-info.java | 2 +-
.../sis/referencing/util/ReferencingUtilities.java | 28 ++++
.../sis/referencing/cs/DefaultPolarCSTest.java | 4 +-
34 files changed, 828 insertions(+), 449 deletions(-)
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridOrientation.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridOrientation.java
index fef4d1925c..4ef84ef025 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridOrientation.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridOrientation.java
@@ -231,7 +231,7 @@ public final class GridOrientation implements Serializable {
if (variant == crsVariant) {
return this;
}
- if (variant == AxesConvention.NORMALIZED) {
+ if (variant == AxesConvention.NORMALIZED || variant == AxesConvention.ORIGINAL) {
throw new IllegalArgumentException(Errors.format(Errors.Keys.UnsupportedArgumentValue_1, variant));
}
return new GridOrientation(flippedAxes, variant, canReorderGridAxis);
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
index 70292de25b..0dab42d7cc 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
@@ -18,7 +18,6 @@ package org.apache.sis.referencing.crs;
import java.util.Map;
import java.util.EnumMap;
-import java.util.HashMap;
import java.util.Objects;
import java.util.ConcurrentModificationException;
import jakarta.xml.bind.annotation.XmlType;
@@ -33,8 +32,6 @@ import org.opengis.referencing.crs.SingleCRS;
import org.opengis.referencing.crs.GeneralDerivedCRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.apache.sis.referencing.AbstractReferenceSystem;
-import org.apache.sis.referencing.IdentifiedObjects;
-import org.apache.sis.referencing.NamedIdentifier;
import org.apache.sis.referencing.util.ReferencingUtilities;
import org.apache.sis.metadata.internal.ImplementationHelper;
import org.apache.sis.referencing.cs.AxesConvention;
@@ -45,6 +42,7 @@ import org.apache.sis.io.wkt.Formatter;
import static org.apache.sis.util.Utilities.deepEquals;
import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
import static org.apache.sis.referencing.util.WKTUtilities.toFormattable;
+import org.apache.sis.util.resources.Errors;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
import org.opengis.metadata.Identifier;
@@ -82,7 +80,7 @@ import org.opengis.metadata.Identifier;
* without synchronization.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see AbstractCS
* @see org.apache.sis.referencing.datum.AbstractDatum
@@ -105,7 +103,7 @@ public class AbstractCRS extends AbstractReferenceSystem implements CoordinateRe
/**
* Serial number for inter-operability with different versions.
*/
- private static final long serialVersionUID = -7433284548909530047L;
+ private static final long serialVersionUID = -4925108294894867598L;
/**
* The coordinate system.
@@ -120,11 +118,22 @@ public class AbstractCRS extends AbstractReferenceSystem implements CoordinateRe
/**
* Other coordinate reference systems computed from this CRS by the application of an axes convention.
- * Created only when first needed.
+ * This map is shared by all instances derived from the same original {@code AbstractCRS} instance.
+ * It is serialized in order to preserve metadata about the original instance.
+ * All accesses to this map shall be synchronized on {@code forConvention}.
*
* @see #forConvention(AxesConvention)
*/
- private transient Map<AxesConvention,AbstractCRS> forConvention;
+ final EnumMap<AxesConvention,AbstractCRS> forConvention;
+
+ /**
+ * Creates the value to assign to the {@link #forConvention} map by constructors.
+ */
+ private EnumMap<AxesConvention,AbstractCRS> forConvention() {
+ var m = new EnumMap<AxesConvention,AbstractCRS>(AxesConvention.class);
+ m.put(AxesConvention.ORIGINAL, this);
+ return m;
+ }
/**
* Creates a coordinate reference system from the given properties and coordinate system.
@@ -164,10 +173,27 @@ public class AbstractCRS extends AbstractReferenceSystem implements CoordinateRe
* @param properties the properties to be given to the coordinate reference system.
* @param cs the coordinate system.
*/
+ @SuppressWarnings("this-escape")
public AbstractCRS(final Map<String,?> properties, final CoordinateSystem cs) {
super(properties);
ensureNonNull("cs", cs);
coordinateSystem = cs;
+ forConvention = forConvention();
+ }
+
+ /**
+ * Creates a new CRS derived from the specified one, but with different axis order or unit.
+ *
+ * @param original the original coordinate system from which to derive a new one.
+ * @param id new identifier for this CRS, or {@code null} if none.
+ * @param cs coordinate system with new axis order or units of measurement.
+ *
+ * @see #createSameType(CoordinateSystem)
+ */
+ AbstractCRS(final AbstractCRS original, final Identifier id, final CoordinateSystem cs) {
+ super(ReferencingUtilities.getPropertiesWithoutIdentifiers(original, (id == null) ? null : Map.of(IDENTIFIERS_KEY, id)));
+ coordinateSystem = cs;
+ forConvention = original.forConvention;
}
/**
@@ -181,9 +207,11 @@ public class AbstractCRS extends AbstractReferenceSystem implements CoordinateRe
*
* @see #castOrCopy(CoordinateReferenceSystem)
*/
+ @SuppressWarnings("this-escape")
protected AbstractCRS(final CoordinateReferenceSystem crs) {
super(crs);
coordinateSystem = crs.getCoordinateSystem();
+ forConvention = forConvention();
}
/**
@@ -277,14 +305,6 @@ public class AbstractCRS extends AbstractReferenceSystem implements CoordinateRe
return null;
}
- /**
- * Returns the existing CRS for the given convention, or {@code null} if none.
- */
- final AbstractCRS getCached(final AxesConvention convention) {
- assert Thread.holdsLock(this);
- return (forConvention != null) ? forConvention.get(convention) : null;
- }
-
/**
* Sets the CRS for the given axes convention.
*
@@ -292,15 +312,11 @@ public class AbstractCRS extends AbstractReferenceSystem implements CoordinateRe
* @return the cached CRS. May be different than the given {@code crs} if an existing instance has been found.
*/
final AbstractCRS setCached(final AxesConvention convention, AbstractCRS crs) {
- assert Thread.holdsLock(this);
- if (forConvention == null) {
- forConvention = new EnumMap<>(AxesConvention.class);
- } else if (crs != this) {
- for (final AbstractCRS existing : forConvention.values()) {
- if (crs.equals(existing)) {
- crs = existing;
- break;
- }
+ assert Thread.holdsLock(forConvention);
+ for (final AbstractCRS existing : forConvention.values()) {
+ if (crs.equals(existing, ComparisonMode.IGNORE_METADATA)) {
+ crs = existing;
+ break;
}
}
if (forConvention.put(convention, crs) != null) {
@@ -318,42 +334,39 @@ public class AbstractCRS extends AbstractReferenceSystem implements CoordinateRe
*
* @see AbstractCS#forConvention(AxesConvention)
*/
- public synchronized AbstractCRS forConvention(final AxesConvention convention) {
+ public AbstractCRS forConvention(final AxesConvention convention) {
ensureNonNull("convention", convention);
- AbstractCRS crs = getCached(convention);
- if (crs == null) {
- final AbstractCS cs = AbstractCS.castOrCopy(coordinateSystem);
- final AbstractCS candidate = cs.forConvention(convention);
- if (candidate == cs) {
- crs = this;
- } else {
- /*
- * Copy properties (scope, domain of validity) except the identifier (e.g. "EPSG:4326")
- * because the modified CRS is no longer conform to the authoritative definition.
- * If name contains a namespace (e.g. "EPSG"), remove that namespace for the same reason.
- * For example, "EPSG:WGS 84" will become simply "WGS 84".
- */
- Map<String,?> properties = IdentifiedObjects.getProperties(this, IDENTIFIERS_KEY);
- Identifier name = getName();
- if (name.getCodeSpace() != null || name.getAuthority() != null) {
- name = new NamedIdentifier(null, name.getCode());
- final Map<String,Object> copy = new HashMap<>(properties);
- copy.put(NAME_KEY, name);
- properties = copy;
+ synchronized (forConvention) {
+ AbstractCRS crs = forConvention.get(convention);
+ if (crs == null) {
+ final AbstractCRS original = forConvention.get(AxesConvention.ORIGINAL);
+ final AbstractCS cs = AbstractCS.castOrCopy(original.coordinateSystem);
+ final AbstractCS candidate = cs.forConvention(convention);
+ if (candidate.equals(cs, ComparisonMode.IGNORE_METADATA)) {
+ crs = original;
+ } else if (original != this && candidate.equals(coordinateSystem, ComparisonMode.IGNORE_METADATA)) {
+ crs = this;
+ } else try {
+ crs = createSameType(candidate);
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.CanNotCompute_1, convention), e);
}
- crs = createSameType(properties, candidate);
+ crs = setCached(convention, crs);
}
- crs = setCached(convention, crs);
+ return crs;
}
- return crs;
}
/**
* Returns a coordinate reference system of the same type as this CRS but with different axes.
* This method shall be overridden by all {@code AbstractCRS} subclasses in this package.
+ *
+ * @param cs the coordinate system with new axes.
+ * @return new CRS of the same type and datum than this CRS, but with the given axes.
+ * @throws ClassCastException if the type of the given coordinate system is invalid.
*/
- AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem cs) {
- return new AbstractCRS(properties, cs);
+ AbstractCRS createSameType(final CoordinateSystem cs) {
+ return new AbstractCRS(this, null, cs);
}
/**
@@ -525,9 +538,10 @@ public class AbstractCRS extends AbstractReferenceSystem implements CoordinateRe
*/
AbstractCRS() {
super(org.apache.sis.referencing.util.NilReferencingObject.INSTANCE);
+ forConvention = forConvention();
/*
* The coordinate system is mandatory for SIS working. We do not verify its presence here
- * because the verification would have to be done in an 'afterMarshal(…)' method and throwing
+ * because the verification would have to be done in an `afterMarshal(…)` method and throwing
* an exception in that method causes the whole unmarshalling to fail. But the SC_CRS adapter
* does some verifications.
*/
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractDerivedCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
index fb5a177d56..83c3e4942f 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
@@ -47,9 +47,7 @@ import static org.apache.sis.util.Utilities.deepEquals;
/**
- * A coordinate reference system that is defined by its coordinate
- * {@linkplain org.apache.sis.referencing.operation.DefaultConversion conversion} from another CRS
- * (not by a {@linkplain org.apache.sis.referencing.datum.AbstractDatum datum}).
+ * A coordinate reference system that is defined by its coordinate conversion from another CRS.
*
* @author Martin Desruisseaux (IRD, Geomatys)
*
@@ -108,6 +106,16 @@ abstract class AbstractDerivedCRS<C extends Conversion> extends AbstractCRS impl
conversionFromBase = createConversionFromBase(properties, baseCRS, conversion);
}
+ /**
+ * Creates a new CRS derived from the specified one, but with different axis order or unit.
+ * This is for implementing the {@link #createSameType(CoordinateSystem)} method only.
+ */
+ AbstractDerivedCRS(final AbstractDerivedCRS<C> original, final CoordinateSystem derivedCS) {
+ super(original, null, derivedCS);
+ final Conversion conversion = original.conversionFromBase;
+ conversionFromBase = createConversionFromBase(null, (SingleCRS) conversion.getSourceCRS(), conversion);
+ }
+
/**
* For {@link DefaultDerivedCRS#DefaultDerivedCRS(Map, SingleCRS, CoordinateReferenceSystem, OperationMethod,
* MathTransform, CoordinateSystem)} constructor only (<strong>not legal for {@code ProjectedCRS}</strong>).
@@ -150,7 +158,7 @@ abstract class AbstractDerivedCRS<C extends Conversion> extends AbstractCRS impl
* (through {@link DefaultConversion}) the {@link #getCoordinateSystem()} method on {@code this}.
* Consequently, this method shall be invoked only after the construction of this {@code AbstractDerivedCRS}
* instance is advanced enough for allowing the {@code getCoordinateSystem()} method to execute.
- * Subclasses may consider to make the {@code getCoordinateSystem()} method final for better guarantees.</p>
+ * Subclasses should make their {@code getCoordinateSystem()} method final for better guarantees.</p>
*/
private C createConversionFromBase(final Map<String,?> properties, final SingleCRS baseCRS, final Conversion conversion) {
MathTransformFactory factory = null;
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultCompoundCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
index 8e0d0f126e..d3b4d4945b 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
@@ -37,7 +37,6 @@ import org.opengis.referencing.crs.TemporalCRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.CoordinateSystem;
import org.apache.sis.referencing.AbstractReferenceSystem;
-import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.cs.AxesConvention;
import org.apache.sis.referencing.cs.DefaultCompoundCS;
import org.apache.sis.referencing.util.WKTKeywords;
@@ -112,7 +111,7 @@ import org.opengis.referencing.crs.ParametricCRS;
* SIS factories and static constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createCompoundCRS(String)
*
@@ -131,7 +130,8 @@ public class DefaultCompoundCRS extends AbstractCRS implements CompoundCRS {
* May be the same reference as {@link #singles}.
*
* <p><b>Consider this field as final!</b>
- * This field is modified only at construction and unmarshalling time by {@link #setComponents(List)}</p>
+ * This field is set at construction time by {@link #setComponents(Map, List)} and at
+ * unmarshalling time by {@link #setXMLComponents(CoordinateReferenceSystem[])}.</p>
*/
@SuppressWarnings("serial") // Most SIS implementations are serializable.
private List<? extends CoordinateReferenceSystem> components;
@@ -187,15 +187,16 @@ public class DefaultCompoundCRS extends AbstractCRS implements CompoundCRS {
*/
public DefaultCompoundCRS(final Map<String,?> properties, final CoordinateReferenceSystem... components) {
super(properties, createCoordinateSystem(properties, components));
- setComponents(Arrays.asList(components));
- /*
- * 'singles' is computed by the above method call. Now verify that we do not have an ellipsoidal
- * height with a geographic or projected CRS (see https://issues.apache.org/jira/browse/SIS-303).
- * Note that this is already be done if the given array does not contain nested CompoundCRS.
- */
- if (singles != this.components) {
- verify(properties, singles.toArray(SingleCRS[]::new));
- }
+ setComponents(properties, Arrays.asList(components));
+ }
+
+ /**
+ * Creates a new CRS derived from the specified one, but with different axis order or unit.
+ * This is for implementing the {@link #forConvention(AxesConvention)} method only.
+ */
+ private DefaultCompoundCRS(final DefaultCompoundCRS original, final CoordinateReferenceSystem[] components) {
+ super(original, null, createCoordinateSystem(null, components));
+ setComponents(null, Arrays.asList(components));
}
/**
@@ -276,7 +277,7 @@ public class DefaultCompoundCRS extends AbstractCRS implements CompoundCRS {
this.components = that.components;
this.singles = that.singles;
} else {
- setComponents(crs.getComponents());
+ setComponents(null, crs.getComponents());
}
}
@@ -337,13 +338,21 @@ public class DefaultCompoundCRS extends AbstractCRS implements CompoundCRS {
* Computes the {@link #components} and {@link #singles} fields from the given CRS list.
* If the two lists have the same content, then the two fields will reference the same list.
*
+ * @param properties properties of the compound CRS to construct, or {@code null} if unknown.
+ * @param elements components to set for the CRS.
+ *
* @see #getComponents()
*/
- private void setComponents(final List<? extends CoordinateReferenceSystem> crs) {
- if (setSingleComponents(crs)) {
+ private void setComponents(final Map<String,?> properties, final List<? extends CoordinateReferenceSystem> elements) {
+ if (setSingleComponents(elements)) {
components = singles; // Shares the same list.
} else {
- components = UnmodifiableArrayList.wrap(crs.toArray(CoordinateReferenceSystem[]::new));
+ components = UnmodifiableArrayList.wrap(elements.toArray(CoordinateReferenceSystem[]::new));
+ /*
+ * Verify that we do not have an ellipsoidal height with a geographic or projected CRS.
+ * https://issues.apache.org/jira/browse/SIS-303
+ */
+ verify(properties, singles.toArray(SingleCRS[]::new));
}
}
@@ -372,9 +381,9 @@ public class DefaultCompoundCRS extends AbstractCRS implements CompoundCRS {
*
* @see #getSingleComponents()
*/
- private boolean setSingleComponents(final List<? extends CoordinateReferenceSystem> crs) {
- final List<SingleCRS> flattened = new ArrayList<>(crs.size());
- final boolean identical = ReferencingUtilities.getSingleComponents(crs, flattened);
+ private boolean setSingleComponents(final List<? extends CoordinateReferenceSystem> elements) {
+ final List<SingleCRS> flattened = new ArrayList<>(elements.size());
+ final boolean identical = ReferencingUtilities.getSingleComponents(elements, flattened);
singles = UnmodifiableArrayList.wrap(flattened.toArray(SingleCRS[]::new));
return identical;
}
@@ -389,6 +398,7 @@ public class DefaultCompoundCRS extends AbstractCRS implements CompoundCRS {
@SuppressWarnings("unchecked")
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
+ @SuppressWarnings("LocalVariableHidesMemberVariable")
final List<? extends CoordinateReferenceSystem> components = this.components;
if (components instanceof CheckedContainer<?>) {
final Class<?> type = ((CheckedContainer<?>) components).getElementType();
@@ -471,49 +481,51 @@ public class DefaultCompoundCRS extends AbstractCRS implements CompoundCRS {
}
/**
- * {@inheritDoc}
- *
- * <p>If the given convention is {@link AxesConvention#DISPLAY_ORIENTED} or
- * {@link AxesConvention#NORMALIZED}, then this method will also reorder the components
- * with horizontal CRS (geodetic or projected) first, then vertical CRS, then temporal CRS.</p>
+ * Returns a compound CRS equivalent to this one but with axes rearranged according the given convention.
+ * This method first reorders the axes of each individual CRS {@linkplain #getComponents() component}.
+ * Then, if the given convention is {@link AxesConvention#DISPLAY_ORIENTED} or {@link AxesConvention#NORMALIZED},
+ * this method will also reorder the components with horizontal CRS (geodetic or projected) first,
+ * then vertical CRS, then temporal CRS.
*
* @return {@inheritDoc}
*/
@Override
- public synchronized DefaultCompoundCRS forConvention(final AxesConvention convention) {
+ public DefaultCompoundCRS forConvention(final AxesConvention convention) {
ArgumentChecks.ensureNonNull("convention", convention);
- DefaultCompoundCRS crs = (DefaultCompoundCRS) getCached(convention);
- if (crs == null) {
- crs = this;
- boolean changed = false;
- final boolean reorderCRS = convention.ordinal() <= AxesConvention.DISPLAY_ORIENTED.ordinal();
- final List<? extends CoordinateReferenceSystem> components = reorderCRS ? singles : this.components;
- final CoordinateReferenceSystem[] newComponents = new CoordinateReferenceSystem[components.size()];
- for (int i=0; i<newComponents.length; i++) {
- CoordinateReferenceSystem component = components.get(i);
- AbstractCRS m = castOrCopy(component);
- if (m != (m = m.forConvention(convention))) {
- component = m;
- changed = true;
+ synchronized (forConvention) {
+ DefaultCompoundCRS crs = (DefaultCompoundCRS) forConvention.get(convention);
+ if (crs == null) {
+ crs = (DefaultCompoundCRS) forConvention.get(AxesConvention.ORIGINAL);
+ boolean changed = false;
+ final boolean reorderCRS = convention.ordinal() <= AxesConvention.DISPLAY_ORIENTED.ordinal();
+ final List<? extends CoordinateReferenceSystem> elements = reorderCRS ? crs.singles : crs.components;
+ final CoordinateReferenceSystem[] newComponents = new CoordinateReferenceSystem[elements.size()];
+ for (int i=0; i<newComponents.length; i++) {
+ CoordinateReferenceSystem component = elements.get(i);
+ AbstractCRS m = castOrCopy(component);
+ if (m != (m = m.forConvention(convention))) {
+ component = m;
+ changed = true;
+ }
+ newComponents[i] = component;
}
- newComponents[i] = component;
- }
- if (changed) {
- if (reorderCRS) {
- Arrays.sort(newComponents, SubTypes.BY_TYPE); // This array typically has less than 4 elements.
+ if (changed) {
+ if (reorderCRS) {
+ Arrays.sort(newComponents, SubTypes.BY_TYPE); // This array typically has less than 4 elements.
+ }
+ crs = new DefaultCompoundCRS(crs, newComponents);
}
- crs = new DefaultCompoundCRS(IdentifiedObjects.getProperties(this, IDENTIFIERS_KEY), newComponents);
+ crs = (DefaultCompoundCRS) setCached(convention, crs);
}
- crs = (DefaultCompoundCRS) setCached(convention, crs);
+ return crs;
}
- return crs;
}
/**
* Should never be invoked since we override {@link AbstractCRS#forConvention(AxesConvention)}.
*/
@Override
- final AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem cs) {
+ final AbstractCRS createSameType(final CoordinateSystem cs) {
throw new AssertionError();
}
@@ -577,19 +589,19 @@ public class DefaultCompoundCRS extends AbstractCRS implements CompoundCRS {
protected String formatTo(final Formatter formatter) {
WKTUtilities.appendName(this, formatter, null);
final Convention convention = formatter.getConvention();
- final List<? extends CoordinateReferenceSystem> crs;
+ final List<? extends CoordinateReferenceSystem> elements;
final boolean isStandardCompliant;
final boolean isWKT1 = convention.majorVersion() == 1;
if (isWKT1 || convention == Convention.INTERNAL) {
- crs = getComponents();
+ elements = getComponents();
isStandardCompliant = true; // WKT 1 does not put any restriction.
} else {
- crs = getSingleComponents();
- isStandardCompliant = isStandardCompliant(crs);
+ elements = getSingleComponents();
+ isStandardCompliant = isStandardCompliant(elements);
}
- for (final CoordinateReferenceSystem element : crs) {
+ for (final CoordinateReferenceSystem component : elements) {
formatter.newLine();
- formatter.append(WKTUtilities.toFormattable(element));
+ formatter.append(WKTUtilities.toFormattable(component));
}
formatter.newLine(); // For writing the ID[…] element on its own line.
if (!isStandardCompliant) {
@@ -624,7 +636,7 @@ public class DefaultCompoundCRS extends AbstractCRS implements CompoundCRS {
singles = List.of();
/*
* At least one component CRS is mandatory for SIS working. We do not verify their presence here
- * because the verification would have to be done in an 'afterMarshal(…)' method and throwing an
+ * because the verification would have to be done in an `afterMarshal(…)` method and throwing an
* exception in that method causes the whole unmarshalling to fail. But the SC_CRS adapter does
* some verifications (indirectly, by testing for coordinate system existence).
*/
@@ -652,8 +664,8 @@ public class DefaultCompoundCRS extends AbstractCRS implements CompoundCRS {
/**
* Invoked by JAXB for setting the components of this compound CRS.
*/
- private void setXMLComponents(final CoordinateReferenceSystem[] crs) {
- components = setSingleComponents(Arrays.asList(crs)) ? singles : UnmodifiableArrayList.wrap(crs);
- setCoordinateSystem("coordinateSystem", createCoordinateSystem(null, crs));
+ private void setXMLComponents(final CoordinateReferenceSystem[] elements) {
+ components = setSingleComponents(Arrays.asList(elements)) ? singles : UnmodifiableArrayList.wrap(elements);
+ setCoordinateSystem("coordinateSystem", createCoordinateSystem(null, elements));
}
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
index feb4007d2e..1252bb3b01 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
@@ -94,7 +94,7 @@ import org.opengis.referencing.cs.ParametricCS;
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @author Johann Sorel (Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createDerivedCRS(String)
*
@@ -171,6 +171,14 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements
super(properties, baseCRS, conversion, derivedCS);
}
+ /**
+ * Creates a new CRS derived from the specified one, but with different axis order or unit.
+ * This is for implementing the {@link #createSameType(CoordinateSystem)} method only.
+ */
+ DefaultDerivedCRS(final DefaultDerivedCRS original, final CoordinateSystem derivedCS) {
+ super(original, derivedCS);
+ }
+
/**
* Creates a derived CRS from a math transform. The given {@code MathTransform} shall transform coordinate
* values specifically from the {@code baseCRS} to {@code this} CRS (optionally with an interpolation CRS);
@@ -468,11 +476,14 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements
/**
* Returns a coordinate reference system of the same type as this CRS but with different axes.
+ *
+ * @param cs the coordinate system with new axes.
+ * @return new CRS of the same type and datum than this CRS, but with the given axes.
+ * @throws ClassCastException if the type of the given coordinate system is invalid.
*/
@Override
- AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem derivedCS) {
- final Conversion conversionFromBase = super.getConversionFromBase();
- return new DefaultDerivedCRS(properties, (SingleCRS) conversionFromBase.getSourceCRS(), conversionFromBase, derivedCS);
+ AbstractCRS createSameType(final CoordinateSystem derivedCS) {
+ return new DefaultDerivedCRS(this, derivedCS);
}
/**
@@ -627,6 +638,11 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements
super(other);
}
+ /** Creates a new CRS derived from the specified one, but with different axis order or unit. */
+ private Geodetic(final Geodetic original, final CoordinateSystem derivedCS) {
+ super(original, derivedCS);
+ }
+
/** Creates a new geodetic CRS from the given properties. */
Geodetic(Map<String,?> properties, GeodeticCRS baseCRS, Conversion conversion, CoordinateSystem derivedCS) {
super(properties, baseCRS, conversion, derivedCS);
@@ -645,10 +661,8 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements
}
/** Returns a coordinate reference system of the same type as this CRS but with different axes. */
- @Override AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem derivedCS) {
- final Conversion conversionFromBase = getConversionFromBase();
- return new Geodetic(properties, (GeodeticCRS) conversionFromBase.getSourceCRS(),
- conversionFromBase, derivedCS);
+ @Override AbstractCRS createSameType(final CoordinateSystem derivedCS) {
+ return new Geodetic(this, derivedCS);
}
/** Returns the WKT keyword for this derived CRS type. */
@@ -675,6 +689,11 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements
super(other);
}
+ /** Creates a new CRS derived from the specified one, but with different axis order or unit. */
+ private Vertical(final Vertical original, final VerticalCS derivedCS) {
+ super(original, derivedCS);
+ }
+
/** Creates a new vertical CRS from the given properties. */
Vertical(Map<String,?> properties, VerticalCRS baseCRS, Conversion conversion, VerticalCS derivedCS) {
super(properties, baseCRS, conversion, derivedCS);
@@ -698,10 +717,8 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements
}
/** Returns a coordinate reference system of the same type as this CRS but with different axes. */
- @Override AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem derivedCS) {
- final Conversion conversionFromBase = getConversionFromBase();
- return new Vertical(properties, (VerticalCRS) conversionFromBase.getSourceCRS(),
- conversionFromBase, (VerticalCS) derivedCS);
+ @Override AbstractCRS createSameType(final CoordinateSystem derivedCS) {
+ return new Vertical(this, (VerticalCS) derivedCS);
}
/** Returns the WKT keyword for this derived CRS type. */
@@ -728,6 +745,11 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements
super(other);
}
+ /** Creates a new CRS derived from the specified one, but with different axis order or unit. */
+ private Temporal(final Temporal original, final TimeCS derivedCS) {
+ super(original, derivedCS);
+ }
+
/** Creates a new temporal CRS from the given properties. */
Temporal(Map<String,?> properties, TemporalCRS baseCRS, Conversion conversion, TimeCS derivedCS) {
super(properties, baseCRS, conversion, derivedCS);
@@ -751,10 +773,8 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements
}
/** Returns a coordinate reference system of the same type as this CRS but with different axes. */
- @Override AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem derivedCS) {
- final Conversion conversionFromBase = getConversionFromBase();
- return new Temporal(properties, (TemporalCRS) conversionFromBase.getSourceCRS(),
- conversionFromBase, (TimeCS) derivedCS);
+ @Override AbstractCRS createSameType(final CoordinateSystem derivedCS) {
+ return new Temporal(this, (TimeCS) derivedCS);
}
/** Returns the WKT keyword for this derived CRS type. */
@@ -781,6 +801,11 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements
super(other);
}
+ /** Creates a new CRS derived from the specified one, but with different axis order or unit. */
+ private Parametric(final Parametric original, final ParametricCS derivedCS) {
+ super(original, derivedCS);
+ }
+
/** Creates a new parametric CRS from the given properties. */
Parametric(Map<String,?> properties, ParametricCRS baseCRS, Conversion conversion, ParametricCS derivedCS) {
super(properties, baseCRS, conversion, derivedCS);
@@ -804,10 +829,8 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements
}
/** Returns a coordinate reference system of the same type as this CRS but with different axes. */
- @Override AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem derivedCS) {
- final Conversion conversionFromBase = getConversionFromBase();
- return new Parametric(properties, (ParametricCRS) conversionFromBase.getSourceCRS(),
- conversionFromBase, (ParametricCS) derivedCS);
+ @Override AbstractCRS createSameType(final CoordinateSystem derivedCS) {
+ return new Parametric(this, (ParametricCS) derivedCS);
}
/** Returns the WKT keyword for this derived CRS type. */
@@ -837,6 +860,11 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements
super(other);
}
+ /** Creates a new CRS derived from the specified one, but with different axis order or unit. */
+ private Engineering(final Engineering original, final CoordinateSystem derivedCS) {
+ super(original, derivedCS);
+ }
+
/** Creates a new engineering CRS from the given properties. */
Engineering(Map<String,?> properties, EngineeringCRS baseCRS, Conversion conversion, CoordinateSystem derivedCS) {
super(properties, baseCRS, conversion, derivedCS);
@@ -855,9 +883,8 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements
}
/** Returns a coordinate reference system of the same type as this CRS but with different axes. */
- @Override AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem derivedCS) {
- final Conversion conversionFromBase = getConversionFromBase();
- return new Engineering(properties, (EngineeringCRS) conversionFromBase.getSourceCRS(), conversionFromBase, derivedCS);
+ @Override AbstractCRS createSameType(final CoordinateSystem derivedCS) {
+ return new Engineering(this, derivedCS);
}
/** Returns the WKT keyword for this derived CRS type. */
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java
index fdd1f87bad..3467f5b3d9 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java
@@ -60,7 +60,7 @@ import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
* in the javadoc, this condition holds if all components were created using only SIS factories and static constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.datum.DefaultEngineeringDatum
* @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createEngineeringCRS(String)
@@ -138,14 +138,23 @@ public class DefaultEngineeringCRS extends AbstractCRS implements EngineeringCRS
* @see org.apache.sis.referencing.factory.GeodeticObjectFactory#createEngineeringCRS(Map, EngineeringDatum, CoordinateSystem)
*/
public DefaultEngineeringCRS(final Map<String,?> properties,
- final EngineeringDatum datum,
- final CoordinateSystem cs)
+ final EngineeringDatum datum,
+ final CoordinateSystem cs)
{
super(properties, cs);
ensureNonNull("datum", datum);
this.datum = datum;
}
+ /**
+ * Creates a new CRS derived from the specified one, but with different axis order or unit.
+ * This is for implementing the {@link #createSameType(CoordinateSystem)} method only.
+ */
+ private DefaultEngineeringCRS(final DefaultEngineeringCRS original, final CoordinateSystem cs) {
+ super(original, null, cs);
+ datum = original.datum;
+ }
+
/**
* Constructs a new coordinate reference system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -216,10 +225,13 @@ public class DefaultEngineeringCRS extends AbstractCRS implements EngineeringCRS
/**
* Returns a coordinate reference system of the same type as this CRS but with different axes.
+ *
+ * @param cs the coordinate system with new axes.
+ * @return new CRS of the same type and datum than this CRS, but with the given axes.
*/
@Override
- final AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem cs) {
- return new DefaultEngineeringCRS(properties, datum, cs);
+ final AbstractCRS createSameType(final CoordinateSystem cs) {
+ return new DefaultEngineeringCRS(this, cs);
}
/**
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java
index 45d8f08ef0..afa8eacab4 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java
@@ -69,7 +69,7 @@ import org.apache.sis.referencing.cs.AxesConvention;
* in the javadoc, this condition holds if all components were created using only SIS factories and static constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createGeocentricCRS(String)
*
@@ -82,17 +82,6 @@ public class DefaultGeocentricCRS extends DefaultGeodeticCRS implements Geocentr
*/
private static final long serialVersionUID = 6784642848287659827L;
- /**
- * For {@link #createSameType(Map, CoordinateSystem)} usage only.
- * This constructor does not verify the coordinate system type.
- */
- private DefaultGeocentricCRS(final Map<String,?> properties,
- final GeodeticDatum datum,
- final CoordinateSystem cs)
- {
- super(properties, datum, cs);
- }
-
/**
* Creates a coordinate reference system from the given properties, datum and coordinate system.
* The properties given in argument follow the same rules as for the
@@ -159,6 +148,15 @@ public class DefaultGeocentricCRS extends DefaultGeodeticCRS implements Geocentr
super(properties, datum, cs);
}
+ /**
+ * Creates a new CRS derived from the specified one, but with different axis order or unit.
+ * This is for implementing the {@link #createSameType(CoordinateSystem)} method only.
+ * This constructor does not verify the coordinate system type.
+ */
+ private DefaultGeocentricCRS(final DefaultGeocentricCRS original, final CoordinateSystem cs) {
+ super(original, null, cs);
+ }
+
/**
* Constructs a new coordinate reference system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -228,10 +226,13 @@ public class DefaultGeocentricCRS extends DefaultGeodeticCRS implements Geocentr
/**
* Returns a coordinate reference system of the same type as this CRS but with different axes.
+ *
+ * @param cs the coordinate system with new axes.
+ * @return new CRS of the same type and datum than this CRS, but with the given axes.
*/
@Override
- final AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem cs) {
- return new DefaultGeocentricCRS(properties, super.getDatum(), cs);
+ final AbstractCRS createSameType(final CoordinateSystem cs) {
+ return new DefaultGeocentricCRS(this, cs);
}
/**
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
index 858ebe70b4..d87eac98bf 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
@@ -44,6 +44,9 @@ import org.apache.sis.io.wkt.Formatter;
import org.apache.sis.measure.Units;
import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.metadata.Identifier;
+
/**
* A 2- or 3-dimensional coordinate reference system based on a geodetic datum.
@@ -104,6 +107,15 @@ class DefaultGeodeticCRS extends AbstractCRS implements GeodeticCRS { // If made
this.datum = datum;
}
+ /**
+ * Creates a new CRS derived from the specified one, but with different axis order or unit.
+ * This is for implementing the {@link #createSameType(CoordinateSystem)} method only.
+ */
+ DefaultGeodeticCRS(final DefaultGeodeticCRS original, final Identifier id, final CoordinateSystem cs) {
+ super(original, id, cs);
+ datum = original.datum;
+ }
+
/**
* Constructs a new coordinate reference system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -149,10 +161,14 @@ class DefaultGeodeticCRS extends AbstractCRS implements GeodeticCRS { // If made
/**
* Returns a coordinate reference system of the same type as this CRS but with different axes.
* This method shall be overridden by all {@code DefaultGeodeticCRS} subclasses in this package.
+ *
+ * @param cs the coordinate system with new axes.
+ * @return new CRS of the same type and datum than this CRS, but with the given axes.
+ * @throws ClassCastException if the type of the given coordinate system is invalid.
*/
@Override
- AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem cs) {
- return new DefaultGeodeticCRS(properties, datum, cs);
+ AbstractCRS createSameType(final CoordinateSystem cs) {
+ return new DefaultGeodeticCRS(this, null, cs);
}
/**
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeographicCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeographicCRS.java
index 111f571eeb..0d3d037918 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeographicCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeographicCRS.java
@@ -17,7 +17,6 @@
package org.apache.sis.referencing.crs;
import java.util.Map;
-import java.util.HashMap;
import java.util.Arrays;
import jakarta.xml.bind.annotation.XmlTransient;
import org.opengis.referencing.datum.GeodeticDatum;
@@ -85,7 +84,7 @@ import org.opengis.metadata.Identifier;
* in the javadoc, this condition holds if all components were created using only SIS factories and static constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createGeographicCRS(String)
*
@@ -157,6 +156,14 @@ public class DefaultGeographicCRS extends DefaultGeodeticCRS implements Geograph
super(properties, datum, cs);
}
+ /**
+ * Creates a new CRS derived from the specified one, but with different axis order or unit.
+ * This is for implementing the {@link #createSameType(CoordinateSystem)} method only.
+ */
+ private DefaultGeographicCRS(final DefaultGeographicCRS original, final Identifier id, final EllipsoidalCS cs) {
+ super(original, id, cs);
+ }
+
/**
* Constructs a new coordinate reference system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -242,9 +249,14 @@ public class DefaultGeographicCRS extends DefaultGeodeticCRS implements Geograph
* EPSG:4269 or EPSG:4326, then this method magically add the CRS:27, CRS:83 or CRS:84 identifier.
* Without this special case, the normal behavior would be no identifier. The expected behavior is
* that {@code CommonCRS.WGS84.normalizedGeographic()} returns a CRS having the "CRS:84" identifier.
+ *
+ * @param cs the coordinate system with new axes.
+ * @return new CRS of the same type and datum than this CRS, but with the given axes.
+ * @throws ClassCastException if the type of the given coordinate system is invalid.
*/
@Override
- final AbstractCRS createSameType(Map<String,?> properties, final CoordinateSystem cs) {
+ final AbstractCRS createSameType(final CoordinateSystem cs) {
+ Identifier id = null;
final CoordinateSystemAxis axis = cs.getAxis(0);
if (axis.getMinimumValue() == Longitude.MIN_VALUE &&
axis.getMaximumValue() == Longitude.MAX_VALUE) // For excluding the AxesConvention.POSITIVE_RANGE case.
@@ -253,16 +265,15 @@ public class DefaultGeographicCRS extends DefaultGeodeticCRS implements Geograph
if (EPSG.equals(identifier.getCodeSpace())) try {
final int i = Arrays.binarySearch(EPSG_CODES, Short.parseShort(identifier.getCode()));
if (i >= 0) {
- final Map<String,Object> c = new HashMap<>(properties);
- c.put(IDENTIFIERS_KEY, new ImmutableIdentifier(Citations.WMS, CRS, Short.toString(CRS_CODES[i])));
- properties = c;
+ id = new ImmutableIdentifier(Citations.WMS, CRS, Short.toString(CRS_CODES[i]));
+ break;
}
} catch (NumberFormatException e) {
// Okay to igore, because it is not the purpose of this method to disallow non-numeric codes.
}
}
}
- return new DefaultGeographicCRS(properties, super.getDatum(), (EllipsoidalCS) cs);
+ return new DefaultGeographicCRS(this, id, (EllipsoidalCS) cs);
}
/**
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultImageCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultImageCRS.java
index e7c8162843..4d880b390f 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultImageCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultImageCRS.java
@@ -51,7 +51,7 @@ import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
* in the javadoc, this condition holds if all components were created using only SIS factories and static constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.datum.DefaultImageDatum
* @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createImageCRS(String)
@@ -131,6 +131,15 @@ public class DefaultImageCRS extends AbstractCRS implements ImageCRS {
this.datum = datum;
}
+ /**
+ * Creates a new CRS derived from the specified one, but with different axis order or unit.
+ * This is for implementing the {@link #createSameType(CoordinateSystem)} method only.
+ */
+ private DefaultImageCRS(final DefaultImageCRS original, final AffineCS cs) {
+ super(original, null, cs);
+ datum = original.datum;
+ }
+
/**
* Constructs a new coordinate reference system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -211,10 +220,14 @@ public class DefaultImageCRS extends AbstractCRS implements ImageCRS {
/**
* Returns a coordinate reference system of the same type as this CRS but with different axes.
+ *
+ * @param cs the coordinate system with new axes.
+ * @return new CRS of the same type and datum than this CRS, but with the given axes.
+ * @throws ClassCastException if the type of the given coordinate system is invalid.
*/
@Override
- final AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem cs) {
- return new DefaultImageCRS(properties, datum, (AffineCS) cs);
+ final AbstractCRS createSameType(final CoordinateSystem cs) {
+ return new DefaultImageCRS(this, (AffineCS) cs);
}
/**
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultParametricCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultParametricCRS.java
index 13b595e8d3..c53b99bd4a 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultParametricCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultParametricCRS.java
@@ -51,7 +51,7 @@ import org.opengis.referencing.datum.ParametricDatum;
* in the javadoc, this condition holds if all components were created using only SIS factories and static constants.
*
* @author Johann Sorel (Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.datum.DefaultParametricDatum
* @see org.apache.sis.referencing.cs.DefaultParametricCS
@@ -124,13 +124,22 @@ public class DefaultParametricCRS extends AbstractCRS implements ParametricCRS {
*/
public DefaultParametricCRS(final Map<String,?> properties,
final ParametricDatum datum,
- final ParametricCS cs)
+ final ParametricCS cs)
{
super(properties, cs);
ensureNonNull("datum", datum);
this.datum = datum;
}
+ /**
+ * Creates a new CRS derived from the specified one, but with different axis order or unit.
+ * This is for implementing the {@link #createSameType(CoordinateSystem)} method only.
+ */
+ private DefaultParametricCRS(final DefaultParametricCRS original, final ParametricCS cs) {
+ super(original, null, cs);
+ datum = original.datum;
+ }
+
/**
* Constructs a new coordinate reference system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -212,10 +221,14 @@ public class DefaultParametricCRS extends AbstractCRS implements ParametricCRS {
/**
* Returns a coordinate reference system of the same type as this CRS but with different axes.
+ *
+ * @param cs the coordinate system with new axes.
+ * @return new CRS of the same type and datum than this CRS, but with the given axes.
+ * @throws ClassCastException if the type of the given coordinate system is invalid.
*/
@Override
- final AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem cs) {
- return new DefaultParametricCRS(properties, datum, (ParametricCS) cs);
+ final AbstractCRS createSameType(final CoordinateSystem cs) {
+ return new DefaultParametricCRS(this, (ParametricCS) cs);
}
/**
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultProjectedCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
index fe05bf66ff..870c17a9ae 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
@@ -59,7 +59,7 @@ import static org.apache.sis.referencing.util.WKTUtilities.toFormattable;
* in the javadoc, this condition holds if all components were created using only SIS factories and static constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createProjectedCRS(String)
*
@@ -135,6 +135,14 @@ public class DefaultProjectedCRS extends AbstractDerivedCRS<Projection> implemen
super(properties, baseCRS, conversion, derivedCS);
}
+ /**
+ * Creates a new CRS derived from the specified one, but with different axis order or unit.
+ * This is for implementing the {@link #createSameType(CoordinateSystem)} method only.
+ */
+ private DefaultProjectedCRS(final DefaultProjectedCRS original, final CartesianCS derivedCS) {
+ super(original, derivedCS);
+ }
+
/**
* Constructs a new coordinate reference system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -261,11 +269,12 @@ public class DefaultProjectedCRS extends AbstractDerivedCRS<Projection> implemen
/**
* Returns a coordinate reference system of the same type as this CRS but with different axes.
+ *
+ * @throws ClassCastException if the type of the given coordinate system is invalid.
*/
@Override
- final AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem cs) {
- final Projection conversion = super.getConversionFromBase();
- return new DefaultProjectedCRS(properties, conversion.getSourceCRS(), conversion, (CartesianCS) cs);
+ final AbstractCRS createSameType(final CoordinateSystem cs) {
+ return new DefaultProjectedCRS(this, (CartesianCS) cs);
}
/**
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
index cbc9d8c614..3be96cf380 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
@@ -65,7 +65,7 @@ import static org.apache.sis.util.internal.StandardDateFormat.MILLIS_PER_SECOND;
* in the javadoc, this condition holds if all components were created using only SIS factories and static constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.datum.DefaultTemporalDatum
* @see org.apache.sis.referencing.cs.DefaultTimeCS
@@ -152,6 +152,7 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS {
*
* @see org.apache.sis.referencing.factory.GeodeticObjectFactory#createTemporalCRS(Map, TemporalDatum, TimeCS)
*/
+ @SuppressWarnings("this-escape")
public DefaultTemporalCRS(final Map<String,?> properties,
final TemporalDatum datum,
final TimeCS cs)
@@ -162,6 +163,16 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS {
initializeConverter();
}
+ /**
+ * Creates a new CRS derived from the specified one, but with different axis order or unit.
+ * This is for implementing the {@link #createSameType(CoordinateSystem)} method only.
+ */
+ private DefaultTemporalCRS(final DefaultTemporalCRS original, final TimeCS cs) {
+ super(original, null, cs);
+ datum = original.datum;
+ initializeConverter();
+ }
+
/**
* Constructs a new coordinate reference system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -173,6 +184,7 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS {
*
* @see #castOrCopy(TemporalCRS)
*/
+ @SuppressWarnings("this-escape")
protected DefaultTemporalCRS(final TemporalCRS crs) {
super(crs);
datum = crs.getDatum();
@@ -296,10 +308,12 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS {
/**
* Returns a coordinate reference system of the same type as this CRS but with different axes.
+ *
+ * @throws ClassCastException if the type of the given coordinate system is invalid.
*/
@Override
- final AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem cs) {
- return new DefaultTemporalCRS(properties, datum, (TimeCS) cs);
+ final AbstractCRS createSameType(final CoordinateSystem cs) {
+ return new DefaultTemporalCRS(this, (TimeCS) cs);
}
/**
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultVerticalCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultVerticalCRS.java
index e19f5bb66d..5554f4e16c 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultVerticalCRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultVerticalCRS.java
@@ -49,7 +49,7 @@ import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
* in the javadoc, this condition holds if all components were created using only SIS factories and static constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.datum.DefaultVerticalDatum
* @see org.apache.sis.referencing.cs.DefaultVerticalCS
@@ -129,6 +129,15 @@ public class DefaultVerticalCRS extends AbstractCRS implements VerticalCRS {
this.datum = datum;
}
+ /**
+ * Creates a new CRS derived from the specified one, but with different axis order or unit.
+ * This is for implementing the {@link #createSameType(CoordinateSystem)} method only.
+ */
+ private DefaultVerticalCRS(final DefaultVerticalCRS original, final VerticalCS cs) {
+ super(original, null, cs);
+ datum = original.datum;
+ }
+
/**
* Constructs a new coordinate reference system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -210,10 +219,12 @@ public class DefaultVerticalCRS extends AbstractCRS implements VerticalCRS {
/**
* Returns a coordinate reference system of the same type as this CRS but with different axes.
+ *
+ * @throws ClassCastException if the type of the given coordinate system is invalid.
*/
@Override
- final AbstractCRS createSameType(final Map<String,?> properties, final CoordinateSystem cs) {
- return new DefaultVerticalCRS(properties, datum, (VerticalCS) cs);
+ final AbstractCRS createSameType(final CoordinateSystem cs) {
+ return new DefaultVerticalCRS(this, (VerticalCS) cs);
}
/**
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/package-info.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/package-info.java
index ddd2d99cf2..d71a18efa6 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/package-info.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/package-info.java
@@ -73,7 +73,7 @@
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @author Cédric Briançon (Geomatys)
- * @version 1.4
+ * @version 1.5
* @since 0.4
*/
@XmlSchema(location = "http://schemas.opengis.net/gml/3.2.1/coordinateReferenceSystems.xsd",
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AbstractCS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AbstractCS.java
index d93d6d76f9..dd4d8d06ca 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AbstractCS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AbstractCS.java
@@ -19,6 +19,7 @@ package org.apache.sis.referencing.cs;
import java.util.Map;
import java.util.EnumMap;
import java.util.Arrays;
+import java.util.ConcurrentModificationException;
import java.util.logging.Logger;
import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.XmlElement;
@@ -42,6 +43,7 @@ import org.apache.sis.referencing.CRS;
import org.apache.sis.referencing.util.WKTUtilities;
import org.apache.sis.referencing.util.AxisDirections;
import org.apache.sis.referencing.util.WKTKeywords;
+import org.apache.sis.referencing.util.ReferencingUtilities;
import org.apache.sis.referencing.internal.Resources;
import org.apache.sis.system.Modules;
import org.apache.sis.util.Utilities;
@@ -51,7 +53,6 @@ import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.io.wkt.ElementKind;
import org.apache.sis.io.wkt.Formatter;
-import org.apache.sis.measure.Angle;
import static org.apache.sis.util.ArgumentChecks.*;
@@ -75,7 +76,7 @@ import static org.apache.sis.util.ArgumentChecks.*;
* objects and passed between threads without synchronization.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see DefaultCoordinateSystemAxis
* @see org.apache.sis.referencing.crs.AbstractCRS
@@ -106,7 +107,7 @@ public class AbstractCS extends AbstractIdentifiedObject implements CoordinateSy
/**
* Serial number for inter-operability with different versions.
*/
- private static final long serialVersionUID = 6757665252533744744L;
+ private static final long serialVersionUID = 3394376886951478970L;
/**
* Return value for {@link #validateAxis(AxisDirection, Unit)}
@@ -126,11 +127,22 @@ public class AbstractCS extends AbstractIdentifiedObject implements CoordinateSy
/**
* Other coordinate systems derived from this coordinate systems for other axes conventions.
- * Created only when first needed.
+ * This map is shared by all instances derived from the same original {@code AbstractCRS} instance.
+ * It is serialized in order to preserve metadata about the original instance.
+ * All accesses to this map shall be synchronized on {@code forConvention}.
*
* @see #forConvention(AxesConvention)
*/
- private transient Map<AxesConvention,AbstractCS> derived;
+ final EnumMap<AxesConvention,AbstractCS> forConvention;
+
+ /**
+ * Creates the value to assign to the {@link #forConvention} map by constructors.
+ */
+ private EnumMap<AxesConvention,AbstractCS> forConvention() {
+ var m = new EnumMap<AxesConvention,AbstractCS>(AxesConvention.class);
+ m.put(AxesConvention.ORIGINAL, this);
+ return m;
+ }
/**
* Constructs a coordinate system from a set of properties and a sequence of axes.
@@ -165,12 +177,25 @@ public class AbstractCS extends AbstractIdentifiedObject implements CoordinateSy
*
* @param properties the properties to be given to the identified object.
* @param axes the sequence of axes.
+ * @throws IllegalArgumentException if an axis has an illegal direction or an illegal unit of measurement.
*/
- @SuppressWarnings("OverridableMethodCallInConstructor")
- public AbstractCS(final Map<String,?> properties, CoordinateSystemAxis... axes) {
+ @SuppressWarnings({"this-escape", "OverridableMethodCallInConstructor"})
+ public AbstractCS(final Map<String,?> properties, final CoordinateSystemAxis... axes) {
super(properties);
ensureNonNull("axes", axes);
- this.axes = axes = axes.clone();
+ this.axes = axes.clone();
+ validate(properties);
+ forConvention = forConvention();
+ }
+
+ /**
+ * Verifies that the coordinate system axes are non-null, then validates their directions and units of measurement.
+ * Subclasses may override for adding more verifications, for example ensuring that all axes are perpendicular.
+ *
+ * @param properties properties given at construction time, or {@code null} if none.
+ * @throws IllegalArgumentException if an axis has an illegal direction or an illegal unit of measurement.
+ */
+ void validate(final Map<String,?> properties) {
for (int i=0; i<axes.length; i++) {
final CoordinateSystemAxis axis = axes[i];
ensureNonNullElement("axes", i, axis);
@@ -236,30 +261,22 @@ public class AbstractCS extends AbstractIdentifiedObject implements CoordinateSy
}
/**
- * Ensures that all known axes are perpendicular, ignoring unknown axis directions.
- * This method can be invoked by the constructors of coordinate systems having this requirement.
+ * Creates a new CS derived from the specified one, but with different axis order or unit.
+ *
+ * @param original the original coordinate system from which to derive a new one.
+ * @param name name of the new coordinate system, or {@code null} to inherit.
+ * @param axes the new axes. This array is not cloned.
+ * @param share whether the new CS should use a cache shared with the original CS.
+ * @throws IllegalArgumentException if an axis has illegal unit or direction.
*
- * @param properties properties given at construction time.
- * @throws IllegalArgumentException if an illegal angle is found between two axes.
+ * @see #createForAxes(String, CoordinateSystemAxis[], boolean)
*/
- final void ensurePerpendicularAxis(final Map<String,?> properties) throws IllegalArgumentException {
- final int dimension = getDimension();
- for (int i=0; i<dimension; i++) {
- final AxisDirection axis0 = getAxis(i).getDirection();
- for (int j=i; ++j<dimension;) {
- final AxisDirection axis1 = getAxis(j).getDirection();
- final Angle angle = CoordinateSystems.angle(axis0, axis1);
- /*
- * The angle may be null for grid directions (COLUMN_POSITIVE, COLUMN_NEGATIVE,
- * ROW_POSITIVE, ROW_NEGATIVE). We conservatively accept those directions even if
- * they are not really for Cartesian CS because we do not know the grid geometry.
- */
- if (angle != null && Math.abs(angle.degrees()) != 90) {
- throw new IllegalArgumentException(Resources.forProperties(properties).getString(
- Resources.Keys.NonPerpendicularDirections_2, axis0, axis1));
- }
- }
- }
+ @SuppressWarnings({"this-escape", "OverridableMethodCallInConstructor"})
+ AbstractCS(final AbstractCS original, final String name, final CoordinateSystemAxis[] axes, final boolean share) {
+ super(original.getPropertiesWithoutIdentifiers(name));
+ this.axes = axes;
+ validate(null);
+ forConvention = share ? original.forConvention : forConvention();
}
/**
@@ -269,13 +286,16 @@ public class AbstractCS extends AbstractIdentifiedObject implements CoordinateSy
*
* <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
*
- * @param cs the coordinate system to copy.
+ * @param original the coordinate system to copy.
*
* @see #castOrCopy(CoordinateSystem)
*/
- protected AbstractCS(final CoordinateSystem cs) {
- super(cs);
- axes = (cs instanceof AbstractCS) ? ((AbstractCS) cs).axes : getAxes(cs);
+ @SuppressWarnings({"this-escape", "OverridableMethodCallInConstructor"})
+ protected AbstractCS(final CoordinateSystem original) {
+ super(original);
+ axes = (original instanceof AbstractCS) ? ((AbstractCS) original).axes : getAxes(original);
+ validate(null);
+ forConvention = forConvention();
}
/**
@@ -337,6 +357,16 @@ public class AbstractCS extends AbstractIdentifiedObject implements CoordinateSy
return CoordinateSystem.class;
}
+ /**
+ * Returns the properties (scope, domain of validity) except the identifiers and the EPSG namespace.
+ *
+ * @param name name to associate to the {@link #NAME_KEY} in the returned map, or {@code null} to inherit.
+ * @return the identified object properties without identifier.
+ */
+ final Map<String,?> getPropertiesWithoutIdentifiers(final String name) {
+ return ReferencingUtilities.getPropertiesWithoutIdentifiers(this, (name == null) ? null : Map.of(NAME_KEY, name));
+ }
+
/**
* Returns the number of dimensions of this coordinate system.
* This is the number of axes given at construction time.
@@ -360,6 +390,30 @@ public class AbstractCS extends AbstractIdentifiedObject implements CoordinateSy
return axes[dimension];
}
+ /**
+ * Sets the CS for the given axes convention.
+ *
+ * @param cs the CS to cache.
+ * @return the cached CS. May be different than the given {@code cs} if an existing instance has been found.
+ */
+ final AbstractCS setCached(final AxesConvention convention, AbstractCS cs) {
+ assert Thread.holdsLock(forConvention);
+ /*
+ * It happens often that the CRS created by RIGHT_HANDED, DISPLAY_ORIENTED and NORMALIZED are the same.
+ * Sharing the same instance not only saves memory, but can also makes future comparisons faster.
+ */
+ for (final AbstractCS existing : forConvention.values()) {
+ if (cs.equals(existing, ComparisonMode.IGNORE_METADATA)) {
+ cs = existing;
+ break;
+ }
+ }
+ if (forConvention.put(convention, cs) != null) {
+ throw new ConcurrentModificationException(); // Should never happen, unless we have a synchronization bug.
+ }
+ return cs;
+ }
+
/**
* Returns a coordinate system equivalent to this one but with axes rearranged according the given convention.
* If this coordinate system is already compatible with the given convention, then this method returns {@code this}.
@@ -369,33 +423,24 @@ public class AbstractCS extends AbstractIdentifiedObject implements CoordinateSy
*
* @see org.apache.sis.referencing.crs.AbstractCRS#forConvention(AxesConvention)
*/
- public synchronized AbstractCS forConvention(final AxesConvention convention) {
+ public AbstractCS forConvention(final AxesConvention convention) {
ensureNonNull("convention", convention);
- if (derived == null) {
- derived = new EnumMap<>(AxesConvention.class);
- }
- AbstractCS cs = derived.get(convention);
- if (cs == null) {
- cs = Normalizer.forConvention(this, convention);
+ synchronized (forConvention) {
+ AbstractCS cs = forConvention.get(convention);
if (cs == null) {
- cs = this; // This coordinate system is already normalized.
- } else if (convention != AxesConvention.POSITIVE_RANGE) {
- cs = cs.resolveEPSG(this);
- }
- /*
- * It happen often that the CRS created by RIGHT_HANDED, DISPLAY_ORIENTED and
- * NORMALIZED are the same. If this is the case, sharing the same instance
- * not only save memory but can also make future comparisons faster.
- */
- for (final AbstractCS existing : derived.values()) {
- if (cs.equals(existing)) {
- cs = existing;
- break;
+ final AbstractCS original = forConvention.get(AxesConvention.ORIGINAL);
+ cs = Normalizer.forConvention(original, convention);
+ if (cs == null) {
+ cs = original; // The given coordinate system is already normalized.
+ } else if (equals(cs, ComparisonMode.IGNORE_METADATA)) {
+ cs = this;
+ } else if (convention != AxesConvention.POSITIVE_RANGE) {
+ cs = cs.resolveEPSG(original);
}
+ cs = setCached(convention, cs);
}
- derived.put(convention, cs);
+ return cs;
}
- return cs;
}
/**
@@ -406,13 +451,15 @@ public class AbstractCS extends AbstractIdentifiedObject implements CoordinateSy
* But if the given {@code axes} array has less elements than this coordinate system dimension, then
* this method may return another kind of coordinate system. See {@link AxisFilter} for an example.</p>
*
- * @param axes the set of axes to give to the new coordinate system.
+ * @param name name of the new coordinate system.
+ * @param axes the set of axes to give to the new coordinate system.
+ * @param share whether the new CS should use a cache shared with the original CS.
* @return a new coordinate system of the same type as {@code this}, but using the given axes.
* @throws IllegalArgumentException if {@code axes} contains an unexpected number of axes,
* or if an axis has an unexpected direction or unexpected unit of measurement.
*/
- AbstractCS createForAxes(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
- return new AbstractCS(properties, axes);
+ AbstractCS createForAxes(final String name, final CoordinateSystemAxis[] axes, final boolean share) {
+ return new AbstractCS(this, name, axes, share);
}
/**
@@ -456,18 +503,19 @@ public class AbstractCS extends AbstractIdentifiedObject implements CoordinateSy
}
/**
- * Convenience method for implementations of {@link #createForAxes(Map, CoordinateSystemAxis[])}
+ * Convenience method for implementations of {@code createForAxes(…)}
* when the resulting coordinate system would have an unexpected number of dimensions.
*
- * @param properties the properties which was supposed to be given to the constructor.
- * @param axes the axes which was supposed to be given to the constructor.
- * @param expected the minimal expected number of dimensions (may be less than {@link #getDimension()}).
+ * @param axes the axes which were supposed to be given to the constructor.
+ * @param min minimum number of dimensions, inclusive.
+ * @param max maximum number of dimensions, inclusive.
+ *
+ * @see #createForAxes(String, CoordinateSystemAxis[], boolean)
*/
- static IllegalArgumentException unexpectedDimension(final Map<String,?> properties,
- final CoordinateSystemAxis[] axes, final int expected)
- {
- return new MismatchedDimensionException(Errors.getResources(properties).getString(
- Errors.Keys.MismatchedDimension_3, "filter(cs)", expected, axes.length));
+ static IllegalArgumentException unexpectedDimension(final CoordinateSystemAxis[] axes, final int min, final int max) {
+ final int n = axes.length;
+ final int e = (n < min) ? min : max;
+ return new MismatchedDimensionException(Errors.format(Errors.Keys.MismatchedDimension_3, "filter(cs)", e, n));
}
/**
@@ -592,6 +640,7 @@ public class AbstractCS extends AbstractIdentifiedObject implements CoordinateSy
*/
AbstractCS() {
super(org.apache.sis.referencing.util.NilReferencingObject.INSTANCE);
+ forConvention = forConvention();
axes = EMPTY;
/*
* Coordinate system axes are mandatory for SIS working. We do not verify their presence here
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AxesConvention.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AxesConvention.java
index 846e3ec515..762f5f6977 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AxesConvention.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AxesConvention.java
@@ -101,7 +101,7 @@ import org.apache.sis.measure.Units;
* (e.g. {@link org.apache.sis.geometry.GeneralEnvelope#normalize()}).
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.5
*
* @see AbstractCS#forConvention(AxesConvention)
* @see org.apache.sis.referencing.crs.AbstractCRS#forConvention(AxesConvention)
@@ -274,5 +274,15 @@ public enum AxesConvention implements AxisFilter {
*
* @see org.opengis.referencing.cs.RangeMeaning#WRAPAROUND
*/
- POSITIVE_RANGE;
+ POSITIVE_RANGE,
+
+ /**
+ * The axis order as they were specified in the original coordinate system.
+ * The first time that a {@code forConvention(…)} method is invoked on a new coordinate system (CS),
+ * a reference to that original CS is associated to this enumeration value and can be retrieved from
+ * any derived object.
+ *
+ * @since 1.5
+ */
+ ORIGINAL;
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultAffineCS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultAffineCS.java
index 6330148790..12c9fa3f09 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultAffineCS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultAffineCS.java
@@ -51,7 +51,7 @@ import org.apache.sis.measure.Units;
* constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
* @since 0.4
*/
@XmlType(name = "AffineCSType")
@@ -62,14 +62,6 @@ public class DefaultAffineCS extends AbstractCS implements AffineCS {
*/
private static final long serialVersionUID = 7977674229369042440L;
- /**
- * Constructs a coordinate system of arbitrary dimension. This constructor is
- * not public because {@code AffineCS} are restricted to 2 and 3 dimensions.
- */
- DefaultAffineCS(final Map<String,?> properties, final CoordinateSystemAxis[] axis) {
- super(properties, axis);
- }
-
/**
* Constructs a two-dimensional coordinate system from a set of properties.
* The properties map is given unchanged to the
@@ -133,6 +125,17 @@ public class DefaultAffineCS extends AbstractCS implements AffineCS {
super(properties, axis0, axis1, axis2);
}
+ /**
+ * Creates a new CS derived from the specified one, but with different axis order or unit.
+ *
+ * @see #createForAxes(String, CoordinateSystemAxis[], boolean)
+ */
+ DefaultAffineCS(final DefaultAffineCS original, final String name,
+ final CoordinateSystemAxis[] axes, final boolean share)
+ {
+ super(original, name, axes, share);
+ }
+
/**
* Creates a new coordinate system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -140,12 +143,12 @@ public class DefaultAffineCS extends AbstractCS implements AffineCS {
*
* <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
*
- * @param cs the coordinate system to copy.
+ * @param original the coordinate system to copy.
*
* @see #castOrCopy(AffineCS)
*/
- protected DefaultAffineCS(final AffineCS cs) {
- super(cs);
+ protected DefaultAffineCS(final AffineCS original) {
+ super(original);
}
/**
@@ -218,11 +221,11 @@ public class DefaultAffineCS extends AbstractCS implements AffineCS {
* This method shall be overridden by all {@code AffineCS} subclasses in this package.
*/
@Override
- AbstractCS createForAxes(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
+ AbstractCS createForAxes(final String name, final CoordinateSystemAxis[] axes, final boolean share) {
switch (axes.length) {
case 2: // Fall through
- case 3: return new DefaultAffineCS(properties, axes);
- default: throw unexpectedDimension(properties, axes, 2);
+ case 3: return new DefaultAffineCS(this, name, axes, share);
+ default: throw unexpectedDimension(axes, 2, 3);
}
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCartesianCS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCartesianCS.java
index 2cf03c2f2a..993b983171 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCartesianCS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCartesianCS.java
@@ -19,8 +19,11 @@ package org.apache.sis.referencing.cs;
import java.util.Map;
import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.XmlRootElement;
+import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CartesianCS;
import org.opengis.referencing.cs.CoordinateSystemAxis;
+import org.apache.sis.referencing.internal.Resources;
+import org.apache.sis.measure.Angle;
/**
@@ -53,7 +56,7 @@ import org.opengis.referencing.cs.CoordinateSystemAxis;
* constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createCartesianCS(String)
*
@@ -67,15 +70,6 @@ public class DefaultCartesianCS extends DefaultAffineCS implements CartesianCS {
*/
private static final long serialVersionUID = -6182037957705712945L;
- /**
- * Creates a new coordinate system from an arbitrary number of axes. This constructor is for
- * implementations of the {@link #createForAxes(Map, CoordinateSystemAxis[])} method only,
- * because it does not verify the number of axes.
- */
- private DefaultCartesianCS(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
- super(properties, axes);
- }
-
/**
* Constructs a two-dimensional coordinate system from a set of properties.
* The properties map is given unchanged to the
@@ -118,7 +112,6 @@ public class DefaultCartesianCS extends DefaultAffineCS implements CartesianCS {
final CoordinateSystemAxis axis1)
{
super(properties, axis0, axis1);
- ensurePerpendicularAxis(properties);
}
/**
@@ -139,7 +132,17 @@ public class DefaultCartesianCS extends DefaultAffineCS implements CartesianCS {
final CoordinateSystemAxis axis2)
{
super(properties, axis0, axis1, axis2);
- ensurePerpendicularAxis(properties);
+ }
+
+ /**
+ * Creates a new CS derived from the specified one, but with different axis order or unit.
+ *
+ * @see #createForAxes(String, CoordinateSystemAxis[], boolean)
+ */
+ DefaultCartesianCS(final DefaultCartesianCS original, final String name,
+ final CoordinateSystemAxis[] axes, final boolean share)
+ {
+ super(original, name, axes, share);
}
/**
@@ -149,13 +152,12 @@ public class DefaultCartesianCS extends DefaultAffineCS implements CartesianCS {
*
* <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
*
- * @param cs the coordinate system to copy.
+ * @param original the coordinate system to copy.
*
* @see #castOrCopy(CartesianCS)
*/
- protected DefaultCartesianCS(final CartesianCS cs) {
- super(cs);
- ensurePerpendicularAxis(null);
+ protected DefaultCartesianCS(final CartesianCS original) {
+ super(original);
}
/**
@@ -173,6 +175,35 @@ public class DefaultCartesianCS extends DefaultAffineCS implements CartesianCS {
? (DefaultCartesianCS) object : new DefaultCartesianCS(object);
}
+ /**
+ * Ensures that all known axes are perpendicular, ignoring unknown axis directions.
+ * This method can be invoked by the constructors of coordinate systems having this requirement.
+ *
+ * @param properties properties given at construction time, or {@code null} if none.
+ * @throws IllegalArgumentException if an illegal angle is found between two axes.
+ */
+ @Override
+ final void validate(final Map<String,?> properties) {
+ super.validate(properties);
+ final int dimension = getDimension();
+ for (int i=0; i<dimension; i++) {
+ final AxisDirection axis0 = getAxis(i).getDirection();
+ for (int j=i; ++j < dimension;) {
+ final AxisDirection axis1 = getAxis(j).getDirection();
+ final Angle angle = CoordinateSystems.angle(axis0, axis1);
+ /*
+ * The angle may be null for grid directions (COLUMN_POSITIVE, COLUMN_NEGATIVE,
+ * ROW_POSITIVE, ROW_NEGATIVE). We conservatively accept those directions even if
+ * they are not really for Cartesian CS because we do not know the grid geometry.
+ */
+ if (angle != null && Math.abs(angle.degrees()) != 90) {
+ throw new IllegalArgumentException(Resources.forProperties(properties).getString(
+ Resources.Keys.NonPerpendicularDirections_2, axis0, axis1));
+ }
+ }
+ }
+ }
+
/**
* Returns the GeoAPI interface implemented by this class.
* The SIS implementation returns {@code CartesianCS.class}.
@@ -203,12 +234,12 @@ public class DefaultCartesianCS extends DefaultAffineCS implements CartesianCS {
* Returns a coordinate system with different axes.
*/
@Override
- final AbstractCS createForAxes(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
+ final AbstractCS createForAxes(final String name, final CoordinateSystemAxis[] axes, final boolean share) {
switch (axes.length) {
- case 1: return new DefaultVerticalCS(properties, axes);
+ case 1: return SubTypes.createOneDimensional(this, name, axes);
case 2: // Fall through
- case 3: return new DefaultCartesianCS(properties, axes);
- default: throw unexpectedDimension(properties, axes, 2);
+ case 3: return new DefaultCartesianCS(this, name, axes, share);
+ default: throw unexpectedDimension(axes, 1, 3);
}
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCompoundCS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCompoundCS.java
index 37946de847..e1ce919b4c 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCompoundCS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCompoundCS.java
@@ -50,7 +50,7 @@ import static org.apache.sis.util.Utilities.deepEquals;
* constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
* @since 0.4
*/
@XmlTransient
@@ -105,6 +105,15 @@ public class DefaultCompoundCS extends AbstractCS {
this.components = UnmodifiableArrayList.wrap(components);
}
+ /**
+ * Creates a new CS derived from the specified one, but with different axis order or unit.
+ * This is used for the {@link #forConvention(AxesConvention)} implementation only.
+ */
+ private DefaultCompoundCS(final DefaultCompoundCS original, final CoordinateSystem[] components) {
+ super(original, null, getAxes(components), true);
+ this.components = UnmodifiableArrayList.wrap(components);
+ }
+
/**
* Constructs a compound coordinate system from a sequence of coordinate systems.
* A default name for this CS will be inferred from the names of all specified CS.
@@ -170,6 +179,39 @@ public class DefaultCompoundCS extends AbstractCS {
return components; // Unmodifiable.
}
+ /**
+ * Returns a compound CS equivalent to this one but with axes rearranged according the given convention.
+ * This method reorders the axes of each individual coordinate system {@linkplain #getComponents() component}.
+ *
+ * @return {@inheritDoc}
+ */
+ @Override
+ public DefaultCompoundCS forConvention(final AxesConvention convention) {
+ ensureNonNull("convention", convention);
+ synchronized (forConvention) {
+ DefaultCompoundCS cs = (DefaultCompoundCS) forConvention.get(convention);
+ if (cs == null) {
+ cs = (DefaultCompoundCS) forConvention.get(AxesConvention.ORIGINAL);
+ boolean changed = false;
+ final CoordinateSystem[] newComponents = new CoordinateSystem[cs.components.size()];
+ for (int i=0; i<newComponents.length; i++) {
+ CoordinateSystem component = cs.components.get(i);
+ AbstractCS m = castOrCopy(component);
+ if (m != (m = m.forConvention(convention))) {
+ component = m;
+ changed = true;
+ }
+ newComponents[i] = component;
+ }
+ if (changed) {
+ cs = new DefaultCompoundCS(cs, newComponents);
+ }
+ cs = (DefaultCompoundCS) setCached(convention, cs);
+ }
+ return cs;
+ }
+ }
+
/*
* Do not override createForAxes(…) and forConvention(…) because we cannot create a new DefaultCompoundCS
* without knownledge of the CoordinateSystem components to give to it. It would be possible to recursively
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCylindricalCS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCylindricalCS.java
index afa4399b83..ae6855ecf0 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCylindricalCS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultCylindricalCS.java
@@ -48,7 +48,7 @@ import org.apache.sis.measure.Units;
* constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see DefaultPolarCS
* @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createCylindricalCS(String)
@@ -63,15 +63,6 @@ public class DefaultCylindricalCS extends AbstractCS implements CylindricalCS {
*/
private static final long serialVersionUID = -8290402732390917907L;
- /**
- * Creates a new coordinate system from an arbitrary number of axes. This constructor is for
- * implementations of the {@link #createForAxes(Map, CoordinateSystemAxis[])} method only,
- * because it does not verify the number of axes.
- */
- private DefaultCylindricalCS(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
- super(properties, axes);
- }
-
/**
* Constructs a three-dimensional coordinate system from a set of properties.
* The properties map is given unchanged to the
@@ -118,6 +109,17 @@ public class DefaultCylindricalCS extends AbstractCS implements CylindricalCS {
super(properties, axis0, axis1, axis2);
}
+ /**
+ * Creates a new CS derived from the specified one, but with different axis order or unit.
+ *
+ * @see #createForAxes(String, CoordinateSystemAxis[], boolean)
+ */
+ private DefaultCylindricalCS(final DefaultCylindricalCS original, final String name,
+ final CoordinateSystemAxis[] axes, final boolean share)
+ {
+ super(original, name, axes, share);
+ }
+
/**
* Creates a new coordinate system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -125,12 +127,12 @@ public class DefaultCylindricalCS extends AbstractCS implements CylindricalCS {
*
* <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
*
- * @param cs the coordinate system to copy.
+ * @param original the coordinate system to copy.
*
* @see #castOrCopy(CylindricalCS)
*/
- protected DefaultCylindricalCS(final CylindricalCS cs) {
- super(cs);
+ protected DefaultCylindricalCS(final CylindricalCS original) {
+ super(original);
}
/**
@@ -197,11 +199,11 @@ public class DefaultCylindricalCS extends AbstractCS implements CylindricalCS {
* Returns a coordinate system with different axes.
*/
@Override
- final AbstractCS createForAxes(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
+ final AbstractCS createForAxes(final String name, final CoordinateSystemAxis[] axes, final boolean share) {
switch (axes.length) {
- case 2: return new DefaultPolarCS(properties, axes);
- case 3: return new DefaultCylindricalCS(properties, axes);
- default: throw unexpectedDimension(properties, axes, 2);
+ case 2: return new DefaultPolarCS(getPropertiesWithoutIdentifiers(name), axes[0], axes[1]);
+ case 3: return new DefaultCylindricalCS(this, name, axes, share);
+ default: throw unexpectedDimension(axes, 2, 3);
}
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultEllipsoidalCS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultEllipsoidalCS.java
index 63ab943a46..c843716613 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultEllipsoidalCS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultEllipsoidalCS.java
@@ -48,7 +48,7 @@ import org.apache.sis.measure.Units;
* constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createEllipsoidalCS(String)
*
@@ -62,16 +62,6 @@ public class DefaultEllipsoidalCS extends AbstractCS implements EllipsoidalCS {
*/
private static final long serialVersionUID = -1452492488902329211L;
- /**
- * Creates a new coordinate system from an arbitrary number of axes. This constructor is for
- * implementations of the {@link #createForAxes(Map, CoordinateSystemAxis[])} method only,
- * because it does not verify the number of axes.
- */
- private DefaultEllipsoidalCS(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
- super(properties, axes);
- validateAxes(properties);
- }
-
/**
* Constructs a two-dimensional coordinate system from a set of properties.
* The properties map is given unchanged to the
@@ -114,7 +104,6 @@ public class DefaultEllipsoidalCS extends AbstractCS implements EllipsoidalCS {
final CoordinateSystemAxis axis1)
{
super(properties, axis0, axis1);
- validateAxes(properties);
}
/**
@@ -135,7 +124,17 @@ public class DefaultEllipsoidalCS extends AbstractCS implements EllipsoidalCS {
final CoordinateSystemAxis axis2)
{
super(properties, axis0, axis1, axis2);
- validateAxes(properties);
+ }
+
+ /**
+ * Creates a new CS derived from the specified one, but with different axis order or unit.
+ *
+ * @see #createForAxes(String, CoordinateSystemAxis[], boolean)
+ */
+ private DefaultEllipsoidalCS(final DefaultEllipsoidalCS original, final String name,
+ final CoordinateSystemAxis[] axes, final boolean share)
+ {
+ super(original, name, axes, share);
}
/**
@@ -145,12 +144,12 @@ public class DefaultEllipsoidalCS extends AbstractCS implements EllipsoidalCS {
*
* <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
*
- * @param cs the coordinate system to copy.
+ * @param original the coordinate system to copy.
*
* @see #castOrCopy(EllipsoidalCS)
*/
- protected DefaultEllipsoidalCS(final EllipsoidalCS cs) {
- super(cs);
+ protected DefaultEllipsoidalCS(final EllipsoidalCS original) {
+ super(original);
}
/**
@@ -196,7 +195,9 @@ public class DefaultEllipsoidalCS extends AbstractCS implements EllipsoidalCS {
*
* @param properties the properties given at construction time.
*/
- private void validateAxes(final Map<String,?> properties) {
+ @Override
+ final void validate(final Map<String,?> properties) {
+ super.validate(properties);
int i = super.getDimension();
int n = i - 2; // Number of vertical axes allowed.
while (--i >= 0) {
@@ -238,12 +239,12 @@ public class DefaultEllipsoidalCS extends AbstractCS implements EllipsoidalCS {
* Returns a coordinate system with different axes.
*/
@Override
- final AbstractCS createForAxes(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
+ final AbstractCS createForAxes(final String name, final CoordinateSystemAxis[] axes, final boolean share) {
switch (axes.length) {
- case 1: return new DefaultVerticalCS(properties, axes);
+ case 1: return SubTypes.createOneDimensional(this, name, axes);
case 2: // Fall through
- case 3: return new DefaultEllipsoidalCS(properties, axes);
- default: throw unexpectedDimension(properties, axes, 1);
+ case 3: return new DefaultEllipsoidalCS(this, name, axes, share);
+ default: throw unexpectedDimension(axes, 1, 3);
}
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultLinearCS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultLinearCS.java
index 668684f0ae..01bb2aa3dc 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultLinearCS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultLinearCS.java
@@ -49,7 +49,7 @@ import org.apache.sis.measure.Units;
* constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
* @since 0.4
*/
@XmlType(name = "LinearCSType")
@@ -60,15 +60,6 @@ public class DefaultLinearCS extends AbstractCS implements LinearCS {
*/
private static final long serialVersionUID = -6890723478287625763L;
- /**
- * Creates a new coordinate system from an arbitrary number of axes. This constructor is for
- * implementations of the {@link #createForAxes(Map, CoordinateSystemAxis[])} method only,
- * because it does not verify the number of axes.
- */
- private DefaultLinearCS(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
- super(properties, axes);
- }
-
/**
* Constructs a coordinate system from a set of properties.
* The properties map is given unchanged to the
@@ -109,6 +100,17 @@ public class DefaultLinearCS extends AbstractCS implements LinearCS {
super(properties, axis);
}
+ /**
+ * Creates a new CS derived from the specified one, but with different axis order or unit.
+ *
+ * @see #createForAxes(String, CoordinateSystemAxis[], boolean)
+ */
+ private DefaultLinearCS(final DefaultLinearCS original, final String name,
+ final CoordinateSystemAxis[] axes, final boolean share)
+ {
+ super(original, name, axes, share);
+ }
+
/**
* Creates a new coordinate system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -116,12 +118,12 @@ public class DefaultLinearCS extends AbstractCS implements LinearCS {
*
* <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
*
- * @param cs the coordinate system to copy.
+ * @param original the coordinate system to copy.
*
* @see #castOrCopy(LinearCS)
*/
- protected DefaultLinearCS(final LinearCS cs) {
- super(cs);
+ protected DefaultLinearCS(final LinearCS original) {
+ super(original);
}
/**
@@ -188,10 +190,10 @@ public class DefaultLinearCS extends AbstractCS implements LinearCS {
* Returns a coordinate system with different axes.
*/
@Override
- final AbstractCS createForAxes(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
+ final AbstractCS createForAxes(final String name, final CoordinateSystemAxis[] axes, final boolean share) {
switch (axes.length) {
- case 1: return new DefaultLinearCS(properties, axes);
- default: throw unexpectedDimension(properties, axes, 1);
+ case 1: return new DefaultLinearCS(this, name, axes, share);
+ default: throw unexpectedDimension(axes, 1, 1);
}
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultParametricCS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultParametricCS.java
index 229ddc778c..b026f56205 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultParametricCS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultParametricCS.java
@@ -45,7 +45,7 @@ import org.opengis.referencing.cs.ParametricCS;
* constants.
*
* @author Johann Sorel (Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.crs.DefaultParametricCRS
* @see org.apache.sis.referencing.datum.DefaultParametricDatum
@@ -61,15 +61,6 @@ public class DefaultParametricCS extends AbstractCS implements ParametricCS {
*/
private static final long serialVersionUID = -5588239024582484514L;
- /**
- * Creates a new coordinate system from an arbitrary number of axes. This constructor is for
- * implementations of the {@link #createForAxes(Map, CoordinateSystemAxis[])} method only,
- * because it does not verify the number of axes.
- */
- private DefaultParametricCS(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
- super(properties, axes);
- }
-
/**
* Constructs a coordinate system from a set of properties.
* The properties map is given unchanged to the
@@ -110,6 +101,17 @@ public class DefaultParametricCS extends AbstractCS implements ParametricCS {
super(properties, axis);
}
+ /**
+ * Creates a new CS derived from the specified one, but with different axis order or unit.
+ *
+ * @see #createForAxes(String, CoordinateSystemAxis[], boolean)
+ */
+ private DefaultParametricCS(final DefaultParametricCS original, final String name,
+ final CoordinateSystemAxis[] axes, final boolean share)
+ {
+ super(original, name, axes, share);
+ }
+
/**
* Creates a new coordinate system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -117,12 +119,12 @@ public class DefaultParametricCS extends AbstractCS implements ParametricCS {
*
* <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
*
- * @param cs the coordinate system to copy.
+ * @param original the coordinate system to copy.
*
* @see #castOrCopy(ParametricCS)
*/
- protected DefaultParametricCS(final ParametricCS cs) {
- super(cs);
+ protected DefaultParametricCS(final ParametricCS original) {
+ super(original);
}
/**
@@ -170,10 +172,10 @@ public class DefaultParametricCS extends AbstractCS implements ParametricCS {
* Returns a coordinate system with different axes.
*/
@Override
- final AbstractCS createForAxes(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
+ final AbstractCS createForAxes(final String name, final CoordinateSystemAxis[] axes, final boolean share) {
switch (axes.length) {
- case 1: return new DefaultParametricCS(properties, axes);
- default: throw unexpectedDimension(properties, axes, 1);
+ case 1: return new DefaultParametricCS(this, name, axes, share);
+ default: throw unexpectedDimension(axes, 1, 1);
}
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultPolarCS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultPolarCS.java
index 1332dc078c..b20a4b9113 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultPolarCS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultPolarCS.java
@@ -48,7 +48,7 @@ import org.apache.sis.measure.Units;
* constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see DefaultCylindricalCS
* @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createPolarCS(String)
@@ -63,15 +63,6 @@ public class DefaultPolarCS extends AbstractCS implements PolarCS {
*/
private static final long serialVersionUID = 3960197260975470951L;
- /**
- * Creates a new coordinate system from an arbitrary number of axes. This constructor is for
- * implementations of the {@link #createForAxes(Map, CoordinateSystemAxis[])} method only,
- * because it does not verify the number of axes.
- */
- DefaultPolarCS(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
- super(properties, axes);
- }
-
/**
* Constructs a two-dimensional coordinate system from a set of properties.
* The properties map is given unchanged to the
@@ -116,6 +107,17 @@ public class DefaultPolarCS extends AbstractCS implements PolarCS {
super(properties, axis0, axis1);
}
+ /**
+ * Creates a new CS derived from the specified one, but with different axis order or unit.
+ *
+ * @see #createForAxes(String, CoordinateSystemAxis[], boolean)
+ */
+ private DefaultPolarCS(final DefaultPolarCS original, final String name,
+ final CoordinateSystemAxis[] axes, final boolean share)
+ {
+ super(original, name, axes, share);
+ }
+
/**
* Creates a new coordinate system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -123,12 +125,12 @@ public class DefaultPolarCS extends AbstractCS implements PolarCS {
*
* <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
*
- * @param cs the coordinate system to copy.
+ * @param original the coordinate system to copy.
*
* @see #castOrCopy(PolarCS)
*/
- protected DefaultPolarCS(final PolarCS cs) {
- super(cs);
+ protected DefaultPolarCS(final PolarCS original) {
+ super(original);
}
/**
@@ -195,10 +197,10 @@ public class DefaultPolarCS extends AbstractCS implements PolarCS {
* Returns a coordinate system with different axes.
*/
@Override
- final AbstractCS createForAxes(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
+ final AbstractCS createForAxes(final String name, final CoordinateSystemAxis[] axes, final boolean share) {
switch (axes.length) {
- case 2: return new DefaultPolarCS(properties, axes);
- default: throw unexpectedDimension(properties, axes, 2);
+ case 2: return new DefaultPolarCS(this, name, axes, share);
+ default: throw unexpectedDimension(axes, 2, 2);
}
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultSphericalCS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultSphericalCS.java
index 42365f5448..688eeece48 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultSphericalCS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultSphericalCS.java
@@ -53,7 +53,7 @@ import org.apache.sis.measure.Units;
* constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createSphericalCS(String)
*
@@ -67,15 +67,6 @@ public class DefaultSphericalCS extends AbstractCS implements SphericalCS {
*/
private static final long serialVersionUID = 196295996465774477L;
- /**
- * Creates a new coordinate system from an arbitrary number of axes. This constructor is for
- * implementations of the {@link #createForAxes(Map, CoordinateSystemAxis[])} method only,
- * because it does not verify the number of axes.
- */
- private DefaultSphericalCS(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
- super(properties, axes);
- }
-
/**
* Constructs a three-dimensional coordinate system from a set of properties.
* The properties map is given unchanged to the
@@ -143,6 +134,17 @@ public class DefaultSphericalCS extends AbstractCS implements SphericalCS {
super(properties, axis0, axis1);
}
+ /**
+ * Creates a new CS derived from the specified one, but with different axis order or unit.
+ *
+ * @see #createForAxes(String, CoordinateSystemAxis[], boolean)
+ */
+ private DefaultSphericalCS(final DefaultSphericalCS original, final String name,
+ final CoordinateSystemAxis[] axes, final boolean share)
+ {
+ super(original, name, axes, share);
+ }
+
/**
* Creates a new coordinate system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -150,12 +152,12 @@ public class DefaultSphericalCS extends AbstractCS implements SphericalCS {
*
* <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
*
- * @param cs the coordinate system to copy.
+ * @param original the coordinate system to copy.
*
* @see #castOrCopy(SphericalCS)
*/
- protected DefaultSphericalCS(final SphericalCS cs) {
- super(cs);
+ protected DefaultSphericalCS(final SphericalCS original) {
+ super(original);
}
/**
@@ -220,17 +222,18 @@ public class DefaultSphericalCS extends AbstractCS implements SphericalCS {
* Returns a coordinate system with different axes.
*/
@Override
- @SuppressWarnings("fallthrough")
- final AbstractCS createForAxes(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
+ final AbstractCS createForAxes(final String name, final CoordinateSystemAxis[] axes, final boolean share) {
switch (axes.length) {
case 2: {
+ final Map<String,?> properties = getPropertiesWithoutIdentifiers(name);
if (Units.isLinear(axes[0].getUnit()) || Units.isLinear(axes[1].getUnit())) {
- return new DefaultPolarCS(properties, axes);
+ return new DefaultPolarCS(properties, axes[0], axes[1]);
+ } else {
+ return new DefaultSphericalCS(properties, axes[0], axes[1]);
}
- // Fall through
}
- case 3: return new DefaultSphericalCS(properties, axes);
- default: throw unexpectedDimension(properties, axes, 2);
+ case 3: return new DefaultSphericalCS(this, name, axes, share);
+ default: throw unexpectedDimension(axes, 2, 3);
}
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultTimeCS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultTimeCS.java
index f1dcef7016..8f8a556816 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultTimeCS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultTimeCS.java
@@ -47,7 +47,7 @@ import org.apache.sis.measure.Units;
* constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.crs.DefaultTemporalCRS
* @see org.apache.sis.referencing.datum.DefaultTemporalDatum
@@ -63,15 +63,6 @@ public class DefaultTimeCS extends AbstractCS implements TimeCS {
*/
private static final long serialVersionUID = 5222911412381303989L;
- /**
- * Creates a new coordinate system from an arbitrary number of axes. This constructor is for
- * implementations of the {@link #createForAxes(Map, CoordinateSystemAxis[])} method only,
- * because it does not verify the number of axes.
- */
- private DefaultTimeCS(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
- super(properties, axes);
- }
-
/**
* Constructs a coordinate system from a set of properties.
* The properties map is given unchanged to the
@@ -112,6 +103,17 @@ public class DefaultTimeCS extends AbstractCS implements TimeCS {
super(properties, axis);
}
+ /**
+ * Creates a new CS derived from the specified one, but with different axis order or unit.
+ *
+ * @see #createForAxes(String, CoordinateSystemAxis[], boolean)
+ */
+ private DefaultTimeCS(final DefaultTimeCS original, final String name,
+ final CoordinateSystemAxis[] axes, final boolean share)
+ {
+ super(original, name, axes, share);
+ }
+
/**
* Creates a new coordinate system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -119,12 +121,12 @@ public class DefaultTimeCS extends AbstractCS implements TimeCS {
*
* <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
*
- * @param cs the coordinate system to copy.
+ * @param original the coordinate system to copy.
*
* @see #castOrCopy(TimeCS)
*/
- protected DefaultTimeCS(final TimeCS cs) {
- super(cs);
+ protected DefaultTimeCS(final TimeCS original) {
+ super(original);
}
/**
@@ -189,10 +191,10 @@ public class DefaultTimeCS extends AbstractCS implements TimeCS {
* Returns a coordinate system with different axes.
*/
@Override
- final AbstractCS createForAxes(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
+ final AbstractCS createForAxes(final String name, final CoordinateSystemAxis[] axes, final boolean share) {
switch (axes.length) {
- case 1: return new DefaultTimeCS(properties, axes);
- default: throw unexpectedDimension(properties, axes, 1);
+ case 1: return new DefaultTimeCS(this, name, axes, share);
+ default: throw unexpectedDimension(axes, 1, 1);
}
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultUserDefinedCS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultUserDefinedCS.java
index 2ff922858e..1637f2536f 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultUserDefinedCS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultUserDefinedCS.java
@@ -43,7 +43,7 @@ import org.opengis.referencing.cs.CoordinateSystemAxis;
* constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
* @since 0.4
*/
@XmlType(name = "UserDefinedCSType")
@@ -54,15 +54,6 @@ public class DefaultUserDefinedCS extends AbstractCS implements UserDefinedCS {
*/
private static final long serialVersionUID = -4904091898305706316L;
- /**
- * Creates a new coordinate system from an arbitrary number of axes. This constructor is for
- * implementations of the {@link #createForAxes(Map, CoordinateSystemAxis[])} method only,
- * because it does not verify the number of axes.
- */
- private DefaultUserDefinedCS(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
- super(properties, axes);
- }
-
/**
* Constructs a two-dimensional coordinate system from a set of properties.
* The properties map is given unchanged to the
@@ -127,6 +118,17 @@ public class DefaultUserDefinedCS extends AbstractCS implements UserDefinedCS {
super(properties, axis0, axis1, axis2);
}
+ /**
+ * Creates a new CS derived from the specified one, but with different axis order or unit.
+ *
+ * @see #createForAxes(String, CoordinateSystemAxis[], boolean)
+ */
+ private DefaultUserDefinedCS(final DefaultUserDefinedCS original, final String name,
+ final CoordinateSystemAxis[] axes, final boolean share)
+ {
+ super(original, name, axes, share);
+ }
+
/**
* Creates a new coordinate system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -134,12 +136,12 @@ public class DefaultUserDefinedCS extends AbstractCS implements UserDefinedCS {
*
* <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
*
- * @param cs the coordinate system to copy.
+ * @param original the coordinate system to copy.
*
* @see #castOrCopy(UserDefinedCS)
*/
- protected DefaultUserDefinedCS(final UserDefinedCS cs) {
- super(cs);
+ protected DefaultUserDefinedCS(final UserDefinedCS original) {
+ super(original);
}
/**
@@ -187,11 +189,11 @@ public class DefaultUserDefinedCS extends AbstractCS implements UserDefinedCS {
* Returns a coordinate system with different axes.
*/
@Override
- final AbstractCS createForAxes(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
+ final AbstractCS createForAxes(final String name, final CoordinateSystemAxis[] axes, final boolean share) {
switch (axes.length) {
case 2: // Fall through
- case 3: return new DefaultUserDefinedCS(properties, axes);
- default: throw unexpectedDimension(properties, axes, 2);
+ case 3: return new DefaultUserDefinedCS(this, name, axes, share);
+ default: throw unexpectedDimension(axes, 2, 3);
}
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultVerticalCS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultVerticalCS.java
index 6f50d5b0b6..69f646c179 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultVerticalCS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/DefaultVerticalCS.java
@@ -58,7 +58,7 @@ import org.apache.sis.measure.Units;
* constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.crs.DefaultVerticalCRS
* @see org.apache.sis.referencing.datum.DefaultVerticalDatum
@@ -74,15 +74,6 @@ public class DefaultVerticalCS extends AbstractCS implements VerticalCS {
*/
private static final long serialVersionUID = 1201155778896630499L;
- /**
- * Creates a new coordinate system from an arbitrary number of axes. This constructor is for
- * implementations of the {@link #createForAxes(Map, CoordinateSystemAxis[])} method only,
- * because it does not verify the number of axes.
- */
- DefaultVerticalCS(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
- super(properties, axes);
- }
-
/**
* Constructs a coordinate system from a set of properties.
* The properties map is given unchanged to the
@@ -123,6 +114,17 @@ public class DefaultVerticalCS extends AbstractCS implements VerticalCS {
super(properties, axis);
}
+ /**
+ * Creates a new CS derived from the specified one, but with different axis order or unit.
+ *
+ * @see #createForAxes(String, CoordinateSystemAxis[], boolean)
+ */
+ private DefaultVerticalCS(final DefaultVerticalCS original, final String name,
+ final CoordinateSystemAxis[] axes, final boolean share)
+ {
+ super(original, name, axes, share);
+ }
+
/**
* Creates a new coordinate system with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
@@ -130,12 +132,12 @@ public class DefaultVerticalCS extends AbstractCS implements VerticalCS {
*
* <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
*
- * @param cs the coordinate system to copy.
+ * @param original the coordinate system to copy.
*
* @see #castOrCopy(VerticalCS)
*/
- protected DefaultVerticalCS(final VerticalCS cs) {
- super(cs);
+ protected DefaultVerticalCS(final VerticalCS original) {
+ super(original);
}
/**
@@ -205,10 +207,10 @@ public class DefaultVerticalCS extends AbstractCS implements VerticalCS {
* Returns a coordinate system with different axes.
*/
@Override
- final AbstractCS createForAxes(final Map<String,?> properties, final CoordinateSystemAxis[] axes) {
+ final AbstractCS createForAxes(final String name, final CoordinateSystemAxis[] axes, final boolean share) {
switch (axes.length) {
- case 1: return new DefaultVerticalCS(properties, axes);
- default: throw unexpectedDimension(properties, axes, 1);
+ case 1: return new DefaultVerticalCS(this, name, axes, share);
+ default: throw unexpectedDimension(axes, 1, 1);
}
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/Normalizer.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/Normalizer.java
index e9e3ae16bc..8859b632a8 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/Normalizer.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/Normalizer.java
@@ -120,6 +120,9 @@ final class Normalizer implements Comparable<Normalizer> {
AxisDirections.CLOCKWISE,
AxisDirections.AWAY_FROM
}) ORDER.put(d, ++code);
+ // Set the time coordinate as the last coordinate in all cases.
+ ORDER.put(AxisDirection.PAST, (Integer.MAX_VALUE >>> 1) - 1);
+ ORDER.put(AxisDirection.FUTURE, (Integer.MAX_VALUE >>> 1));
}
/**
@@ -359,8 +362,9 @@ final class Normalizer implements Comparable<Normalizer> {
* We need to change the Coordinate System name, since it is likely to not be valid anymore.
*/
final AbstractCS impl = castOrCopy(cs);
- final StringBuilder buffer = (StringBuilder) CharSequences.camelCaseToSentence(impl.getInterface().getSimpleName());
- return impl.createForAxes(Map.of(AbstractCS.NAME_KEY, AxisDirections.appendTo(buffer, newAxes)), newAxes);
+ final var buffer = (StringBuilder) CharSequences.camelCaseToSentence(impl.getInterface().getSimpleName());
+ final String name = AxisDirections.appendTo(buffer, newAxes);
+ return impl.createForAxes(name, newAxes, changes instanceof AxesConvention);
}
/**
@@ -382,9 +386,11 @@ final class Normalizer implements Comparable<Normalizer> {
* of -60° still locate the same point in the old and the new coordinate system. But the preferred way to
* locate that point become the 300° value if the longitude range has been shifted to positive values.</p>
*
+ * @param cs the coordinate system to shift.
+ * @param share whether the new CS should use a cache shared with the original CS.
* @return a coordinate system using the given kind of longitude range, or {@code null} if no change is needed.
*/
- private static AbstractCS shiftAxisRange(final CoordinateSystem cs) {
+ private static AbstractCS shiftAxisRange(final CoordinateSystem cs, final boolean share) {
boolean changed = false;
final CoordinateSystemAxis[] axes = new CoordinateSystemAxis[cs.getDimension()];
for (int i=0; i<axes.length; i++) {
@@ -408,7 +414,7 @@ final class Normalizer implements Comparable<Normalizer> {
if (!changed) {
return null;
}
- return castOrCopy(cs).createForAxes(IdentifiedObjects.getProperties(cs, EXCLUDES), axes);
+ return castOrCopy(cs).createForAxes(null, axes, share);
}
/**
@@ -448,7 +454,7 @@ final class Normalizer implements Comparable<Normalizer> {
case NORMALIZED: // Fall through
case DISPLAY_ORIENTED: return normalize(cs, convention, true);
case RIGHT_HANDED: return normalize(cs, null, true);
- case POSITIVE_RANGE: return shiftAxisRange(cs);
+ case POSITIVE_RANGE: return shiftAxisRange(cs, true);
default: throw new AssertionError(convention);
}
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/SubTypes.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/SubTypes.java
index 71ae3137b9..83783054bc 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/SubTypes.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/SubTypes.java
@@ -16,8 +16,11 @@
*/
package org.apache.sis.referencing.cs;
+import java.util.Map;
import org.opengis.referencing.cs.AffineCS;
+import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystem;
+import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.cs.CylindricalCS;
import org.opengis.referencing.cs.EllipsoidalCS;
import org.opengis.referencing.cs.LinearCS;
@@ -26,6 +29,7 @@ import org.opengis.referencing.cs.SphericalCS;
import org.opengis.referencing.cs.TimeCS;
import org.opengis.referencing.cs.UserDefinedCS;
import org.opengis.referencing.cs.VerticalCS;
+import org.apache.sis.referencing.util.AxisDirections;
/**
@@ -91,4 +95,31 @@ final class SubTypes {
}
return new AbstractCS(object);
}
+
+ /**
+ * Creates a one-dimensional coordinate system derived from the specified CS.
+ *
+ * @param original the two- or three-dimensional CRS from which to extract an axis.
+ * @param name name of the new coordinate system.
+ * @param axes the user-specified coordinate system axes. Only the first one will be used.
+ * @return the one-dimensional coordinate system with the specified axis.
+ */
+ static AbstractCS createOneDimensional(final AbstractCS original, final String name, final CoordinateSystemAxis[] axes) {
+ final CoordinateSystemAxis axis = axes[0];
+ final AxisDirection dir = AxisDirections.absolute(axis.getDirection());
+ final boolean isTemporal;
+ if (AxisDirection.UP.equals(dir)) {
+ isTemporal = false;
+ } else if (AxisDirection.FUTURE.equals(dir)) { // Happen with Minkowski coordinate system.
+ isTemporal = true;
+ } else {
+ throw AbstractCS.unexpectedDimension(axes, 2, 3);
+ }
+ final Map<String,?> properties = original.getPropertiesWithoutIdentifiers(name);
+ if (isTemporal) {
+ return new DefaultTimeCS(properties, axis);
+ } else {
+ return new DefaultVerticalCS(properties, axis);
+ }
+ }
}
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/package-info.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/package-info.java
index 0b9e22c1be..ba79901991 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/package-info.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/package-info.java
@@ -33,7 +33,7 @@
* and units between two coordinate systems, or filtering axes.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
* @since 0.4
*/
@XmlSchema(location = "http://schemas.opengis.net/gml/3.2.1/coordinateSystems.xsd",
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/ReferencingUtilities.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/ReferencingUtilities.java
index 5a96079516..fb136a72ac 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/ReferencingUtilities.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/ReferencingUtilities.java
@@ -47,6 +47,7 @@ import org.apache.sis.util.CharSequences;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.referencing.NamedIdentifier;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.AbstractIdentifiedObject;
import org.apache.sis.referencing.datum.DefaultPrimeMeridian;
@@ -424,6 +425,33 @@ public final class ReferencingUtilities extends Static {
&& AxisDirection.EAST .equals(cs.getAxis(1).getDirection());
}
+ /**
+ * Returns the properties (scope, domain of validity) except the identifiers and the EPSG namespace.
+ * The identifiers are removed because a modified CRS is no longer conform to the authoritative definition.
+ * If the name contains a namespace (e.g. "EPSG"), this method removes that namespace for the same reason.
+ * For example, "EPSG:WGS 84" will become simply "WGS 84".
+ *
+ * @param object the identified object for which to get properties map.
+ * @param overwrite properties overwriting the inherited ones, or {@code null} if none.
+ * @return the identified object properties.
+ */
+ public static Map<String,?> getPropertiesWithoutIdentifiers(final IdentifiedObject object, final Map<String,?> overwrite) {
+ final Map<String,?> properties = IdentifiedObjects.getProperties(object, IdentifiedObject.IDENTIFIERS_KEY);
+ final Identifier name = object.getName();
+ final boolean keepName = name.getCodeSpace() == null && name.getAuthority() == null;
+ if (keepName && overwrite == null) {
+ return properties;
+ }
+ final var copy = new HashMap<String,Object>(properties);
+ if (!keepName) {
+ copy.put(IdentifiedObject.NAME_KEY, new NamedIdentifier(null, name.getCode()));
+ }
+ if (overwrite != null) {
+ copy.putAll(overwrite);
+ }
+ return copy;
+ }
+
/**
* Returns the properties of the given object but potentially with a modified name.
* Current implement truncates the name at the first non-white character which is not
diff --git a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/DefaultPolarCSTest.java b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/DefaultPolarCSTest.java
index 623c0894bc..02aea810f8 100644
--- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/DefaultPolarCSTest.java
+++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/DefaultPolarCSTest.java
@@ -74,10 +74,10 @@ public final class DefaultPolarCSTest extends TestCase {
radius);
DefaultPolarCS normalized = cs.forConvention(AxesConvention.RIGHT_HANDED);
- assertNotSame("Should create a new CoordinateSystem.", cs, normalized);
assertAxisDirectionsEqual("Right-handed", normalized,
- AxisDirections.CLOCKWISE, // Interchanged (r,θ) order for making right handed.
+ AxisDirections.CLOCKWISE,
AxisDirection.SOUTH);
+ assertSame(cs, normalized);
normalized = cs.forConvention(AxesConvention.NORMALIZED);
assertNotSame("Should create a new CoordinateSystem.", cs, normalized);