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 0707557f01169941fd6aa69dc445dc2f0fedb829
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Wed Apr 22 17:50:21 2020 +0200
Make `CoordinateFormat` more robust to change of CRS.
---
.../java/org/apache/sis/gui/map/StatusBar.java | 3 +-
.../gui/referencing/RecentReferenceSystems.java | 10 +-
.../org/apache/sis/geometry/CoordinateFormat.java | 269 ++++++++++++++-------
.../apache/sis/referencing/GeodeticCalculator.java | 3 +-
.../apache/sis/geometry/CoordinateFormatTest.java | 9 +-
5 files changed, 201 insertions(+), 93 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 ae8f08b..5f4abe9 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
@@ -51,6 +51,7 @@ import org.apache.sis.coverage.grid.GridGeometry;
import org.apache.sis.coverage.grid.GridExtent;
import org.apache.sis.portrayal.RenderException;
import org.apache.sis.internal.util.Strings;
+import org.apache.sis.measure.Quantities;
import org.apache.sis.measure.Units;
import org.apache.sis.util.Classes;
import org.apache.sis.util.Exceptions;
@@ -371,7 +372,7 @@ public class StatusBar extends Widget implements EventHandler<MouseEvent>
{
sourceCoordinates = targetCoordinates.coordinates; // Okay to share array
if same dimension.
}
setDisplayCRS(crs);
- format.setPrecision(resolution, unit);
+ format.setGroundPrecision(Quantities.create(resolution, unit));
lastX = lastY = Double.NaN;
}
diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/referencing/RecentReferenceSystems.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/referencing/RecentReferenceSystems.java
index fd4b0da..cba3feb 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/gui/referencing/RecentReferenceSystems.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/referencing/RecentReferenceSystems.java
@@ -590,7 +590,7 @@ public class RecentReferenceSystems {
*/
final ObservableList<ReferenceSystem> items = referenceSystems;
final ComparisonMode mode = duplicationCriterion.get();
- final int count = items.size() - NUM_OTHER_ITEMS;
+ int count = items.size() - NUM_OTHER_ITEMS;
boolean found = false;
for (int i=0; i<count; i++) {
if (Utilities.deepEquals(newValue, items.get(i), mode)) {
@@ -608,7 +608,13 @@ public class RecentReferenceSystems {
*/
if (!found) {
if (count >= NUM_SHOWN_ITEMS) {
- items.remove(count - 1); // Remove the last item before
`OTHER`.
+ final List<ReferenceSystem> selected = getSelectedItems();
+ for (int i=count; --i >= NUM_CORE_ITEMS;) {
+ if (!selected.contains(items.get(i))) { // Do not
remove selected items.
+ items.remove(i); // Remove
an item before `OTHER`.
+ if (--count < NUM_SHOWN_ITEMS) break;
+ }
+ }
}
items.add(Math.min(items.size(), NUM_CORE_ITEMS), newValue);
notifyChanges();
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 4be8aaf..b1e925d 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
@@ -32,6 +32,7 @@ import java.io.IOException;
import java.io.UncheckedIOException;
import javax.measure.Unit;
import javax.measure.UnitConverter;
+import javax.measure.Quantity;
import javax.measure.quantity.Time;
import javax.measure.IncommensurableException;
import org.opengis.geometry.DirectPosition;
@@ -58,6 +59,7 @@ import org.apache.sis.measure.AngleFormat;
import org.apache.sis.measure.Latitude;
import org.apache.sis.measure.Longitude;
import org.apache.sis.measure.Units;
+import org.apache.sis.measure.Quantities;
import org.apache.sis.referencing.CRS;
import org.apache.sis.io.CompoundFormat;
@@ -79,11 +81,10 @@ import org.apache.sis.io.CompoundFormat;
* or by overriding the {@link #createFormat(Class)} protected method.
*
* <h2>Coordinate reference system</h2>
- * If the Coordinate Reference System (CRS) of the positions to format is known, it should
- * {@linkplain #setDefaultCRS(CoordinateReferenceSystem) be specified} before to invoke other
methods in this
- * class because that CRS may impact calculation of properties like the number of fraction
digits achieving a
- * {@linkplain #setPrecision(double, Unit) specified precision}.
- * That default CRS is used only if the {@link DirectPosition} does not specify its own CRS.
+ * {@code CoordinateFormat} uses the {@link DirectPosition#getCoordinateReferenceSystem()}
value for determining
+ * how to format each coordinate value. If the position does not specify a coordinate reference
system, then the
+ * {@linkplain #setDefaultCRS(CoordinateReferenceSystem) default CRS} is assumed. If no default
CRS has been
+ * specified, then all coordinates are formatted as decimal numbers.
*
* <p>{@code CoordinateFormat} does <strong>not</strong> transform the
given coordinates in a unique CRS.
* If the coordinates need to be formatted in a specific CRS, then the caller should
@@ -122,6 +123,9 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
/**
* The separator between each coordinate values to be formatted.
* The default value is a space.
+ *
+ * @see #getSeparator()
+ * @see #setSeparator(String)
*/
private String separator;
@@ -131,6 +135,13 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
private String parseSeparator;
/**
+ * The desired ground precision, or {@code null} if unspecified.
+ *
+ * @see #setGroundPrecision(Quantity)
+ */
+ private Quantity<?> groundPrecision;
+
+ /**
* The desired precisions for each coordinate, or {@code null} if unspecified.
* The length of this array does not need to be equal to the number of dimensions;
* extraneous values are ignored and missing values are assumed equal to 0.
@@ -145,14 +156,29 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
private double[] desiredPrecisions;
/**
+ * Whether the {@link Format} instances have been configured for the precision specified
by
+ * {@link #groundPrecision} and {@link #desiredPrecisions}. We use a field separated
from
+ * {@link #lastCRS} because precision needs to be set only for formatting, not for parsing.
+ *
+ * @see #setPrecisions(double...)
+ * @see #setGroundPrecision(Quantity)
+ * @see #configure(CoordinateReferenceSystem)
+ */
+ private transient boolean isPrecisionApplied;
+
+ /**
* The coordinate reference system to assume if no CRS is attached to the position to
format.
* May be {@code null}.
+ *
+ * @see #setDefaultCRS(CoordinateReferenceSystem)
*/
private CoordinateReferenceSystem defaultCRS;
/**
- * The coordinate reference system of the last {@link DirectPosition} that we formatted.
+ * The coordinate reference system of the last {@link DirectPosition} that we parsed
or formatted.
* This is used for determining if we need to recompute all other transient fields in
this class.
+ *
+ * @see #createFormats(CoordinateReferenceSystem)
*/
private transient CoordinateReferenceSystem lastCRS;
@@ -164,6 +190,8 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
/**
* The type for each value in the {@code formats} array, or {@code null} if not yet computed.
* Types are: 0=number, 1=longitude, 2=latitude, 3=other angle, 4=date, 5=elapsed time.
+ *
+ * @see #createFormats(CoordinateReferenceSystem)
*/
private transient byte[] types;
@@ -172,6 +200,8 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
* not been able to configure the precision. This is the same array than {@link #formats},
* unless {@link #setPrecisions(double...)} has been invoked.
* Values at different indices may reference the same {@link Format} instance.
+ *
+ * @see #createFormats(CoordinateReferenceSystem)
*/
private transient Format[] sharedFormats;
@@ -179,6 +209,8 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
* The formats to use for formatting each coordinate value, or {@code null} if not yet
computed.
* The length of this array should be equal to the number of dimensions in {@link #lastCRS}.
* Values at different indices may reference the same {@link Format} instance.
+ *
+ * @see #createFormats(CoordinateReferenceSystem)
*/
private transient Format[] formats;
@@ -271,7 +303,7 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
/**
* Returns the coordinate reference system to use if no CRS is explicitly associated
to a given {@code DirectPosition}.
* This CRS determines the type of format to use for each coordinate (number, angle or
date) and the number of fraction
- * digits to use for achieving a {@linkplain #setPrecision(double, Unit) specified precision}.
+ * digits to use for achieving a {@linkplain #setGroundPrecision(Quantity) specified
precision on ground}.
*
* @return the default coordinate reference system, or {@code null} if none.
*/
@@ -291,33 +323,44 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
}
/**
- * Computes the value of transient fields from the given CRS.
+ * Computes the values of transient fields from the given CRS. The {@link #lastCRS} field
is set to the given CRS
+ * for allowing callers to check if this method needs to be invoked again (this method
does not check by itself).
+ * This method does not configure the formats for precisions specified by {@link #setPrecisions(double...)}
and
+ * related methods; that work is done by {@link #configure(CoordinateReferenceSystem)}
at formatting time
+ * (it is not needed at parsing time).
+ *
+ * @param crs the CRS for which to create the {@link Format} instances.
+ *
+ * @see #configure(CoordinateReferenceSystem)
*/
- private void configure(final CoordinateReferenceSystem crs) {
- types = null;
- formats = null;
- sharedFormats = null;
- units = null;
- toFormatUnit = null;
- unitSymbols = null;
- epochs = null;
- negate = 0;
- lastCRS = crs;
- if (crs == null) {
- return;
- }
+ private void createFormats(final CoordinateReferenceSystem crs) {
+ types = null;
+ formats = null;
+ sharedFormats = null;
+ units = null;
+ toFormatUnit = null;
+ unitSymbols = null;
+ epochs = null;
+ negate = 0L;
+ lastCRS = crs;
+ isPrecisionApplied = false;
/*
* If no CRS were specified, we will format everything as numbers. Working with null
CRS
* is sometime useful because null CRS are allowed in DirectPosition according ISO
19107.
- * Otherwise (if a CRS is given), infer the format subclasses from the axes.
*/
+ if (crs == null) {
+ return;
+ }
final CoordinateSystem cs = crs.getCoordinateSystem();
if (cs == null) {
return; // Paranoiac check (should never be
null).
}
- final int dimension = cs.getDimension();
- final byte[] types = new byte [dimension];
- final Format[] formats = new Format[dimension];
+ /*
+ * Otherwise (if a CRS is given), infer the format subclasses from the axes.
+ */
+ final int dimension = cs.getDimension();
+ final byte[] types = new byte [dimension];
+ final Format[] formats = new Format[dimension];
for (int i=0; i<dimension; i++) {
final CoordinateSystemAxis axis = cs.getAxis(i);
if (axis == null) { // Paranoiac
check.
@@ -383,9 +426,9 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
}
}
}
- this.types = types; // Assign only on success.
+ this.types = types; // Assign only on success.
this.formats = formats;
- sharedFormats = formats;
+ sharedFormats = formats; // `getFormatClone(int)` will separate arrays later
if needed.
}
/**
@@ -461,9 +504,7 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
* @since 1.1
*/
public double[] getPrecisions() {
- if (lastCRS != defaultCRS) {
- configure(defaultCRS);
- }
+ configure(defaultCRS);
Format[] cf = formats;
if (cf == null) {
cf = new Format[DEFAULT_DIMENSION];
@@ -492,21 +533,21 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
* will be shown with two fraction digits when formatted as decimal numbers, or with
"D°MM"
* pattern when formatted as angles.
*
- * <p>This precision does not have a clear relationship to the precision on the
ground.
+ * <p>This precision does not have a direct relationship to the precision on the
ground.
* For example a precision of 0.01 could be one centimeter or 10 meters, depending if
* the units of measurement in that dimension is meter or kilometer.
- * For a precision related to the ground, use {@link #setPrecision(double, Unit)} instead.</p>
+ * For a precision related to the ground, use {@link #setGroundPrecision(Quantity)} instead.</p>
*
* <p>If any value in the given array is 0 or {@link Double#NaN}, then there is
a choice:
- * if {@link #setPrecision(double, Unit)} has been invoked, the ground precision specified
to that
+ * if {@link #setGroundPrecision(Quantity)} has been invoked, the precision specified
to that
* method will apply (if possible). Otherwise an implementation-specific default precision
is used.
- * So it is possible to use {@link #setPrecision(double, Unit)} for specifying a precision
in "real
- * world" units and to use this {@code setPrecisions(double...)} method for adjusting
the precision
- * of only the vertical axis for example.</p>
+ * A typical use case is to use {@link #setGroundPrecision(Quantity)} for specifying
an horizontal
+ * precision in "real world" units and to use this {@code setPrecisions(double...)} method
for adjusting
+ * the precision of the vertical axis only.</p>
*
* @param precisions desired precision at which to format coordinate values in each
dimension
- * (may have 0 values for unspecified precision in some of those
dimensions),
- * or {@code null} for restoring the default values.
+ * (may have 0 or {@link Double#NaN} values for unspecified precisions
in some
+ * of those dimensions), or {@code null} for restoring the default
values.
*
* @see AngleFormat#setPrecision(double, boolean)
* @see DecimalFormat#setMaximumFractionDigits(int)
@@ -514,20 +555,27 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
* @since 1.1
*/
public void setPrecisions(final double... precisions) {
+ /*
+ * Implementation note: this method configures (indirectly through calls to `applyPrecision(int)`)
+ * the formats given in the `formats` array but does not touch the `sharedFormats`
array. This is
+ * the opposite of `setGroundPrecision(…)` which performs a more global change
that affect formats
+ * in the `sharedFormats` array.
+ */
if (precisions == null) {
desiredPrecisions = null;
- formats = sharedFormats;
+ formats = sharedFormats; // `getFormatClone(int)` will separate arrays
later if needed.
} else {
- if (desiredPrecisions == null || desiredPrecisions.length != 0) {
+ if (desiredPrecisions == null || desiredPrecisions.length != precisions.length)
{
desiredPrecisions = new double[precisions.length];
- Arrays.fill(desiredPrecisions, Double.NaN);
+ // Initial zero values mean "unspecified".
}
+ isPrecisionApplied &= (formats != null);
for (int i=0; i<precisions.length; i++) {
double p = Math.abs(precisions[i]);
if (!(p < Double.POSITIVE_INFINITY)) p = 0; // Use ! for
replacing NaN.
if (desiredPrecisions[i] != (desiredPrecisions[i] = p)) {
// Precision changed. Keep format up to date.
- if (formats != null && i < formats.length) {
+ if (isPrecisionApplied && i < formats.length) {
applyPrecision(i);
}
}
@@ -544,7 +592,7 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
private void applyPrecision(final int dim) {
final double precision = desiredPrecisions[dim];
if (precision > 0) {
- final Format format = formats[dim];
+ final Format format = formats[dim]; // Will be cloned below if
needed.
/*
* Intentionally check the DecimalFormat subtype, not the more generic NumberFormat
type,
* because the calculation below assumes base 10 and assumes that fraction digits
are for
@@ -562,13 +610,57 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
}
/**
+ * Computes the values of transient fields from the given CRS and configure the format
precisions.
+ * This method updates the {@link #lastCRS} and {@link #isPrecisionApplied} fields.
+ * This method does nothing if above-cited fields are already up to date.
+ *
+ * @param crs the CRS for which to create and configure the {@link Format} instances.
+ *
+ * @see #createFormats(CoordinateReferenceSystem)
+ */
+ private void configure(final CoordinateReferenceSystem crs) {
+ if (lastCRS != crs) {
+ createFormats(crs); // This method sets the `lastCRS` field.
+ }
+ if (!isPrecisionApplied) {
+ if (groundPrecision != null) {
+ applyGroundPrecision(crs);
+ }
+ if (desiredPrecisions != null) {
+ if (sharedFormats == null) {
+ formats = sharedFormats = new Format[desiredPrecisions.length];
+ Arrays.fill(formats, getDefaultFormat());
+ types = new byte[formats.length];
+ }
+ final int n = Math.min(desiredPrecisions.length, formats.length);
+ for (int i=0; i<n; i++) {
+ applyPrecision(i); // Will clone Format instances if needed.
+ }
+ }
+ isPrecisionApplied = true;
+ }
+ }
+
+ /**
+ * @deprecated Renamed {@link #setGroundPrecision(Quantity)}
+ * for avoiding confusion with {@link #setPrecisions(double...)}.
+ *
+ * @param resolution the desired resolution.
+ * @param unit unit of the desired resolution.
+ *
+ * @since 1.0
+ */
+ @Deprecated
+ public void setPrecision(double resolution, Unit<?> unit) {
+ setGroundPrecision(Quantities.create(resolution, unit));
+ }
+
+ /**
* Adjusts the number of fraction digits to show in coordinates for achieving the given
precision.
* The {@link NumberFormat} and {@link AngleFormat} are configured for coordinates expressed
in the
- * {@linkplain #getDefaultCRS() default coordinate reference system} defined at the moment
this method is invoked.
- * The number of fraction digits is <em>not</em> updated if a different CRS
is specified after this method call
- * or if the coordinates to format are associated to a different CRS.
+ * coordinate reference system of the position to format.
*
- * <p>The given resolution will be converted to the units used by coordinate system
axes. For example if a 10 metres
+ * The given resolution will be converted to the units used by coordinate system axes.
For example if a 10 metres
* resolution is specified but the {@linkplain #getDefaultCRS() default CRS} axes use
kilometres, then this method
* converts the resolution to 0.01 kilometre and uses that value for inferring that coordinates
should be formatted
* with 2 fraction digits. If the resolution is specified in an angular units such as
degrees, this method uses the
@@ -576,21 +668,41 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
* computing an equivalent resolution in linear units. For example if the ellipsoid of
default CRS is WGS84,
* then this method considers a resolution of 1 second of angle as equivalent to a resolution
of about 31 meters.
* Conversions work also in the opposite direction (from linear to angular units) and
are also used for choosing
- * which angle fields (degrees, minutes or seconds) to show.</p>
+ * which angle fields (degrees, minutes or seconds) to show.
*
- * @param resolution the desired resolution.
- * @param unit unit of the desired resolution.
+ * <p>If both {@link #setPrecisions(double...)} and {@code setGroundPrecision(Quantity)}
are used,
+ * then the values specified with {@code setPrecisions(…)} have precedence and this
ground precision
+ * is used only as a fallback. A typical use case is to specify the ground precision
for horizontal
+ * dimensions, then to specify a different precision <var>dz</var> for the
vertical axis only with
+ * {@code setPrecisions(NaN, NaN, dz)}.</p>
+ *
+ * @param precision the desired precision together with its linear or angular unit.
*
* @see DecimalFormat#setMaximumFractionDigits(int)
* @see AngleFormat#setPrecision(double, boolean)
*
- * @since 1.0
+ * @since 1.1
*/
@SuppressWarnings("null")
- public void setPrecision(double resolution, Unit<?> unit) {
- ArgumentChecks.ensureFinite("resolution", resolution);
- ArgumentChecks.ensureNonNull("unit", unit);
- resolution = Math.abs(resolution);
+ public void setGroundPrecision(final Quantity<?> precision) {
+ ArgumentChecks.ensureNonNull("precision", precision);
+ groundPrecision = precision;
+ if (isPrecisionApplied) {
+ applyGroundPrecision(lastCRS);
+ }
+ }
+
+ /**
+ * Configures the formats for {@link #groundPrecision} value. Contrarily to {@link #applyPrecision(int)},
+ * this method modifies the default formats provided by {@link #getFormat(Class)}. They
are the formats
+ * stored in the {@link #sharedFormats} array. Those formats are used as fallback when
the {@link #formats}
+ * array does not provide more specific format.
+ *
+ * @param crs the target CRS in the conversion from ground units to CRS units.
+ */
+ private void applyGroundPrecision(final CoordinateReferenceSystem crs) {
+ final double resolution = Math.abs(groundPrecision.getValue().doubleValue());
+ final Unit<?> unit = groundPrecision.getUnit();
if (Units.isTemporal(unit)) {
return; // Setting temporal resolution is not
yet implemented.
}
@@ -603,7 +715,7 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
Resolution related = null;
IncommensurableException error = null;
if (specified.isAngular || Units.isLinear(unit)) try {
- related = specified.related(ReferencingUtilities.getEllipsoid(defaultCRS));
+ related = specified.related(ReferencingUtilities.getEllipsoid(crs));
} catch (IncommensurableException e) {
error = e;
}
@@ -613,8 +725,8 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
* units which result in the finest resolution.
*/
boolean relatedUsed = false;
- if (defaultCRS != null) {
- final CoordinateSystem cs = defaultCRS.getCoordinateSystem();
+ if (crs != null) {
+ final CoordinateSystem cs = crs.getCoordinateSystem();
if (cs != null) { // Paranoiac
check (should never be null).
final int dimension = cs.getDimension();
for (int i=0; i<dimension; i++) {
@@ -636,7 +748,7 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
}
}
if (error != null) {
- Logging.unexpectedException(Logging.getLogger(Loggers.MEASURE), CoordinateFormat.class,
"setPrecision", error);
+ Logging.unexpectedException(Logging.getLogger(Loggers.MEASURE), CoordinateFormat.class,
"setGroundPrecision", error);
}
specified.setPrecision(this);
if (relatedUsed) {
@@ -646,9 +758,9 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
/**
* Desired resolution in a given units, together with methods for converting to the units
of a coordinate system axis.
- * This is a helper class for {@link CoordinateFormat#setPrecision(double, Unit)} implementation.
An execution of that
- * method typically creates two instances of this {@code Resolution} class: one for the
resolution in metres and another
- * one for the resolution in degrees.
+ * This is a helper class for {@link CoordinateFormat#setGroundPrecision(Quantity)} implementation.
An execution of
+ * that method typically creates two instances of this {@code Resolution} class: one
for the resolution in metres
+ * and another one for the resolution in degrees.
*/
private static final class Resolution {
/** The desired resolution in the unit of measurement given by {@link #unit}. */
@@ -726,7 +838,8 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
/**
* Configures the {@link NumberFormat} or {@link AngleFormat} for a number of fraction
digits
- * sufficient for the given resolution.
+ * sufficient for the given resolution. This method configures the shared formats
returned by
+ * {@link #getFormat(Class)}. They are the formats stored in the {@link #sharedFormats}
array.
*/
void setPrecision(final CoordinateFormat owner) {
final Format format = owner.getFormat(isAngular ? Angle.class : Number.class);
@@ -872,26 +985,12 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
if (crs == null) {
crs = defaultCRS; // May still be null.
}
- if (crs != lastCRS) {
- configure(crs);
- }
/*
- * Unconditionally configure the formatters for the desired precisions because those
precisions
- * may change for every point. Note that the formatters may not have been created
if the CRS is
- * null (because `configure(…)` does not know which format to use), in which case
generic number
- * formats will be used.
+ * Configure the formatters for the desired precision, which can potentially change
for each point.
+ * Note that the formatters may not have been created if the CRS is null (because
`createFormats(…)`
+ * does not know which format to use), in which case generic number formats will
be used.
*/
- if (desiredPrecisions != null) {
- if (sharedFormats == null) {
- formats = sharedFormats = new Format[desiredPrecisions.length];
- Arrays.fill(formats, getDefaultFormat());
- types = new byte[formats.length];
- }
- final int n = Math.min(desiredPrecisions.length, formats.length);
- for (int i=0; i<n; i++) {
- applyPrecision(i);
- }
- }
+ configure(crs);
/*
* Standard java.text.Format API can only write into a StringBuffer. If the given
Appendable is not a
* StringBuffer, then we will need to format in a temporary buffer before to copy
to the Appendable.
@@ -937,7 +1036,7 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
case LONGITUDE: object = new Longitude (value); break;
case LATITUDE: object = new Latitude (value); break;
case ANGLE: object = new Angle (value); break;
- case DATE: object = new Date(Math.round(value) + epochs[i]); break;
+ case DATE: object = new Date(Math.addExact(Math.round(value), epochs[i]));
break;
}
} else {
object = value;
@@ -1005,7 +1104,7 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
* If no such CRS has been specified, then we will parse everything as plain numbers.
*/
if (lastCRS != defaultCRS) {
- configure(defaultCRS);
+ createFormats(defaultCRS);
}
final double[] coordinates;
Format format;
@@ -1079,7 +1178,7 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
if (object instanceof Angle) {
value = ((Angle) object).degrees();
} else if (object instanceof Date) {
- value = ((Date) object).getTime() - epochs[i];
+ value = Math.subtractExact(((Date) object).getTime(), epochs[i]);
} else {
value = ((Number) object).doubleValue();
}
@@ -1150,7 +1249,7 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition>
{
final CoordinateFormat clone = (CoordinateFormat) super.clone();
clone.dummy = null;
clone.buffer = null;
- clone.configure(null);
+ clone.createFormats(null);
if (desiredPrecisions != null) {
clone.desiredPrecisions = desiredPrecisions.clone();
}
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 8ed2c3b..4dd9582 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
@@ -36,6 +36,7 @@ import org.opengis.geometry.DirectPosition;
import org.apache.sis.measure.AngleFormat;
import org.apache.sis.measure.Latitude;
import org.apache.sis.measure.Units;
+import org.apache.sis.measure.Quantities;
import org.apache.sis.geometry.CoordinateFormat;
import org.apache.sis.internal.referencing.PositionTransformer;
import org.apache.sis.internal.referencing.ReferencingUtilities;
@@ -1109,7 +1110,7 @@ public class GeodeticCalculator {
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);
+ pointFormat.setGroundPrecision(Quantities.create(Formulas.LINEAR_TOLERANCE,
Units.METRE));
final TableAppender table = new TableAppender(buffer, " │ ");
table.setCellAlignment(TableAppender.ALIGN_CENTER);
table.appendHorizontalSeparator();
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 d098362..60b1e38 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
@@ -24,6 +24,7 @@ import java.text.ParseException;
import java.io.IOException;
import org.opengis.geometry.DirectPosition;
import org.apache.sis.measure.Angle;
+import org.apache.sis.measure.Quantities;
import org.apache.sis.measure.Units;
import org.apache.sis.referencing.crs.HardCodedCRS;
import org.apache.sis.test.mock.VerticalCRSMock;
@@ -257,16 +258,16 @@ public final strictfp class CoordinateFormatTest extends TestCase {
}
/**
- * Tests {@link CoordinateFormat#setPrecision(double, Unit)}.
+ * Tests {@link CoordinateFormat#setGroundPrecision(Quantity)}.
*/
@Test
- public void testSetPrecision() {
+ public void testSetGroundPrecision() {
final CoordinateFormat format = new CoordinateFormat(Locale.FRANCE, null);
final DirectPosition2D pos = new DirectPosition2D(40.123456789, 9.87654321);
format.setDefaultCRS(HardCodedCRS.WGS84_φλ);
- format.setPrecision(0.01, Units.GRAD);
+ format.setGroundPrecision(Quantities.create(0.01, Units.GRAD));
assertEquals("40°07,4′N 9°52,6′E", format.format(pos));
- format.setPrecision(0.01, Units.METRE);
+ format.setGroundPrecision(Quantities.create(0.01, Units.METRE));
assertEquals("40°07′24,4444″N 9°52′35,5556″E", format.format(pos));
}
|