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 2b94c39aca000c337ff37b8c09a8e0a801ae00c2 Author: Matthieu_Bastianelli <matthieu.bastiane...@geomatys.com> AuthorDate: Wed Jul 24 14:33:59 2019 +0200 feat (referencing) : add some tests for satellite-tracking projections from tables 38 and 39 of Snyder's Manual (page 238). Fix the condition of the while loop when applying Newton method. --- .../referencing/provider/SatelliteTracking.java | 6 +- .../projection/ConicSatelliteTracking.java | 139 +++++++++--------- .../projection/CylindricalSatelliteTracking.java | 44 +++--- .../projection/ConicSatelliteTrackingTest.java | 156 +++++++++++++++------ .../CylindricalSatelliteTrackingTest.java | 49 +++---- .../sis/test/suite/ReferencingTestSuite.java | 2 + 6 files changed, 236 insertions(+), 160 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 6784123..787b404 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 @@ -151,7 +151,7 @@ public class SatelliteTracking extends MapProjection { SATELLITE_ORBIT_INCLINATION = builder .addName("satellite_orbit_inclination") .setDescription("Angle of inclination between the plane of the Earth's Equator and the plane of the satellite orbit") - .create(0, Units.RADIAN); + .create(0, Units.DEGREE); SATELLITE_ORBITAL_PERIOD = builder .addName("satellite_orbital_period") @@ -162,7 +162,7 @@ public class SatelliteTracking extends MapProjection { .addName("ascending_node_period") .setDescription("Length of Earth's rotation with respect to the precessed ascending node") .createStrictlyPositive(98.884, Units.MINUTE); - + PARAMETERS = builder.addName(NAME) .createGroupForMapProjection(CENTRAL_MERIDIAN, STANDARD_PARALLEL_1, STANDARD_PARALLEL_2, @@ -187,7 +187,7 @@ public class SatelliteTracking extends MapProjection { protected NormalizedProjection createProjection(final Parameters parameters) throws ParameterNotFoundException { ArgumentChecks.ensureNonNull("Parameters", parameters); - if (parameters.getValue(STANDARD_PARALLEL_2) == -parameters.getValue(STANDARD_PARALLEL_1)) { + if (parameters.getValue(STANDARD_PARALLEL_2) == -parameters.getValue(STANDARD_PARALLEL_1)) { return new org.apache.sis.referencing.operation.projection.CylindricalSatelliteTracking(this, parameters); } else { return new org.apache.sis.referencing.operation.projection.ConicSatelliteTracking(this, parameters); 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 f7247df..d650fa2 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 @@ -34,13 +34,13 @@ import org.apache.sis.referencing.operation.transform.ContextualParameters; /** * <cite>Cylindrical Satellite-Tracking projections</cite>. - * + * * <cite> * - All groundtracks for satellites orbiting the Earth with the same orbital * parameters are shown as straight lines on the map. * * - Cylindrical {@link CylindricalSatelliteTracking} - * or conical {@link ConicSatelliteTracking} form available. + * or conical {@link ConicSatelliteTracking} form available. * * - Neither conformal nor equal-area. * @@ -78,33 +78,35 @@ import org.apache.sis.referencing.operation.transform.ContextualParameters; * @version 1.0 */ public class ConicSatelliteTracking extends NormalizedProjection{ - + /** * {@code SATELLITE_ORBIT_INCLINATION} */ final double i; - + /** * Coefficients for both cylindrical and conic Satellite-Tracking Projection. */ final double cos_i, sin_i, cos2_i, cos_φ1, p2_on_p1; - + // /** // * Radius of the circle radius of the circle to which groundtracks // * are tangent on the map. // */ // private final double ρs; - + /** * Projection Cone's constant. */ private final double n; - + /** - * Approximation of the Minimum latitude at infinite radius. - * + * 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}. + * In such a situation the coefficent ρ computed for transformations + * is infinite. */ private final double latitudeLimit; /** @@ -143,11 +145,11 @@ public class ConicSatelliteTracking extends NormalizedProjection{ /** * Constructor for ConicSatelliteTracking. - * - * Calculation are based on <cite>28 .SATTELITE-TRACKING PROJECTIONS </cite> + * + * Calculation are based on <cite>28 .SATTELITE-TRACKING PROJECTIONS </cite> * in <cite> Map Projections - A Working Manual</cite> By John P. Snyder. - * - * @param initializer + * + * @param initializer */ ConicSatelliteTracking(final Initializer initializer) { super(initializer); @@ -155,7 +157,7 @@ public class ConicSatelliteTracking extends NormalizedProjection{ //====================================================================== // Common for both cylindrical and conic sattelite tracking projections : //====================================================================== - i = toRadians(initializer.getAndStore(SATELLITE_ORBIT_INCLINATION)); // Radian input value. + i = toRadians(initializer.getAndStore(SATELLITE_ORBIT_INCLINATION)); cos_i = cos(i); sin_i = sin(i); cos2_i = cos_i * cos_i; @@ -164,11 +166,11 @@ public class ConicSatelliteTracking extends NormalizedProjection{ final double φ1 = toRadians(initializer.getAndStore(STANDARD_PARALLEL_1)); //appropriated use of toRadians?? cos_φ1 = cos(φ1); final double cos2_φ1 = cos_φ1 * cos_φ1; - + //====================================================================== // For conic projection : //======================= - if(!(this instanceof CylindricalSatelliteTracking)) { + if (!(this instanceof CylindricalSatelliteTracking)) { final double sin_φ1 = sin(φ1); final double φ0 = toRadians(initializer.getAndStore(LATITUDE_OF_ORIGIN)); //appropriated use of toRadians?? final double cos_φ0 = cos(φ0); @@ -176,13 +178,13 @@ 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 DoubleUnaryOperator computeFn = (cos2_φn) -> atan((p2_on_p1 * cos2_φn - cos_i) / sqrt(cos2_φn - cos2_i)); // eq.28-9 in Snyder +// 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 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 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); @@ -203,10 +205,10 @@ public class ConicSatelliteTracking extends NormalizedProjection{ final double L0 = λt0 - p2_on_p1 * dλ0; final double L1 = λt1 - p2_on_p1 * dλ1; - if (φ1 == PI / 2 - i) { //tracking limit + if (φ1 == PI - i) { //tracking limit computed as 180 - i from Snyder's manual p.238 final double factor = (p2_on_p1 * cos_i - 1); final double factor2 = factor * factor; - n = sin_i / (factor2); //eq. 28-18 in Snyder + n = sin_i / (factor2); //eq. 28-18 in Snyder } else if (φ2 != φ1) { final double cos_φ2 = cos(φ2); final double cos2_φ2 = cos_φ2 * cos_φ2; @@ -219,10 +221,10 @@ public class ConicSatelliteTracking extends NormalizedProjection{ 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 + 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 } s0 = F1 - n * L1; - ρ0 = cos_φ1xsin_F1 / (n * sin(n * L0 + s0)); // *R in eq.28-12 in Snyder + ρ0 = cos_φ1xsin_F1 / (n * sin(n * L0 + s0)); // *R in eq.28-12 in Snyder //======================== Unsure ====================================== // Aim to assess the limit latitude associated with -s0/n L-value. @@ -234,14 +236,17 @@ public class ConicSatelliteTracking extends NormalizedProjection{ // //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); normalize.convertAfter(0, n, null); //For conic tracking - }else{ + + final MatrixSIS denormalize = context.getMatrix(ContextualParameters.MatrixRole.DENORMALIZATION); + denormalize.convertBefore(1, 1, ρ0); //For conic tracking + } else { n = latitudeLimit = cos_φ1xsin_F1 = s0 = ρ0 = NaN; positiveN = false; } @@ -263,58 +268,59 @@ public class ConicSatelliteTracking extends NormalizedProjection{ * @throws ProjectionException if the coordinates can not be converted. */ @Override - public Matrix transform(double[] srcPts, int srcOff, + public Matrix transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, boolean derivate) throws ProjectionException { - + final double λ = srcPts[srcOff]; final double φ = srcPts[srcOff + 1]; - + /* * According to the Snyder (page 236) in those cases cannot or should not be plotted. */ - if( ((positiveN)&&(φ<=latitudeLimit)) || ((!positiveN)&&(φ>=latitudeLimit)) ){ + if ( ((positiveN) && (φ<=latitudeLimit)) || ((!positiveN) && (φ>=latitudeLimit)) ){ throw new ProjectionException(Resources.format(Resources.Keys.CanNotTransformCoordinates_2)); } - + final double sin_φ = sin(φ); final double dλ = -asin(sin_φ / sin_i); final double λt = atan(tan(dλ) * cos_i); final double L = λt - p2_on_p1 * dλ; - + /* * As {@code latitudeLimit} is an approximation we repeat the test here. */ - if( ((positiveN)&&(L<=-s0/n)) || ((!positiveN)&&(L>=-s0/n)) ){ + if ( ((positiveN) && (L<=-s0/n)) || ((!positiveN) && (L>=-s0/n)) ){ //TODO if usefull, could we add : // latitudeLimit = φ; throw new ProjectionException(Resources.format(Resources.Keys.CanNotTransformCoordinates_2)); } - - final double ρ = cos_φ1xsin_F1/(n*sin(n*L+s0)); + + final double ρ = cos_φ1xsin_F1/(n*sin(n*L+s0)); final double θ = λ; // extracted n - + final double sinθ = sin(θ); final double cosθ = cos(θ); if (dstPts != null) { dstPts[dstOff ] = ρ * sinθ; // x - dstPts[dstOff + 1] = ρ0 - ρ*cosθ; // y //TODO : extract ρ0 when ensuring : λ = λ - λ0; +// dstPts[dstOff + 1] = ρ0 - ρ*cosθ; // y //TODO : extract ρ0 when ensuring : λ = λ - λ0; + dstPts[dstOff + 1] = - ρ*cosθ; } - + if (!derivate) { return null; } //=========================TO Resolve ================================= -// final double dx_dλ = ρ*n*cosθ; +// final double dx_dλ = ρ*n*cosθ; // final double dx_dφ =?; // // final double dy_dλ = ρ*n*sinθ; // final double dy_dφ = ?; //====================================================================== - + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - + //Additionally we can compute the scale factors : // k = ρ*n/cos(φ); // /R // h = k*tan(F)/tan(n*L+s0); @@ -330,41 +336,42 @@ public class ConicSatelliteTracking extends NormalizedProjection{ protected void inverseTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff) throws ProjectionException { - + final double x = srcPts[srcOff]; - final double y = srcPts[srcOff + 1] - ρ0; - +// final double y = srcPts[srcOff + 1] - ρ0; + final double y = srcPts[srcOff + 1]; + //TODO : extract - ρ0 : MatrixSIS convertBefore and convertAfter?? - - if((x== 0) && (y == 0)) { + + if ((x== 0) && (y == 0)) { //TODO : which values does it imply? throw new UnsupportedOperationException("Not supported yet for those coordinates."); //To change body of generated methods, choose Tools | Templates. } - - final double ρ = positiveN? hypot(x,y) : -hypot(x,y); + + final double ρ = positiveN ? hypot(x,y) : -hypot(x,y); final double θ = atan(x/(-y) ); //undefined if x=y=0 final double L = (asin(cos_φ1xsin_F1/(ρ*n)) -s0)/n; //undefined if x=y=0 //eq.28-26 in Snyder with R=1 - + //TODO ensure that λ0 will be added. ; In eq. Snyder 28-23 : λ0 + θ/n - dstPts[dstOff ] = θ ;//λ + dstPts[dstOff ] = θ ;//λ dstPts[dstOff+1] = latitudeFromNewtonMethod(L); //φ } - + protected final double latitudeFromNewtonMethod(final double l){ double dλ = -PI/2; double dλn = Double.MIN_VALUE; double A, A2, Δdλ; - + int count=0; int maxIteration = 100; //TODO : check the value. - - while((count==0) || dλ-dλn >= (0.1*PI/180)){ //TODO : check the condition. It is considered here that convergence is reached when improvement is lower than 0.1°. - if(count >= maxIteration){ + + while ((count==0) || abs(dλ-dλn) >= (0.01*PI/180)){ //TODO : check the condition. It is considered here that convergence is reached when improvement is lower than 0.01°. + if (count >= maxIteration){ throw new RuntimeException(Resources.format(Resources.Keys.NoConvergence)); } dλn = dλ; -// λt = l + p2_on_p1 * dλ_n; +// λt = l + p2_on_p1 * dλ_n; // dλ = atan(tan(λt) / cos_i); A = tan(l + p2_on_p1*dλn) / cos_i; @@ -376,48 +383,48 @@ public class ConicSatelliteTracking extends NormalizedProjection{ } // λt = L + p2_on_p1 * dλ; final double sin_dλ = sin(dλ); - return -asin(sin_dλ * sin_i); + return -asin(sin_dλ * sin_i); } - - + + 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 + 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 + 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 + 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. -// * +// * // * @return radius ρs. // */ // public double getRadiusOfTangencyCircle(){ 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 1284583..13f8521 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 @@ -29,15 +29,15 @@ import org.apache.sis.referencing.operation.matrix.MatrixSIS; import org.apache.sis.referencing.operation.transform.ContextualParameters; /** - * <cite>Cylindrical Satellite-Tracking projections</cite>. - * + * <cite>Cylindrical Satellite-Tracking projections</cite>. + * * <cite> * - All groundtracks * for satellites orbiting the Earth with the same orbital parameters are shown * as straight lines on the map. * * - Cylindrical {@link CylindricalSatelliteTracking} - * or conical {@link ConicSatelliteTracking} form available. + * or conical {@link ConicSatelliteTracking} form available. * * - Neither conformal nor equal-area. * @@ -76,13 +76,13 @@ import org.apache.sis.referencing.operation.transform.ContextualParameters; */ public class CylindricalSatelliteTracking extends ConicSatelliteTracking { - + /** - * F1' in Snyder : tangente of the angle on both the globe and on the map between - * the groundtrack and the meridian at latitude φ1. + * F1' in Snyder : tangente of the angle on both the globe and on the map between + * the groundtrack and the meridian at latitude φ1. */ final double dF1; - + /** * Create a Cylindrical Satellite Tracking Projection from the given * parameters. @@ -99,15 +99,15 @@ public class CylindricalSatelliteTracking extends ConicSatelliteTracking { private CylindricalSatelliteTracking(final Initializer initializer) { super(initializer); - + final double cos2_φ1 = cos_φ1 * cos_φ1; dF1 = (p2_on_p1 * cos2_φ1 - cos_i) / sqrt(cos2_φ1 - cos2_i); - + final MatrixSIS normalize = context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION); // final MatrixSIS denormalize = context.getMatrix(ContextualParameters.MatrixRole.DENORMALIZATION); normalize .convertAfter (0, cos_φ1, null); //For conic tracking - + // denormalize.convertBefore(0, 1/PI, null); // denormalize.convertBefore(1, , null); @@ -117,10 +117,10 @@ public class CylindricalSatelliteTracking extends ConicSatelliteTracking { * Converts the specified (λ,φ) coordinate (units in radians) and stores the result in {@code dstPts} * (linear distance on a unit sphere). In addition, opportunistically computes the projection derivative * if {@code derivate} is {@code true}. - * + * * <cite> The Yaxis lies along the central meridian λ0, y increasing northerly, * and X axis intersects perpendicularly at O_PARALLEL φ0, x increasing easterly. - * </cite> + * </cite> * * @return the matrix of the projection derivative at the given source position, * or {@code null} if the {@code derivate} argument is {@code false}. @@ -130,12 +130,12 @@ public class CylindricalSatelliteTracking extends ConicSatelliteTracking { public Matrix transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, boolean derivate) throws ProjectionException { - + final double λ = srcPts[srcOff]; final double φ = srcPts[srcOff + 1]; // TODO : check the condition and the thrown exception. - if (abs(φ) > PI / 2 - abs(PI / 2 - i)) { // Exceed tracking limit + if (abs(φ) > PI / 2 - abs(PI / 2 - i)) { // Exceed tracking limit throw new ProjectionException(Resources.format(Resources.Keys.CanNotTransformCoordinates_2)); } @@ -155,8 +155,8 @@ public class CylindricalSatelliteTracking extends ConicSatelliteTracking { /* ===================================================================== * Uncomputed scale factors : *=========================== - * F' : tangente of the angle on the globe between the groundtrack and - * the meridian at latitude φ + * F' : tangente of the angle on the globe between the groundtrack and + * the meridian at latitude φ * final double dF = (p2_on_p1 * cos2_φ - cos_i) / sqrt(cos2_φ - cos2_i); * k = cos_φ1/cos_φ; // Parallel eq. Snyder 28-7 * h = k* dF / dF1; // Meridian eq. Snyder 28-8 @@ -170,7 +170,7 @@ public class CylindricalSatelliteTracking extends ConicSatelliteTracking { // // final double dy_dλ = 0; // final double dy_dφ = - + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @@ -181,15 +181,15 @@ public class CylindricalSatelliteTracking extends ConicSatelliteTracking { * @throws ProjectionException if the coordinates can not be converted. */ @Override - protected void inverseTransform(double[] srcPts, int srcOff, - double[] dstPts, int dstOff) + protected void inverseTransform(double[] srcPts, int srcOff, + double[] dstPts, int dstOff) throws ProjectionException { - + final double x = srcPts[srcOff]; final double y = srcPts[srcOff + 1]; - + final double L = y * dF1 / cos_φ1; // In eq. Snyder 28-19 : L = y * dF1 / R . cos_φ1 - + dstPts[dstOff ] = x; 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 0b20c88..7152538 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,6 +18,7 @@ */ package org.apache.sis.referencing.operation.projection; +import static java.lang.Math.sin; import java.util.Collections; import org.apache.sis.internal.referencing.Formulas; import org.apache.sis.internal.referencing.NilReferencingObject; @@ -26,12 +27,14 @@ import org.apache.sis.measure.Units; import org.apache.sis.referencing.datum.DefaultEllipsoid; import org.apache.sis.referencing.operation.transform.MathTransformFactoryMock; import org.apache.sis.test.DependsOn; -import static org.junit.Assert.assertTrue; import org.junit.Test; import org.opengis.parameter.ParameterValueGroup; import org.opengis.referencing.operation.TransformException; import org.opengis.util.FactoryException; +import static java.lang.StrictMath.toRadians; +import static org.junit.Assert.assertTrue; + /** * Tests coordiantes computed by applying a conic satellite-tracking projection * with {@link ConicSatelliteTracking}. @@ -41,7 +44,6 @@ import org.opengis.util.FactoryException; * @since 1.0 * @module */ -@DependsOn(ConformalProjectionTest.class) public class ConicSatelliteTrackingTest extends MapProjectionTestCase { /** @@ -64,8 +66,8 @@ public class ConicSatelliteTrackingTest extends MapProjectionTestCase { */ void createProjection(final double i, final double orbitalT, final double ascendingNodeT, - final double λ0, final double φ1, - final double φ2, final double φ0) + final double λ0, final double φ1, + final double φ2, final double φ0) throws FactoryException { final SatelliteTracking provider = new SatelliteTracking(); @@ -73,7 +75,7 @@ public class ConicSatelliteTrackingTest extends MapProjectionTestCase { final DefaultEllipsoid sphere = DefaultEllipsoid.createEllipsoid( Collections.singletonMap(DefaultEllipsoid.NAME_KEY, NilReferencingObject.UNNAMED), 1, 1, Units.METRE); - + values.parameter("semi_major").setValue(sphere.getSemiMajorAxis()); values.parameter("semi_minor").setValue(sphere.getSemiMinorAxis()); values.parameter("satellite_orbit_inclination").setValue(i); @@ -81,16 +83,16 @@ public class ConicSatelliteTrackingTest extends MapProjectionTestCase { values.parameter("ascending_node_period").setValue(ascendingNodeT); values.parameter("central_meridian").setValue(λ0); values.parameter("standard_parallel_1").setValue(φ1); - + if (!Double.isNaN(φ2)) { values.parameter("standard_parallel_2").setValue(φ2); - }else{ + } else { values.parameter("standard_parallel_2").setValue(-φ1); //Cylindrical case } if (!Double.isNaN(φ0)) { values.parameter("latitude_of_origin").setValue(φ0); } - + transform = new MathTransformFactoryMock(provider).createParameterizedTransform(values); validate(); } @@ -98,7 +100,7 @@ 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 + * 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 @@ -109,13 +111,13 @@ public class ConicSatelliteTrackingTest extends MapProjectionTestCase { public void testTransform() throws FactoryException, TransformException { tolerance = 1E-5; createProjection( - 99.092, //satellite_orbit_inclination + 99.092, //satellite_orbit_inclination 103.267, //satellite_orbital_period - 1440.0, //ascending_node_period - -90, //central_meridian - 45, //standard_parallel_1 - 70, //standard_parallel_2 - 30 //latitude_of_origin + 1440.0, //ascending_node_period + -90, //central_meridian + 45, //standard_parallel_1 + 70, //standard_parallel_2 + 30 //latitude_of_origin ); assertTrue(isInverseTransformSupported); verifyTransform( @@ -126,7 +128,7 @@ public class ConicSatelliteTrackingTest extends MapProjectionTestCase { 0.2001910, 0.2121685 }); } - + /** * Tests the projection of a few points on a sphere. * @@ -134,47 +136,111 @@ public class ConicSatelliteTrackingTest extends MapProjectionTestCase { * Satellite-Tracking Projections shown in table 39 from * <cite> Map Projections - A working Manual</cite> * + * As this table only introduce the values for n, F1 and ρ coefficients, the + * test was realized by checking these coefficients in debugger mode and by + * extracting the computed results of the projection. Thus this method + * should be used as a non-regression test. + * * @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; - + tolerance = Formulas.LINEAR_TOLERANCE; + //---------------------------------------------------------------------- // φ1 = 30° ; φ2 = 60° //--------------------- createProjection( - 99.092, //satellite_orbit_inclination + 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 + 1440.0, //ascending_node_period + -90, //central_meridian + 30, //standard_parallel_1 + 60, //standard_parallel_2 + 0 //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 -// }); - - } + double n = 0.49073; + + verifyTransform( + new double[]{ // (λ,φ) coordinates in degrees to project. + 0, -10, + 0, 0, + 0, 10, + 0, 70, + -120, 80.908 //Tracking limit + }, + new double[]{ // Expected (x,y) results in metres. + 2.67991 * sin(n * (toRadians( 0 - -90))), 0.46093, + 2.38332 * sin(n * (toRadians( 0 - -90))), 0.67369, + 2.14662 * sin(n * (toRadians( 0 - -90))), 0.84348, + 0.98470 * sin(n * (toRadians( 0 - -90))), 1.67697, + 0.50439 * sin(n * (toRadians(-120 - -90))), 1.89549 //Tracking limit + }); + + //---------------------------------------------------------------------- + // φ1 = 45° ; φ2 = 70° + //--------------------- + createProjection( + 99.092, //satellite_orbit_inclination + 103.267, //satellite_orbital_period + 1440.0, //ascending_node_period + -90, //central_meridian + 45, //standard_parallel_1 + 70, //standard_parallel_2 + 0 //latitude_of_origin + ); + + n = 0.69478; + + verifyTransform( + new double[]{ // (λ,φ) coordinates in degrees to project. + 0, -10, + 0, 0, + 0, 10, + 0, 70, + -120, 80.908 //Tracking limit + }, + new double[]{ // Expected (x,y) results in metres. + 2.92503 * sin(n * (toRadians( 0 - -90))), 0.90110, + 2.25035 * sin(n * (toRadians( 0 - -90))), 1.21232, + 1.82978 * sin(n * (toRadians( 0 - -90))), 1.40632, + 0.57297 * sin(n * (toRadians( 0 - -90))), 1.98605, + 0.28663 * sin(n * (toRadians(-120 - -90))), 1.982485 //Tracking limit + }); + //---------------------------------------------------------------------- + // φ1 = 45° ; φ2 = 70° + //--------------------- + createProjection( + 99.092, //satellite_orbit_inclination + 103.267, //satellite_orbital_period + 1440.0, //ascending_node_period + -90, //central_meridian + 45, //standard_parallel_1 + 80.908, //standard_parallel_2 + 0 //latitude_of_origin + ); + + n = 0.88475; + + verifyTransform( + new double[]{ // (λ,φ) coordinates in degrees to project. + 0, -10, + 0, 0, + 0, 10, + 0, 70, + -120, 80.908 //Tracking limit + }, + new double[]{ // Expected (x,y) results in metres. + 4.79153 * sin(n * (toRadians( 0 - -90))), 1.80001, + 2.66270 * sin(n * (toRadians( 0 - -90))), 2.18329, + 1.84527 * sin(n * (toRadians( 0 - -90))), 2.33046, + 0.40484 * sin(n * (toRadians( 0 - -90))), 2.58980, + 0.21642 * sin(n * (toRadians(-120 - -90))), 2.46908 //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 c207af3..02c1b09 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 @@ -35,9 +35,9 @@ import org.opengis.util.FactoryException; * @module */ public class CylindricalSatelliteTrackingTest extends ConicSatelliteTrackingTest { - - - + + + /** * Creates a new instance of {@link ConicSatelliteTracking} concatenated * with the (de)normalization matrices. The new instance is stored in the @@ -58,17 +58,17 @@ public class CylindricalSatelliteTrackingTest extends ConicSatelliteTrackingTest */ private void createProjection(final double i, final double orbitalT, final double ascendingNodeT, - final double λ0, final double φ1) + final double λ0, final double φ1) throws FactoryException { super.createProjection(i, orbitalT, ascendingNodeT, λ0, φ1, NaN, NaN); } - + /** * Tests the projection of a few points on a sphere. * - * Test based on the numerical example given by Snyder p. 360 to 363 of + * 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. @@ -93,7 +93,7 @@ public class CylindricalSatelliteTrackingTest extends ConicSatelliteTrackingTest 0.2267249, 0.6459071 }); } - + /** * Tests the projection of a few points on a sphere. * @@ -106,11 +106,12 @@ public class CylindricalSatelliteTrackingTest extends ConicSatelliteTrackingTest * @throws TransformException if an error occurred while projecting a point. */ @Test - public void testSampleCoordinates() throws FactoryException, TransformException { - + public void testSampleCoordinatesCylindricalProjection() + throws FactoryException, TransformException { + //Following tests don't pass with the former tolerance. - tolerance = Formulas.LINEAR_TOLERANCE; - + tolerance = Formulas.LINEAR_TOLERANCE; + //---------------------------------------------------------------------- // φ1 = 0° //--------- @@ -121,12 +122,12 @@ 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, 0, -10, 10, 60, 40, 80, 70, @@ -140,8 +141,8 @@ public class CylindricalSatelliteTrackingTest extends ConicSatelliteTrackingTest xConverterFactor * 80, 2.34465, xConverterFactor * -120, 7.23571 //Tracking limit }); - - + + //---------------------------------------------------------------------- // φ1 = +- 30° //------------ @@ -152,12 +153,12 @@ public class CylindricalSatelliteTrackingTest extends ConicSatelliteTrackingTest 0, //central_meridian -30 //standard_parallel_1 ); - + xConverterFactor=0.015115; verifyTransform( new double[]{ // (λ,φ) coordinates in degrees to project. 0, 0, - 10, 0, + 10, 0, -10, 10, 60, 40, 80, 70, @@ -171,7 +172,7 @@ public class CylindricalSatelliteTrackingTest extends ConicSatelliteTrackingTest xConverterFactor * 80, 1.89918, xConverterFactor * -120, 5.86095 //Tracking limit }); - + //---------------------------------------------------------------------- // φ1 = +- 45° //------------ @@ -182,12 +183,12 @@ public class CylindricalSatelliteTrackingTest extends ConicSatelliteTrackingTest 0, //central_meridian 45 //standard_parallel_1 ); - + xConverterFactor=0.012341; verifyTransform( new double[]{ // (λ,φ) coordinates in degrees to project. 0, 0, - 10, 0, + 10, 0, -10, 10, 60, 40, 80, 70, @@ -201,8 +202,8 @@ public class CylindricalSatelliteTrackingTest extends ConicSatelliteTrackingTest xConverterFactor * 80, 1.37124, xConverterFactor * -120, 4.23171 //Tracking limit }); - - + + } - + } diff --git a/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java b/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java index dec780f..aa68d1f 100644 --- a/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java +++ b/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java @@ -180,6 +180,8 @@ import org.junit.BeforeClass; org.apache.sis.referencing.operation.projection.SinusoidalTest.class, org.apache.sis.referencing.operation.projection.PolyconicTest.class, org.apache.sis.referencing.operation.projection.MollweideTest.class, + org.apache.sis.referencing.operation.projection.ConicSatelliteTrackingTest.class, + org.apache.sis.referencing.operation.projection.CylindricalSatelliteTrackingTest.class, // Coordinate operation and derived Coordinate Reference Systems (cyclic dependency). org.apache.sis.referencing.operation.DefaultTransformationTest.class,