Author: desruisseaux
Date: Wed Mar 25 17:13:15 2015
New Revision: 1669159
URL: http://svn.apache.org/r1669159
Log:
Referencing: partial port of Mercator initialization operations
(construction of normalization and denormalization affines).
Modified:
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/transform/ContextualParameters.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/formulas.html
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/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=1669159&r1=1669158&r2=1669159&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 17:13:15 2015
@@ -25,6 +25,7 @@ import org.apache.sis.internal.referenci
import org.apache.sis.internal.referencing.provider.Mercator2SP;
import org.apache.sis.internal.referencing.provider.PseudoMercator;
import org.apache.sis.internal.referencing.provider.MillerCylindrical;
+import org.apache.sis.referencing.operation.matrix.MatrixSIS;
import org.apache.sis.referencing.operation.matrix.Matrix2;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.parameter.Parameters;
@@ -87,6 +88,37 @@ public class Mercator extends UnitaryPro
*/
protected Mercator(final OperationMethod method, final Parameters values) {
super(method, values);
+ double φ1 = abs(values.doubleValue(Mercator2SP.STANDARD_PARALLEL));
+ double φ0 = values.doubleValue(Mercator2SP.LATITUDE_OF_ORIGIN);
+ double λ0 = values.doubleValue(Mercator2SP.CENTRAL_MERIDIAN);
+ double k0 = values.doubleValue(Mercator2SP.SCALE_FACTOR);
+ double FE = values.doubleValue(Mercator2SP.FALSE_EASTING);
+ double FN = values.doubleValue(Mercator2SP.FALSE_NORTHING);
+
+ φ1 = toRadians(φ1);
+ k0 *= cos(φ1);
+ if (!isSpherical()) {
+ k0 /= rν(sin(φ1));
+ }
+ final MatrixSIS normalize = parameters.normalizeGeographicInputs(λ0);
+ final MatrixSIS denormalize = parameters.denormalizeCartesianOutputs(
+ values.doubleValue(Mercator2SP.SEMI_MAJOR) * k0, FE, FN);
+ /*
+ * A correction that allows us to employ a latitude of origin that is
not correspondent to the equator,
+ * as described in Snyder and al. at page 47. This is the same
correction factor than the one applied
+ * for the Mercator (2SP) case, constant "ko" in EPSG:9805.
+ *
+ * The scale correction is multiplied with the global scale, which
allows the Apache SIS referencing
+ * module to merge this correction with the scale factor in a single
multiplication.
+ */
+ φ0 = toRadians(φ0);
+ double scale = cos(φ0) / rν(sin(φ0));
+ final boolean isMiller =
IdentifiedObjects.isHeuristicMatchForName(values.getDescriptor(),
MillerCylindrical.NAME);
+ if (isMiller) {
+ scale *= 1.25;
+ }
+ denormalize.concatenate(0, scale, null);
+ denormalize.concatenate(1, scale, null);
}
/**
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java?rev=1669159&r1=1669158&r2=1669159&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
[UTF-8] Wed Mar 25 17:13:15 2015
@@ -31,6 +31,7 @@ import org.opengis.referencing.operation
import org.opengis.referencing.operation.MathTransformFactory;
import org.apache.sis.internal.referencing.ExtendedPrecisionMatrix;
import org.apache.sis.internal.referencing.WKTUtilities;
+import org.apache.sis.internal.util.DoubleDouble;
import org.apache.sis.parameter.Parameterized;
import org.apache.sis.referencing.operation.matrix.Matrices;
import org.apache.sis.referencing.operation.matrix.MatrixSIS;
@@ -75,8 +76,8 @@ import static org.apache.sis.util.Argume
* {@link ParameterValueGroup}, initializes the projection, then saves the
parameter values that
* it actually used in a new {@code ContextualParameters} instance.</li>
*
- * <li>The map projection constructor may keep only the non-linear
parameters for itself, and gives the linear parameters
- * to the {@link #normalizeGeographic(double)} and {@link
#denormalizeCartesian(double, double, double, double)} methods.
+ * <li>The map projection constructor may keep only the non-linear
parameters for itself, and gives the linear parameters to the
+ * {@link #normalizeGeographicInputs(double)} and {@link
#denormalizeCartesianOutputs(double, double, double)} methods.
* The constructor is free to apply additional operations on the two
affine transforms
* ({@linkplain #normalization(boolean) normalize / denormalize}) after
the above-cited methods have been invoked.</li>
* </ol>
@@ -115,17 +116,7 @@ public class ContextualParameters extend
*
* @see #normalization(boolean)
*/
- private Matrix normalize,
-
- /**
- * The affine transform to be applied before (<cite>normalize</cite>) and
after (<cite>denormalize</cite>)
- * the kernel operation.On {@code ContextualParameters} construction,
those affines are initially identity
- * transforms, to be modified in-place by callers of {@link
#normalization(boolean)}.
- * After {@link #createConcatenatedTransform(MathTransformFactory,
MathTransform)} has been invoked,
- * they are typically (but not necessarily) replaced by the {@link
LinearTransform} instance itself.
- * @see #normalization(boolean)
- */
- denormalize;
+ private Matrix normalize, denormalize;
/**
* Creates a new group of parameters for the given non-linear coordinate
operation method.
@@ -156,41 +147,6 @@ public class ContextualParameters extend
}
/**
- * The affine transforms to be applied before or after the kernel
operation. Those affines are initially
- * identity transforms. Callers should invoke this method at the
non-linear transform construction time
- * (or at some time close to construction) in order to set the affine
coefficients.
- *
- * @param norm {@code true} for fetching the <cite>normalize</cite>
transform to apply before the kernel,
- * or {@code false} for the <cite>denormalize</cite> transform to
apply after the kernel.
- * @return The requested normalize ({@code true}) or denormalize ({@code
false}) affine transform.
- */
- public final MatrixSIS normalization(final boolean norm) {
- return MatrixSIS.castOrCopy(norm ? normalize : denormalize);
- }
-
- /**
- * Creates a chain of {@linkplain ConcatenatedTransform concatenated
transforms} from the
- * <cite>normalize</cite> transform, the given kernel and the
<cite>denormalize</cite> transform.
- *
- * @param kernel The (usually non-linear) kernel.
- * @return The concatenation of <cite>normalize</cite> → <cite>the given
kernel</cite> → <cite>denormalize</cite>
- * transforms.
- */
- final MathTransform createConcatenatedTransform(final MathTransformFactory
factory, MathTransform kernel)
- throws FactoryException
- {
- final MathTransform n = factory.createAffineTransform(normalize);
- final MathTransform d = factory.createAffineTransform(denormalize);
- Matrix m;
- if ((m = MathTransforms.getMatrix(n)) != null) normalize = m;
- if ((m = MathTransforms.getMatrix(d)) != null) denormalize = m;
- if (factory instanceof DefaultMathTransformFactory) {
- kernel = ((DefaultMathTransformFactory) factory).unique(kernel);
- }
- return
factory.createConcatenatedTransform(factory.createConcatenatedTransform(n,
kernel), d);
- }
-
- /**
* Returns the parameters for the whole <cite>normalize</cite> →
<cite>non-linear kernel</cite> →
* <cite>denormalize</cite> sequence. The parameter values may take effect
in either the
* {@linkplain #normalization(boolean) normalize/denormalize} transforms
or in the kernel.
@@ -230,6 +186,97 @@ public class ContextualParameters extend
}
/**
+ * Prepends a normalization step before the non-linear kernel, which will
convert ordinate values
+ * in the two first dimensions from degrees to radians. Before this
conversion, the normalization
+ * can optionally subtract the given λ0 value (in degrees) from the
longitude.
+ *
+ * <p>In other words, invoking this method is equivalent to convert
coordinates using the following
+ * affine transform before any other operation:</p>
+ *
+ * <center><p>{@include formulas.html#Normalize}</p></center>
+ *
+ * @param λ0 Longitude of the central meridian, in degrees.
+ * @return The normalization affine transform as a matrix.
+ * Callers can change that matrix directly if they want to apply
additional normalization operations.
+ */
+ public MatrixSIS normalizeGeographicInputs(final double λ0) {
+ /*
+ * In theory the check for (λ0 != 0) is useless. However Java has a
notion of negative zero, and we want
+ * to avoid negative zeros because we do not want them to appear in
WKT formatting of matrix elements.
+ */
+ final DoubleDouble toRadians = DoubleDouble.createDegreesToRadians();
+ DoubleDouble offset = null;
+ if (λ0 != 0) {
+ offset = new DoubleDouble(-λ0);
+ offset.multiply(toRadians);
+ }
+ final MatrixSIS normalize = normalization(true);
+ normalize.concatenate(0, toRadians, offset);
+ normalize.concatenate(1, toRadians, null);
+ return normalize;
+ }
+
+ /**
+ * Appends a normalization step after the non-linear kernel, which will
scale the projected ordinates
+ * and add the false easting and northing.
+ *
+ * <p>In other words, invoking this method is equivalent to convert
coordinates using the following
+ * affine transform after the non-linear kernel:</p>
+ *
+ * <center><p>{@include formulas.html#Deormalize}</p></center>
+ *
+ * @param scale The <cite>semi-major axis length</cite> (<var>a</var>),
optionally multiplied by other scale factor (<var>k</var>₀).
+ * @param tx The false easting (FE).
+ * @param ty The false northing (FN).
+ * @return The denormalization affine transform as a matrix.
+ * Callers can change that matrix directly if they want to apply
additional denormalization operations.
+ */
+ public MatrixSIS denormalizeCartesianOutputs(double scale, double tx,
double ty) {
+ final DoubleDouble s = new DoubleDouble(scale);
+ final MatrixSIS denormalize = normalization(false);
+ denormalize.concatenate(0, s, tx);
+ denormalize.concatenate(1, s, ty);
+ return denormalize;
+ }
+
+ /**
+ * The affine transforms to be applied before or after the kernel
operation. Those affines are initially
+ * identity transforms. Callers should invoke this method at the
non-linear transform construction time
+ * (or at some time close to construction) in order to set the affine
coefficients.
+ *
+ * @param norm {@code true} for fetching the <cite>normalize</cite>
transform to apply before the kernel,
+ * or {@code false} for the <cite>denormalize</cite> transform to
apply after the kernel.
+ * @return The requested normalize ({@code true}) or denormalize ({@code
false}) affine transform.
+ */
+ public final MatrixSIS normalization(final boolean norm) {
+ return MatrixSIS.castOrCopy(norm ? normalize : denormalize);
+ }
+
+ /**
+ * Creates a chain of {@linkplain ConcatenatedTransform concatenated
transforms} from the
+ * <cite>normalize</cite> transform, the given kernel and the
<cite>denormalize</cite> transform.
+ *
+ * @param factory The factory to use for creating math transform
instances.
+ * @param kernel The (usually non-linear) kernel.
+ * @return The concatenation of <cite>normalize</cite> → <cite>the given
kernel</cite> → <cite>denormalize</cite>
+ * transforms.
+ * @throws FactoryException if an error occurred while creating a math
transform instance.
+ */
+ public MathTransform createConcatenatedTransform(final
MathTransformFactory factory, MathTransform kernel)
+ throws FactoryException
+ {
+ final MathTransform n = factory.createAffineTransform(normalize);
+ final MathTransform d = factory.createAffineTransform(denormalize);
+ Matrix m;
+ if ((m = MathTransforms.getMatrix(n)) != null) normalize = m;
+ if ((m = MathTransforms.getMatrix(d)) != null) denormalize = m;
+ if (factory instanceof DefaultMathTransformFactory) {
+ kernel = ((DefaultMathTransformFactory) factory).unique(kernel);
+ }
+ return
factory.createConcatenatedTransform(factory.createConcatenatedTransform(n,
kernel), d);
+ }
+
+ /**
* Unsupported operation, since {@code ContextualParameters} groups do not
contain sub-groups.
* This limitation may be revisited in future SIS version.
*
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/formulas.html
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/formulas.html?rev=1669159&r1=1669158&r2=1669159&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/formulas.html
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/formulas.html
[UTF-8] Wed Mar 25 17:13:15 2015
@@ -113,5 +113,57 @@
</math>
</td></tr>
</table>
+
+
+
+
+ <h2>Normalize</h2>
+ <math display="block" alttext="MathML capable browser required">
+ <mfenced open="[" close="]">
+ <mtable>
+ <mtr>
+ <mtd><mi>π</mi><mo>/</mo><mn>180</mn></mtd>
+ <mtd><mn>0</mn></mtd>
+
<mtd><mo>-</mo><mo>(</mo><mi>π</mi><mo>/</mo><mn>180</mn><mo>)</mo> <mo>∙</mo>
<msub><mi>λ</mi><mn>0</mn></msub></mtd>
+ </mtr>
+ <mtr>
+ <mtd><mn>0</mn></mtd>
+ <mtd><mi>π</mi><mo>/</mo><mn>180</mn></mtd>
+ <mtd><mn>0</mn></mtd>
+ </mtr>
+ <mtr>
+ <mtd><mn>0</mn></mtd>
+ <mtd><mn>0</mn></mtd>
+ <mtd><mn>1</mn></mtd>
+ </mtr>
+ </mtable>
+ </mfenced>
+ </math>
+
+
+
+
+ <h2>Denormalize</h2>
+ <math display="block" alttext="MathML capable browser required">
+ <mfenced open="[" close="]">
+ <mtable>
+ <mtr>
+ <mtd><mi>a</mi> <mo>∙</mo> <msub><mi>k</mi><mn>0</mn></msub></mtd>
+ <mtd><mn>0</mn></mtd>
+ <mtd><mi>FE</mi></mtd>
+ </mtr>
+ <mtr>
+ <mtd><mn>0</mn></mtd>
+ <mtd><mi>a</mi> <mo>∙</mo> <msub><mi>k</mi><mn>0</mn></msub></mtd>
+ <mtd><mi>FN</mi></mtd>
+ </mtr>
+ <mtr>
+ <mtd><mn>0</mn></mtd>
+ <mtd><mn>0</mn></mtd>
+ <mtd><mn>1</mn></mtd>
+ </mtr>
+ </mtable>
+ </mfenced>
+ </math>
</body>
</html>
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=1669159&r1=1669158&r2=1669159&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 17:13:15 2015
@@ -225,17 +225,17 @@ public final strictfp class UnitaryProje
*/
@Test
@DependsOnMethod("testExpOfNorthing")
- public void test_dN_dφ() throws TransformException {
+ public void test_dy_dφ() throws TransformException {
tolerance = 1E-7;
- doTest_dN_dφ(new NoOp(false)); // Spherical case
- doTest_dN_dφ(new NoOp(true)); // Ellipsoidal case
+ doTest_dy_dφ(new NoOp(false)); // Spherical case
+ doTest_dy_dφ(new NoOp(true)); // Ellipsoidal case
}
/**
- * Implementation of {@link #test_dN_dφ()}.
+ * Implementation of {@link #test_dy_dφ()}.
* The {@link #projection} field must have been set before this method is
called.
*/
- private void doTest_dN_dφ(final NoOp projection) throws TransformException
{
+ private void doTest_dy_dφ(final NoOp projection) throws TransformException
{
transform = new AbstractMathTransform1D() {
@Override public double transform(final double φ) {
return expOfNorthing(projection, φ);