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 b718383130431e75d10490d604a1a3c612566321 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Mon Feb 21 12:44:29 2022 +0100 Fix wrong coordinates in inverse Oblique Stereographic projection. https://issues.apache.org/jira/browse/SIS-537 (contribution by Emmanuel Giasson). --- .../operation/projection/ObliqueStereographic.java | 9 ++--- .../projection/ObliqueStereographicTest.java | 38 +++++++++++++++++++--- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueStereographic.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueStereographic.java index 8a96322..b926b91 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueStereographic.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ObliqueStereographic.java @@ -62,7 +62,8 @@ import static org.apache.sis.internal.referencing.provider.ObliqueStereographic. * * @author Rémi Maréchal (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 1.1 + * @author Emmanuel Giasson (Thales) + * @version 1.2 * @since 0.7 * @module */ @@ -355,8 +356,8 @@ public class ObliqueStereographic extends NormalizedProjection { { final double x = srcPts[srcOff ]; final double y = srcPts[srcOff+1]; - final double i = atan(x / (h + y)); - final double j = atan(x / (g - y)) - i; + final double i = atan2(x, h + y); + final double j = atan2(x, g - y) - i; /* * The conformal longitude is Λ = j + 2i + Λ₀. In the particular case of stereographic projection, * the geodetic longitude λ is equals to Λ. Furthermore in Apache SIS implementation, Λ₀ is added by @@ -377,7 +378,7 @@ public class ObliqueStereographic extends NormalizedProjection { final double ψi = log(tan(φ/2 + PI/4) * pow((1 - ℯsinφ) / (1 + ℯsinφ), he)); final double Δφ = (ψ - ψi) * cos(φ) * (1 - ℯsinφ*ℯsinφ) / ome; φ += Δφ; - if (!(abs(Δφ) > ITERATION_TOLERANCE)) { // Use '!' for accepting NaN. + if (!(abs(Δφ) > ITERATION_TOLERANCE)) { // Use `!` for accepting NaN. dstPts[dstOff ] = λ; dstPts[dstOff+1] = φ; return; diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ObliqueStereographicTest.java b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ObliqueStereographicTest.java index 0e178f5..f705115 100644 --- a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ObliqueStereographicTest.java +++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ObliqueStereographicTest.java @@ -41,7 +41,8 @@ import static org.junit.Assert.*; * * @author Rémi Maréchal (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 1.1 + * @author Emmanuel Giasson (Thales) + * @version 1.2 * @since 0.7 * @module */ @@ -142,6 +143,16 @@ public final strictfp class ObliqueStereographicTest extends MapProjectionTestCa } /** + * Creates the complete transform from the given parameter values. + * Input and output coordinates will be in degrees, contrarily to the transform + * created by above {@link #createNormalizedProjection(boolean)} method. + */ + private void createCompleteTransform(final OperationMethod op, final ParameterValueGroup p) throws FactoryException { + transform = new ObliqueStereographic(op, (Parameters) p).createMapProjection( + DefaultFactories.forBuildin(MathTransformFactory.class)); + } + + /** * The point given in the EPSG guide for testing the map projection. * (φ<sub>t</sub>, λ<sub>t</sub>) is the source geographic coordinate in degrees and * (x<sub>t</sub>, y<sub>t</sub>) is the target projected coordinate in metres. @@ -227,6 +238,27 @@ public final strictfp class ObliqueStereographicTest extends MapProjectionTestCa } /** + * Tests consistency between forward and inverse projection using a point that was known to fail. + * + * @throws FactoryException if an error occurred while creating the map projection. + * @throws TransformException if an error occurred while projecting a coordinate. + * + * @see <a href="https://issues.apache.org/jira/browse/SIS-537">SIS-537</a> + */ + @Test + public void testObliqueStereographicConsistency() throws FactoryException, TransformException { + final OperationMethod op = new org.apache.sis.internal.referencing.provider.ObliqueStereographic(); + final ParameterValueGroup p = op.getParameters().createValue(); + p.parameter("semi_major").setValue(WGS84_A); + p.parameter("semi_minor").setValue(WGS84_B); + p.parameter("Latitude of natural origin") .setValue( 45, Units.DEGREE); + p.parameter("Longitude of natural origin").setValue(-70, Units.DEGREE); + createCompleteTransform(op, p); + tolerance = Formulas.ANGULAR_TOLERANCE; + verifyInverse(30, 45); + } + + /** * Verifies the consistency of spherical formulas with the elliptical formulas. * This test transforms the point given in the EPSG guide and takes the result * of the elliptical implementation as a reference. @@ -376,9 +408,7 @@ public final strictfp class ObliqueStereographicTest extends MapProjectionTestCa p.parameter("Scale factor at natural origin").setValue(0.994); p.parameter("False easting") .setValue(2000000); p.parameter("False northing") .setValue(2000000); - - transform = new ObliqueStereographic(op, (Parameters) p).createMapProjection( - DefaultFactories.forBuildin(MathTransformFactory.class)); + createCompleteTransform(op, p); tolerance = 0.01; verifyTransform(new double[] {44, 73}, new double[] {3320416.75, 632668.43}); }