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: Replace GridGeometry.reduce(lower, upper) by reduce(dimensions) and add test.
Date Fri, 04 Jan 2019 10:32:39 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 d9b0d29  Replace GridGeometry.reduce(lower, upper) by reduce(dimensions) and add
test.
d9b0d29 is described below

commit d9b0d2911f7ee70fc30789f4a7e4addbec8c65dc
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Fri Jan 4 11:31:40 2019 +0100

    Replace GridGeometry.reduce(lower, upper) by reduce(dimensions) and add test.
---
 .../org/apache/sis/coverage/grid/GridExtent.java   | 74 ++++++++++++++++------
 .../org/apache/sis/coverage/grid/GridGeometry.java | 61 ++++++++++--------
 .../org/apache/sis/internal/raster/Resources.java  |  5 ++
 .../sis/internal/raster/Resources.properties       |  1 +
 .../sis/internal/raster/Resources_fr.properties    |  1 +
 .../apache/sis/coverage/grid/GridExtentTest.java   | 21 +++---
 .../apache/sis/coverage/grid/GridGeometryTest.java | 43 ++++++++++++-
 .../main/java/org/apache/sis/referencing/CRS.java  | 10 ++-
 8 files changed, 157 insertions(+), 59 deletions(-)

diff --git a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
index 5b278dd..89b89d1 100644
--- a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
+++ b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
@@ -47,6 +47,7 @@ import org.apache.sis.geometry.Envelopes;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
 import org.apache.sis.referencing.operation.transform.TransformSeparator;
 import org.apache.sis.io.TableAppender;
+import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.iso.Types;
 
 // Branch-dependent imports
@@ -753,35 +754,66 @@ public class GridExtent implements Serializable {
     }
 
     /**
+     * Verifies the validity of a given {@code dimensions} argument.
+     *
+     * @param  dimensions  the user-supplied argument to validate.
+     * @param  limit       maximal number of dimensions, exclusive.
+     * @return {@code true} if the caller can return {@code this}.
+     */
+    static boolean verifyDimensions(final int[] dimensions, final int limit) {
+        ArgumentChecks.ensureNonNull("dimensions", dimensions);
+        final int n = dimensions.length;
+        if (n == 0) {
+            throw new IllegalArgumentException(Errors.format(Errors.Keys.EmptyArgument_1,
"dimensions"));
+        }
+        if (!ArraysExt.isSorted(dimensions, true)) {
+            throw new IllegalArgumentException(Resources.format(Resources.Keys.NotStrictlyOrderedDimensions));
+        }
+        int d = dimensions[0];
+        if (d >= 0) {
+            d = dimensions[n - 1];
+            if (d < limit) {
+                return n == limit;
+            }
+        }
+        throw new IndexOutOfBoundsException(Errors.format(Errors.Keys.IndexOutOfBounds_1,
d));
+    }
+
+    /**
      * Returns a grid envelope that encompass only some dimensions of this grid envelope.
-     * This method copies this grid envelope into a new grid envelope, beginning at dimension
-     * {@code lower} and extending to dimension {@code upper-1} inclusive. Thus the dimension
-     * of the sub grid envelope is {@code upper - lower}.
+     * This method copies the specified dimensions of this grid envelope into a new grid
envelope.
+     * The given dimensions must be in strictly ascending order without duplicated values.
+     * The dimension of the sub grid envelope will be {@code dimensions.length}.
      *
      * <p>This method performs a <cite>dimensionality reduction</cite>
and can be used as the
-     * converse of {@link #append(DimensionNameType, long, long, boolean)}.</p>
+     * converse of {@link #append(DimensionNameType, long, long, boolean)}.
+     * This method can not be used for changing dimension order.</p>
      *
-     * @param  lower  the first dimension to copy, inclusive.
-     * @param  upper  the last  dimension to copy, exclusive.
-     * @return the sub-envelope, or {@code this} if [{@code lower} … {@code upper}] is
[0 … {@link #getDimension() dimension}].
+     * @param  dimensions  the dimensions to select, in strictly increasing order.
+     * @return the sub-envelope, or {@code this} if the given array contains all dimensions
of this grid extent.
      * @throws IndexOutOfBoundsException if an index is out of bounds.
      *
-     * @see GridGeometry#reduce(int, int)
+     * @see GridGeometry#reduce(int...)
      */
-    public GridExtent reduce(final int lower, final int upper) {
-        final int dimension = getDimension();
-        ArgumentChecks.ensureValidIndexRange(dimension, lower, upper);
-        final int newDim = upper - lower;
-        if (newDim == dimension) {
+    public GridExtent reduce(final int... dimensions) {
+        final int sd = getDimension();
+        if (verifyDimensions(dimensions, sd)) {
             return this;
         }
-        DimensionNameType[] axisTypes = types;
-        if (axisTypes != null) {
-            axisTypes = Arrays.copyOfRange(axisTypes, lower, upper);
+        final int td = dimensions.length;
+        DimensionNameType[] tt = null;
+        if (types != null) {
+            tt = new DimensionNameType[td];
+            for (int i=0; i<td; i++) {
+                tt[i] = types[dimensions[i]];
+            }
+        }
+        final GridExtent sub = new GridExtent(td, tt);
+        for (int i=0; i<td; i++) {
+            final int j = dimensions[i];
+            sub.coordinates[i]    = coordinates[j];
+            sub.coordinates[i+td] = coordinates[j+sd];
         }
-        final GridExtent sub = new GridExtent(newDim, axisTypes);
-        System.arraycopy(coordinates, lower,           sub.coordinates, 0,      newDim);
-        System.arraycopy(coordinates, lower+dimension, sub.coordinates, newDim, newDim);
         return sub;
     }
 
@@ -799,7 +831,7 @@ public class GridExtent implements Serializable {
      * grid borders.</div>
      *
      * This method does not reduce the number of dimensions of the grid extent.
-     * For dimensionality reduction, see {@link #reduce(int, int)}.
+     * For dimensionality reduction, see {@link #reduce(int...)}.
      *
      * @param  strides  the strides. Length shall be equal to the number of dimension and
all values shall be greater than zero.
      * @return the sub-sampled extent, or {@code this} is sub-sampling results in the same
extent.
@@ -838,7 +870,7 @@ public class GridExtent implements Serializable {
      * the number of dimensions of the grid extent.
      *
      * <p>This method does not reduce the number of dimensions of the grid extent.
-     * For dimensionality reduction, see {@link #reduce(int, int)}.</p>
+     * For dimensionality reduction, see {@link #reduce(int...)}.</p>
      *
      * @param  slicePoint           where to take a slice. NaN values are handled as if their
dimensions were absent.
      * @param  modifiedDimensions   mapping from {@code slicePoint} dimensions to this {@code
GridExtent} dimensions,
diff --git a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
index 4001abb..9a66bc0 100644
--- a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
+++ b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
@@ -482,35 +482,39 @@ public class GridGeometry implements Serializable {
     }
 
     /**
-     * Creates a new grid geometry over the specified range of dimensions of the given grid
geometry.
+     * Creates a new grid geometry over the specified dimensions of the given grid geometry.
      *
-     * @param  other  the grid geometry to copy.
-     * @param  lower  the first dimension to copy, inclusive.
-     * @param  upper  the last  dimension to copy, exclusive.
+     * @param  other       the grid geometry to copy.
+     * @param  dimensions  the dimensions to select, in strictly increasing order (this may
not be verified).
      * @throws FactoryException if an error occurred while separating the "grid to CRS" transform.
      *
-     * @see #reduce(int, int)
+     * @see #reduce(int...)
      */
-    private GridGeometry(final GridGeometry other, final int lower, final int upper) throws
FactoryException {
-        extent = (other.extent != null) ? other.extent.reduce(lower, upper) : null;
-        final int n = upper - lower;
-        final int[] dimensions;
+    private GridGeometry(final GridGeometry other, int[] dimensions) throws FactoryException
{
+        extent = (other.extent != null) ? other.extent.reduce(dimensions) : null;
+        final int n = dimensions.length;
         if (other.gridToCRS != null) {
+            final int[] sources = dimensions;
             TransformSeparator sep = new TransformSeparator(other.gridToCRS);
-            sep.addSourceDimensionRange(lower, upper);
+            sep.addSourceDimensions(sources);
             gridToCRS  = sep.separate();
             dimensions = sep.getTargetDimensions();
             assert dimensions.length == n : Arrays.toString(dimensions);
-
+            if (!ArraysExt.isSorted(dimensions, true)) {
+                throw new IllegalGridGeometryException(Resources.format(Resources.Keys.IllegalGridGeometryComponent_1,
"dimensions"));
+            }
+            /*
+             * We redo a separation for 'cornerToCRS' instead than applying a translation
of the 'gridToCRS'
+             * computed above because we don't know which of 'gridToCRS' and 'cornerToCRS'
has less NaN values.
+             */
             sep = new TransformSeparator(other.cornerToCRS);
-            sep.addSourceDimensionRange(lower, upper);
+            sep.addSourceDimensions(sources);
             sep.addTargetDimensions(dimensions);
             cornerToCRS = sep.separate();
             assert Arrays.equals(sep.getSourceDimensions(), dimensions) : Arrays.toString(dimensions);
         } else {
             gridToCRS   = null;
             cornerToCRS = null;
-            dimensions  = ArraysExt.sequence(lower, upper);
         }
         final ImmutableEnvelope env = other.envelope;
         if (env != null) {
@@ -653,7 +657,7 @@ public class GridGeometry implements Serializable {
      * In such case the envelope needs to contain all dimensions.</p>
      *
      * <p>This method does not reduce the number of dimensions of this grid geometry.
-     * For dimensionality reduction, see {@link #reduce(int, int)}.</p>
+     * For dimensionality reduction, see {@link #reduce(int...)}.</p>
      *
      * @param  areaOfInterest  the desired spatiotemporal region in any CRS (transformations
will be applied as needed).
      * @return a grid extent of the same dimension than the grid geometry which intersects
the given area of interest.
@@ -681,7 +685,7 @@ public class GridGeometry implements Serializable {
      * See {@link #slice(DirectPosition)} for examples.
      *
      * <p>This method does not reduce the number of dimensions of this grid geometry.
-     * For dimensionality reduction, see {@link #reduce(int, int)}.</p>
+     * For dimensionality reduction, see {@link #reduce(int...)}.</p>
      *
      * @param  slicePoint   the coordinates where to get a slice.
      * @return a slice of the grid extent at the given slice point.
@@ -1024,7 +1028,7 @@ public class GridGeometry implements Serializable {
      * then no sub-sampling will be applied on the missing dimensions.
      *
      * <p>This method does not reduce the number of dimensions of this grid geometry.
-     * For dimensionality reduction, see {@link #reduce(int, int)}.</p>
+     * For dimensionality reduction, see {@link #reduce(int...)}.</p>
      *
      * @param  areaOfInterest    the desired spatiotemporal region in any CRS (transformations
will be applied as needed),
      *                           or {@code null} for not restricting the sub-grid to a sub-area.
@@ -1069,7 +1073,7 @@ public class GridGeometry implements Serializable {
      * </ul></div>
      *
      * This method does not reduce the number of dimensions of this grid geometry.
-     * For dimensionality reduction, see {@link #reduce(int, int)}.
+     * For dimensionality reduction, see {@link #reduce(int...)}.
      *
      * @param  slicePoint   the coordinates where to get a slice.
      * @return a slice of this grid geometry at the given slice point. May be {@code this}.
@@ -1094,24 +1098,25 @@ public class GridGeometry implements Serializable {
 
     /**
      * Returns a grid geometry that encompass only some dimensions of this grid geometry.
-     * This method copies this grid geometry into a new grid geometry, beginning at dimension
-     * {@code lower} and extending to dimension {@code upper-1} inclusive. Thus the dimension
-     * of the sub grid geometry is {@code upper - lower}.
+     * This method copies the specified dimensions of this grid geometry into a new grid
geometry.
+     * The given dimensions must be in strictly ascending order without duplicated values.
+     * The dimension of the sub grid grid geometry will be {@code dimensions.length}.
      *
-     * <p>This method performs a <cite>dimensionality reduction</cite>.</p>
+     * <p>This method performs a <cite>dimensionality reduction</cite>.
+     * This method can not be used for changing dimension order.</p>
      *
-     * @param  lower  the first grid dimension to copy, inclusive.
-     * @param  upper  the last  grid dimension to copy, exclusive.
-     * @return the sub grid geometry, or {@code this} if [{@code lower} … {@code upper}]
is [0 … {@link #getDimension() dimension}].
+     * @param  dimensions  the dimensions to select, in strictly increasing order.
+     * @return the sub grid geometry, or {@code this} if the given array contains all dimensions
of this grid grid geometry.
      * @throws IndexOutOfBoundsException if an index is out of bounds.
      *
-     * @see GridExtent#reduce(int, int)
+     * @see GridExtent#reduce(int...)
+     * @see org.apache.sis.referencing.CRS#reduce(CoordinateReferenceSystem, int...)
      */
-    public GridGeometry reduce(final int lower, final int upper) {
-        if (lower == 0 && upper == getDimension()) {
+    public GridGeometry reduce(final int... dimensions) {
+        if (GridExtent.verifyDimensions(dimensions, getDimension())) {
             return this;
         } else try {
-            return new GridGeometry(this, lower, upper);
+            return new GridGeometry(this, dimensions);
         } catch (FactoryException e) {
             throw new IllegalGridGeometryException(e, "dimensions");
         }
diff --git a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.java b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.java
index 51ef8eb..865cd1d 100644
--- a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.java
+++ b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.java
@@ -145,6 +145,11 @@ public final class Resources extends IndexedResourceBundle {
         public static final short NonLinearInDimensions_1 = 20;
 
         /**
+         * The specified dimensions are not in strictly ascending order.
+         */
+        public static final short NotStrictlyOrderedDimensions = 24;
+
+        /**
          * The ({0}, {1}) pixel coordinate is outside iterator domain.
          */
         public static final short OutOfIteratorDomain_2 = 1;
diff --git a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.properties
b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.properties
index 0f5531c..fd2bd6f 100644
--- a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.properties
+++ b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources.properties
@@ -36,6 +36,7 @@ MismatchedSampleModel             = The two images use different sample
models.
 MismatchedTileGrid                = The two images have different tile grid.
 NoCategoryForValue_1              = No category for value {0}.
 NonLinearInDimensions_1           = non-linear in {0} dimension{0,choice,1#|2#s}:
+NotStrictlyOrderedDimensions      = The specified dimensions are not in strictly ascending
order.
 OutOfIteratorDomain_2             = The ({0}, {1}) pixel coordinate is outside iterator domain.
 PointOutsideCoverageDomain_1      = Point ({0}) is outside the coverage domain.
 TooManyQualitatives               = Too many qualitative categories.
diff --git a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources_fr.properties
b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources_fr.properties
index 0dc3acb..4dcd1d7 100644
--- a/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources_fr.properties
+++ b/core/sis-raster/src/main/java/org/apache/sis/internal/raster/Resources_fr.properties
@@ -41,6 +41,7 @@ MismatchedSampleModel             = Les deux images disposent les pixels
diff\u0
 MismatchedTileGrid                = Les deux images utilisent des grilles de tuiles diff\u00e9rentes.
 NoCategoryForValue_1              = Aucune cat\u00e9gorie n\u2019est d\u00e9finie pour la
valeur {0}.
 NonLinearInDimensions_1           = non-lin\u00e9aire dans {0} dimension{0,choice,1#|2#s}\u2008:
+NotStrictlyOrderedDimensions      = Les dimensions sp\u00e9cifi\u00e9es ne sont pas en ordre
strictement croissant.
 OutOfIteratorDomain_2             = La coordonn\u00e9e pixel ({0}, {1}) est en dehors du
domaine de l\u2019it\u00e9rateur.
 PointOutsideCoverageDomain_1      = Le point ({0}) est en dehors du domaine de la couverture
de donn\u00e9es.
 TooManyQualitatives               = Trop de cat\u00e9gories qualitatives.
diff --git a/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridExtentTest.java
b/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridExtentTest.java
index 01bfeff..c6ca296 100644
--- a/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridExtentTest.java
+++ b/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridExtentTest.java
@@ -122,17 +122,22 @@ public final strictfp class GridExtentTest extends TestCase {
     }
 
     /**
-     * Tests {@link GridExtent#reduce(int, int)}.
+     * Tests {@link GridExtent#reduce(int...)}.
      */
     @Test
     public void testReduce() {
-        GridExtent extent = create3D();
-        extent = extent.reduce(0, 2);
-        assertEquals("dimension", 2, extent.getDimension());
-        assertExtentEquals(extent, 0, 100, 499);
-        assertExtentEquals(extent, 1, 200, 799);
-        assertEquals(DimensionNameType.COLUMN, extent.getAxisType(0).get());
-        assertEquals(DimensionNameType.ROW,    extent.getAxisType(1).get());
+        final GridExtent extent = create3D();
+        GridExtent reduced = extent.reduce(0, 1);
+        assertEquals("dimension", 2, reduced.getDimension());
+        assertExtentEquals(reduced, 0, 100, 499);
+        assertExtentEquals(reduced, 1, 200, 799);
+        assertEquals(DimensionNameType.COLUMN, reduced.getAxisType(0).get());
+        assertEquals(DimensionNameType.ROW,    reduced.getAxisType(1).get());
+
+        reduced = extent.reduce(2);
+        assertEquals("dimension", 1, reduced.getDimension());
+        assertExtentEquals(reduced, 0, 40, 49);
+        assertEquals(DimensionNameType.TIME, reduced.getAxisType(0).get());
     }
 
     /**
diff --git a/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridGeometryTest.java
b/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridGeometryTest.java
index b692e2f..0533f1b 100644
--- a/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridGeometryTest.java
+++ b/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridGeometryTest.java
@@ -20,6 +20,7 @@ import org.opengis.metadata.spatial.DimensionNameType;
 import org.opengis.referencing.datum.PixelInCell;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.referencing.operation.matrix.Matrix2;
 import org.apache.sis.referencing.operation.matrix.Matrix3;
 import org.apache.sis.referencing.operation.matrix.Matrix4;
 import org.apache.sis.referencing.operation.matrix.Matrices;
@@ -368,10 +369,13 @@ public final strictfp class GridGeometryTest extends TestCase {
                         0.5, 0,   0, -180,
                         0,   0,   2,    3,
                         0,   0,   0,    1)), HardCodedCRS.WGS84_3D);
+        /*
+         * There is two ways to ask for a slice. The first way is to set some coordinates
to NaN.
+         */
         GridGeometry slice = grid.slice(new GeneralDirectPosition(Double.NaN, Double.NaN,
15));
         assertNotSame(grid, slice);
         assertSame("gridToCRS", grid.gridToCRS, slice.gridToCRS);
-        final long[] expectedLow  = {336, 20, 6};
+        final long[] expectedLow  = {336,  20, 6};
         final long[] expectedHigh = {401, 419, 6};
         assertExtentEquals(expectedLow, expectedHigh, slice.getExtent());
         /*
@@ -385,4 +389,41 @@ public final strictfp class GridGeometryTest extends TestCase {
         assertSame("gridToCRS", grid.gridToCRS, slice.gridToCRS);
         assertExtentEquals(expectedLow, expectedHigh, slice.getExtent());
     }
+
+    /**
+     * Tests {@link GridGeometry#reduce(int...)}.
+     */
+    @Test
+    public void testReduce() {
+        final GridGeometry grid = new GridGeometry(
+                new GridExtent(null, new long[] {336, 20, 4}, new long[] {401, 419, 10},
true),
+                PixelInCell.CELL_CORNER, MathTransforms.linear(new Matrix4(
+                        0,   0.5, 0,  -90,
+                        0.5, 0,   0, -180,
+                        0,   0,   2,    3,
+                        0,   0,   0,    1)), HardCodedCRS.GEOID_3D);
+        /*
+         * Tests on the two first dimensions.
+         */
+        GridGeometry reduced = grid.reduce(0, 1);
+        assertNotSame(grid, reduced);
+        assertExtentEquals(new long[] {336, 20}, new long[] {401, 419}, reduced.getExtent());
+        assertSame("CRS", HardCodedCRS.WGS84, reduced.getCoordinateReferenceSystem());
+        assertArrayEquals("resolution", new double[] {0.5, 0.5}, reduced.getResolution(false),
STRICT);
+        assertMatrixEquals("gridToCRS", new Matrix3(
+                  0, 0.5,  -90,
+                  0.5, 0, -180,
+                  0,   0,    1), MathTransforms.getMatrix(reduced.getGridToCRS(PixelInCell.CELL_CORNER)),
STRICT);
+        /*
+         * Tests on the last dimension.
+         */
+        reduced = grid.reduce(2);
+        assertNotSame(grid, reduced);
+        assertExtentEquals(new long[] {4}, new long[] {10}, reduced.getExtent());
+        assertSame("CRS", HardCodedCRS.GRAVITY_RELATED_HEIGHT, reduced.getCoordinateReferenceSystem());
+        assertArrayEquals("resolution", new double[] {2}, reduced.getResolution(false), STRICT);
+        assertMatrixEquals("gridToCRS", new Matrix2(
+                  2, 3,
+                  0, 1), MathTransforms.getMatrix(reduced.getGridToCRS(PixelInCell.CELL_CORNER)),
STRICT);
+    }
 }
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 e91666d..f1e837d 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
@@ -933,7 +933,15 @@ public final class CRS extends Static {
 
     /**
      * Gets or creates a coordinate reference system with a subset of the dimensions of the
given CRS.
-     * This method can be used for dimensionality reduction.
+     * This method can be used for dimensionality reduction, but not for changing axis order.
+     * The specified dimensions are used as if they were in strictly increasing order without
duplicated values.
+     *
+     * <div class="section">Ellipsoidal height</div>
+     * This method can transform a three-dimensional geographic CRS into a two-dimensional
geographic CRS.
+     * In this aspect, this method is the converse of {@link #compound(CoordinateReferenceSystem...)}.
+     * This method can also extract the {@linkplain CommonCRS.Vertical#ELLIPSOIDAL ellipsoidal
height}
+     * from a three-dimensional geographic CRS, but this is generally not recommended since
ellipsoidal
+     * heights make little sense without their (<var>latitude</var>, <var>longitude</var>)
locations.
      *
      * @param  crs         the CRS to reduce the dimensionality, or {@code null} if none.
      * @param  dimensions  the dimensions to retain. The dimensions will be taken in increasing
order, ignoring duplicated values.


Mime
View raw message