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 c425e58d03fe85716b0587cab0d0b2f806c9dc72 Author: Martin Desruisseaux <[email protected]> AuthorDate: Thu Feb 26 12:16:02 2026 +0100 Fix formatting of resolution in TileMatrixSet. --- .../sis/storage/tiling/TileMatrixSetFormat.java | 16 ++++-- .../apache/sis/util/internal/shared/Numerics.java | 59 ++++++++++++++++++++++ .../apache/sis/gui/coverage/TileMatrixSetPane.java | 2 + 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TileMatrixSetFormat.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TileMatrixSetFormat.java index 38049ca48a..2bc3e1e040 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TileMatrixSetFormat.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TileMatrixSetFormat.java @@ -127,9 +127,9 @@ public class TileMatrixSetFormat extends CompoundFormat<TileMatrixSet> { /** * Updates the axis name in the dimension <var>i</var> of the grid extent. - * This method verifies that all grid dimensions have the same name. + * This method verifies that grid dimensions in all rows have the same axis names. */ - private final void searchCommonAxisName(final String[] gridAxes, final int i) { + private void searchCommonAxisName(final String[] gridAxes, final int i) { tilingScheme.getAxisType(i).ifPresent((axis) -> { final String name = axis.identifier().orElseGet(() -> axis.name().toLowerCase(Locale.US)); final String current = gridAxes[i]; @@ -163,9 +163,15 @@ public class TileMatrixSetFormat extends CompoundFormat<TileMatrixSet> { final int n = Numerics.suggestFractionDigits(ArraysExt.resize(values, count)); format.setMinimumFractionDigits(n); format.setMaximumFractionDigits(n); - for (final Row row : rows) { - if (i < row.resolution.length) { - row.formattedResolution[i] = format.format(row.resolution[i]); + final int column = i; // Because lambda requires final values. + final String[] formatted = Numerics.formatAndTrimTrailingZeros(format, values.length, (j) -> { + final double[] resolution = rows.get(j).resolution; + return (column < resolution.length) ? resolution[column] : Double.NaN; + }); + for (int j=0; j<values.length; j++) { + final String[] resolution = rows.get(j).formattedResolution; + if (i < resolution.length) { + resolution[i] = formatted[j]; } } } diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/Numerics.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/Numerics.java index dae6a203b6..4062f1de00 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/Numerics.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/Numerics.java @@ -18,9 +18,12 @@ package org.apache.sis.util.internal.shared; import java.util.Arrays; import java.text.Format; +import java.text.NumberFormat; import java.text.DecimalFormat; +import java.text.FieldPosition; import java.math.BigInteger; import java.util.function.BiFunction; +import java.util.function.IntToDoubleFunction; import static java.lang.Math.min; import static java.lang.Math.max; import static java.lang.Math.abs; @@ -652,6 +655,62 @@ public final class Numerics { return fractionDigitsForDelta(delta); } + /** + * Gets the character used for zero. + * If the given format is not a {@link DecimalFormat}, arbitrarily returns the white space. + * + * @param format the format for which to get the zero digit. + * @return the zero digit, or {@code ' '} if the format is not decimal. + */ + private static char getZeroDigit(final Format format) { + return (format instanceof DecimalFormat) ? ((DecimalFormat) format).getDecimalFormatSymbols().getZeroDigit() : ' '; + } + + /** + * Formats values then removes the same number of trailing zeros in the fraction digits of all values. + * For this method to be useful, the given format should use a fixed number of fraction digits. + * NaN and infinite values are formatted as usual but ignored in the removal of trailing zeros. + * + * @param format the format to use. + * @param count number of values to format. + * @param values provider of values to format. + * @return an array of length {@code count} with the formatted values. + */ + public static String[] formatAndTrimTrailingZeros(final NumberFormat format, final int count, final IntToDoubleFunction values) { + final var formatted = new String[count]; + final var buffer = new StringBuffer(); + final var fractionEnd = new int[count]; + final var fractionField = new FieldPosition(NumberFormat.Field.FRACTION); + final char zeroDigit = getZeroDigit(format); + int numberOfTrailingZeros = Integer.MAX_VALUE; + for (int i=0; i<count; i++) { + final double value = values.applyAsDouble(i); + String text = format.format(value, buffer, fractionField).toString(); + formatted[i] = text; + if (numberOfTrailingZeros != 0 && Double.isFinite(value)) { + final int end = fractionField.getEndIndex(); + fractionEnd[i] = end; + int firstNonZero = end; + final int start = Math.max(fractionField.getBeginIndex(), end - numberOfTrailingZeros); + while (--firstNonZero > start) { + if (text.charAt(firstNonZero) != zeroDigit) break; + } + numberOfTrailingZeros = Math.min(numberOfTrailingZeros, end - (firstNonZero + 1)); + } + buffer.setLength(0); + } + if (numberOfTrailingZeros != 0) { + for (int i=0; i<count; i++) { + final int end = fractionEnd[i]; + if (end != 0) { + formatted[i] = buffer.append(formatted[i]).delete(end - numberOfTrailingZeros, end).toString(); + buffer.setLength(0); + } + } + } + return formatted; + } + /** * Formats the given value with the given format, using scientific notation if needed. * This is a workaround for {@link DecimalFormat} not switching automatically to scientific notation for large numbers. diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/TileMatrixSetPane.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/TileMatrixSetPane.java index df58248410..1da5ecb6ff 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/TileMatrixSetPane.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/TileMatrixSetPane.java @@ -418,6 +418,8 @@ public class TileMatrixSetPane extends Widget { * The Tile Matrix Set properties are fetched in a background thread. * * @param newValue the Tile Matrix Set to use for building new content. + * + * @todo Defer the execution of the background task if this pane is not currently visible. */ private void tileMatrixSetChanged(final TileMatrixSet newValue) { tileMatrices.getItems().clear();
