Author: desruisseaux
Date: Fri Jul 31 21:59:39 2015
New Revision: 1693658
URL: http://svn.apache.org/r1693658
Log:
Allow NormalizedProjection constructors to know whether the second defining
parameter of the Ellipsoid
is the semi-major axis length or the inverse flattening factor, and in the
later case allow constructors
to get the definitive flattening factor in order to compute the excentricity
more accuratly.
The intend is not to get more accurate map projection. Instead, we do that
because some code sometime
compute back the original semi-minor axis length (for example) from the
excentricity. Our goal is to
allow (if possible) such code to get a value closer to the original value
(idealy the exact same value).
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestCase.java
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Formulas.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -106,9 +106,7 @@ public final class Formulas extends Stat
/**
* Returns the radius of a hypothetical sphere having the same surface
than the ellipsoid
- * specified by the given axis length. This method does not verify if
{@code a == b}
- * (in which case {@code a} could be returned directly); it is up to the
caller to perform
- * such optimization if desired.
+ * specified by the given axis length.
*
* @param a The semi-major axis length.
* @param b The semi-minor axis length.
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -126,7 +126,7 @@ public final class Equirectangular exten
.addName("Latitude of 1st standard parallel")
.addName(Citations.OGC, Constants.STANDARD_PARALLEL_1)
.addName(Citations.ESRI, "Standard_Parallel_1")
- .addName(Citations.NETCDF, "standard_parallel")
+ .addName(Citations.NETCDF, Constants.STANDARD_PARALLEL)
.addName(Citations.GEOTIFF, "ProjStdParallel1")
.addName(Citations.PROJ4, "lat_ts"), false);
@@ -144,7 +144,7 @@ public final class Equirectangular exten
.addName("False easting")
.addName(Citations.OGC, Constants.FALSE_EASTING)
.addName(Citations.ESRI, "False_Easting")
- .addName(Citations.NETCDF, "false_easting")
+ .addName(Citations.NETCDF, Constants.FALSE_EASTING)
.addName(Citations.GEOTIFF, "FalseEasting")
.addName(Citations.PROJ4, "x_0"));
@@ -153,7 +153,7 @@ public final class Equirectangular exten
.addName("False northing")
.addName(Citations.OGC, Constants.FALSE_NORTHING)
.addName(Citations.ESRI, "False_Northing")
- .addName(Citations.NETCDF, "false_northing")
+ .addName(Citations.NETCDF, Constants.FALSE_NORTHING)
.addName(Citations.GEOTIFF, "FalseNorthing")
.addName(Citations.PROJ4, "y_0"));
/*
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionDescriptor.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -58,30 +58,6 @@ final class MapProjectionDescriptor exte
private static final long serialVersionUID = -9142116135803309453L;
/**
- * The NetCDF parameter name for the Earth radius.
- *
- * @see Constants#SEMI_MAJOR
- * @see Constants#SEMI_MINOR
- */
- static final String EARTH_RADIUS = "earth_radius";
-
- /**
- * The NetCDF parameter name for inverse flattening.
- *
- * @see Constants#SEMI_MAJOR
- * @see Constants#SEMI_MINOR
- */
- static final String INVERSE_FLATTENING = "inverse_flattening";
-
- /**
- * The NetCDF parameter name for the standard parallels.
- *
- * @see Constants#STANDARD_PARALLEL_1
- * @see Constants#STANDARD_PARALLEL_2
- */
- static final String STANDARD_PARALLEL = "standard_parallel";
-
- /**
* {@code true} if the {@link #STANDARD_PARALLEL} parameter can be added.
*/
final boolean hasStandardParallels;
@@ -146,14 +122,17 @@ final class MapProjectionDescriptor exte
*/
@Override
public GeneralParameterDescriptor descriptor(final String name) throws
ParameterNotFoundException {
- if (isHeuristicMatchForName(name, EARTH_RADIUS)) {
+ if (isHeuristicMatchForName(name, Constants.EARTH_RADIUS)) {
return MapProjectionParameters.EarthRadius.DESCRIPTOR;
}
- if (isHeuristicMatchForName(name, INVERSE_FLATTENING)) {
+ if (isHeuristicMatchForName(name, Constants.INVERSE_FLATTENING)) {
return MapProjectionParameters.InverseFlattening.DESCRIPTOR;
}
+ if (isHeuristicMatchForName(name, Constants.IS_IVF_DEFINITIVE)) {
+ return MapProjectionParameters.IsIvfDefinitive.DESCRIPTOR;
+ }
if (hasStandardParallels) {
- if (isHeuristicMatchForName(name, STANDARD_PARALLEL)) {
+ if (isHeuristicMatchForName(name, Constants.STANDARD_PARALLEL)) {
return MapProjectionParameters.StandardParallel.DESCRIPTOR;
}
}
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/MapProjectionParameters.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -33,6 +33,9 @@ import org.apache.sis.util.ArraysExt;
import static org.opengis.referencing.IdentifiedObject.NAME_KEY;
import static org.apache.sis.metadata.iso.citation.Citations.NETCDF;
+// Branch-specific imports
+import java.util.Objects;
+
/**
* Map projection parameters, with special processing for alternative ways to
express the ellipsoid axis length
@@ -60,7 +63,7 @@ final class MapProjectionParameters exte
* The {@link InverseFlattening} parameter instance, created when first
needed.
* This is an "invisible" parameter, never shown in the {@link #values()}
list.
*/
- private transient ParameterValue<Double> inverseFlattening;
+ private transient InverseFlattening inverseFlattening;
/**
* The {@link StandardParallel} parameter instance, created when first
needed.
@@ -69,6 +72,12 @@ final class MapProjectionParameters exte
private transient ParameterValue<double[]> standardParallel;
/**
+ * The {@link IsIvfDefinitive} parameter instance, created when first
needed.
+ * This is an "invisible" parameter, never shown in the {@link #values()}
list.
+ */
+ private transient ParameterValue<Boolean> isIvfDefinitive;
+
+ /**
* Creates a new parameter value group. An instance of {@link
MapProjectionDescriptor}
* is mandatory, because some method in this class will need to cast the
descriptor.
*/
@@ -97,38 +106,46 @@ final class MapProjectionParameters exte
*/
@Override
ParameterValue<?> parameterIfExist(final String name) throws
ParameterNotFoundException {
- if (MapProjectionDescriptor.isHeuristicMatchForName(name,
MapProjectionDescriptor.EARTH_RADIUS)) {
- ParameterValue<?> value = earthRadius;
- if (value == null) {
- value = earthRadius = new EarthRadius(
- parameter(Constants.SEMI_MAJOR),
- parameter(Constants.SEMI_MINOR));
+ if (MapProjectionDescriptor.isHeuristicMatchForName(name,
Constants.EARTH_RADIUS)) {
+ if (earthRadius == null) {
+ earthRadius = new EarthRadius(parameter(Constants.SEMI_MAJOR),
+ parameter(Constants.SEMI_MINOR));
}
- return value;
+ return earthRadius;
+ }
+ if (MapProjectionDescriptor.isHeuristicMatchForName(name,
Constants.INVERSE_FLATTENING)) {
+ return getInverseFlattening();
}
- if (MapProjectionDescriptor.isHeuristicMatchForName(name,
MapProjectionDescriptor.INVERSE_FLATTENING)) {
- ParameterValue<?> value = inverseFlattening;
- if (value == null) {
- value = inverseFlattening = new InverseFlattening(
- parameter(Constants.SEMI_MAJOR),
- parameter(Constants.SEMI_MINOR));
+ if (MapProjectionDescriptor.isHeuristicMatchForName(name,
Constants.IS_IVF_DEFINITIVE)) {
+ if (isIvfDefinitive == null) {
+ isIvfDefinitive = new IsIvfDefinitive(getInverseFlattening());
}
- return value;
+ return isIvfDefinitive;
}
if (((MapProjectionDescriptor) getDescriptor()).hasStandardParallels) {
- if (MapProjectionDescriptor.isHeuristicMatchForName(name,
MapProjectionDescriptor.STANDARD_PARALLEL)) {
- ParameterValue<?> value = standardParallel;
- if (value == null) {
- value = standardParallel = new StandardParallel(
- parameter(Constants.STANDARD_PARALLEL_1),
- parameter(Constants.STANDARD_PARALLEL_2));
+ if (MapProjectionDescriptor.isHeuristicMatchForName(name,
Constants.STANDARD_PARALLEL)) {
+ if (standardParallel == null) {
+ standardParallel = new
StandardParallel(parameter(Constants.STANDARD_PARALLEL_1),
+
parameter(Constants.STANDARD_PARALLEL_2));
}
- return value;
+ return standardParallel;
}
}
return super.parameterIfExist(name);
}
+ /**
+ * Returns the {@link InverseFlattening} instance, creating it when first
needed.
+ * This parameter is used also by {@link IsIvfDefinitive}.
+ */
+ private InverseFlattening getInverseFlattening() {
+ if (inverseFlattening == null) {
+ inverseFlattening = new
InverseFlattening(parameter(Constants.SEMI_MAJOR),
+
parameter(Constants.SEMI_MINOR));
+ }
+ return inverseFlattening;
+ }
+
@@ -152,17 +169,10 @@ final class MapProjectionParameters exte
* This is not a standard parameter.
*/
static final ParameterDescriptor<Double> DESCRIPTOR = new
DefaultParameterDescriptor<>(
- toMap(MapProjectionDescriptor.EARTH_RADIUS), 0, 1,
Double.class,
+ InverseFlattening.toMap(Constants.EARTH_RADIUS), 0, 1,
Double.class,
MeasurementRange.createGreaterThan(0.0, SI.METRE), null, null);
/**
- * Helper method for {@link #DESCRIPTOR} constructions.
- */
- static Map<String,?> toMap(final String name) {
- return Collections.singletonMap(NAME_KEY, new
NamedIdentifier(NETCDF, name));
- }
-
- /**
* The parameters for the semi-major and semi-minor axis length.
*/
private final ParameterValue<?> semiMajor, semiMinor;
@@ -181,8 +191,8 @@ final class MapProjectionParameters exte
*/
@Override
protected void setValue(final Object value, final Unit<?> unit) {
- super.setValue(value, unit); // Perform argument check.
- final double r = (Double) value;
+ super.setValue(value, unit); // Perform argument check.
+ final double r = (Double) value; // At this point, can not be
anything else than Double.
semiMajor.setValue(r, unit);
semiMinor.setValue(r, unit);
}
@@ -243,21 +253,60 @@ final class MapProjectionParameters exte
* This is not a standard parameter.
*/
static final ParameterDescriptor<Double> DESCRIPTOR = new
DefaultParameterDescriptor<>(
- EarthRadius.toMap(MapProjectionDescriptor.INVERSE_FLATTENING),
0, 1, Double.class,
+ toMap(Constants.INVERSE_FLATTENING), 0, 1, Double.class,
MeasurementRange.createGreaterThan(0.0, Unit.ONE), null, null);
/**
+ * Helper method for {@link #DESCRIPTOR} constructions.
+ */
+ static Map<String,?> toMap(final String name) {
+ return Collections.singletonMap(NAME_KEY, new
NamedIdentifier(NETCDF, name));
+ }
+
+ /**
* The parameters for the semi-major and semi-minor axis length.
*/
private final ParameterValue<?> semiMajor, semiMinor;
/**
+ * The declared inverse flattening values, together with a snapshot of
axis lengths
+ * at the time the inverse flattening has been set.
+ */
+ private double inverseFlattening, a, b;
+
+ /**
* Creates a new parameter.
*/
InverseFlattening(final ParameterValue<?> semiMajor, final
ParameterValue<?> semiMinor) {
super(DESCRIPTOR);
this.semiMajor = semiMajor;
this.semiMinor = semiMinor;
+ invalidate();
+ }
+
+ /**
+ * Declares that the inverse flattening factor is not definitive.
+ * We use the fact that the {@code ==} operator gives {@code false} if
a value is NaN.
+ */
+ void invalidate() {
+ a = b = Double.NaN;
+ }
+
+ /**
+ * Returns {@code true} if the inverse flattening factor has been
explicitely specified
+ * and seems to still valid.
+ */
+ boolean isIvfDefinitive() {
+ if (inverseFlattening > 0) {
+ final Number ca = (Number) semiMajor.getValue();
+ if (ca != null && ca.doubleValue() == a) {
+ final Number cb = (Number) semiMinor.getValue();
+ if (cb != null && cb.doubleValue() == b) {
+ return Objects.equals(semiMajor.getUnit(),
semiMinor.getUnit());
+ }
+ }
+ }
+ return false;
}
/**
@@ -266,27 +315,31 @@ final class MapProjectionParameters exte
*/
@Override
protected void setValue(final Object value, final Unit<?> unit) {
- super.setValue(value, unit); // Perform argument check.
- final double ivf = (Double) value;
- if (!Double.isNaN(ivf)) {
- final Double a = (Double) semiMajor.getValue();
- if (a != null) {
- semiMinor.setValue(Formulas.getSemiMinor(a, ivf),
semiMajor.getUnit());
- }
+ super.setValue(value, unit); // Perform argument check.
+ final double ivf = (Double) value; // At this point, can not be
anything else than Double.
+ final Number ca = (Number) semiMajor.getValue();
+ if (ca != null) {
+ a = ca.doubleValue();
+ b = Formulas.getSemiMinor(a, ivf);
+ semiMinor.setValue(b, semiMajor.getUnit());
+ } else {
+ invalidate();
}
+ inverseFlattening = ivf;
}
/**
- * Invoked when the parameter value is requested.
- * Unconditionally computes the inverse flattening factor from the
axis lengths.
+ * Invoked when the parameter value is requested. Computes the inverse
flattening factor
+ * from the axis lengths if the currently stored value does not seem
to be valid anymore.
*/
@Override
public double doubleValue() {
- final Double a = (Double) semiMajor.getValue();
- if (a != null && semiMinor.getValue() != null) {
- return Formulas.getInverseFlattening(a,
semiMinor.doubleValue(semiMajor.getUnit()));
+ final double ca = semiMajor.doubleValue();
+ final double cb = semiMinor.doubleValue(semiMajor.getUnit());
+ if (ca == a && cb == b && inverseFlattening > 0) {
+ return inverseFlattening;
}
- return Double.NaN;
+ return Formulas.getInverseFlattening(ca, cb);
}
/**
@@ -302,6 +355,69 @@ final class MapProjectionParameters exte
/**
+ * Whether the inverse flattening parameter is definitive.
+ *
+ * @see org.apache.sis.referencing.datum.DefaultEllipsoid#isIvfDefinitive()
+ */
+ static final class IsIvfDefinitive extends DefaultParameterValue<Boolean> {
+ /**
+ * For cross-version compatibility. Actually instances of this class
+ * are not expected to be serialized, but we try to be a bit safer
here.
+ */
+ private static final long serialVersionUID = 5988883252321358629L;
+
+ /**
+ * All names known to Apache SIS for the "is IVF definitive" parameter.
+ * This is not a standard parameter.
+ */
+ static final ParameterDescriptor<Boolean> DESCRIPTOR = new
DefaultParameterDescriptor<>(
+ InverseFlattening.toMap(Constants.IS_IVF_DEFINITIVE), 0, 1,
Boolean.class, null, null, null);
+
+ /**
+ * The parameters for the inverse flattening factor.
+ */
+ private final InverseFlattening inverseFlattening;
+
+ /**
+ * Creates a new parameter.
+ */
+ IsIvfDefinitive(final InverseFlattening inverseFlattening) {
+ super(DESCRIPTOR);
+ this.inverseFlattening = inverseFlattening;
+ }
+
+ /**
+ * Invoked when a new parameter value is set.
+ */
+ @Override
+ protected void setValue(final Object value, final Unit<?> unit) {
+ super.setValue(value, unit); // Perform argument check.
+ if (!(Boolean) value) {
+ inverseFlattening.invalidate();
+ }
+ }
+
+ /**
+ * Invoked when the parameter value is requested.
+ */
+ @Override
+ public boolean booleanValue() {
+ return inverseFlattening.isIvfDefinitive();
+ }
+
+ /**
+ * Getters other than the above {@code booleanValue()} delegate to
this method.
+ */
+ @Override
+ public Boolean getValue() {
+ return booleanValue();
+ }
+ }
+
+
+
+
+ /**
* The standard parallels parameter as an array of {@code double}. This
parameter is computed automatically
* from the {@code "standard_parallel_1"} and {@code
"standard_parallel_1"} standard parameters. When this
* non-standard parameter is explicitely set, the array elements are given
to the above-cited standard parameters.
@@ -319,7 +435,7 @@ final class MapProjectionParameters exte
* {@link #STANDARD_PARALLEL_2}. This is not a standard parameter.
*/
static final ParameterDescriptor<double[]> DESCRIPTOR = new
DefaultParameterDescriptor<>(
- EarthRadius.toMap(MapProjectionDescriptor.STANDARD_PARALLEL),
+ InverseFlattening.toMap(Constants.STANDARD_PARALLEL),
0, 1, double[].class, null, null, null);
/**
@@ -368,15 +484,15 @@ final class MapProjectionParameters exte
*/
@Override
public double[] getValue() {
- final Double p1 = (Double) standardParallel1.getValue();
- final Double p2 = (Double) standardParallel2.getValue();
+ final Number p1 = (Number) standardParallel1.getValue();
+ final Number p2 = (Number) standardParallel2.getValue();
if (p2 == null) {
if (p1 == null) {
return ArraysExt.EMPTY_DOUBLE;
}
- return new double[] {p1};
+ return new double[] {p1.doubleValue()};
}
- return new double[] {(p1 != null) ? p1 : Double.NaN, p2};
+ return new double[] {(p1 != null) ? p1.doubleValue() : Double.NaN,
p2.doubleValue()};
}
}
}
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterBuilder.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -385,7 +385,7 @@ public class ParameterBuilder extends Bu
* <tr><td>{@code "semi_major"}</td> <td>Always</td>
<td>Standard parameter defined by WKT 1.</td></tr>
* <tr><td>{@code "semi_minor"}</td> <td>Always</td>
<td>Standard parameter defined by WKT 1.</td></tr>
* <tr><td>{@code "earth_radius"}</td> <td>Hidden</td>
<td>Mapped to {@code "semi_major"} and {@code "semi_minor"}
parameters.</td></tr>
- * <tr><td>{@code "inverse_flattening"}</td> <td>Hidden</td>
<td>Mapped to {@code "semi_major"} and {@code "semi_minor"}
parameters.</td></tr>
+ * <tr><td>{@code "inverse_flattening"}</td> <td>Hidden</td>
<td>Computed from the {@code "semi_major"} and {@code "semi_minor"}
parameters.</td></tr>
* <tr><td>{@code "standard_parallel"}</td> <td>Hidden</td>
* <td>Array of 1 or 2 elements mapped to {@code
"standard_parallel_1"} and {@code "standard_parallel_2"}.</td></tr>
* </table>
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -18,8 +18,10 @@ package org.apache.sis.referencing.opera
import java.util.Map;
import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.parameter.ParameterNotFoundException;
import org.opengis.referencing.operation.OperationMethod;
import org.apache.sis.internal.referencing.provider.MapProjection;
+import org.apache.sis.internal.util.Constants;
import org.apache.sis.parameter.Parameters;
import org.apache.sis.internal.util.DoubleDouble;
import org.apache.sis.referencing.operation.matrix.MatrixSIS;
@@ -67,6 +69,11 @@ final class Initializer {
* <var>ℯ</var> is the {@linkplain #excentricity excentricity},
* <var>a</var> is the <cite>semi-major</cite> axis length and
* <var>b</var> is the <cite>semi-minor</cite> axis length.
+ *
+ * <p>This is stored as a double-double value because this parameter is
sometime used for computing back
+ * the semi-minor axis length or the inverse flattening factor. In such
case we wish to find the original
+ * {@code double} parameter value without rounding errors. This wish
usually do not apply to other internal
+ * {@link NormalizedProjection} parameters.</p>
*/
final DoubleDouble excentricitySquared;
@@ -117,13 +124,31 @@ final class Initializer {
DoubleDouble k = new DoubleDouble(a); // The value by which to
multiply all results of normalized projection.
if (a != b) {
/*
- * ℯ² = 1 - (b/a)²
+ * (1) Using axis lengths: ℯ² = 1 - (b/a)²
+ * (2) Using flattening; ℯ² = 2f - f² where f is the (NOT
inverse) flattening factor.
*
- * Double-double arithmetic here makes a difference in the 3 last
digits for WGS84 ellipsoid.
+ * If the inverse flattening factor is the definitive factor for
the ellipsoid, we use (2).
+ * Otherwise use (1). With double-double arithmetic, this makes a
difference in the 3 last
+ * digits for the WGS84 ellipsoid.
*/
- if (DoubleDouble.DISABLED) {
- final double rs = b / a;
- excentricitySquared.value = 1 - (rs * rs);
+ boolean isIvfDefinitive;
+ try {
+ isIvfDefinitive =
parameters.parameter(Constants.IS_IVF_DEFINITIVE).booleanValue();
+ } catch (ParameterNotFoundException e) {
+ /*
+ * Should never happen with Apache SIS implementation, but may
happen if the given parameters come
+ * from another implementation. We can safely abandon our
attempt to get the inverse flattening value,
+ * since it was redundant with semi-minor axis length.
+ */
+ isIvfDefinitive = false;
+ }
+ if (isIvfDefinitive) {
+ final DoubleDouble f = new
DoubleDouble(parameters.parameter(Constants.INVERSE_FLATTENING).doubleValue());
+ f.inverseDivide(1,0);
+ excentricitySquared.setFrom(f);
+ excentricitySquared.multiply(2,0);
+ f.multiply(f);
+ excentricitySquared.subtract(f);
} else {
final DoubleDouble rs = new DoubleDouble(b);
rs.divide(k); // rs = b/a
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -96,7 +96,10 @@ public class LambertConicConformal exten
}
/**
- * Constant for the Belgium 2SP case. This is 29.2985 seconds, given here
in radians.
+ * Constant for the Belgium 2SP case. Defined as 29.2985 seconds, given
here in radians.
+ * Use double-double arithmetic not for map projection accuracy, but for
consistency with
+ * the normalization matrix which use that precision for "degrees to
radians" conversion.
+ * The goal is to have cleaner results after matrix inversions and
multiplications.
*
* <div class="note"><b>Tip:</b> how to verify the value:
* {@preformat java
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -36,6 +36,7 @@ import org.opengis.parameter.ParameterVa
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.ParameterNotFoundException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.datum.Ellipsoid;
@@ -535,12 +536,34 @@ public class DefaultMathTransformFactory
*/
failure = e;
}
+ final boolean isIvfDefinitive;
if (mismatchedParam != null) {
final LogRecord record = Messages.getResources((Locale)
null).getLogRecord(Level.WARNING,
Messages.Keys.MismatchedEllipsoidAxisLength_3,
ellipsoid.getName().getCode(),
mismatchedParam.getDescriptor().getName().getCode(),
mismatchedValue);
record.setLoggerName(Loggers.COORDINATE_OPERATION);
Logging.log(DefaultMathTransformFactory.class,
"createBaseToDerived", record);
+ isIvfDefinitive = false;
+ } else {
+ isIvfDefinitive = ellipsoid.isIvfDefinitive();
+ }
+ /*
+ * Following is specific to Apache SIS. We use this non-standard
API for allowing the
+ * NormalizedProjection class (our base class for all map
projection implementations)
+ * to known that the ellipsoid definitive parameter is the inverse
flattening factor
+ * instead than the semi-major axis length. It makes a small
difference in the accuracy
+ * of the excentricity parameter.
+ */
+ if (isIvfDefinitive) try {
+
parameters.parameter(Constants.INVERSE_FLATTENING).setValue(ellipsoid.getInverseFlattening());
+ } catch (ParameterNotFoundException e) {
+ /*
+ * Should never happen with Apache SIS implementation, but may
happen if the given parameters come
+ * from another implementation. We can safely abandon our
attempt to set the inverse flattening value,
+ * since it was redundant with semi-minor axis length.
+ */
+
Logging.recoverableException(Logging.getLogger(Loggers.COORDINATE_OPERATION),
+ DefaultMathTransformFactory.class,
"createBaseToDerived", e);
}
}
MathTransform baseToDerived;
Modified:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/parameter/MapProjectionParametersTest.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -28,12 +28,13 @@ import org.junit.Test;
import static org.junit.Assert.*;
import static org.apache.sis.internal.util.Constants.SEMI_MAJOR;
import static org.apache.sis.internal.util.Constants.SEMI_MINOR;
+import static org.apache.sis.internal.util.Constants.EARTH_RADIUS;
+import static org.apache.sis.internal.util.Constants.INVERSE_FLATTENING;
+import static org.apache.sis.internal.util.Constants.IS_IVF_DEFINITIVE;
import static org.apache.sis.internal.util.Constants.CENTRAL_MERIDIAN;
+import static org.apache.sis.internal.util.Constants.STANDARD_PARALLEL;
import static org.apache.sis.internal.util.Constants.STANDARD_PARALLEL_1;
import static org.apache.sis.internal.util.Constants.STANDARD_PARALLEL_2;
-import static org.apache.sis.parameter.MapProjectionDescriptor.EARTH_RADIUS;
-import static
org.apache.sis.parameter.MapProjectionDescriptor.INVERSE_FLATTENING;
-import static
org.apache.sis.parameter.MapProjectionDescriptor.STANDARD_PARALLEL;
/**
@@ -103,17 +104,24 @@ public final strictfp class MapProjectio
final MapProjectionDescriptor descriptor = createDescriptor(0);
final ParameterValueGroup parameters = descriptor.createValue();
- parameters.parameter(SEMI_MAJOR).setValue(6378206.4); // Clarke 1866
+ parameters.parameter(SEMI_MAJOR).setValue(6378206.4); // Clarke 1866
parameters.parameter(SEMI_MINOR).setValue(6356583.8);
assertEquals(294.97870,
parameters.parameter(INVERSE_FLATTENING).doubleValue(), 0.00001);
assertEquals(6378206.4, parameters.parameter(SEMI_MAJOR)
.doubleValue(), 0.5);
assertEquals(6356583.8, parameters.parameter(SEMI_MINOR)
.doubleValue(), 0.5);
+ assertFalse("isIvfDefinitive",
parameters.parameter(IS_IVF_DEFINITIVE).booleanValue());
- parameters.parameter(SEMI_MAJOR).setValue(6378137.000); // WGS84
+ parameters.parameter(SEMI_MAJOR).setValue(6378137.0); // WGS84
parameters.parameter(INVERSE_FLATTENING).setValue(298.257223563);
assertEquals(298.257,
parameters.parameter(INVERSE_FLATTENING).doubleValue(), 0.001);
assertEquals(6378137, parameters.parameter(SEMI_MAJOR)
.doubleValue(), 0.5);
assertEquals(6356752, parameters.parameter(SEMI_MINOR)
.doubleValue(), 0.5);
+ assertTrue("isIvfDefinitive",
parameters.parameter(IS_IVF_DEFINITIVE).booleanValue());
+
+ parameters.parameter(SEMI_MAJOR).setValue(6378350.9); // Clarke 1858
(approximative)
+ parameters.parameter(SEMI_MINOR).setValue(6356675.0);
+ assertEquals(294.26,
parameters.parameter(INVERSE_FLATTENING).doubleValue(), 0.001);
+ assertFalse("isIvfDefinitive",
parameters.parameter(IS_IVF_DEFINITIVE).booleanValue());
}
/**
Modified:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/LambertConicConformalTest.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -105,7 +105,7 @@ public final strictfp class LambertConic
createNormalizedProjection(true, 40);
assertWktEqualsRegex("\\Q" +
"PARAM_MT[“Lambert conic conformal”,\n" +
- " PARAMETER[“excentricity”, 0.08181919084262244],\n" +
+ " PARAMETER[“excentricity”, 0.0818191908426215],\n" +
" PARAMETER[“n”, 0.64278760968653\\E\\d*\\]\\]"); //
0.6427876096865393 in the original test.
}
Modified:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -66,6 +66,9 @@ strictfp class MapProjectionTestCase ext
final Ellipsoid ellipsoid = (ellipse ? GeodeticDatumMock.WGS84 :
GeodeticDatumMock.SPHERE).getEllipsoid();
parameters.parameter(Constants.SEMI_MAJOR).setValue(ellipsoid.getSemiMajorAxis());
parameters.parameter(Constants.SEMI_MINOR).setValue(ellipsoid.getSemiMinorAxis());
+ if (ellipse) {
+
parameters.parameter(Constants.INVERSE_FLATTENING).setValue(ellipsoid.getInverseFlattening());
+ }
return parameters;
}
Modified:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/MercatorTest.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -75,7 +75,7 @@ public final strictfp class MercatorTest
createNormalizedProjection(true);
assertWktEquals(
"PARAM_MT[“Mercator”,\n" +
- " PARAMETER[“excentricity”, 0.08181919084262244]]");
+ " PARAMETER[“excentricity”, 0.0818191908426215]]");
}
/**
Modified:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NoOp.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -45,7 +45,17 @@ final strictfp class NoOp extends Confor
* @param ellipsoidal {@code true} for an ellipsoidal case, or {@code
false} for a spherical case.
*/
NoOp(final boolean ellipsoidal) {
- this(parameters((ellipsoidal ? GeodeticDatumMock.WGS84 :
GeodeticDatumMock.SPHERE).getEllipsoid()));
+ this(ellipsoidal, ellipsoidal);
+ }
+
+ /**
+ * Creates a new "no-operation".
+ *
+ * @param ellipsoidal {@code true} for an ellipsoidal case, or {@code
false} for a spherical case.
+ * @param declareIvf {@code true} for declaring the inverse flattening
factor.
+ */
+ NoOp(final boolean ellipsoidal, final boolean declareIvf) {
+ this(parameters((ellipsoidal ? GeodeticDatumMock.WGS84 :
GeodeticDatumMock.SPHERE).getEllipsoid(), declareIvf));
}
/**
@@ -71,9 +81,14 @@ final strictfp class NoOp extends Confor
* ("Relax constraint on placement of this()/super() call in
constructors").
*/
@Workaround(library="JDK", version="1.7")
- private static Parameters parameters(final Ellipsoid ellipsoid) {
- return parameters(ellipsoid.getSemiMajorAxis(),
- ellipsoid.getSemiMinorAxis());
+ private static Parameters parameters(final Ellipsoid ellipsoid, final
boolean declareIvf) {
+ final Parameters parameters = parameters(
+ ellipsoid.getSemiMajorAxis(),
+ ellipsoid.getSemiMinorAxis());
+ if (declareIvf) {
+
parameters.parameter(Constants.INVERSE_FLATTENING).setValue(ellipsoid.getInverseFlattening());
+ }
+ return parameters;
}
/**
Modified:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/NormalizedProjectionTest.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -65,8 +65,17 @@ public final strictfp class NormalizedPr
NormalizedProjection projection;
transform = projection = new NoOp(false);
assertEquals("excentricity", 0.0, projection.excentricity, 0.0);
+ /*
+ * Tested methods. Note the similarity between (1) and (3).
+ *
+ * (1) Using double arithmetic and axis lengths:
0.08181919084262157
+ * (2) Using double-double arithmetic and axis lengths:
0.08181919084262244
+ * (3) Using double-double arithmetic and flattening:
0.0818191908426215
+ */
+ transform = projection = new NoOp(true, false);
+ assertEquals("excentricity", 0.08181919084262244,
projection.excentricity, 0.0);
- transform = projection = new NoOp(true);
- assertEquals("excentricity", 0.08181919084262157,
projection.excentricity, TOLERANCE);
+ transform = projection = new NoOp(true, true);
+ assertEquals("excentricity", 0.0818191908426215,
projection.excentricity, 0.0);
}
}
Modified:
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -78,17 +78,34 @@ public final class Constants extends Sta
public static final byte CRS84 = 84;
/**
+ * The NetCDF parameter name for the Earth radius.
+ */
+ public static final String EARTH_RADIUS = "earth_radius";
+
+ /**
* Name of the {@value} projection parameter, which is handled specially
during WKT formatting.
*/
public static final String SEMI_MAJOR = "semi_major",
SEMI_MINOR = "semi_minor";
/**
+ * The NetCDF parameter name for inverse flattening, and whether that
parameter is definitive.
+ * The later is specific to SIS.
+ */
+ public static final String INVERSE_FLATTENING = "inverse_flattening",
+ IS_IVF_DEFINITIVE = "is_ivf_definitive";
+
+ /**
* The OGC parameter name for the central meridian.
*/
public static final String CENTRAL_MERIDIAN = "central_meridian";
/**
+ * The NetCDF parameter name for the standard parallels.
+ */
+ public static final String STANDARD_PARALLEL = "standard_parallel";
+
+ /**
* The OGC parameter name for the standard parallels.
*/
public static final String STANDARD_PARALLEL_1 = "standard_parallel_1",
@@ -125,6 +142,7 @@ public final class Constants extends Sta
*/
public static final String FALSE_EASTING = "false_easting",
FALSE_NORTHING = "false_northing";
+
/**
* Name of the {@value} matrix parameters.
*/
Modified:
sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestCase.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestCase.java?rev=1693658&r1=1693657&r2=1693658&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestCase.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/TestCase.java
[UTF-8] Fri Jul 31 21:59:39 2015
@@ -24,7 +24,6 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
-import org.apache.sis.internal.system.Modules;
import org.apache.sis.util.logging.Logging;
import org.junit.runner.RunWith;
@@ -182,6 +181,7 @@ public abstract strictfp class TestCase
*
* @param success {@code true} if this method is invoked on build success,
*/
+ @SuppressWarnings("UseOfSystemOutOrSystemErr")
static void flushOutput() {
System.out.flush();
System.err.flush();