sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 03/03: Better formatting of GeodeticCalculator, using the default accuracy (currently 1 cm).
Date Sat, 18 May 2019 13:15:19 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

commit 10215933bdc7bd6d5c919cd624485ebc3dad933d
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Sat May 18 15:12:48 2019 +0200

    Better formatting of GeodeticCalculator, using the default accuracy (currently 1 cm).
---
 .../internal/referencing/ReferencingUtilities.java |  37 +++++++
 .../apache/sis/referencing/GeodeticCalculator.java | 106 ++++++++++++++-------
 2 files changed, 110 insertions(+), 33 deletions(-)

diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
index 1d47591..664920d 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
@@ -44,6 +44,7 @@ import org.apache.sis.util.Static;
 import org.apache.sis.util.Utilities;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.AbstractIdentifiedObject;
@@ -52,6 +53,7 @@ import org.apache.sis.referencing.crs.DefaultGeographicCRS;
 import org.apache.sis.referencing.cs.AxesConvention;
 import org.apache.sis.referencing.cs.DefaultEllipsoidalCS;
 import org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory.Context;
+import org.apache.sis.internal.metadata.AxisDirections;
 
 import static java.util.Collections.singletonMap;
 
@@ -559,4 +561,39 @@ public final class ReferencingUtilities extends Static {
         }
         return mapping;
     }
+
+    /**
+     * Returns short names for all axes of the given CRS. This method uses short names like
"Latitude" or "Height",
+     * even if the full ISO 19111 names are "Geodetic latitude" or "Ellipsoidal height".
This is suitable as header
+     * for columns in a table. This method does not include abbreviation or units in the
returned names.
+     *
+     * @param  resources  the resources from which to get "latitude" and "longitude" localized
labels.
+     * @param  crs        the coordinate reference system from which to get axis names.
+     * @return axis names, localized if possible.
+     */
+    public static String[] getShortAxisNames(final Vocabulary resources, final CoordinateReferenceSystem
crs) {
+        final boolean isGeographic = (crs instanceof GeographicCRS);
+        final boolean isProjected  = (crs instanceof ProjectedCRS);
+        final CoordinateSystem cs = crs.getCoordinateSystem();
+        final String[] names = new String[cs.getDimension()];
+        for (int i=0; i<names.length; i++) {
+            short key = 0;
+            final CoordinateSystemAxis axis = cs.getAxis(i);
+            final AxisDirection direction = axis.getDirection();
+            if (AxisDirections.isCardinal(direction)) {
+                final boolean isMeridional = AxisDirection.NORTH.equals(direction) || AxisDirection.SOUTH.equals(direction);
+                if (isGeographic) {
+                    key = isMeridional ? Vocabulary.Keys.Latitude : Vocabulary.Keys.Longitude;
+                } else if (isProjected) {
+                    // We could add "Easting" / "Northing" here for ProjectedCRS in a future
version.
+                }
+            } else if (AxisDirection.UP.equals(direction)) {
+                if (isGeographic | isProjected) {
+                    key = Vocabulary.Keys.Height;
+                }
+            }
+            names[i] = (key != 0) ? resources.getString(key) : axis.getName().getCode();
+        }
+        return names;
+    }
 }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/GeodeticCalculator.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/GeodeticCalculator.java
index d474b26..2138605 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/GeodeticCalculator.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/GeodeticCalculator.java
@@ -20,6 +20,7 @@ import java.awt.Shape;
 import java.util.Locale;
 import java.io.IOException;
 import java.io.UncheckedIOException;
+import java.text.NumberFormat;
 import javax.measure.Unit;
 import javax.measure.quantity.Length;
 
@@ -32,14 +33,16 @@ import org.opengis.geometry.coordinate.Position;
 import org.opengis.geometry.DirectPosition;
 
 import org.apache.sis.io.TableAppender;
-import org.apache.sis.measure.Angle;
+import org.apache.sis.measure.AngleFormat;
 import org.apache.sis.measure.Latitude;
+import org.apache.sis.measure.Units;
 import org.apache.sis.geometry.CoordinateFormat;
 import org.apache.sis.internal.referencing.PositionTransformer;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.referencing.j2d.ShapeUtilities;
 import org.apache.sis.internal.referencing.Resources;
 import org.apache.sis.internal.referencing.Formulas;
+import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.ArgumentChecks;
@@ -693,51 +696,88 @@ public class GeodeticCalculator {
 
     /**
      * Returns a string representation of start point, end point, azimuths and distance.
+     * The text representation is implementation-specific and may change in any future version.
+     * Current implementation is like below:
+     *
+     * {@preformat text
+     *   Coordinate reference system: Unspecified datum based upon the GRS 1980 Authalic
Sphere
+     *   ┌─────────────┬─────────────────┬──────────────────┬─────────────┐
+     *   │             │    Latitude     │    Longitude     │   Azimuth   │
+     *   │ Start point │  9°39′06.1120″N │ 132°37′37.1248″W │  -17°10′37″
│
+     *   │ End point   │ 70°32′45.0206″N │ 109°50′05.0533″E │ -119°03′12″
│
+     *   └─────────────┴─────────────────┴──────────────────┴─────────────┘
+     *   Geodesic distance: 9,967,530.74 m
+     * }
      *
      * @return a string representation of this calculator state.
      */
     @Override
     public String toString() {
-        final Locale     locale    = Locale.getDefault();
-        final Vocabulary resources = Vocabulary.getResources(locale);
-        final StringBuilder buffer = new StringBuilder();
-        final String lineSeparator = System.lineSeparator();
-        final CoordinateReferenceSystem crs = userToGeodetic.getCoordinateReferenceSystem();
-        final boolean isGeographic = crs.equals(userToGeodetic.defaultCRS);
+        final StringBuilder buffer        = new StringBuilder();
+        final Locale        locale        = Locale.getDefault();
+        final Vocabulary    resources     = Vocabulary.getResources(locale);
+        final String        lineSeparator = System.lineSeparator();
+        final CoordinateReferenceSystem crs = getPositionCRS();
         try {
+            /*
+             * Header: name of the Coordinate Reference System.
+             */
             resources.appendLabel(Vocabulary.Keys.CoordinateRefSys, buffer);
             buffer.append(' ').append(crs.getName().getCode()).append(lineSeparator);
-            final TableAppender table = new TableAppender(buffer, " │ ");
-            table.appendHorizontalSeparator();
-            table.nextColumn(); if (isGeographic) table.append(resources.getString(Vocabulary.Keys.Latitude));
-            table.nextColumn(); if (isGeographic) table.append(resources.getString(Vocabulary.Keys.Longitude));
-            for (int i=crs.getCoordinateSystem().getDimension(); --i >= 2;) {
-                table.nextColumn();     // Insert space for additional coordinates, e.g.
ellipsoidal height.
-            }
-            table.nextColumn();
-            table.append(resources.getString(Vocabulary.Keys.Azimuth)).nextLine();
-            final CoordinateFormat cf = new CoordinateFormat(locale, null);
-            cf.setSeparator("\t");      // For distributing coordinate values on different
columns.
-            boolean endPoint = false;
-            do {
-                table.append(resources.getString(endPoint ? Vocabulary.Keys.EndPoint : Vocabulary.Keys.StartPoint))
-                     .nextColumn();
-                try {
-                    cf.format(endPoint ? getEndPoint() : getStartPoint(), table);
+            /*
+             * Start point and end point together with their azimuth, formatted as a table.
+             */
+            if ((validity & (START_POINT | STARTING_AZIMUTH | END_POINT | ENDING_AZIMUTH))
!= 0) {
+                final String[] axes = ReferencingUtilities.getShortAxisNames(resources, crs);
+                final AngleFormat    azimuthFormat = new AngleFormat("DD°MM′SS″", locale);
+                final CoordinateFormat pointFormat = new CoordinateFormat(locale, null);
+                pointFormat.setSeparator("\t");      // For distributing coordinate values
on different columns.
+                pointFormat.setDefaultCRS(crs);
+                pointFormat.setPrecision(Formulas.LINEAR_TOLERANCE, Units.METRE);
+                final TableAppender table = new TableAppender(buffer, " │ ");
+                table.setCellAlignment(TableAppender.ALIGN_CENTER);
+                table.appendHorizontalSeparator();
+                for (final String axis : axes) {
                     table.nextColumn();
-                    table.append(new Angle(endPoint ? getEndingAzimuth() : getStartingAzimuth()).toString());
-                } catch (IllegalStateException | TransformException e) {
-                    // Ignore.
+                    table.append(axis);
                 }
-                table.nextLine();
-            } while ((endPoint = !endPoint) == true);
-            table.appendHorizontalSeparator();
-            table.flush();
-            resources.appendLabel(Vocabulary.Keys.GeodesicDistance, buffer);
+                table.nextColumn();
+                table.append(resources.getString(Vocabulary.Keys.Azimuth)).nextLine();
+                boolean endPoint = false;
+                do {
+                    table.setCellAlignment(TableAppender.ALIGN_LEFT);
+                    table.append(resources.getString(endPoint ? Vocabulary.Keys.EndPoint
: Vocabulary.Keys.StartPoint)).nextColumn();
+                    table.setCellAlignment(TableAppender.ALIGN_RIGHT);
+                    try {
+                        pointFormat.format(endPoint ? getEndPoint() : getStartPoint(), table);
+                        table.nextColumn();
+                        table.append(azimuthFormat.format(endPoint ? getEndingAzimuth() :
getStartingAzimuth()));
+                    } catch (IllegalStateException | TransformException e) {
+                        // Ignore.
+                    }
+                    table.nextLine();
+                } while ((endPoint = !endPoint) == true);
+                table.appendHorizontalSeparator();
+                table.flush();
+            }
+            /*
+             * Distances, formatted with a number of decimal fraction digits suitable for
at least 1 centimetre precision.
+             */
+            try {
+                final Unit<Length> unit = getDistanceUnit();
+                final double distance   = getGeodesicDistance();
+                final double precision  = Units.METRE.getConverterTo(unit).convert(Formulas.LINEAR_TOLERANCE);
+                final NumberFormat nf = NumberFormat.getNumberInstance(locale);
+                nf.setMaximumFractionDigits(max(Numerics.suggestFractionDigits(precision),
0));
+                resources.appendLabel(Vocabulary.Keys.GeodesicDistance, buffer);
+                buffer.append(' ').append(nf.format(distance))
+                      .append(' ').append(unit).append(lineSeparator);
+            } catch (IllegalStateException e) {
+                // Ignore.
+            }
         } catch (IOException e) {
             throw new UncheckedIOException(e);      // Should never happen since we are writting
in a StringBuilder.
         }
-        buffer.append(String.format(locale, " %f %s", geodesicDistance, getDistanceUnit()));
         return buffer.toString();
     }
 }


Mime
View raw message