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: Provide more information in GridGeometry.toString() and complete the testFromGeospatialEnvelope().
Date Mon, 15 Oct 2018 16:59:52 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 1aebac6  Provide more information in GridGeometry.toString() and complete the testFromGeospatialEnvelope().
1aebac6 is described below

commit 1aebac6decbd299413bff80ca7f510fd7853c34f
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Mon Oct 15 18:59:23 2018 +0200

    Provide more information in GridGeometry.toString() and complete the testFromGeospatialEnvelope().
---
 .../org/apache/sis/coverage/grid/GridExtent.java   |  67 ++++-
 .../org/apache/sis/coverage/grid/GridGeometry.java | 281 ++++++++++++++-------
 .../apache/sis/coverage/grid/GridGeometryTest.java |  20 +-
 .../org/apache/sis/util/resources/Vocabulary.java  |  35 +++
 .../sis/util/resources/Vocabulary.properties       |   7 +
 .../sis/util/resources/Vocabulary_fr.properties    |   7 +
 6 files changed, 309 insertions(+), 108 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 aeefa6e..9ebd773 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
@@ -16,11 +16,14 @@
  */
 package org.apache.sis.coverage.grid;
 
+import java.util.Map;
+import java.util.HashMap;
 import java.util.Arrays;
 import java.util.Optional;
+import java.util.Locale;
 import java.io.Serializable;
-import java.util.Map;
-import java.util.HashMap;
+import java.io.IOException;
+import java.io.UncheckedIOException;
 import org.opengis.geometry.DirectPosition;
 import org.opengis.metadata.spatial.DimensionNameType;
 import org.opengis.referencing.cs.AxisDirection;
@@ -30,6 +33,7 @@ import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.util.collection.WeakValueHashMap;
 import org.apache.sis.internal.metadata.AxisDirections;
 import org.apache.sis.internal.raster.Resources;
@@ -593,20 +597,59 @@ public class GridExtent implements Serializable {
      */
     @Override
     public String toString() {
-        final TableAppender table = new TableAppender(" ");
+        final StringBuilder out = new StringBuilder(256);
+        appendTo(out, Vocabulary.getResources((Locale) null), false);
+        return out.toString();
+    }
+
+    /**
+     * Writes a string representation of this grid envelope in the given buffer.
+     *
+     * @param out         where to write the string representation.
+     * @param vocabulary  resources for some words, or {@code null} if not yet fetched.
+     * @param tree        whether to format lines of a tree in the margin on the left.
+     */
+    final void appendTo(final StringBuilder out, final Vocabulary vocabulary, final boolean
tree) {
+        final TableAppender table = new TableAppender(out, "");
         final int dimension = getDimension();
         for (int i=0; i<dimension; i++) {
-            String name;
-            if ((types == null) || (name = Types.getCodeLabel(types[i])) == null) {
-                name = Integer.toString(i);
+            CharSequence name;
+            if ((types == null) || (name = Types.getCodeTitle(types[i])) == null) {
+                name = vocabulary.getString(Vocabulary.Keys.Dimension_1, i);
             }
-            table.append(name).append(':').nextColumn();
-            table.setCellAlignment(TableAppender.ALIGN_RIGHT);
-            table.append(Long.toString(ordinates[i])).nextColumn();
-            table.append("to").nextColumn();
-            table.append(Long.toString(ordinates[i + dimension])).nextLine();
+            final long lower = ordinates[i];
+            final long upper = ordinates[i + dimension];
             table.setCellAlignment(TableAppender.ALIGN_LEFT);
+            if (tree) {
+                branch(table, i < dimension - 1);
+            }
+            table.append(name).append(": ").nextColumn();
+            table.append('[').nextColumn();
+            table.setCellAlignment(TableAppender.ALIGN_RIGHT);
+            table.append(Long.toString(lower)).append(" … ").nextColumn();
+            table.append(Long.toString(upper)).append("] ") .nextColumn();
+            table.append('(').append(vocabulary.getString(Vocabulary.Keys.CellCount_1,
+                    Long.toUnsignedString(upper - lower + 1))).append(')').nextLine();
+        }
+        flush(table);
+    }
+
+    /**
+     * Formats the symbols on the left side of a node in a tree.
+     */
+    static void branch(final TableAppender table, final boolean hasMore) {
+        table.append(hasMore ? '├' : '└').append("─ ");
+    }
+
+    /**
+     * Writes the content of given table without throwing {@link IOException}.
+     * Shall be invoked only when the destination is known to be {@link StringBuilder}.
+     */
+    static void flush(final TableAppender table) {
+        try {
+            table.flush();
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
         }
-        return table.toString();
     }
 }
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 47d800f..122eba6 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
@@ -18,8 +18,12 @@ package org.apache.sis.coverage.grid;
 
 import java.util.Arrays;
 import java.util.Objects;
+import java.util.Locale;
 import java.io.Serializable;
+import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.awt.image.RenderedImage;            // For javadoc only.
+import org.opengis.metadata.Identifier;
 import org.opengis.geometry.Envelope;
 import org.opengis.geometry.MismatchedDimensionException;
 import org.opengis.referencing.datum.PixelInCell;
@@ -27,18 +31,23 @@ import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.apache.sis.math.MathFunctions;
 import org.apache.sis.geometry.Envelopes;
 import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.geometry.ImmutableEnvelope;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
 import org.apache.sis.referencing.operation.transform.PassThroughTransform;
 import org.apache.sis.internal.raster.Resources;
+import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.Debug;
+import org.apache.sis.io.TableAppender;
 
 
 /**
@@ -323,7 +332,7 @@ public class GridGeometry implements Serializable {
         }
         this.gridToCRS   = PixelTranslation.translate(gridToCRS, anchor, PixelInCell.CELL_CENTER);
         this.cornerToCRS = PixelTranslation.translate(gridToCRS, anchor, PixelInCell.CELL_CORNER);
-        Matrix matrix = MathTransforms.getMatrix(gridToCRS);
+        Matrix scales = MathTransforms.getMatrix(gridToCRS);
         int numToIgnore = 1;
         if (envelope != null && cornerToCRS != null) {
             GeneralEnvelope env = Envelopes.transform(cornerToCRS.inverse(), envelope);
@@ -331,15 +340,15 @@ public class GridGeometry implements Serializable {
             env = extent.toCRS(cornerToCRS);
             env.setCoordinateReferenceSystem(envelope.getCoordinateReferenceSystem());
             this.envelope = new ImmutableEnvelope(env);
-            if (matrix == null) {
-                matrix = gridToCRS.derivative(extent.getCentroid());    // 'gridToCRS' can
not be null if 'cornerToCRS' is non-null.
+            if (scales == null) {
+                scales = gridToCRS.derivative(extent.getCentroid());    // 'gridToCRS' can
not be null if 'cornerToCRS' is non-null.
                 numToIgnore = 0;
             }
         } else {
             this.extent   = null;
             this.envelope = ImmutableEnvelope.castOrCopy(envelope);
         }
-        resolution = (matrix != null) ? resolution(matrix, numToIgnore) : null;
+        resolution = (scales != null) ? resolution(scales, numToIgnore) : null;
         nonLinears = findNonLinearTargets(gridToCRS);
     }
 
@@ -788,12 +797,12 @@ public class GridGeometry implements Serializable {
      * Current implementation is equivalent to the following:
      *
      * {@preformat java
-     *   return toString(EXTENT | CRS | GRID_TO_CRS | RESOLUTION);
+     *   return toString(EXTENT | ENVELOPE | CRS | GRID_TO_CRS | RESOLUTION);
      * }
      */
     @Override
     public String toString() {
-        return toString(EXTENT | CRS | GRID_TO_CRS | RESOLUTION);
+        return toString(EXTENT | ENVELOPE | CRS | GRID_TO_CRS | RESOLUTION);
     }
 
     /**
@@ -801,114 +810,204 @@ public class GridGeometry implements Serializable {
      * The string representation is for debugging purpose only and may change
      * in any future SIS version.
      *
-     * @param  bitmask  any combination of {@link #EXTENT}, {@link #CRS},
-     *         {@link #GRID_TO_CRS} and {@link #RESOLUTION}.
+     * @param  bitmask  combination of {@link #EXTENT}, {@link #ENVELOPE},
+     *         {@link #CRS}, {@link #GRID_TO_CRS} and {@link #RESOLUTION}.
      * @return a string representation of the given elements.
      */
     @Debug
     public String toString(final int bitmask) {
-        if ((bitmask & ~(EXTENT | CRS | GRID_TO_CRS | RESOLUTION)) != 0) {
+        if ((bitmask & ~(EXTENT | ENVELOPE | CRS | GRID_TO_CRS | RESOLUTION)) != 0) {
             throw new IllegalArgumentException(Errors.format(
                     Errors.Keys.IllegalArgumentValue_2, "bitmask", bitmask));
         }
-        final boolean visible = Integer.bitCount(bitmask) >= 2;
-        final int dimension = (extent != null) ? extent.getDimension() : 0;
-        final StringBuilder buffer = new StringBuilder();
-        if ((bitmask & EXTENT) != 0) {
-            appendLabel(buffer, "Grid size", visible);
-            if (dimension == 0) {
-                buffer.append("unspecified");
-            } else {
+        return new Formatter(bitmask).toString();
+    }
+
+    /**
+     * Helper class for formatting a {@link GridGeometry} instance.
+     */
+    private final class Formatter {
+        /**
+         * Combination of {@link #EXTENT}, {@link #ENVELOPE},
+         * {@link #CRS}, {@link #GRID_TO_CRS} and {@link #RESOLUTION}.
+         */
+        private final int bitmask;
+
+        /**
+         * Where to write the {@link GridGeometry} string representation.
+         */
+        private final StringBuilder buffer;
+
+        /**
+         * Platform-specific end-of-line characters.
+         */
+        private final String lineSeparator;
+
+        /**
+         * Localized words.
+         */
+        private final Vocabulary vocabulary;
+
+        /**
+         * The locale for the texts. Not used for numbers and dates.
+         */
+        private final Locale locale;
+
+        /**
+         * The coordinate reference system, or {@code null} if none.
+         */
+        private final CoordinateReferenceSystem crs;
+
+        /**
+         * The coordinate system, or {@code null} if none.
+         */
+        private final CoordinateSystem cs;
+
+        /**
+         * Creates a new formatter for the given combination of {@link #EXTENT}, {@link #ENVELOPE},
+         * {@link #CRS}, {@link #GRID_TO_CRS} and {@link #RESOLUTION}.
+         */
+        Formatter(final int bitmask) {
+            this.bitmask  = bitmask;
+            lineSeparator = System.lineSeparator();
+            locale        = Locale.getDefault(Locale.Category.DISPLAY);
+            vocabulary    = Vocabulary.getResources(locale);
+            buffer        = new StringBuilder(512);
+            crs           = (envelope != null) ? envelope.getCoordinateReferenceSystem()
: null;
+            cs            = (crs != null) ? crs.getCoordinateSystem() : null;
+        }
+
+        /**
+         * Returns a string representation of the enclosing {@link GridGeometry} instance.
+         */
+        @Override
+        public final String toString() {
+            /*
+             * Example: Grid extent
+             * ├─ Dimension 0: [370 … 389]  (20 cells)
+             * └─ Dimension 1: [ 41 … 340] (300 cells)
+             */
+            if (section(EXTENT, Vocabulary.Keys.GridExtent, extent)) {
+                extent.appendTo(buffer, vocabulary, true);
+            }
+            /*
+             * Example: Envelope
+             * ├─ Geodetic latitude:  -69.75 … 80.25  Δφ = 0.5°
+             * └─ Geodetic longitude:   4.75 … 14.75  Δλ = 0.5°
+             */
+            if (section(ENVELOPE, Vocabulary.Keys.Envelope, envelope)) {
+                final boolean appendResolution = (bitmask & RESOLUTION) != 0 &&
resolution != null;
+                final TableAppender table = new TableAppender(buffer, "");
+                final int dimension = envelope.getDimension();
+                for (int i=0; i<dimension; i++) {
+                    final CoordinateSystemAxis axis = (cs != null) ? cs.getAxis(i) : null;
+                    final String name = (axis != null) ? axis.getName().getCode() :
+                            vocabulary.getString(Vocabulary.Keys.Dimension_1, i);
+                    GridExtent.branch(table, i < dimension - 1);
+                    table.append(name).append(": ").nextColumn();
+                    table.setCellAlignment(TableAppender.ALIGN_RIGHT);
+                    table.append(Double.toString(envelope.getLower(i))).nextColumn();
+                    table.setCellAlignment(TableAppender.ALIGN_LEFT);
+                    table.append(" … ").append(Double.toString(envelope.getUpper(i)));
+                    if (appendResolution) {
+                        final boolean isLinear = (i < Long.SIZE) && (nonLinears
& (1L << i)) == 0;
+                        table.nextColumn();
+                        table.append("  Δ");
+                        if (axis != null) {
+                            table.append(axis.getAbbreviation());
+                        }
+                        table.nextColumn();
+                        table.append(' ').append(isLinear ? '=' : '≈').append(' ');
+                        appendResolution(table, i);
+                    }
+                    table.nextLine();
+                }
+                GridExtent.flush(table);
+            } else if (section(RESOLUTION, Vocabulary.Keys.Resolution, resolution)) {
                 /*
-                 * Get the string representations of all GridExtent numbers before to write
them.
-                 * We do that for computing their length, in order to apply right alignment.
+                 * Example: Resolution
+                 * └─ 0.5° × 0.5°
                  */
-                final int NUM_PROPERTIES = 3;
-                final int[] columnSizes = new int[dimension];
-                final String[] values = new String[dimension * NUM_PROPERTIES];      // Will
contain (span, low, high) tuples.
-                for (int i=0; i<values.length; i++) {
-                    final long value;
-                    int margin = 0;
-                    final int dim = i / NUM_PROPERTIES;
-                    switch (i % NUM_PROPERTIES) {
-                        case 0: value = extent.getSize(dim); if (i != 0) margin = 1; break;
-                        case 1: value = extent.getLow (dim); break;
-                        case 2: value = extent.getHigh(dim); break;
-                        default: throw new AssertionError(i);
-                    }
-                    final int length = (values[i] = String.valueOf(value)).length() + margin;
-                    if (length > columnSizes[dim]) columnSizes[dim] = length;
+                String separator = "└─ ";
+                for (int i=0; i<resolution.length; i++) {
+                    appendResolution(buffer.append(separator), i);
+                    separator = " × ";
+                }
+                buffer.append(lineSeparator);
+            }
+            /*
+             * Example: Coordinate reference system
+             * └─ EPSG:4326 — WGS 84 (φ,λ)
+             */
+            if (section(CRS, Vocabulary.Keys.CoordinateRefSys, crs)) {
+                buffer.append("└─ ");
+                final Identifier id = IdentifiedObjects.getIdentifier(crs, null);
+                if (id != null) {
+                    buffer.append(IdentifiedObjects.toString(id)).append(" — ");
                 }
-                for (int t=0; t<NUM_PROPERTIES; t++) {
-                    String separator = ", ";
-                    switch (t) {
-                        case 0: separator = " ×"; break;
-                        case 1: appendLabel(buffer, "Grid low",  visible); break;
-                        case 2: appendLabel(buffer, "Grid high", visible); break;
+                buffer.append(crs.getName()).append(lineSeparator);
+            }
+            /*
+             * Example: Conversion
+             * └─ 2D → 2D non linear in 2
+             */
+            if (section(GRID_TO_CRS, Vocabulary.Keys.Conversion, gridToCRS)) {
+                final Matrix matrix = MathTransforms.getMatrix(gridToCRS);
+                if (matrix != null) {
+                    String separator = "└─ ";
+                    for (final CharSequence line : CharSequences.splitOnEOL(Matrices.toString(matrix)))
{
+                        buffer.append(separator).append(line).append(lineSeparator);
+                        separator = "   ";
                     }
-                    for (int i=0; i<dimension; i++) {
-                        if (i != 0) buffer.append(separator);
-                        final String value = values[i*NUM_PROPERTIES + t];
-                        buffer.append(CharSequences.spaces(columnSizes[i] - value.length())).append(value);
+                } else {
+                    buffer.append("└─ ").append(gridToCRS.getSourceDimensions()).append("D
→ ")
+                                        .append(gridToCRS.getTargetDimensions()).append('D');
+                    long nonLinearDimensions = nonLinears;
+                    String separator = " non linear in ";
+                    while (nonLinearDimensions != 0) {
+                        final int i = Long.numberOfTrailingZeros(nonLinearDimensions);
+                        nonLinearDimensions &= ~(1L << i);
+                        buffer.append(separator).append(cs != null ? cs.getAxis(i).getName()
: String.valueOf(i));
+                        separator = ", ";
                     }
+                    buffer.append(lineSeparator);
                 }
             }
+            return buffer.toString();
         }
-        CoordinateSystem cs = null;
-        if ((bitmask & CRS) != 0) {
-            appendLabel(buffer, "CRS", visible);
-            CoordinateReferenceSystem crs;
-            if (envelope == null || (crs = envelope.getCoordinateReferenceSystem()) == null)
{
-                buffer.append("unspecified");
-            } else {
-                buffer.append(crs.getName());
-                cs = crs.getCoordinateSystem();
-            }
-        }
-        if ((bitmask & GRID_TO_CRS) != 0) {
-            appendLabel(buffer, "Conversion", visible);
-            if (gridToCRS == null) {
-                buffer.append("unspecified");
-            } else {
-                buffer.append(gridToCRS.getSourceDimensions()).append("D → ")
-                      .append(gridToCRS.getTargetDimensions()).append('D');
-                long nonLinearDimensions = nonLinears;
-                String separator = " non linear in ";
-                while (nonLinearDimensions != 0) {
-                    final int i = Long.numberOfTrailingZeros(nonLinearDimensions);
-                    nonLinearDimensions &= ~(1L << i);
-                    buffer.append(separator).append(cs != null ? cs.getAxis(i).getName()
: String.valueOf(i));
-                    separator = ", ";
+
+        /**
+         * Starts a new section for the given property.
+         *
+         * @param  property  one of {@link #EXTENT}, {@link #ENVELOPE}, {@link #CRS}, {@link
#GRID_TO_CRS} and {@link #RESOLUTION}.
+         * @param  title     the {@link Vocabulary} key for the title to show for this section,
if formatted.
+         * @param  value     the value to be formatted in that section.
+         * @return {@code true} if the caller shall format the value.
+         */
+        private boolean section(final int property, final short title, final Object value)
{
+            if ((bitmask & property) != 0) {
+                buffer.append(vocabulary.getString(title)).append(lineSeparator);
+                if (value != null) {
+                    return true;
                 }
+                buffer.append("└─ ").append(vocabulary.getString(Vocabulary.Keys.Unspecified)).append(lineSeparator);
             }
+            return false;
         }
-        if ((bitmask & RESOLUTION) != 0) {
-            appendLabel(buffer, "Resolution", visible);
-            if (resolution == null) {
-                buffer.append("unspecified");
-            } else for (int i=0; i<resolution.length; i++) {
-                if (i != 0) buffer.append(" × ");
-                buffer.append((float) resolution[i]);
+
+        private void appendResolution(final Appendable out, final int dimension) {
+            try {
+                out.append(Float.toString((float) resolution[dimension]));
                 if (cs != null) {
-                    final String unit = String.valueOf(cs.getAxis(i).getUnit());
+                    final String unit = String.valueOf(cs.getAxis(dimension).getUnit());
                     if (unit.isEmpty() || Character.isLetterOrDigit(unit.codePointAt(0)))
{
-                        buffer.append(' ');
+                        out.append(' ');
                     }
-                    buffer.append(unit);
+                    out.append(unit);
                 }
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
             }
         }
-        return buffer.append(System.lineSeparator()).toString();
-    }
-
-    /**
-     * Appends the given text to the given buffer, followed by colon and spaces.
-     * Adjusted for the specific needs of {@link #toString()} implementation.
-     */
-    private static void appendLabel(final StringBuilder appendTo, final String label, final
boolean visible) {
-        if (appendTo.length() != 0) appendTo.append(System.lineSeparator());
-        if (visible) {
-            appendTo.append(label).append(':').append(CharSequences.spaces(12 - label.length()));
-        }
     }
 }
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 1da415f..5c34e88 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
@@ -46,7 +46,7 @@ public final strictfp class GridGeometryTest extends TestCase {
     /**
      * Verifies grid extent coordinates.
      */
-    private static void assertExtentEquals(final GridExtent extent, final long[] low, final
long[] high) {
+    private static void assertExtentEquals(final long[] low, final long[] high, final GridExtent
extent) {
         assertArrayEquals("extent.low",  low,  extent.getLow() .getCoordinateValues());
         assertArrayEquals("extent.high", high, extent.getHigh().getCoordinateValues());
     }
@@ -68,7 +68,7 @@ public final strictfp class GridGeometryTest extends TestCase {
          */
         final MathTransform trCorner = grid.getGridToCRS(PixelInCell.CELL_CORNER);
         assertSame("gridToCRS", identity, trCorner);
-        assertExtentEquals(grid.getExtent(), low, high);
+        assertExtentEquals(low, high, grid.getExtent());
         /*
          * Verify computed math transform.
          */
@@ -114,7 +114,7 @@ public final strictfp class GridGeometryTest extends TestCase {
          */
         final MathTransform trCenter = grid.getGridToCRS(PixelInCell.CELL_CENTER);
         assertSame("gridToCRS", identity, trCenter);
-        assertExtentEquals(grid.getExtent(), low, high);
+        assertExtentEquals(low, high, grid.getExtent());
         /*
          * Verify computed math transform.
          */
@@ -205,7 +205,17 @@ public final strictfp class GridGeometryTest extends TestCase {
             0,   0.5, -90,
             0.5, 0,  -180,
             0,   0,     1}));
-        final GridGeometry grid = new GridGeometry(PixelInCell.CELL_CENTER, gridToCRS, envelope);
-        // TODO: verify values.
+        final GridGeometry grid = new GridGeometry(PixelInCell.CELL_CORNER, gridToCRS, envelope);
+        assertExtentEquals(
+                new long[] {370, 40},
+                new long[] {389, 339}, grid.getExtent());
+        assertEnvelopeEquals(new GeneralEnvelope(
+                new double[] {-70,  5},
+                new double[] {+80, 15}), grid.getEnvelope(), STRICT);
+        assertArrayEquals("resolution", new double[] {0.5, 0.5}, grid.getResolution(false),
STRICT);
+        assertMatrixEquals("gridToCRS", Matrices.create(3, 3, new double[] {
+                0, 0.5,  -89.75,
+                0.5, 0, -179.75,
+                0,   0,    1}), MathTransforms.getMatrix(grid.getGridToCRS(PixelInCell.CELL_CENTER)),
STRICT);
     }
 }
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
index f652cd7..8cffb6f 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
@@ -122,6 +122,11 @@ public final class Vocabulary extends IndexedResourceBundle {
         public static final short CausedBy_1 = 11;
 
         /**
+         * {0} cells
+         */
+        public static final short CellCount_1 = 149;
+
+        /**
          * Character encoding
          */
         public static final short CharacterEncoding = 12;
@@ -162,6 +167,11 @@ public final class Vocabulary extends IndexedResourceBundle {
         public static final short Container = 18;
 
         /**
+         * Conversion
+         */
+        public static final short Conversion = 150;
+
+        /**
          * Coordinate
          */
         public static final short Coordinate = 129;
@@ -262,6 +272,11 @@ public final class Vocabulary extends IndexedResourceBundle {
         public static final short DigitalElevationModel = 146;
 
         /**
+         * Dimension {0}
+         */
+        public static final short Dimension_1 = 148;
+
+        /**
          * Dimensions
          */
         public static final short Dimensions = 34;
@@ -317,6 +332,11 @@ public final class Vocabulary extends IndexedResourceBundle {
         public static final short EntryCount_1 = 121;
 
         /**
+         * Envelope
+         */
+        public static final short Envelope = 151;
+
+        /**
          * Exit
          */
         public static final short Exit = 143;
@@ -352,6 +372,11 @@ public final class Vocabulary extends IndexedResourceBundle {
         public static final short GeographicIdentifier = 135;
 
         /**
+         * Grid extent
+         */
+        public static final short GridExtent = 152;
+
+        /**
          * Height
          */
         public static final short Height = 46;
@@ -617,6 +642,11 @@ public final class Vocabulary extends IndexedResourceBundle {
         public static final short RepresentativeValue = 141;
 
         /**
+         * Resolution
+         */
+        public static final short Resolution = 153;
+
+        /**
          * Root
          */
         public static final short Root = 90;
@@ -732,6 +762,11 @@ public final class Vocabulary extends IndexedResourceBundle {
         public static final short Unnamed = 108;
 
         /**
+         * Unspecified
+         */
+        public static final short Unspecified = 154;
+
+        /**
          * Untitled
          */
         public static final short Untitled = 109;
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
index 41d1935..c2c24a8 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
@@ -27,6 +27,7 @@ AxisChanges             = Axis changes
 BarometricAltitude      = Barometric altitude
 Cardinality             = Cardinality
 CausedBy_1              = Caused by {0}
+CellCount_1             = {0} cells
 CharacterEncoding       = Character encoding
 Characteristics         = Characteristics
 Classpath               = Classpath
@@ -35,6 +36,7 @@ Code_1                  = {0} code
 Commands                = Commands
 ConstantPressureSurface = Constant pressure surface
 Container               = Container
+Conversion              = Conversion
 Coordinate              = Coordinate
 CoordinateRefSys        = Coordinate reference system
 Correlation             = Correlation
@@ -55,6 +57,7 @@ Designation             = Designation
 Destination             = Destination
 Details                 = Details
 DigitalElevationModel   = Digital elevation model
+Dimension_1             = Dimension {0}
 Dimensions              = Dimensions
 Directory               = Directory
 DittoMark               = \u2033
@@ -66,6 +69,7 @@ EllipsoidChange         = Ellipsoid change
 EllipsoidalHeight       = Ellipsoidal height
 EndDate                 = End date
 EntryCount_1            = {0} entr{0,choice,0#y|2#ies}
+Envelope                = Envelope
 Exit                    = Exit
 File                    = File
 Geocentric              = Geocentric
@@ -73,6 +77,7 @@ GeocentricRadius        = Geocentric radius
 GeocentricConversion    = Geocentric conversion
 GeodeticDataset         = Geodetic dataset
 GeographicIdentifier    = Geographic identifier
+GridExtent              = Grid extent
 Height                  = Height
 Identifier              = Identifier
 Implementation          = Implementation
@@ -126,6 +131,7 @@ Read                    = Read
 Remarks                 = Remarks
 RemoteConfiguration     = Remote configuration
 RepresentativeValue     = Representative value
+Resolution              = Resolution
 Root                    = Root
 RootMeanSquare          = Root Mean Square
 Scale                   = Scale
@@ -147,6 +153,7 @@ TruncatedJulian         = Truncated Julian
 Type                    = Type
 Unknown                 = Unknown
 Unnamed                 = Unnamed
+Unspecified             = Unspecified
 Untitled                = Untitled
 UnavailableContent      = Unavailable content.
 Units                   = Units
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
index 3be60cc..7dab7e5 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
@@ -34,6 +34,7 @@ AxisChanges             = Changements d\u2019axes
 BarometricAltitude      = Altitude barom\u00e9trique
 Cardinality             = Cardinalit\u00e9
 CausedBy_1              = Caus\u00e9e par {0}
+CellCount_1             = {0} cellules
 CharacterEncoding       = Encodage des caract\u00e8res
 Characteristics         = Caract\u00e9ristiques
 Classpath               = Chemin de classes
@@ -42,6 +43,7 @@ Code_1                  = Code {0}
 Commands                = Commandes
 ConstantPressureSurface = Surface \u00e0 pression constante
 Container               = Conteneur
+Conversion              = Conversion
 Coordinate              = Coordonn\u00e9e
 CoordinateRefSys        = Syst\u00e8me de r\u00e9f\u00e9rence des coordonn\u00e9es
 Correlation             = Corr\u00e9lation
@@ -62,6 +64,7 @@ Designation             = D\u00e9signation
 Destination             = Destination
 Details                 = D\u00e9tails
 DigitalElevationModel   = Mod\u00e8le num\u00e9rique de terrain
+Dimension_1             = Dimension {0}
 Dimensions              = Dimensions
 Directory               = R\u00e9pertoire
 DittoMark               = \u2033
@@ -73,6 +76,7 @@ EllipsoidChange         = Changement d\u2019ellipso\u00efde
 EllipsoidalHeight       = Hauteur ellipso\u00efdale
 EntryCount_1            = {0} entr\u00e9e{0,choice,0#|2#s}
 EndDate                 = Date de fin
+Envelope                = Enveloppe
 Exit                    = Quitter
 File                    = Fichier
 Geocentric              = G\u00e9ocentrique
@@ -80,6 +84,7 @@ GeocentricRadius        = Rayon g\u00e9ocentrique
 GeocentricConversion    = Conversion g\u00e9ocentrique
 GeodeticDataset         = Base de donn\u00e9es g\u00e9od\u00e9sique
 GeographicIdentifier    = Identifiant g\u00e9ographique
+GridExtent              = \u00c9tendue de la grille
 Height                  = Hauteur
 Identifier              = Identifiant
 Implementation          = Impl\u00e9mentation
@@ -133,6 +138,7 @@ Read                    = Lecture
 Remarks                 = Remarques
 RemoteConfiguration     = Configuration distante
 RepresentativeValue     = Valeur repr\u00e9sentative
+Resolution              = R\u00e9solution
 Root                    = Racine
 RootMeanSquare          = Moyenne quadratique
 Scale                   = \u00c9chelle
@@ -154,6 +160,7 @@ TruncatedJulian         = Julien tronqu\u00e9
 Type                    = Type
 Unknown                 = Inconnu
 Unnamed                 = Sans nom
+Unspecified             = Non-sp\u00e9cifi\u00e9
 Untitled                = Sans titre
 UnavailableContent      = Contenu non-disponible.
 Units                   = Unit\u00e9s


Mime
View raw message