Author: desruisseaux
Date: Wed Mar 25 00:25:22 2015
New Revision: 1669028
URL: http://svn.apache.org/r1669028
Log:
Referencing: rewrite some equation in a way closer to EPSG Guidance Note Number
7, part 2, Version 49.
This has the side effect of bringing the equations meaning closer to a "real
world" meaning.
For example the former "t function" is now more clearly related to a part of
the Mercator projection
(Note: we define that equation in the parent class because Mercator is
considered a special case of
Lambert projection with the equator as the single standard parallel, so we will
reuse that equation).
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator2SP.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/UnitaryProjection.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/UnitaryProjectionTest.java
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java?rev=1669028&r1=1669027&r2=1669028&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator1SP.java
[UTF-8] Wed Mar 25 00:25:22 2015
@@ -50,31 +50,31 @@ public final class Mercator1SP extends M
static final String NAME = "Mercator (variant A)";
/**
- * The operation parameter descriptor for the <cite>Latitude of natural
origin</cite> parameter value.
+ * The operation parameter descriptor for the <cite>Latitude of natural
origin</cite> (φ₀) parameter value.
* Valid values range is (-90 … 90)° and default value is 0°.
*/
static final ParameterDescriptor<Double> LATITUDE_OF_ORIGIN;
/**
- * The operation parameter descriptor for the <cite>Longitude of natural
origin</cite> parameter value.
+ * The operation parameter descriptor for the <cite>Longitude of natural
origin</cite> (λ₀) parameter value.
* Valid values range is [-180 … 180]° and default value is 0°.
*/
static final ParameterDescriptor<Double> CENTRAL_MERIDIAN;
/**
- * The operation parameter descriptor for the <cite>Scale factor at
natural origin</cite> parameter value.
+ * The operation parameter descriptor for the <cite>Scale factor at
natural origin</cite> (k₀) parameter value.
* Valid values range is (0 … ∞) and default value is 1.
*/
static final ParameterDescriptor<Double> SCALE_FACTOR;
/**
- * The operation parameter descriptor for the <cite>False easting</cite>
parameter value.
+ * The operation parameter descriptor for the <cite>False easting</cite>
(FE) parameter value.
* Valid values range is unrestricted and default value is 0 metre.
*/
static final ParameterDescriptor<Double> FALSE_EASTING;
/**
- * The operation parameter descriptor for the <cite>False northing</cite>
parameter value.
+ * The operation parameter descriptor for the <cite>False northing</cite>
(FN) parameter value.
* Valid values range is unrestricted and default value is 0 metre.
*/
static final ParameterDescriptor<Double> FALSE_NORTHING;
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator2SP.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator2SP.java?rev=1669028&r1=1669027&r2=1669028&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator2SP.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Mercator2SP.java
[UTF-8] Wed Mar 25 00:25:22 2015
@@ -45,13 +45,13 @@ public final class Mercator2SP extends M
private static final long serialVersionUID = 6356028352681135786L;
/**
- * The operation parameter descriptor for the <cite>Latitude of 1st
standard parallel</cite> parameter value.
+ * The operation parameter descriptor for the <cite>Latitude of 1st
standard parallel</cite> (φ₁) parameter value.
* Valid values range is (-90 … 90)° and default value is 0°.
*/
public static final ParameterDescriptor<Double> STANDARD_PARALLEL;
/**
- * The operation parameter descriptor for the <cite>Latitude of natural
origin</cite> parameter value.
+ * The operation parameter descriptor for the <cite>Latitude of natural
origin</cite> (φ₀) parameter value.
* Valid values range is (-90 … 90)° and default value is 0°.
*
* <p>This parameter is taken from {@link Mercator1SP}. It is not formally
a parameter from the {@code Mercator2SP}
@@ -60,13 +60,13 @@ public final class Mercator2SP extends M
public static final ParameterDescriptor<Double> LATITUDE_OF_ORIGIN;
/**
- * The operation parameter descriptor for the <cite>Longitude of natural
origin</cite> parameter value.
+ * The operation parameter descriptor for the <cite>Longitude of natural
origin</cite> (λ₀) parameter value.
* Valid values range is [-180 … 180]° and default value is 0°.
*/
- static final ParameterDescriptor<Double> CENTRAL_MERIDIAN;
+ public static final ParameterDescriptor<Double> CENTRAL_MERIDIAN;
/**
- * The operation parameter descriptor for the <cite>Scale factor at
natural origin</cite> parameter value.
+ * The operation parameter descriptor for the <cite>Scale factor at
natural origin</cite> (k₀) parameter value.
* Valid values range is (0 … ∞) and default value is 1.
*
* <p>This parameter is taken from {@link Mercator1SP}. It is not formally
a parameter from the {@code Mercator2SP}
@@ -75,13 +75,13 @@ public final class Mercator2SP extends M
public static final ParameterDescriptor<Double> SCALE_FACTOR;
/**
- * The operation parameter descriptor for the <cite>False easting</cite>
parameter value.
+ * The operation parameter descriptor for the <cite>False easting</cite>
(FE) parameter value.
* Valid values range is unrestricted and default value is 0 metre.
*/
public static final ParameterDescriptor<Double> FALSE_EASTING;
/**
- * The operation parameter descriptor for the <cite>False northing</cite>
parameter value.
+ * The operation parameter descriptor for the <cite>False northing</cite>
(FN) parameter value.
* Valid values range is unrestricted and default value is 0 metre.
*/
public static final ParameterDescriptor<Double> FALSE_NORTHING;
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java?rev=1669028&r1=1669027&r2=1669028&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
[UTF-8] Wed Mar 25 00:25:22 2015
@@ -26,6 +26,7 @@ import org.apache.sis.internal.referenci
import org.apache.sis.internal.referencing.provider.PseudoMercator;
import org.apache.sis.internal.referencing.provider.MillerCylindrical;
import org.apache.sis.referencing.operation.matrix.Matrix2;
+import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.parameter.Parameters;
import static java.lang.Math.*;
@@ -54,14 +55,6 @@ import static java.lang.Double.*;
* The projection of 90°S gives {@linkplain Double#NEGATIVE_INFINITY negative
infinity}.
* Projection of a latitude outside the [-90-ε … 90+ε]° range produces
{@linkplain Double#NaN NaN}.
*
- * <div class="section">References</div>
- * <ul>
- * <li>John P. Snyder (Map Projections - A Working Manual,<br>
- * U.S. Geological Survey Professional Paper 1395, 1987)</li>
- * <li>"Coordinate Conversions and Transformations including Formulas",<br>
- * EPSG Guidance Note Number 7, Version 19.</li>
- * </ul>
- *
* @author André Gosselin (MPO)
* @author Martin Desruisseaux (MPO, IRD, Geomatys)
* @author Rueben Schulz (UBC)
@@ -128,9 +121,10 @@ public class Mercator extends UnitaryPro
final double[] dstPts, final int dstOff,
final boolean derivate) throws ProjectionException
{
- final double λ = srcPts[srcOff];
- final double φ = srcPts[srcOff + 1];
- final double sinφ = sin(φ);
+ final double λ = srcPts[srcOff];
+ final double φ = srcPts[srcOff + 1];
+ final double sinφ = sin(φ);
+ final double ℯsinφ = excentricity * sinφ;
/*
* Projection of zero is zero. However the formulas below have a
slight rounding error
* which produce values close to 1E-10, so we will avoid them when
y=0. In addition of
@@ -142,11 +136,11 @@ public class Mercator extends UnitaryPro
} else {
// See the javadoc of the Spherical inner class for a note
// about why we perform explicit checks for the pole cases.
- final double a = abs(φ);
- if (a < PI/2) {
- y = -log(t(φ, sinφ));
+ final double absφ = abs(φ);
+ if (absφ < PI/2) {
+ y = log(exp_y(φ, ℯsinφ)); // Snyder (7-7)
} else {
- y = copySign(a <= (PI/2 + ANGLE_TOLERANCE) ? POSITIVE_INFINITY
: NaN, φ);
+ y = copySign(absφ <= (PI/2 + ANGLE_TOLERANCE) ?
POSITIVE_INFINITY : NaN, φ);
}
}
if (dstPts != null) {
@@ -159,9 +153,8 @@ public class Mercator extends UnitaryPro
/*
* End of map projection. Now compute the derivative, if requested.
*/
- final double cosφ = cos(φ);
- final double ℯsinφ = sinφ * excentricity;
- final double t = (1 - sinφ) / cosφ;
+ final double cosφ = cos(φ);
+ final double t = (1 - sinφ) / cosφ;
return new Matrix2(1, 0, 0, 0.5*(t + 1/t) - excentricitySquared*cosφ /
(1 - ℯsinφ*ℯsinφ));
}
@@ -185,15 +178,16 @@ public class Mercator extends UnitaryPro
} else {
dstOff--;
while (--numPts >= 0) {
- double y = dstPts[dstOff += 2]; // Same as srcPts[srcOff + 1].
- if (y != 0) {
+ final double φ = dstPts[dstOff += 2]; // Same as srcPts[srcOff
+ 1].
+ final double y;
+ if (φ != 0) {
// See the javadoc of the Spherical inner class for a note
// about why we perform explicit checks for the pole cases.
- final double a = abs(y);
- if (a < PI/2) {
- y = -log(t(y, sin(y)));
+ final double absφ = abs(φ);
+ if (absφ < PI/2) {
+ y = log(exp_y(φ, excentricity * sin(φ)));
} else {
- y = copySign(a <= (PI/2 + ANGLE_TOLERANCE) ?
POSITIVE_INFINITY : NaN, y);
+ y = copySign(absφ <= (PI/2 + ANGLE_TOLERANCE) ?
POSITIVE_INFINITY : NaN, φ);
}
dstPts[dstOff] = y;
}
@@ -227,10 +221,6 @@ public class Mercator extends UnitaryPro
* which is the correct answer. In practice the infinite value emerges by
itself at only one pole, and the other
* one produces a high value (approximatively 1E+16). This is because
there is no accurate representation of π/2
* in base 2, and consequently {@code tan(π/2)} does not returns the
infinite value.
- *
- * <p>The {@code Spherical} formula has the opposite behavior than {@link
Mercator} regarding which pole returns
- * the infinite value. In {@code Spherical}, this is the South pole. In
{@code Mercator} (ellipsoidal case), this
- * is the North pole. Using explicit checks allow us to enforce the same
behavior for the two implementations.</p>
* </div>
*
* @author Martin Desruisseaux (MPO, IRD, Geomatys)
@@ -293,7 +283,7 @@ public class Mercator extends UnitaryPro
// See class javadoc for a note about explicit check for poles.
final double a = abs(φ);
if (a < PI/2) {
- y = log(tan(PI/4 + 0.5*φ));
+ y = log(tan(PI/4 + 0.5*φ)); // Snyder (7-2)
} else {
y = copySign(a <= (PI/2 + ANGLE_TOLERANCE) ?
POSITIVE_INFINITY : NaN, φ);
}
@@ -335,7 +325,7 @@ public class Mercator extends UnitaryPro
if (y != 0) {
final double a = abs(y);
if (a < PI/2) {
- y = log(tan(PI/4 + 0.5*y));
+ y = log(tan(PI/4 + 0.5*y)); // Snyder (7-2)
} else {
y = copySign(a <= (PI/2 + ANGLE_TOLERANCE) ?
POSITIVE_INFINITY : NaN, y);
}
@@ -355,7 +345,7 @@ public class Mercator extends UnitaryPro
{
double x = srcPts[srcOff ];
double y = srcPts[srcOff+1];
- y = PI/2 - 2 * atan(exp(-y));
+ y = PI/2 - 2 * atan(exp(-y)); // Snyder (7-4)
assert pseudo || checkInverseTransform(srcPts, srcOff, dstPts,
dstOff, x, y);
dstPts[dstOff ] = x;
dstPts[dstOff+1] = y;
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/UnitaryProjection.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/UnitaryProjection.java?rev=1669028&r1=1669027&r2=1669028&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/UnitaryProjection.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/UnitaryProjection.java
[UTF-8] Wed Mar 25 00:25:22 2015
@@ -412,67 +412,91 @@ public abstract class UnitaryProjection
//////////////////////////////////////////////////////////////////////////////////////////
////////
////////
- //////// FORMULAS FROM SNYDER
////////
+ //////// FORMULAS FROM EPSG or SNYDER
////////
////////
////////
//////////////////////////////////////////////////////////////////////////////////////////
/**
- * Computes functions (9-13) and (15-9) from Snyder.
- * This function is part of the following chapters:
+ * Computes the reciprocal of the radius of curvature of the ellipsoid
perpendicular to the meridian at latitude φ.
+ * That radius of curvature is:
*
+ * <blockquote>ν = 1 / √(1 - ℯ²∙sin²φ)</blockquote>
+ *
+ * This method returns 1/ν.
+ *
+ * <div class="section">Relationship with Snyder</div>
+ * This is related to functions (14-15) from Snyder (used for computation
of scale factors
+ * at the true scale latitude) as below:
+ *
+ * <blockquote>m = cosφ / rν</blockquote>
+ *
+ * Special cases:
* <ul>
- * <li>(9-13) in the <cite>Oblique Mercator projection</cite>
chapter.</li>
- * <li>(15-9) in the <cite>Lambert Conformal Conic projection</cite>
chapter.</li>
- * <li>Negative of part of (7-7) in the <cite>Mercator projection</cite>
chapter.
- * In the case of Mercator projection, this is {@code exp(-y)} where
<var>y</var>
- * is the northing on the unit ellipse.</li>
+ * <li>If φ is 0°, then <var>m</var> is 1.</li>
+ * <li>If φ is ±90°, then <var>m</var> is 0 provided that we are not in
the spherical case
+ * (otherwise we get {@link Double#NaN}).</li>
* </ul>
*
- * This function is the converse of {@link #φ(double)}.
+ * @param sinφ The sine of the φ latitude in radians.
+ * @return Reciprocal of the radius of curvature of the ellipsoid
perpendicular to the meridian at latitude φ.
+ */
+ final double rν(final double sinφ) {
+ return sqrt(1 - excentricitySquared * (sinφ*sinφ));
+ }
+
+ /**
+ * Computes part of the Mercator projection for the given latitude. This
formulas is also part of
+ * Lambert Conic Conformal projection, since Mercator can be considered as
a special case of that
+ * Lambert projection with the equator as the single standard parallel.
+ *
+ * <p>The Mercator projection is given by the {@linkplain Math#log(double)
natural logarithm} of the
+ * value returned by this method. This function is <em>almost</em> the
converse of {@link #φ(double)}.
*
* <div class="section">Properties</div>
- * This function has a periodicity of 2π. The result is always a positive
value when φ is valid
- * (more on it below). More specifically its behavior at some particular
points is:
+ * This function has the following identity (ignoring rounding errors):
+ *
+ * <blockquote>exp_y(φ) = 1/exp_y(-φ)</blockquote>
+ *
+ * This function has a periodicity of 2π.
+ * The result is always a positive value when φ is valid (more on it
below).
+ * More specifically its behavior at some particular points is:
*
* <ul>
* <li>If φ is NaN or infinite, then the result is NaN.</li>
- * <li>If φ is π/2, then the result is close to 0.</li>
+ * <li>If φ is -π/2, then the result is close to 0.</li>
* <li>If φ is 0, then the result is close to 1.</li>
- * <li>If φ is -π/2, then the result tends toward positive infinity.
+ * <li>If φ is +π/2, then the result tends toward positive infinity.
* The actual result is not infinity however, but some large value
like 1E+10.</li>
* <li>If φ, after removal of any 2π periodicity, still outside the
[-π/2 … π/2] range,
* then the result is a negative number. If the caller is going to
compute the logarithm
* of the returned value as in the Mercator projection, he will get
NaN.</li>
* </ul>
*
- * <div class="section">Relationship with other formulas</div>
- * Function (3-1) from Snyder gives the <cite>conformal latitude</cite> χ
as (Adam, 1921, p.18, 84):
+ * <div class="section">Relationship with Snyder</div>
+ * This function is related to the following functions from Snyder:
*
- * <blockquote>
- * χ = 2∙arctan( tan(π/4 + φ/2) ∙ [(1 - ℯ∙sinφ)/(1 + ℯ∙sinφ)]^(ℯ/2) ) -
π/2
- * </blockquote>
- *
- * This method can compute the part inside the {@code arctan(…)}
expression as below
- * (note the negative sign in front of φ):
- *
- * <blockquote>
- * χ = 2∙arctan( t(-φ, sinφ) ) - π/2
- * </blockquote>
- *
- * @param φ The latitude in radians.
- * @param sinφ The sine of the φ argument (often already computed by the
caller).
- * @return Function 9-13 or 15-9, or the negative of function 7-7 from
Snyder.
+ * <ul>
+ * <li>(7-7) in the <cite>Mercator projection</cite> chapter.</li>
+ * <li>Reciprocal of (9-13) in the <cite>Oblique Mercator
projection</cite> chapter.</li>
+ * <li>Reciprocal of (15-9) in the <cite>Lambert Conformal Conic
projection</cite> chapter.
+ * Note: tan(π/4 - φ/2) = 1/tan(π/4 + φ/2).</li>
+ * </ul>
+ *
+ * @param φ The latitude in radians.
+ * @param ℯsinφ The sine of the φ argument multiplied by {@link
#excentricity}.
+ * @return {@code Math.exp} of the Mercator projection of the given
latitude.
*/
- final double t(final double φ, double sinφ) {
- sinφ *= excentricity;
- return tan(PI/4 - 0.5*φ) / pow((1-sinφ) / (1+sinφ), 0.5*excentricity);
+ final double exp_y(final double φ, final double ℯsinφ) {
+ return tan(PI/4 + 0.5*φ) * pow((1 - ℯsinφ) / (1 + ℯsinφ),
0.5*excentricity);
}
/**
* Iteratively solve equation (7-9) from Snyder (<cite>Mercator
projection</cite> chapter).
- * This is the converse of the above {@link #t(double, double)} function.
- * The input should be a positive number, otherwise the result will be
either outside
- * the [-π/2 … π/2] range, or will be NaN. Its behavior at some particular
points is:
+ * This is <em>almost</em> the converse of the above {@link #exp_y(double,
double)} function.
+ * In a Mercator inverse projection, the value of {@code t} argument is
{@code exp(-y)}.
+ *
+ * <p>The input should be a positive number, otherwise the result will be
either outside
+ * the [-π/2 … π/2] range, or will be NaN. Its behavior at some particular
points is:</p>
*
* <ul>
* <li>If {@code t} is zero, then the result is close to π/2.</li>
@@ -480,13 +504,13 @@ public abstract class UnitaryProjection
* <li>If {@code t} is positive infinity, then the result is close to
-π/2.</li>
* </ul>
*
- * @param t The value returned by {@link #t(double, double)}.
+ * @param t The <em>reciprocal</em> of the value returned by {@link
#exp_y(double)}.
* @return The latitude in radians.
* @throws ProjectionException if the iteration does not converge.
*/
final double φ(final double t) throws ProjectionException {
final double hℯ = 0.5 * excentricity;
- double φ = (PI/2) - 2*atan(t);
+ double φ = (PI/2) - 2*atan(t); // Snyder (7-11)
for (int i=0; i<MAXIMUM_ITERATIONS; i++) {
final double ℯsinφ = excentricity * sin(φ);
final double Δφ = abs(φ - (φ = PI/2 - 2*atan(t * pow((1 -
ℯsinφ)/(1 + ℯsinφ), hℯ))));
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java?rev=1669028&r1=1669027&r2=1669028&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java
[UTF-8] Wed Mar 25 00:25:22 2015
@@ -154,6 +154,14 @@
* are usually not given.
* </div>
*
+ * <div class="section">References</div>
+ * <ul>
+ * <li>"Coordinate Conversions and Transformations including Formulas",<br>
+ * Geomatics Guidance Note Number 7, part 2, Version 49.</li>
+ * <li>John P. Snyder (Map Projections - A Working Manual,<br>
+ * U.S. Geological Survey Professional Paper 1395, 1987)</li>
+ * </ul>
+ *
* @author Martin Desruisseaux (Geomatys)
* @author Rémi Maréchal (Geomatys)
* @author Adrian Custer (Geomatys)
Modified:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/UnitaryProjectionTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/UnitaryProjectionTest.java?rev=1669028&r1=1669027&r2=1669028&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/UnitaryProjectionTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/UnitaryProjectionTest.java
[UTF-8] Wed Mar 25 00:25:22 2015
@@ -52,19 +52,19 @@ public final strictfp class UnitaryProje
private UnitaryProjection projection;
/**
- * Computes {@link UnitaryProjection#t(double, double)} for the given
latitude.
+ * Computes {@link UnitaryProjection#exp_y(double, double)} for the given
latitude.
*
* @param φ The latitude in radians.
- * @return Function 9-13 or 15-9, or the negative of function 7-7 from
Snyder.
+ * @return {@code Math.exp} of the Mercator projection of the given
latitude.
*/
- private double t(final double φ) {
- return projection.t(φ, sin(φ));
+ private double exp_y(final double φ) {
+ return projection.exp_y(φ, projection.excentricity * sin(φ));
}
/**
* Computes {@link UnitaryProjection#φ(double)}.
*
- * @param t The value returned by {@link #t(double)}.
+ * @param t The reciprocal of the value returned by {@link
#exp_y(double)}.
* @return The latitude in radians.
* @throws ProjectionException if the iteration does not converge.
*/
@@ -117,7 +117,7 @@ public final strictfp class UnitaryProje
}
/**
- * Tests the {@link UnitaryProjection#t(double, double)} function.
+ * Tests the {@link UnitaryProjection#exp_y(double, double)} function.
*
* {@preformat text
* Forward: y = -log(t(φ))
@@ -125,37 +125,37 @@ public final strictfp class UnitaryProje
* }
*/
@Test
- public void test_t() {
+ public void testExp_y() {
projection = new NoOp(false); // Spherical case
- doTest_t();
+ doTestExp_y();
projection = new NoOp(true); // Ellipsoidal case
- doTest_t();
+ doTestExp_y();
}
/**
- * Implementation of {@link #test_t()}.
+ * Implementation of {@link #testExp_y()}.
* The {@link #projection} field must have been set before this method is
called.
*/
- private void doTest_t() {
- assertEquals("Function contract", NaN, t(NaN),
TOLERANCE);
- assertEquals("Function contract", NaN, t(POSITIVE_INFINITY),
TOLERANCE);
- assertEquals("Function contract", NaN, t(NEGATIVE_INFINITY),
TOLERANCE);
- assertEquals("Function contract", 1, t(0),
TOLERANCE);
- assertEquals("Function contract", 0, t(+PI/2),
TOLERANCE);
- assertTrue ("Function contract", t(-PI/2) > 1E+16);
- assertTrue ("Out of bounds", t(+PI/2 + 0.1) < 0);
- assertTrue ("Out of bounds", t(-PI/2 - 0.1) < 0);
- assertEquals("Out of bounds", -1, t(PI),
TOLERANCE);
- assertTrue ("Out of bounds", t(PI*3/2) <
-1E+16);
- assertEquals("Function periodicity", 1, t(2*PI),
TOLERANCE);
- assertEquals("Function periodicity", 0, t(PI*5/2),
TOLERANCE);
+ private void doTestExp_y() {
+ assertEquals("Function contract", NaN, exp_y(NaN),
TOLERANCE);
+ assertEquals("Function contract", NaN, exp_y(POSITIVE_INFINITY),
TOLERANCE);
+ assertEquals("Function contract", NaN, exp_y(NEGATIVE_INFINITY),
TOLERANCE);
+ assertEquals("Function contract", 1, exp_y(0),
TOLERANCE);
+ assertEquals("Function contract", 0, exp_y(-PI/2),
TOLERANCE);
+ assertTrue ("Function contract", exp_y(+PI/2) >
1E+16);
+ assertTrue ("Out of bounds", exp_y(-PI/2 - 0.1) < 0);
+ assertTrue ("Out of bounds", exp_y(+PI/2 + 0.1) < 0);
+ assertEquals("Out of bounds", -1, exp_y(-PI),
TOLERANCE);
+ assertTrue ("Out of bounds", exp_y(-PI*3/2) <
-1E+16);
+ assertEquals("Function periodicity", 1, exp_y(-2*PI),
TOLERANCE);
+ assertEquals("Function periodicity", 0, exp_y(-PI*5/2),
TOLERANCE);
/*
* Use in a way close to (but not identical)
* to the way the Mercator projection need it.
*/
- assertEquals("Forward 0°N", 0, -log(t(0)),
TOLERANCE);
- assertEquals("Forward 90°N", POSITIVE_INFINITY, -log(t(+PI/2)),
TOLERANCE);
- assertTrue ("Forward 90°S", -LN_INFINITY > -log(t(-PI/2)));
+ assertEquals("Forward 0°N", 0, log(exp_y(0)),
TOLERANCE);
+ assertEquals("Forward 90°S", NEGATIVE_INFINITY, log(exp_y(-PI/2)),
TOLERANCE);
+ assertTrue ("Forward 90°N", LN_INFINITY < log(exp_y(+PI/2)));
}
/**
@@ -167,7 +167,7 @@ public final strictfp class UnitaryProje
* @throws ProjectionException Should never happen.
*/
@Test
- @DependsOnMethod("test_t")
+ @DependsOnMethod("testExp_y")
public void test_φ() throws ProjectionException {
projection = new NoOp(false); // Spherical case
doTest_φ(TOLERANCE);
@@ -195,12 +195,12 @@ public final strictfp class UnitaryProje
*/
for (int i=-90; i<=270; i+=5) {
final double φ = toRadians(i);
- final double t = t(φ);
+ final double t = 1 / exp_y(φ);
final double back = toDegrees(φ(t));
if (i <= 90) {
- assertTrue("tsfn in valid range should be positive.", t >= 0);
+ assertTrue("φ(t) in valid range should be positive.", t >= 0);
} else {
- assertTrue("tsfn in invalid range should be negative.", t < 0);
+ assertTrue("φ(t) in invalid range should be negative.", t < 0);
}
assertEquals("Inverse function doesn't match.", i, back,
tolerance);
}