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 db22d5470c243dfab438f440e8ad08f8cee2db59
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Thu Jun 30 11:00:29 2022 +0200

    Adjust the precision of coordinate numbers shown when automatically 
scalling from meters to kilometers.
---
 .../org/apache/sis/geometry/CoordinateFormat.java  | 23 ++++++++++++++++------
 .../apache/sis/geometry/CoordinateFormatTest.java  | 11 +++++++++--
 2 files changed, 26 insertions(+), 8 deletions(-)

diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
 
b/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
index bd629e9ff3..194ae0ec89 100644
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
@@ -25,6 +25,7 @@ import java.text.FieldPosition;
 import java.text.ParsePosition;
 import java.text.ParseException;
 import java.util.Optional;
+import java.util.Set;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.Locale;
@@ -51,6 +52,7 @@ import 
org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.util.LocalizedParseException;
 import org.apache.sis.internal.util.Numerics;
+import org.apache.sis.internal.jdk9.JDK9;
 import org.apache.sis.math.DecimalFunctions;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Errors;
@@ -128,6 +130,13 @@ public class CoordinateFormat extends 
CompoundFormat<DirectPosition> {
      */
     private static final int DEFAULT_DIMENSION = 4;
 
+    /**
+     * Units of measurement which are allowed to be automatically scaled to a 
larger unit.
+     * For example if the unit of measurement of an axis is meter but the 
precision is 1000 metres,
+     * then {@code CoordinateFormat} will automatically uses kilometres units 
instead of metres.
+     */
+    private static final Set<Unit<?>> SCALABLES = JDK9.setOf(Units.METRE, 
Units.PASCAL);
+
     /**
      * The separator between each coordinate values to be formatted.
      * The default value is a EM space space (U+2003).
@@ -819,10 +828,7 @@ public class CoordinateFormat extends 
CompoundFormat<DirectPosition> {
              * fractions of 1 (by contrast, CompactNumberFormat may apply 
fraction to larger values).
              */
             if (format instanceof DecimalFormat && (types == null || 
types[dim] != INDEX)) {
-                final int c = 
Math.max(DecimalFunctions.fractionDigitsForDelta(precision, false), 0);
-                final DecimalFormat nf = (DecimalFormat) getFormatClone(dim);
-                nf.setMinimumFractionDigits(c);
-                nf.setMaximumFractionDigits(c);
+                int digits = 
DecimalFunctions.fractionDigitsForDelta(precision, false);
                 if (unitSymbols != null) {
                     /*
                      * The `units` array can not be null if `unitSymbols` is 
non-null since unit symbols
@@ -830,8 +836,9 @@ public class CoordinateFormat extends 
CompoundFormat<DirectPosition> {
                      * but more general scaling may be added in a future 
version.
                      */
                     final Unit<?> unit = units[dim];
-                    if (Units.METRE.equals(unit) || Units.PASCAL.equals(unit)) 
{
-                        if (precision >= 1000) {
+                    if (SCALABLES.contains(unit)) {
+                        if (precision >= 10) {          // If precision < 
1000, we will use 1 or 2 fraction digits.
+                            digits += 3;                // Because 
`scaleUnit(…)` scales by a factor 1000.
                             scaleUnit(dim, unit);
                         } else if (toFormatUnit != null) {
                             toFormatUnit[dim] = null;
@@ -839,6 +846,10 @@ public class CoordinateFormat extends 
CompoundFormat<DirectPosition> {
                         }
                     }
                 }
+                digits = Math.max(digits, 0);
+                final DecimalFormat nf = (DecimalFormat) getFormatClone(dim);
+                nf.setMinimumFractionDigits(digits);
+                nf.setMaximumFractionDigits(digits);
             } else if (format instanceof AngleFormat) {
                 ((AngleFormat) getFormatClone(dim)).setPrecision(precision, 
true);
             }
diff --git 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/CoordinateFormatTest.java
 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/CoordinateFormatTest.java
index 79427aa5ae..f7ad6838d5 100644
--- 
a/core/sis-referencing/src/test/java/org/apache/sis/geometry/CoordinateFormatTest.java
+++ 
b/core/sis-referencing/src/test/java/org/apache/sis/geometry/CoordinateFormatTest.java
@@ -42,7 +42,7 @@ import static org.junit.Assert.*;
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Michael Hausegger
  *
- * @version 1.1
+ * @version 1.3
  *
  * @see org.apache.sis.measure.AngleFormatTest
  *
@@ -364,9 +364,16 @@ public final strictfp class CoordinateFormatTest extends 
TestCase {
         assertPositionEquals(pos, format.parseObject("400 km E 600 km S"));
         assertPositionEquals(pos, format.parseObject("400,000 m E 600,000 m 
S"));
         /*
-         * Test reverting back to unscaled units.
+         * Scaled units but with a fraction digit.
          */
         format.setPrecisions(100, 200);
+        assertEquals("400.0 km E 600.0 km S", format.format(pos));
+        assertPositionEquals(pos, format.parseObject("400,000 m E 600,000 m 
S"));
+        assertPositionEquals(pos, format.parseObject("400 km E 600 km S"));
+        /*
+         * Test reverting back to unscaled units.
+         */
+        format.setPrecisions(1, 2);
         assertEquals("400,000 m E 600,000 m S", format.format(pos));
         assertPositionEquals(pos, format.parseObject("400,000 m E 600,000 m 
S"));
         assertPositionEquals(pos, format.parseObject("400 km E 600 km S"));

Reply via email to