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 4f56a8248c305e9348aeb433968af2b7697cc9b1 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Tue Nov 30 14:15:57 2021 +0100 `CoverageCanvas` needs to take background value in account during "resample" operations. --- .../java/org/apache/sis/gui/map/StatusBar.java | 8 ++++++- .../org/apache/sis/gui/map/ValuesUnderCursor.java | 24 ++++++++++----------- .../sis/coverage/grid/ResampledGridCoverage.java | 17 +++------------ .../sis/internal/coverage/SampleDimensions.java | 25 ++++++++++++++++++++++ .../sis/internal/map/coverage/RenderingData.java | 1 + 5 files changed, 48 insertions(+), 27 deletions(-) diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/map/StatusBar.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/map/StatusBar.java index 75e74f2..ded8c86 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/gui/map/StatusBar.java +++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/map/StatusBar.java @@ -126,6 +126,12 @@ public class StatusBar extends Widget implements EventHandler<MouseEvent> { private static final Insets PADDING = new Insets(5, Styles.SCROLLBAR_WIDTH, 6, 9); /** + * An arbitrary increase in size of the text field where sample values are shown. + * This is in case {@link #computeSizeOfSampleValues(String, Iterable)} underestimates the required size. + */ + private static final int VALUES_PADDING = 9; + + /** * The container of controls making the status bar. */ private final HBox view; @@ -1242,7 +1248,7 @@ public class StatusBar extends Widget implements EventHandler<MouseEvent> { if (!(width > 0)) { // May be 0 if canvas is not yet added to scene graph. return false; } - sampleValues.setPrefWidth(width); + sampleValues.setPrefWidth(width + VALUES_PADDING); } return true; } diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/map/ValuesUnderCursor.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/map/ValuesUnderCursor.java index 6e8d291..3518f4c 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/gui/map/ValuesUnderCursor.java +++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/map/ValuesUnderCursor.java @@ -333,17 +333,17 @@ public abstract class ValuesUnderCursor { // Same configuration than previous coverage. return; } - final int n = bands.size(); - units = new String[n]; - sampleFormats = new NumberFormat[n]; - outsideText = null; // Will be recomputed on next `evaluate(…)` call. + final int numBands = bands.size(); + units = new String[numBands]; + sampleFormats = new NumberFormat[numBands]; + outsideText = null; // Will be recomputed on next `evaluate(…)` call. /* * Only the first band is initially selected, unless the image has only 2 or 3 bands * in which case all bands are selected. An image with two bands is often giving the * (u,v) components of velocity vectors, which we want to keep together by default. */ selectedBands.clear(); - selectedBands.set(0, (n <= 3) ? n : 1, true); + selectedBands.set(0, (numBands <= 3) ? numBands : 1, true); nodata.clear(); /* * Loop below initializes number formats and unit symbols for all bands, regardless @@ -354,10 +354,10 @@ public abstract class ValuesUnderCursor { final Map<Unit<?>,String> sharedSymbols = new HashMap<>(); final Locale locale = getLocale(property); final UnitFormat unitFormat = new UnitFormat(locale); - final CheckMenuItem[] menuItems = new CheckMenuItem[n]; - for (int i=0; i<n; i++) { - final SampleDimension sd = bands.get(i); - menuItems[i] = createMenuItem(i, sd, locale); + final CheckMenuItem[] menuItems = new CheckMenuItem[numBands]; + for (int b=0; b<numBands; b++) { + final SampleDimension sd = bands.get(b); + menuItems[b] = createMenuItem(b, sd, locale); /* * Build the list of texts to show for missing values. A coverage can have * different NaN values representing different kind of missing values. @@ -365,7 +365,7 @@ public abstract class ValuesUnderCursor { for (final Category c : sd.forConvertedValues(true).getCategories()) { final float value = ((Number) c.getSampleRange().getMinValue()).floatValue(); if (Float.isNaN(value)) try { - nodata.putIfAbsent(toNodataKey(i, value), c.getName().toString(locale)); + nodata.putIfAbsent(toNodataKey(b, value), c.getName().toString(locale)); } catch (IllegalArgumentException e) { recoverableException("changed", e); } @@ -374,7 +374,7 @@ public abstract class ValuesUnderCursor { * Format in advance the units of measurement. If none, an empty string is used. * Note: it is quite common that all bands use the same unit of measurement. */ - units[i] = sd.getUnits().map((unit) -> sharedSymbols.computeIfAbsent(unit, + units[b] = sd.getUnits().map((unit) -> sharedSymbols.computeIfAbsent(unit, (key) -> format(unitFormat, key))).orElse(""); /* * Infer a number of fraction digits to use for the resolution of sample values in each band. @@ -391,7 +391,7 @@ public abstract class ValuesUnderCursor { * - Key -1 is for default format with unspecified number of fraction digits. * - Key -2 is for scientific notation. */ - sampleFormats[i] = sharedFormats.computeIfAbsent(nf, (precision) -> { + sampleFormats[b] = sharedFormats.computeIfAbsent(nf, (precision) -> { switch (precision) { case 0: return NumberFormat.getIntegerInstance(locale); case DEFAULT_FORMAT: return NumberFormat.getNumberInstance(locale); diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ResampledGridCoverage.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ResampledGridCoverage.java index 758678b..d095047 100644 --- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ResampledGridCoverage.java +++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ResampledGridCoverage.java @@ -16,9 +16,7 @@ */ package org.apache.sis.coverage.grid; -import java.util.List; import java.util.Arrays; -import java.util.Optional; import java.awt.Dimension; import java.awt.Rectangle; import java.awt.image.RenderedImage; @@ -32,10 +30,10 @@ import org.opengis.referencing.operation.Matrix; import org.apache.sis.geometry.Envelopes; import org.apache.sis.image.DataType; import org.apache.sis.image.ImageProcessor; -import org.apache.sis.coverage.SampleDimension; import org.apache.sis.geometry.GeneralEnvelope; import org.apache.sis.internal.feature.Resources; import org.apache.sis.internal.util.DoubleDouble; +import org.apache.sis.internal.coverage.SampleDimensions; import org.apache.sis.internal.referencing.DirectPositionView; import org.apache.sis.internal.referencing.ExtendedPrecisionMatrix; import org.apache.sis.referencing.operation.transform.LinearTransform; @@ -54,7 +52,7 @@ import org.apache.sis.util.Utilities; * * @author Martin Desruisseaux (Geomatys) * @author Johann Sorel (Geomatys) - * @version 1.1 + * @version 1.2 * @since 1.1 * @module */ @@ -122,17 +120,8 @@ final class ResampledGridCoverage extends GridCoverage { * If no background value is declared, default is 0 for integer data or * NaN for floating point values. */ - final List<SampleDimension> bands = getSampleDimensions(); - final Number[] fillValues = new Number[bands.size()]; - for (int i=fillValues.length; --i >= 0;) { - final SampleDimension band = bands.get(i); - final Optional<Number> bg = band.getBackground(); - if (bg.isPresent()) { - fillValues[i] = bg.get(); - } - } processor = processor.clone(); - processor.setFillValues(fillValues); + processor.setFillValues(SampleDimensions.backgrounds(getSampleDimensions())); changeOfCRS.setAccuracyOf(processor); imageProcessor = GridCoverageProcessor.unique(processor); final Dimension s = imageProcessor.getInterpolation().getSupportSize(); diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/SampleDimensions.java b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/SampleDimensions.java index 1881373..c0121ec 100644 --- a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/SampleDimensions.java +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/SampleDimensions.java @@ -17,6 +17,7 @@ package org.apache.sis.internal.coverage; import java.util.List; +import java.util.Optional; import java.util.function.DoubleUnaryOperator; import org.apache.sis.coverage.SampleDimension; import org.apache.sis.coverage.Category; @@ -41,6 +42,30 @@ public final class SampleDimensions extends Static { } /** + * Returns the background values of all bands in the given list. + * The length of the returned array is the number of sample dimensions. + * If a sample dimension does not declare a background value, the corresponding array element is null. + * + * @param bands the bands for which to get background values, or {@code null}. + * @return the background values, or {@code null} if the given argument was null. + * Otherwise the returned array is never null but may contain null elements. + */ + public static Number[] backgrounds(final List<SampleDimension> bands) { + if (bands == null) { + return null; + } + final Number[] fillValues = new Number[bands.size()]; + for (int i=fillValues.length; --i >= 0;) { + final SampleDimension band = bands.get(i); + final Optional<Number> bg = band.getBackground(); + if (bg.isPresent()) { + fillValues[i] = bg.get(); + } + } + return fillValues; + } + + /** * Returns the {@code sampleFilters} arguments to use in a call to * {@link ImageProcessor#statistics ImageProcessor.statistics(…)} for excluding no-data values. * If the given sample dimensions are {@linkplain SampleDimension#converted() converted to units of measurement}, diff --git a/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/coverage/RenderingData.java b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/coverage/RenderingData.java index d5ab73f..da8b572 100644 --- a/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/coverage/RenderingData.java +++ b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/coverage/RenderingData.java @@ -278,6 +278,7 @@ public class RenderingData implements Cloneable { */ @SuppressWarnings("AssignmentToCollectionOrArrayFieldFromParameter") public final void setCoverageSpace(final GridGeometry domain, final List<SampleDimension> ranges) { + processor.setFillValues(SampleDimensions.backgrounds(ranges)); dataRanges = ranges; // Not cloned because already an unmodifiable list. dataGeometry = domain; /*