sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: 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).
Date Wed, 29 May 2019 16:16:11 GMT
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} &lt;
{@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) {


Mime
View raw message