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 c9746c3198d9cefcde6394e4089cfa5ac506e2b3 Author: Matthieu_Bastianelli <matthieu.bastiane...@geomatys.com> AuthorDate: Tue Jul 23 12:52:07 2019 +0200 feat (sis-referencing & internal) : add test for cylindrical satellite-tracking projection and refactor of the ConicSatelliteTracking classe to use methods instead of lambda expressions --- .../referencing/provider/SatelliteTracking.java | 3 - .../projection/ConicSatelliteTracking.java | 110 +++++++++++++-------- .../projection/CylindricalSatelliteTracking.java | 2 +- .../projection/ConicSatelliteTrackingTest.java | 59 ++++++++++- .../CylindricalSatelliteTrackingTest.java | 103 +++++++++++++++++-- 5 files changed, 223 insertions(+), 54 deletions(-) diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/SatelliteTracking.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/SatelliteTracking.java index 3e9382d..6784123 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/SatelliteTracking.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/SatelliteTracking.java @@ -19,10 +19,7 @@ package org.apache.sis.internal.referencing.provider; import javax.xml.bind.annotation.XmlTransient; -import static org.apache.sis.internal.referencing.provider.AbstractProvider.createZeroConstant; -import static org.apache.sis.internal.referencing.provider.Mercator1SP.LATITUDE_OF_ORIGIN; import org.apache.sis.measure.Units; -import org.apache.sis.metadata.iso.citation.Citations; import org.apache.sis.parameter.ParameterBuilder; import org.apache.sis.parameter.Parameters; import org.apache.sis.referencing.operation.projection.ConicSatelliteTracking; diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ConicSatelliteTracking.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ConicSatelliteTracking.java index 3c8d556..f7247df 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ConicSatelliteTracking.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ConicSatelliteTracking.java @@ -27,7 +27,6 @@ import org.opengis.referencing.operation.Matrix; import org.opengis.referencing.operation.OperationMethod; import static java.lang.Math.*; -import java.util.function.DoubleUnaryOperator; import org.apache.sis.internal.referencing.Resources; import static org.apache.sis.internal.referencing.provider.SatelliteTracking.*; import org.apache.sis.referencing.operation.matrix.MatrixSIS; @@ -100,11 +99,14 @@ public class ConicSatelliteTracking extends NormalizedProjection{ * Projection Cone's constant. */ private final double n; + /** - * Approximation of the limiting lattitude to which the {@code L coefficient} + * Approximation of the Minimum latitude at infinite radius. + * + * Limiting latitude to which the {@code L coefficient} * is associated with a particular case {@code L equals -s0/n}. */ - private final double lattitudeLimit; + private final double latitudeLimit; /** * Boolean attribute indicating if the projection cone's constant is positive. * */ @@ -174,31 +176,29 @@ public class ConicSatelliteTracking extends NormalizedProjection{ final double sin_φ0 = sin(φ0); final double φ2 = toRadians(initializer.getAndStore(STANDARD_PARALLEL_2)); //appropriated use of toRadians?? -// final double F0 = atan( (p2_on_p1*cos2_φ0 - cos_i)/sqrt(cos2_φ0 - cos2_i) ); -// final double F1 = atan( (p2_on_p1*cos2_φ1 - cos_i)/sqrt(cos2_φ1 - cos2_i) ); -// final double F2 = atan( (p2_on_p1*cos2_φ2 - cos_i)/sqrt(cos2_φ2 - cos2_i) ); -// final double dλ0 = -asin(sin_φ0/sin_i); -// final double dλ1 = -asin(sin_φ1/sin_i); -// final double dλ2 = -asin(sin_φ2/sin_i); -// final double λt0 = atan( tan(dλ0) * cos_i ); -// final double λt1 = atan( tan(dλ1) * cos_i ); -// final double λt2 = atan( tan(dλ2) * cos_i ); - final DoubleUnaryOperator computeFn = (cos2_φn) -> atan((p2_on_p1 * cos2_φn - cos_i) / sqrt(cos2_φn - cos2_i)); // eq.28-9 in Snyder - final double F0 = computeFn.applyAsDouble(cos2_φ0); +// final DoubleUnaryOperator computeFn = (cos2_φn) -> atan((p2_on_p1 * cos2_φn - cos_i) / sqrt(cos2_φn - cos2_i)); // eq.28-9 in Snyder +// final double F0 = computeFn.applyAsDouble(cos2_φ0); +// final double F1 = computeFn.applyAsDouble(cos2_φ1); +// final DoubleUnaryOperator computedλn = (sin_φn) -> -asin(sin_φn / sin_i); // eq.28-2a in Snyder +// final double dλ0 = computedλn.applyAsDouble(sin_φ0); +// final double dλ1 = computedλn.applyAsDouble(sin_φ1); +// final DoubleUnaryOperator computeλtn = (dλn) -> atan(tan(dλn) * cos_i); // eq.28-3a in Snyder +// final double λt0 = computeλtn.applyAsDouble(dλ0); +// final double λt1 = computeλtn.applyAsDouble(dλ1); + + final double F0 = computeFn(cos2_φ0); /* - *Inclination of the groundtrack to the meridian at latitude φ1 + * Inclination of the groundtrack to the meridian at latitude φ1 */ - final double F1 = computeFn.applyAsDouble(cos2_φ1); + final double F1 = computeFn(cos2_φ1); cos_φ1xsin_F1 = cos_φ1 * sin(F1); - final DoubleUnaryOperator computedλn = (sin_φn) -> -asin(sin_φn / sin_i); // eq.28-2a in Snyder - final double dλ0 = computedλn.applyAsDouble(sin_φ0); - final double dλ1 = computedλn.applyAsDouble(sin_φ1); + final double dλ0 = computedλn(sin_φ0); + final double dλ1 = computedλn(sin_φ1); - final DoubleUnaryOperator computeλtn = (dλn) -> atan(tan(dλn) * cos_i); // eq.28-3a in Snyder - final double λt0 = computeλtn.applyAsDouble(dλ0); - final double λt1 = computeλtn.applyAsDouble(dλ1); + final double λt0 = computeλtn(dλ0); + final double λt1 = computeλtn(dλ1); final double L0 = λt0 - p2_on_p1 * dλ0; final double L1 = λt1 - p2_on_p1 * dλ1; @@ -211,10 +211,12 @@ public class ConicSatelliteTracking extends NormalizedProjection{ final double cos_φ2 = cos(φ2); final double cos2_φ2 = cos_φ2 * cos_φ2; final double sin_φ2 = sin(φ2); - final double dλ2 = computedλn.applyAsDouble(sin_φ2); - final double λt2 = computeλtn.applyAsDouble(dλ2); +// final double dλ2 = computedλn.applyAsDouble(sin_φ2); + final double dλ2 = computedλn(sin_φ2); + final double λt2 = computeλtn(dλ2); final double L2 = λt2 - p2_on_p1 * dλ2; - final double F2 = computeFn.applyAsDouble(cos2_φ2); +// final double F2 = computeFn.applyAsDouble(cos2_φ2); + final double F2 = computeFn(cos2_φ2); n = (F2 - F1) / (L2 - L1); } else { n = sin_φ1 * (p2_on_p1 * (2 * cos2_i - cos2_φ1) - cos_i) / (p2_on_p1 * cos2_φ1 - cos_i); //eq. 28-17 in Snyder @@ -223,28 +225,24 @@ public class ConicSatelliteTracking extends NormalizedProjection{ ρ0 = cos_φ1xsin_F1 / (n * sin(n * L0 + s0)); // *R in eq.28-12 in Snyder //======================== Unsure ====================================== - // Aim to assess the limit lattitude associated with -s0/n L-value. + // Aim to assess the limit latitude associated with -s0/n L-value. // - lattitudeLimit = lattitudeFromNewtonMethod(-s0 / n); + latitudeLimit = latitudeFromNewtonMethod(-s0 / n); positiveN = (n >= 0); //====================================================================== // //Additionally we can compute the radius of the circle to which groundtracks // //are tangent on the map : // ρs = cos_φ1xsin_F1 / n; //*R - //====================================================================== /* * At this point, all parameters have been processed. Now process to their * validation and the initialization of (de)normalize affine transforms. */ - final MatrixSIS normalize = context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION); -// final MatrixSIS denormalize = context.getMatrix(ContextualParameters.MatrixRole.DENORMALIZATION); - normalize .convertAfter (0, n, null); //For conic tracking -// denormalize.convertBefore(0, 1/PI, null); -// denormalize.convertBefore(1, , null); + final MatrixSIS normalize = context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION); + normalize.convertAfter(0, n, null); //For conic tracking }else{ - n = lattitudeLimit = cos_φ1xsin_F1 = s0 = ρ0 = NaN; + n = latitudeLimit = cos_φ1xsin_F1 = s0 = ρ0 = NaN; positiveN = false; } } @@ -275,7 +273,7 @@ public class ConicSatelliteTracking extends NormalizedProjection{ /* * According to the Snyder (page 236) in those cases cannot or should not be plotted. */ - if( ((positiveN)&&(φ<=lattitudeLimit)) || ((!positiveN)&&(φ>=lattitudeLimit)) ){ + if( ((positiveN)&&(φ<=latitudeLimit)) || ((!positiveN)&&(φ>=latitudeLimit)) ){ throw new ProjectionException(Resources.format(Resources.Keys.CanNotTransformCoordinates_2)); } @@ -285,11 +283,11 @@ public class ConicSatelliteTracking extends NormalizedProjection{ final double L = λt - p2_on_p1 * dλ; /* - * As {@code lattitudeLimit} is an approximation we repeat the test here. + * As {@code latitudeLimit} is an approximation we repeat the test here. */ if( ((positiveN)&&(L<=-s0/n)) || ((!positiveN)&&(L>=-s0/n)) ){ //TODO if usefull, could we add : - // lattitudeLimit = φ; + // latitudeLimit = φ; throw new ProjectionException(Resources.format(Resources.Keys.CanNotTransformCoordinates_2)); } @@ -349,10 +347,10 @@ public class ConicSatelliteTracking extends NormalizedProjection{ //TODO ensure that λ0 will be added. ; In eq. Snyder 28-23 : λ0 + θ/n dstPts[dstOff ] = θ ;//λ - dstPts[dstOff+1] = lattitudeFromNewtonMethod(L); //φ + dstPts[dstOff+1] = latitudeFromNewtonMethod(L); //φ } - protected final double lattitudeFromNewtonMethod(final double l){ + protected final double latitudeFromNewtonMethod(final double l){ double dλ = -PI/2; double dλn = Double.MIN_VALUE; double A, A2, Δdλ; @@ -382,10 +380,40 @@ public class ConicSatelliteTracking extends NormalizedProjection{ } - public double getLattitudeLimit(){ - return lattitudeLimit; + public double getLatitudeLimit(){ + return latitudeLimit; } + /** + * Method to compute the φn coefficient according to equation 28-9 + * in Snyder's Map Projections manual. + * + * @param cos2_φn : square of the φn 's cosinus. + * @return Fn coefficient associated with the φn latittude. + */ + private double computeFn(final double cos2_φn) { + return atan((p2_on_p1 * cos2_φn - cos_i) / sqrt(cos2_φn - cos2_i)); // eq.28-9 in Snyder + } + /** + * Method to compute the φn coefficient according to equation 28-2a + * in Snyder's Map Projections manual. + * + * @param sin_φn : φn 's sinus. + * @return dλn coefficient associated with the φn latittude. + */ + private double computedλn(final double sin_φn) { + return -asin(sin_φn / sin_i); // eq.28-2a in Snyder + } + /** + * Method to compute the φn coefficient according to equation 28-3a + * in Snyder's Map Projections manual. + * + * @param dλn coefficient associated with the φn latittude. + * @return λtn coefficient associated with the φn latittude. + */ + private double computeλtn(final double dλn) { + return atan(tan(dλn) * cos_i); // eq.28-3a in Snyder + } // /** // * Radius of the circle radius of the circle to which groundtracks // * are tangent on the map. diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/CylindricalSatelliteTracking.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/CylindricalSatelliteTracking.java index 70ea6fe..1284583 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/CylindricalSatelliteTracking.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/CylindricalSatelliteTracking.java @@ -191,7 +191,7 @@ public class CylindricalSatelliteTracking extends ConicSatelliteTracking { final double L = y * dF1 / cos_φ1; // In eq. Snyder 28-19 : L = y * dF1 / R . cos_φ1 dstPts[dstOff ] = x; - dstPts[dstOff+1] = lattitudeFromNewtonMethod(L); //φ + dstPts[dstOff+1] = latitudeFromNewtonMethod(L); //φ } } diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConicSatelliteTrackingTest.java b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConicSatelliteTrackingTest.java index 28d83df..0b20c88 100644 --- a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConicSatelliteTrackingTest.java +++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ConicSatelliteTrackingTest.java @@ -18,8 +18,8 @@ */ package org.apache.sis.referencing.operation.projection; -import static java.lang.Double.NaN; import java.util.Collections; +import org.apache.sis.internal.referencing.Formulas; import org.apache.sis.internal.referencing.NilReferencingObject; import org.apache.sis.internal.referencing.provider.SatelliteTracking; import org.apache.sis.measure.Units; @@ -57,7 +57,7 @@ public class ConicSatelliteTrackingTest extends MapProjectionTestCase { * @param λ0 : central meridian. * @param φ1 : first parallel of conformality, with true scale. * @param φ2 : second parallel of conformality, without true scale. - * @param φ0 : lattitude_of_origin : latitude Crossing the central meridian + * @param φ0 : latitude_of_origin : latitude Crossing the central meridian * at the desired origin of rectangular coordinates (null or NaN for * cylindrical satellite tracking projection.) * @return @@ -98,6 +98,9 @@ public class ConicSatelliteTrackingTest extends MapProjectionTestCase { /** * Tests the projection of a few points on a sphere. * + * Test based on the numerical example given by Snyder p. 360 to 363 of + * <cite> Map Projections - A working Manual</cite> + * * @throws FactoryException if an error occurred while creating the map * projection. * @throws TransformException if an error occurred while projecting a point. @@ -112,7 +115,7 @@ public class ConicSatelliteTrackingTest extends MapProjectionTestCase { -90, //central_meridian 45, //standard_parallel_1 70, //standard_parallel_2 - 30 //lattitude_of_origin + 30 //latitude_of_origin ); assertTrue(isInverseTransformSupported); verifyTransform( @@ -123,5 +126,55 @@ public class ConicSatelliteTrackingTest extends MapProjectionTestCase { 0.2001910, 0.2121685 }); } + + /** + * Tests the projection of a few points on a sphere. + * + * Test based on the sample coordinates for several of the + * Satellite-Tracking Projections shown in table 39 from + * <cite> Map Projections - A working Manual</cite> + * + * @throws FactoryException if an error occurred while creating the map + * projection. + * @throws TransformException if an error occurred while projecting a point. + */ + @Test + public void testSampleCoordinates() throws FactoryException, TransformException { + + //Following tests don't pass with the former tolerance. + tolerance = Formulas.LINEAR_TOLERANCE; + + //---------------------------------------------------------------------- + // φ1 = 30° ; φ2 = 60° + //--------------------- + createProjection( + 99.092, //satellite_orbit_inclination + 103.267, //satellite_orbital_period + 1440.0, //ascending_node_period + -90, //central_meridian + 30, //standard_parallel_1 + 60, //standard_parallel_2 + 30 //latitude_of_origin + ); +// double xConverterFactor=0.017453; +// verifyTransform( +// new double[]{ // (λ,φ) coordinates in degrees to project. +// 0, 0, +//// 10, 0, +//// -10, 10, +//// 60, 40, +//// 80, 70, +//// -120, 80.908 //Tracking limit +// }, +// new double[]{ // Expected (x,y) results in metres. +// 0, 0, +//// xConverterFactor * 10, 0, +//// xConverterFactor * -10, 0.17579, +//// xConverterFactor * 60, 0.79741, +//// xConverterFactor * 80, 2.34465, +//// xConverterFactor * -120, 7.23571 //Tracking limit +// }); + + } } diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/CylindricalSatelliteTrackingTest.java b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/CylindricalSatelliteTrackingTest.java index 0a86ba6..c207af3 100644 --- a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/CylindricalSatelliteTrackingTest.java +++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/CylindricalSatelliteTrackingTest.java @@ -51,7 +51,7 @@ public class CylindricalSatelliteTrackingTest extends ConicSatelliteTrackingTest * @param λ0 : central meridian. * @param φ1 : first parallel of conformality, with true scale. * @param φ2 : second parallel of conformality, without true scale. - * @param φ0 : lattitude_of_origin : latitude Crossing the central meridian + * @param φ0 : latitude_of_origin : latitude Crossing the central meridian * at the desired origin of rectangular coordinates (null or NaN for * cylindrical satellite tracking projection.) * @return @@ -66,6 +66,9 @@ public class CylindricalSatelliteTrackingTest extends ConicSatelliteTrackingTest /** * Tests the projection of a few points on a sphere. * + * Test based on the numerical example given by Snyder p. 360 to 363 of + * <cite> Map Projections - A working Manual</cite> + * * @throws FactoryException if an error occurred while creating the map * projection. * @throws TransformException if an error occurred while projecting a point. @@ -89,7 +92,28 @@ public class CylindricalSatelliteTrackingTest extends ConicSatelliteTrackingTest new double[]{ // Expected (x,y) results in metres. 0.2267249, 0.6459071 }); + } + + /** + * Tests the projection of a few points on a sphere. + * + * Test based on the sample coordinates for several of the + * Satellite-Tracking Projections shown in table 38 from + * <cite> Map Projections - A working Manual</cite> + * + * @throws FactoryException if an error occurred while creating the map + * projection. + * @throws TransformException if an error occurred while projecting a point. + */ + @Test + public void testSampleCoordinates() throws FactoryException, TransformException { + //Following tests don't pass with the former tolerance. + tolerance = Formulas.LINEAR_TOLERANCE; + + //---------------------------------------------------------------------- + // φ1 = 0° + //--------- createProjection( 99.092, //satellite_orbit_inclination 103.267, //satellite_orbital_period @@ -97,21 +121,88 @@ public class CylindricalSatelliteTrackingTest extends ConicSatelliteTrackingTest 0, //central_meridian 0 //standard_parallel_1 ); + + double xConverterFactor=0.017453; + verifyTransform( + new double[]{ // (λ,φ) coordinates in degrees to project. + 0, 0, + 10, 0, + -10, 10, + 60, 40, + 80, 70, + -120, 80.908 //Tracking limit + }, + new double[]{ // Expected (x,y) results in metres. + 0, 0, + xConverterFactor * 10, 0, + xConverterFactor * -10, 0.17579, + xConverterFactor * 60, 0.79741, + xConverterFactor * 80, 2.34465, + xConverterFactor * -120, 7.23571 //Tracking limit + }); - tolerance = Formulas.LINEAR_TOLERANCE; //Don't pass with the former tolerance. - final double xConverterFactor=0.017453; + //---------------------------------------------------------------------- + // φ1 = +- 30° + //------------ + createProjection( + 99.092, //satellite_orbit_inclination + 103.267, //satellite_orbital_period + 1440.0, //ascending_node_period + 0, //central_meridian + -30 //standard_parallel_1 + ); + + xConverterFactor=0.015115; verifyTransform( new double[]{ // (λ,φ) coordinates in degrees to project. 0, 0, 10, 0, - -10, 10 + -10, 10, + 60, 40, + 80, 70, + -120, 80.908 //Tracking limit }, new double[]{ // Expected (x,y) results in metres. 0, 0, - xConverterFactor * 10, 0, - xConverterFactor * -10, 0.17579, + xConverterFactor * 10, 0, + xConverterFactor * -10, 0.14239, + xConverterFactor * 60, 0.64591, + xConverterFactor * 80, 1.89918, + xConverterFactor * -120, 5.86095 //Tracking limit }); + + //---------------------------------------------------------------------- + // φ1 = +- 45° + //------------ + createProjection( + 99.092, //satellite_orbit_inclination + 103.267, //satellite_orbital_period + 1440.0, //ascending_node_period + 0, //central_meridian + 45 //standard_parallel_1 + ); + + xConverterFactor=0.012341; + verifyTransform( + new double[]{ // (λ,φ) coordinates in degrees to project. + 0, 0, + 10, 0, + -10, 10, + 60, 40, + 80, 70, + -120, 80.908 //Tracking limit + }, + new double[]{ // Expected (x,y) results in metres. + 0, 0, + xConverterFactor * 10, 0, + xConverterFactor * -10, 0.10281, + xConverterFactor * 60, 0.46636, + xConverterFactor * 80, 1.37124, + xConverterFactor * -120, 4.23171 //Tracking limit + }); + + } }