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 89ae3d8 Fix a failure to replace the ProjectedCRS component in the CRS of a netCDF
file when there is more than one additional axis (e.g. vertical + temporal).
89ae3d8 is described below
commit 89ae3d8246a47237c33b8201b9744ff50906d5c2
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Wed May 29 18:14:55 2019 +0200
Fix a failure to replace the ProjectedCRS component in the CRS of a netCDF file when there
is more than one additional axis (e.g. vertical + temporal).
---
.../referencing/GeodeticObjectBuilder.java | 86 +++++++++++++++++++++-
.../main/java/org/apache/sis/referencing/CRS.java | 4 +-
.../apache/sis/internal/netcdf/GridMapping.java | 30 ++------
3 files changed, 91 insertions(+), 29 deletions(-)
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
index 24eca3f..09ce3dd 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
@@ -32,6 +32,7 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.crs.TemporalCRS;
+import org.opengis.referencing.crs.CompoundCRS;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CSFactory;
import org.opengis.referencing.cs.CartesianCS;
@@ -44,6 +45,7 @@ import org.opengis.referencing.operation.OperationMethod;
import org.opengis.referencing.operation.Conversion;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.resources.Errors;
+import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.internal.metadata.EllipsoidalHeightCombiner;
import org.apache.sis.internal.referencing.provider.TransverseMercator;
import org.apache.sis.internal.referencing.provider.PolarStereographicA;
@@ -52,6 +54,7 @@ import org.apache.sis.metadata.iso.extent.DefaultExtent;
import org.apache.sis.measure.Latitude;
import org.apache.sis.referencing.Builder;
import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.referencing.IdentifiedObjects;
/**
@@ -65,7 +68,7 @@ import org.apache.sis.referencing.CommonCRS;
* @since 0.6
* @module
*/
-public class GeodeticObjectBuilder extends Builder<GeodeticObjectBuilder> {
+public final class GeodeticObjectBuilder extends Builder<GeodeticObjectBuilder> {
/**
* The geodetic datum, or {@code null} if none.
*/
@@ -119,6 +122,24 @@ public class GeodeticObjectBuilder extends Builder<GeodeticObjectBuilder>
{
}
/**
+ * Creates a new builder using the given factories and locale.
+ *
+ * @param factories the factories to use for geodetic objects creation.
+ * @param locale the locale for error message in exceptions.
+ */
+ public GeodeticObjectBuilder(final ReferencingFactoryContainer factories, final Locale
locale) {
+ this.factories = factories;
+ this.locale = locale;
+ }
+
+ /**
+ * Creates a map of properties containing only the name of the given object.
+ */
+ private static Map<String,Object> name(final IdentifiedObject template) {
+ return Collections.singletonMap(IdentifiedObject.NAME_KEY, template.getName());
+ }
+
+ /**
* Sets the domain of validity as a geographic bounding box set to the specified values.
* The bounding box crosses the anti-meridian if {@code eastBoundLongitude} <
{@code westBoundLongitude}.
* If this method has already been invoked previously, the new value overwrites the previous
one.
@@ -498,9 +519,66 @@ public class GeodeticObjectBuilder extends Builder<GeodeticObjectBuilder>
{
}
/**
- * Creates a map of properties containing only the name of the given object.
+ * Replaces the component starting at given index by the given component. This method
can be used for replacing
+ * e.g. the horizontal component of a CRS, or the vertical component, <i>etc.</i>.
If a new compound CRS needs
+ * to be created and a {@linkplain #addName(org.opengis.util.GenericName) name has been
specified}, that name
+ * will be used.
+ *
+ * <p><b>Limitations:</b></p>
+ * Current implementation can replace exactly one component of {@link CompoundCRS}.
+ * If the given replacement spans more than one component, then this method will fail.
+ *
+ * @param source the coordinate reference system in which to replace a component.
+ * @param firstDimension index of the first dimension to replace.
+ * @param replacement the component to insert in place of the CRS component at given
index.
+ * @return a CRS with the component replaced.
+ * @throws FactoryException if the object creation failed.
+ *
+ * @see org.apache.sis.referencing.CRS#getComponentAt(CoordinateReferenceSystem, int,
int)
*/
- private static Map<String,Object> name(final IdentifiedObject template) {
- return Collections.singletonMap(IdentifiedObject.NAME_KEY, template.getName());
+ public CoordinateReferenceSystem replaceComponent(final CoordinateReferenceSystem source,
+ final int firstDimension, final CoordinateReferenceSystem replacement) throws
FactoryException
+ {
+ final int srcDim = ReferencingUtilities.getDimension(source);
+ final int repDim = ReferencingUtilities.getDimension(replacement);
+ if (firstDimension == 0 && srcDim == repDim) {
+ return replacement;
+ }
+ ArgumentChecks.ensureValidIndex(srcDim - repDim, firstDimension);
+ if (source instanceof CompoundCRS) {
+ final CoordinateReferenceSystem[] components = CollectionsExt.toArray(((CompoundCRS)
source).getComponents(), CoordinateReferenceSystem.class);
+ int lower = 0;
+ for (int i=0; i<components.length; i++) {
+ final CoordinateReferenceSystem c = components[i];
+ if (firstDimension >= lower) {
+ /*
+ * Reached the index of the CRS component to replace. Invoke this method
recursively in case we have nested
+ * components, but without using the names and identifiers that may have
been specified for the final CRS.
+ */
+ Object name = properties.remove(IdentifiedObject.NAME_KEY);
+ Object alias = properties.remove(IdentifiedObject.ALIAS_KEY);
+ Object ids = properties.remove(IdentifiedObject.IDENTIFIERS_KEY);
+ final CoordinateReferenceSystem nc = replaceComponent(c, firstDimension
- lower, replacement);
+ /*
+ * Restore the names and identifiers before to create the final CompoundCRS.
If no name was specified,
+ * reuse the primary name of existing CRS but not the identifiers.
+ */
+ if (name == null) {
+ name = source.getName();
+ }
+ properties.put(IdentifiedObject.NAME_KEY, name);
+ properties.put(IdentifiedObject.ALIAS_KEY, alias);
+ properties.put(IdentifiedObject.IDENTIFIERS_KEY, ids);
+ if (nc == c) {
+ return source; // No change.
+ }
+ components[i] = nc;
+ return createCompoundCRS(components);
+ }
+ lower += ReferencingUtilities.getDimension(c);
+ }
+ }
+ throw new IllegalArgumentException(Resources.forLocale(locale).getString(
+ Resources.Keys.CanNotSeparateCRS_1, IdentifiedObjects.getName(source, null)));
}
}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
index a1e900b..1c2d1eb 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
@@ -1337,8 +1337,8 @@ public final class CRS extends Static {
* <li>Otherwise (i.e. no component match), this method returns {@code null}.</li>
* </ul>
*
- * This method does <strong>not</strong> attempt to build new CRS from the
components.
- * For example it does not attempt to create a 3D geographic CRS from a 2D one + a vertical
component.
+ * This method does <strong>not</strong> build new CRS from the components.
For example this method does not
+ * create a {@link CompoundCRS} or a three-dimensional CRS if the given range spans more
than one component.
*
* @param crs the coordinate reference system to decompose, or {@code null}.
* @param lower the first dimension to keep, inclusive.
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridMapping.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridMapping.java
index eaba501..6733462 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridMapping.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridMapping.java
@@ -42,7 +42,6 @@ import org.opengis.referencing.datum.GeodeticDatum;
import org.opengis.referencing.datum.PrimeMeridian;
import org.opengis.referencing.datum.Ellipsoid;
import org.opengis.referencing.datum.PixelInCell;
-import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.CRS;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.referencing.crs.AbstractCRS;
@@ -57,6 +56,7 @@ import org.apache.sis.internal.metadata.AxisDirections;
import org.apache.sis.storage.DataStoreContentException;
import org.apache.sis.coverage.grid.GridGeometry;
import org.apache.sis.coverage.grid.GridExtent;
+import org.apache.sis.internal.referencing.GeodeticObjectBuilder;
import org.apache.sis.internal.referencing.provider.PseudoPlateCarree;
import org.apache.sis.internal.system.Modules;
import org.apache.sis.internal.util.Constants;
@@ -517,28 +517,12 @@ final class GridMapping {
* Replace the grid CRS (or a component of it) by the CRS parsed from WKT
or EPSG code with same (if possible)
* axis order. If the grid CRS contains more axes (for example elevation
or time axis), we try to keep them.
*/
- CoordinateReferenceSystem[] components = {
- CRS.getComponentAt(templateCRS, 0, firstAffectedCoordinate), givenCRS,
- CRS.getComponentAt(templateCRS, firstAffectedCoordinate + subCS.getDimension(),
cs.getDimension())
- };
- int count = 0;
- for (CoordinateReferenceSystem c : components) {
- if (c != null) components[count++] = c;
- }
- switch (count) {
- case 0: /* Keep givenCRS as-is */ break; // Should never
happen.
- case 1: givenCRS = components[0]; break;
- default: {
- components = ArraysExt.resize(components, count);
- Map<String,?> properties = IdentifiedObjects.getProperties(templateCRS);
- try {
- givenCRS = variable.decoder.getCRSFactory().createCompoundCRS(properties,
components);
- } catch (FactoryException e) {
- canNotCreate(variable, Resources.Keys.CanNotCreateCRS_3, e);
- return null;
- }
- break;
- }
+ try {
+ givenCRS = new GeodeticObjectBuilder(variable.decoder, variable.decoder.listeners.getLocale())
+ .replaceComponent(templateCRS, firstAffectedCoordinate,
givenCRS);
+ } catch (FactoryException e) {
+ canNotCreate(variable, Resources.Keys.CanNotCreateCRS_3, e);
+ return null;
}
isSameGrid = templateCRS.equals(givenCRS);
if (isSameGrid) {
|