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 2019/12/19 18:00:15 UTC
[sis] branch geoapi-4.0 updated (0431f2e -> 67c5d18)
This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a change to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git.
from 0431f2e Partial review of GridCoverage.evaluate(DirectPosition) method. - Add a new FractionalGridCoordinates class with some of the calculations done by GridCoverage methods. - Rename toGridCoord as toGridCoordinates and change the return type to FractionalGridCoordinates. - Remove toLongExact(DirectPosition), replaced by FractionalGridCoordinates.
new 4358ee9 Adjustment in the exception thrown if grid coordinates are outside the given bounds.
new 67c5d18 Add an `ImageUtilities` class for methods to be needed by `GridCoverage2D`.
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../coverage/grid/FractionalGridCoordinates.java | 42 ++++--
.../sis/internal/coverage/ImageUtilities.java | 154 +++++++++++++++++++++
.../grid/FractionalGridCoordinatesTest.java | 6 +-
.../sis/internal/coverage/ImageUtilitiesTest.java | 77 +++++++++++
.../apache/sis/test/suite/FeatureTestSuite.java | 1 +
.../org/apache/sis/util/resources/Vocabulary.java | 45 ++++++
.../sis/util/resources/Vocabulary.properties | 9 ++
.../sis/util/resources/Vocabulary_fr.properties | 9 ++
8 files changed, 326 insertions(+), 17 deletions(-)
create mode 100644 core/sis-feature/src/main/java/org/apache/sis/internal/coverage/ImageUtilities.java
create mode 100644 core/sis-feature/src/test/java/org/apache/sis/internal/coverage/ImageUtilitiesTest.java
[sis] 02/02: Add an `ImageUtilities` class for methods to be needed
by `GridCoverage2D`.
Posted by de...@apache.org.
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
commit 67c5d18936c47de51f842a93bbcb597f8d42918b
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Thu Dec 19 18:51:17 2019 +0100
Add an `ImageUtilities` class for methods to be needed by `GridCoverage2D`.
---
.../sis/internal/coverage/ImageUtilities.java | 154 +++++++++++++++++++++
.../sis/internal/coverage/ImageUtilitiesTest.java | 77 +++++++++++
.../apache/sis/test/suite/FeatureTestSuite.java | 1 +
.../org/apache/sis/util/resources/Vocabulary.java | 45 ++++++
.../sis/util/resources/Vocabulary.properties | 9 ++
.../sis/util/resources/Vocabulary_fr.properties | 9 ++
6 files changed, 295 insertions(+)
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/ImageUtilities.java b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/ImageUtilities.java
new file mode 100644
index 0000000..73fa6aa
--- /dev/null
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/ImageUtilities.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.coverage;
+
+import java.util.Arrays;
+import java.awt.color.ColorSpace;
+import java.awt.image.ColorModel;
+import java.awt.image.PackedColorModel;
+import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
+import org.apache.sis.internal.system.Modules;
+import org.apache.sis.util.logging.Logging;
+import org.apache.sis.util.resources.Vocabulary;
+
+
+/**
+ * Utility methods related to images and their color model or sample model.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.1
+ * @since 1.1
+ * @module
+ */
+public final class ImageUtilities {
+ /**
+ * Do not allow instantiation of this class.
+ */
+ private ImageUtilities() {
+ }
+
+ /**
+ * Returns names of bands based on inspection of the color model.
+ * The bands are identified by {@link Vocabulary.Keys} values for
+ * red, green, blue, cyan, magenta, yellow, black, gray, <i>etc</i>.
+ * If a band can not be identified, then its corresponding value is 0.
+ *
+ * @param image the image for which to get band names (can not be null).
+ * @return {@link Vocabulary.Keys} identifying the bands.
+ */
+ @SuppressWarnings("fallthrough")
+ public static short[] bandNames(final RenderedImage image) {
+ final SampleModel sm = image.getSampleModel();
+ final int n;
+ if (sm != null) {
+ n = sm.getNumBands();
+ } else {
+ // Should not happen since SampleModel is essential, but we try to be robust.
+ n = image.getTile(image.getMinTileX(), image.getMinTileY()).getNumBands();
+ }
+ final short[] keys = new short[n];
+ final ColorModel cm = image.getColorModel();
+ if (cm != null) {
+ final ColorSpace cs = cm.getColorSpace();
+ if (cs != null) {
+ /*
+ * Get one of the following sets of color names (ignoring order for now):
+ *
+ * - Red, Green, Blue
+ * - Cyan, Magenta, Yellow, Black
+ * - Gray
+ */
+ switch (cs.getType()) {
+ case ColorSpace.TYPE_CMYK: {
+ if (n >= 4) keys[3] = Vocabulary.Keys.Black;
+ // Fallthrough
+ }
+ case ColorSpace.TYPE_CMY: {
+ switch (n) {
+ default: keys[2] = Vocabulary.Keys.Yellow; // Fallthrough everywhere.
+ case 2: keys[1] = Vocabulary.Keys.Magenta;
+ case 1: keys[0] = Vocabulary.Keys.Cyan;
+ case 0: break;
+ }
+ break;
+ }
+ case ColorSpace.TYPE_RGB: {
+ switch (n) {
+ default: keys[2] = Vocabulary.Keys.Blue; // Fallthrough everywhere.
+ case 2: keys[1] = Vocabulary.Keys.Green;
+ case 1: keys[0] = Vocabulary.Keys.Red;
+ case 0: break;
+ }
+ break;
+ }
+ case ColorSpace.TYPE_GRAY: {
+ if (n != 0) keys[0] = Vocabulary.Keys.Gray;
+ break;
+ }
+ }
+ /*
+ * If the color model has more components than the number of colors,
+ * then the additional component is an alpha channel.
+ */
+ final int nc = cm.getNumColorComponents();
+ if (nc < n && nc < cm.getNumComponents()) {
+ keys[nc] = Vocabulary.Keys.Transparency;
+ }
+ /*
+ * In current version we do not try to adapt the bands order to the masks.
+ * A few tests suggest that the following methods provide the same values:
+ *
+ * - PackedColorModel.getMasks()
+ * - SinglePixelPackedSampleModel.getBitMasks()
+ *
+ * For a BufferedImage.TYPE_INT_ARGB, both methods give in that order:
+ *
+ * masks[0]: 00FF0000 (red)
+ * masks[1]: 0000FF00 (green)
+ * masks[2]: 000000FF (blue)
+ * masks[3]: FF000000 (alpha) — this last element is absent with TYPE_INT_RGB.
+ *
+ * For a BufferedImage.TYPE_INT_BGR, both methods give in that order:
+ *
+ * masks[0]: 000000FF (red)
+ * masks[1]: 0000FF00 (green)
+ * masks[2]: 00FF0000 (blue)
+ *
+ * So it looks like that SampleModel already normalizes the color components
+ * to (Red, Green, Blue) order, at least when the image has been created with
+ * a standard constructor. However we do not know yet what would be the behavior
+ * if masks are not the same. For now we just log a warning.
+ */
+ int[] m1 = null;
+ int[] m2 = null;
+ if (cm instanceof PackedColorModel) {
+ m1 = ((PackedColorModel) cm).getMasks();
+ }
+ if (sm instanceof SinglePixelPackedSampleModel) {
+ m2 = ((SinglePixelPackedSampleModel) sm).getBitMasks();
+ }
+ if (!Arrays.equals(m1, m2)) {
+ // If this logging happen, we should revisit this method and improve it.
+ Logging.getLogger(Modules.RASTER).warning("Band names may be in wrong order.");
+ }
+ }
+ }
+ return keys;
+ }
+}
diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/ImageUtilitiesTest.java b/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/ImageUtilitiesTest.java
new file mode 100644
index 0000000..ba21f6c
--- /dev/null
+++ b/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/ImageUtilitiesTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.coverage;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.RenderedImage;
+import org.apache.sis.util.resources.Vocabulary;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Tests {@link ImageUtilities}.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.1
+ * @since 1.1
+ * @module
+ */
+public final strictfp class ImageUtilitiesTest extends TestCase {
+ /**
+ * Tests {@link ImageUtilities#bandNames(RenderedImage)}.
+ */
+ @Test
+ public void testBandNames() {
+ RenderedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
+ assertArrayEquals(new short[] {
+ Vocabulary.Keys.Red,
+ Vocabulary.Keys.Green,
+ Vocabulary.Keys.Blue,
+ Vocabulary.Keys.Transparency
+ }, ImageUtilities.bandNames(image));
+ /*
+ * Same as above, but without alpha channel.
+ */
+ image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+ assertArrayEquals(new short[] {
+ Vocabulary.Keys.Red,
+ Vocabulary.Keys.Green,
+ Vocabulary.Keys.Blue
+ }, ImageUtilities.bandNames(image));
+ /*
+ * Same as above but in sample values packed in reverse order. Note that while values
+ * are packed in BGR order, the sample model is still providing the values in RGB order.
+ * For that reason, the band order below is the same than in above test.
+ */
+ image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_BGR);
+ assertArrayEquals(new short[] {
+ Vocabulary.Keys.Red,
+ Vocabulary.Keys.Green,
+ Vocabulary.Keys.Blue
+ }, ImageUtilities.bandNames(image));
+ /*
+ * One-banded image.
+ */
+ image = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY);
+ assertArrayEquals(new short[] {
+ Vocabulary.Keys.Gray
+ }, ImageUtilities.bandNames(image));
+ }
+}
diff --git a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
index 2a59156..edd4256 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
@@ -85,6 +85,7 @@ import org.junit.runners.Suite;
org.apache.sis.coverage.CategoryListTest.class,
org.apache.sis.coverage.SampleDimensionTest.class,
org.apache.sis.coverage.SampleRangeFormatTest.class,
+ org.apache.sis.internal.coverage.ImageUtilitiesTest.class,
org.apache.sis.internal.coverage.ScaledColorSpaceTest.class,
org.apache.sis.internal.coverage.BufferedGridCoverageTest.class,
org.apache.sis.internal.coverage.GridCoverage2DTest.class,
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 23aeb70..cf576a6 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,16 @@ public final class Vocabulary extends IndexedResourceBundle {
public static final short BarometricAltitude = 13;
/**
+ * Black
+ */
+ public static final short Black = 175;
+
+ /**
+ * Blue
+ */
+ public static final short Blue = 176;
+
+ /**
* Cardinality
*/
public static final short Cardinality = 14;
@@ -217,6 +227,11 @@ public final class Vocabulary extends IndexedResourceBundle {
public static final short CurrentDirectory = 32;
/**
+ * Cyan
+ */
+ public static final short Cyan = 177;
+
+ /**
* Cycle omitted
*/
public static final short CycleOmitted = 33;
@@ -407,6 +422,16 @@ public final class Vocabulary extends IndexedResourceBundle {
public static final short GeographicIdentifier = 70;
/**
+ * Gray
+ */
+ public static final short Gray = 178;
+
+ /**
+ * Green
+ */
+ public static final short Green = 179;
+
+ /**
* Grid extent
*/
public static final short GridExtent = 71;
@@ -527,6 +552,11 @@ public final class Vocabulary extends IndexedResourceBundle {
public static final short LowerBound = 94;
/**
+ * Magenta
+ */
+ public static final short Magenta = 180;
+
+ /**
* Mandatory
*/
public static final short Mandatory = 95;
@@ -692,6 +722,11 @@ public final class Vocabulary extends IndexedResourceBundle {
public static final short Read = 127;
/**
+ * Red
+ */
+ public static final short Red = 181;
+
+ /**
* Remarks
*/
public static final short Remarks = 128;
@@ -822,6 +857,11 @@ public final class Vocabulary extends IndexedResourceBundle {
public static final short TransformationAccuracy = 152;
/**
+ * Transparency
+ */
+ public static final short Transparency = 183;
+
+ /**
* Truncated Julian
*/
public static final short TruncatedJulian = 153;
@@ -925,6 +965,11 @@ public final class Vocabulary extends IndexedResourceBundle {
* Write
*/
public static final short Write = 173;
+
+ /**
+ * Yellow
+ */
+ public static final short Yellow = 182;
}
/**
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 56682fe..89741cf 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,8 @@ AxisChanges = Axis changes
Azimuth = Azimuth
Band_1 = Band {0}
BarometricAltitude = Barometric altitude
+Black = Black
+Blue = Blue
Cardinality = Cardinality
CausedBy_1 = Caused by {0}
CellCount_1 = {0} cells
@@ -47,6 +49,7 @@ Create = Create
CurrentDateTime = Current date and time
CurrentDirectory = Current directory
CycleOmitted = Cycle omitted
+Cyan = Cyan
DataBase = Database
DataDirectory = Data directory
DataFormats = Data formats
@@ -84,6 +87,8 @@ GeodesicDistance = Geodesic distance
GeodeticDataset = Geodetic dataset
GeographicExtent = Geographic extent
GeographicIdentifier = Geographic identifier
+Gray = Gray
+Green = Green
GridExtent = Grid extent
Height = Height
Identifier = Identifier
@@ -108,6 +113,7 @@ Localization = Localization
LocationType = Location type
Logging = Logging
LowerBound = Lower bound
+Magenta = Magenta
Mandatory = Mandatory
Mapping = Mapping
MaximumValue = Maximum value
@@ -141,6 +147,7 @@ Plugins = Plug-ins
Preprocessing = Preprocessing
Quoted_1 = \u201c{0}\u201d
Read = Read
+Red = Red
Remarks = Remarks
RemoteConfiguration = Remote configuration
RepresentativeValue = Representative value
@@ -167,6 +174,7 @@ Time_1 = {0} time
Timezone = Timezone
Transformation = Transformation
TransformationAccuracy = Transformation accuracy
+Transparency = Transparency
TruncatedJulian = Truncated Julian
Type = Type
Unknown = Unknown
@@ -188,3 +196,4 @@ Warnings = Warnings
WestBound = West bound
World = World
Write = Write
+Yellow = Yellow
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 0e80ee4..e9e6323 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,8 @@ AxisChanges = Changements d\u2019axes
Azimuth = Azimut
Band_1 = Bande {0}
BarometricAltitude = Altitude barom\u00e9trique
+Black = Noir
+Blue = Bleu
Cardinality = Cardinalit\u00e9
CausedBy_1 = Caus\u00e9e par {0}
CellCount_1 = {0} cellules
@@ -53,6 +55,7 @@ CoverageDomain = Domaine de la couverture de donn\u00e9es
Create = Cr\u00e9ation
CurrentDateTime = Date et heure courantes
CurrentDirectory = R\u00e9pertoire courant
+Cyan = Cyan
CycleOmitted = Cycle omit
DataBase = Base de donn\u00e9es
DataDirectory = R\u00e9pertoire des donn\u00e9es
@@ -91,6 +94,8 @@ GeodesicDistance = Distance g\u00e9od\u00e9sique
GeodeticDataset = Base de donn\u00e9es g\u00e9od\u00e9sique
GeographicExtent = \u00c9tendue g\u00e9ographique
GeographicIdentifier = Identifiant g\u00e9ographique
+Gray = Gris
+Green = Vert
GridExtent = \u00c9tendue de la grille
Height = Hauteur
Identifier = Identifiant
@@ -115,6 +120,7 @@ Localization = R\u00e9gionalisation
LocationType = Type de location
Logging = Journalisation
LowerBound = Limite basse
+Magenta = Magenta
Mandatory = Requis
Mapping = Cartographie
MaximumValue = Valeur maximale
@@ -148,6 +154,7 @@ Plugins = Modules d\u2019extension
Preprocessing = Pr\u00e9traitement
Quoted_1 = \u00ab\u202f{0}\u202f\u00bb
Read = Lecture
+Red = Rouge
Remarks = Remarques
RemoteConfiguration = Configuration distante
RepresentativeValue = Valeur repr\u00e9sentative
@@ -174,6 +181,7 @@ Time_1 = Heure {0}
Timezone = Fuseau horaire
Transformation = Transformation
TransformationAccuracy = Pr\u00e9cision de la transformation
+Transparency = Transparence
TruncatedJulian = Julien tronqu\u00e9
Type = Type
Unknown = Inconnu
@@ -195,3 +203,4 @@ Warnings = Avertissements
WestBound = Limite ouest
World = Monde
Write = \u00c9criture
+Yellow = Jaune
[sis] 01/02: Adjustment in the exception thrown if grid coordinates
are outside the given bounds.
Posted by de...@apache.org.
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
commit 4358ee9ab593983b9acff774bb00c2bc24385bd1
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Thu Dec 19 11:04:57 2019 +0100
Adjustment in the exception thrown if grid coordinates are outside the given bounds.
---
.../coverage/grid/FractionalGridCoordinates.java | 42 ++++++++++++++--------
.../grid/FractionalGridCoordinatesTest.java | 6 ++--
2 files changed, 31 insertions(+), 17 deletions(-)
diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/FractionalGridCoordinates.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/FractionalGridCoordinates.java
index d7df49c..89cedbb 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/FractionalGridCoordinates.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/FractionalGridCoordinates.java
@@ -21,6 +21,7 @@ import java.io.Serializable;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.coverage.grid.GridCoordinates;
+import org.opengis.coverage.PointOutsideCoverageException;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
@@ -205,9 +206,10 @@ public class FractionalGridCoordinates implements GridCoordinates, Serializable
* If non-null, then this method enforces the following additional rules:</p>
*
* <ul>
- * <li>Coordinates must be inside the given bounds, otherwise an {@link DisjointExtentException} is thrown.</li>
+ * <li>Coordinates rounded to nearest integers must be inside the given bounds,
+ * otherwise a {@link PointOutsideCoverageException} is thrown.</li>
* <li>If the computed extent overlaps an area outside the bounds, then the extent will be shifted (if an explicit
- * size was given) or clipped (if default size is used) in order to be be fully contained inside the bounds.</li>
+ * size was given) or clipped (if automatic size is used) in order to be be fully contained inside the bounds.</li>
* <li>If a given size is larger than the corresponding bounds {@linkplain GridExtent#getSize(int) size},
* then the returned extent will be clipped to the bounds.</li>
* </ul>
@@ -216,7 +218,7 @@ public class FractionalGridCoordinates implements GridCoordinates, Serializable
* A shift may exist if necessary for keeping the extent inside the {@code bounds} argument, but will never
* move the grid coordinates outside the [<var>low</var> … <var>high</var>+1) range of returned extent.</p>
*
- * @param bounds if the coordinates shall be contained inside a grid, that grid. Otherwise {@code null}.
+ * @param bounds if the coordinates shall be contained inside a grid, that grid extent. Otherwise {@code null}.
* @param size the desired extent sizes as strictly positive numbers, or 0 sentinel values for automatic
* sizes (1 or 2 depending on bounds and coordinate values). This array may have any length;
* if shorter than the number of dimensions, missing values default to 0.
@@ -224,7 +226,8 @@ public class FractionalGridCoordinates implements GridCoordinates, Serializable
* @throws IllegalArgumentException if a {@code size} value is negative.
* @throws ArithmeticException if a coordinate value is outside the range of {@code long} values.
* @throws MismatchedDimensionException if {@code bounds} dimension is not equal to grid coordinates dimension.
- * @throws DisjointExtentException if the returned extent would not intersect the given bounds.
+ * @throws PointOutsideCoverageException if the grid coordinates (rounded to nearest integers) are outside the
+ * given bounds.
* @return a grid extent of the given size (if possible) containing those grid coordinates.
*/
public GridExtent toExtent(final GridExtent bounds, final long... size) {
@@ -257,24 +260,24 @@ public class FractionalGridCoordinates implements GridCoordinates, Serializable
* In such case we can no longer enforce the `lower ≤ value ≤ upper` rule. The best
* we can do is to take the nearest neighbor.
*/
+ final long nearest = Math.round(value);
long lower, upper;
if (margin == 1) {
- lower = upper = Math.round(value);
+ lower = upper = nearest;
} else {
- final double base = Math.floor(value);
- lower = (long) base; // Inclusive.
- upper = (long) Math.ceil(value); // Inclusive too (lower == upper if value is an integer).
+ lower = (long) Math.floor(value); // Inclusive.
+ upper = (long) Math.ceil (value); // Inclusive too (lower == upper if value is an integer).
if (margin != 0) {
- margin -= (upper - lower + 1);
+ margin -= (upper - lower + 1); // Total number of cells to add.
assert margin >= 0 : margin; // Because (upper - lower + 1) ≤ 2
if ((margin & 1) != 0) {
- if (value - base >= 0.5) {
+ if (nearest >= upper) {
upper = Math.incrementExact(upper);
} else {
lower = Math.decrementExact(lower);
}
}
- margin /= 2;
+ margin >>= 1; // Number of cells to add on each side.
lower = Math.subtractExact(lower, margin);
upper = Math.addExact(upper, margin);
margin = 2; // Any value different than 0 for remembering that it was explicitly specified.
@@ -287,8 +290,12 @@ public class FractionalGridCoordinates implements GridCoordinates, Serializable
if (bounds != null) {
final long validMin = bounds.getLow(i);
final long validMax = bounds.getHigh(i);
- if (lower > validMax || upper < validMin) {
- throw new DisjointExtentException(bounds.getAxisIdentification(i,i), validMin, validMax, lower, upper);
+ if (nearest > validMax || nearest < validMin) {
+ final StringBuilder b = new StringBuilder();
+ writeCoordinates(b);
+ throw new PointOutsideCoverageException(
+ Resources.format(Resources.Keys.GridCoordinateOutsideCoverage_4,
+ bounds.getAxisIdentification(i,i), validMin, validMax, b.toString()));
}
if (upper > validMax) {
if (margin != 0) { // In automatic mode (margin = 0) just clip, don't shift.
@@ -439,11 +446,18 @@ public class FractionalGridCoordinates implements GridCoordinates, Serializable
@Override
public String toString() {
final StringBuilder buffer = new StringBuilder("GridCoordinates[");
+ writeCoordinates(buffer);
+ return buffer.append(']').toString();
+ }
+
+ /**
+ * Writes coordinates in the given buffer.
+ */
+ private void writeCoordinates(final StringBuilder buffer) {
for (int i=0; i<coordinates.length; i++) {
if (i != 0) buffer.append(' ');
StringBuilders.trimFractionalPart(buffer.append(coordinates[i]));
}
- return buffer.append(']').toString();
}
/**
diff --git a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/FractionalGridCoordinatesTest.java b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/FractionalGridCoordinatesTest.java
index bb9e0b5..9e8170b 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/FractionalGridCoordinatesTest.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/FractionalGridCoordinatesTest.java
@@ -92,10 +92,10 @@ public final strictfp class FractionalGridCoordinatesTest extends TestCase {
*/
@Test
public void testToExtentBounded() {
- final GridExtent bounds = new GridExtent(null, null, new long[] {4, 2, 7}, true);
+ final GridExtent bounds = new GridExtent(null, new long[] {0, -1, 0}, new long[] {4, 2, 8}, true);
final GridExtent extent = instance().toExtent(bounds, 3, 5, 4);
GridExtentTest.assertExtentEquals(extent, 0, 2, 4);
- GridExtentTest.assertExtentEquals(extent, 1, 0, 2);
- GridExtentTest.assertExtentEquals(extent, 2, 4, 7);
+ GridExtentTest.assertExtentEquals(extent, 1, -1, 2);
+ GridExtentTest.assertExtentEquals(extent, 2, 5, 8);
}
}