/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sis.referencing.operation.projection;

import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.operation.OperationMethod;
import org.opengis.referencing.operation.TransformException;
import org.opengis.referencing.operation.MathTransformFactory;
import org.opengis.util.FactoryException;
import org.apache.sis.parameter.Parameters;
import org.apache.sis.referencing.operation.transform.ContextualParameters;
import org.apache.sis.referencing.operation.matrix.Matrix2;
import org.apache.sis.internal.referencing.Formulas;
import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.measure.Units;
import org.apache.sis.test.DependsOnMethod;
import org.apache.sis.test.DependsOn;
import org.junit.Test;

import static java.lang.StrictMath.*;
import static org.junit.Assert.*;


/**
 * Tests the {@link ObliqueStereographic} class.
 *
 * @author  Rémi Maréchal (Geomatys)
 * @author  Martin Desruisseaux (Geomatys)
 * @version 0.8
 * @since   0.7
 * @module
 */
@DependsOn({
    InitializerTest.class,
    NormalizedProjectionTest.class
})
public final strictfp class ObliqueStereographicTest extends MapProjectionTestCase {
    /**
     * Parameter values provided by the <a href="http://www.iogp.org/pubs/373-07-2.pdf">EPSG guide</a>
     * for testing {@link ObliqueStereographic} transform conformity. The test uses the parameters for
     * the <cite>Amersfoort / RD New</cite> projection:
     *
     * <ul>
     *   <li>Semi-major axis length:            <var>a</var>  = 6377397.155 metres</li>
     *   <li>Inverse flattening:              1/<var>f</var>  = 299.15281</li>
     *   <li>Latitude of natural origin:        <var>φ₀</var> = 52°09'22.178"N</li>
     *   <li>Longitude of natural origin:       <var>λ₀</var> =  5°23'15.500"E</li>
     *   <li>Scale factor at natural origin:    <var>k₀</var> = 0.9999079</li>
     *   <li>False easting:                     <var>FE</var> = 155000.00 metres</li>
     *   <li>False northing:                    <var>FN</var> = 463000.00 metres</li>
     * </ul>
     *
     * Other parameters (<var>n</var>, <var>R</var>, <var>g</var>, <var>h</var>) are computed from the above.
     * Those parameters fall in three groups:
     *
     * <ul>
     *   <li>Parameters used in linear operations (additions or multiplications) performed <strong>before</strong> the
     *       non-linear part (the "kernel") of the map projection. Those parameters are <var>λ₀</var> and <var>n</var>
     *       and their values are stored in the normalization matrix given by
     *       <code>{@linkplain ContextualParameters#getMatrix ContextualParameters.getMatrix}(NORMALIZATION)</code>.</li>
     *
     *   <li>Parameters used in linear operations (additions or multiplications) performed <strong>after</strong> the
     *       non-linear part (the "kernel") of the map projection. Those parameters are <var>k₀</var>, <var>R</var>,
     *       <var>FE</var> and <var>FN</var> and their values are stored in the denormalization matrix given by
     *       <code>{@linkplain ContextualParameters#getMatrix ContextualParameters.getMatrix}(DENORMALIZATION)</code>.</li>
     *
     *   <li>Other parameters are either used in the non-linear "kernel" of the map projection or used for computing the
     *       above-cited parameters.</li>
     * </ul>
     *
     * <p><b>Note 1:</b> value of <var>R</var> is computed by {@link Initializer#radiusOfConformalSphere(double)}.</p>
     *
     * <p><b>Note 2:</b> we do not follow the Java naming convention here (constants in upper cases) in order to use
     * as much as possible the exact same symbols as in the EPSG guide.</p>
     */
    private static final double φ0  = 0.910296727,      // Latitude of natural origin (rad)
        /* Before kernel */     λ0  = 0.094032038,      // Longitude of natural origin (rad)
        /*  After kernel */     R   = 6382644.571,      // Radius of conformal sphere (m)
                                a   = 6377397.155,      // Semi-major axis length (m)
                                ivf = 299.15281,        // Inverse flattening factor
                                e   = 0.08169683,       // Eccentricity
        /* Before kernel */     n   = 1.000475857,      // Coefficient computed from eccentricity and φ₀.
        /*  After kernel */     k0  = 0.9999079,        // Scale factor
        /*  After kernel */     FE  = 155000.00,        // False Easting (m)
        /*  After kernel */     FN  = 463000.00;        // False Northing (m)

    /**
     * Compares the <var>n</var> value given in the EPSG guide with the value computed from the formula.
     */
    @Test
    public void testN() {
        assertEquals(n, sqrt(1 + (e*e * pow(cos(φ0), 4)) / (1 - e*e)), 0.5E-9);
    }

    /**
     * Creates a new instance of {@link ObliqueStereographic} for a sphere or an ellipsoid.
     * The new instance is stored in the inherited {@link #transform} field.
     *
     * @param  ellipse  {@code false} for the spherical case, or {@code true} for the ellipsoidal case.
     */
    private void createNormalizedProjection(final boolean ellipse) {
        final OperationMethod op = new org.apache.sis.internal.referencing.provider.ObliqueStereographic();
        final ParameterValueGroup p = op.getParameters().createValue();
        /*
         * Following parameters are not given explicitly by EPSG definitions since they are
         * usually inferred from the datum.  However in the particular case of this test, we
         * need to provide them. The names used below are either OGC names or SIS extensions.
         */
        if (!ellipse) {
            p.parameter("semi_major").setValue(R);
            p.parameter("semi_minor").setValue(R);
        } else {
            p.parameter("semi_major").setValue(a);
            p.parameter("inverse_flattening").setValue(ivf);
        }
        /*
         * Following parameters are reproduced verbatim from EPSG registry and EPSG guide.
         */
        p.parameter("Latitude of natural origin")    .setValue(φ0, Units.RADIAN);
        p.parameter("Longitude of natural origin")   .setValue(λ0, Units.RADIAN);
        p.parameter("Scale factor at natural origin").setValue(k0);
        p.parameter("False easting")                 .setValue(FE, Units.METRE);
        p.parameter("False northing")                .setValue(FN, Units.METRE);

        transform = new ObliqueStereographic(op, (Parameters) p);
    }

    /**
     * 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.
     */
    private static final double φt = 53,                // Latitude in degrees
                                λt = 6,                 // Longitude in degrees
                                Et = 196105.283,        // Easting in metres
                                Nt = 557057.739;        // Northing in metres

    /**
     * Tests {@link ObliqueStereographic#transform(double[], int, double[], int, boolean)}
     * with the values given by the EPSG guide.
     *
     * @throws TransformException if an error occurred while projecting the coordinate.
     */
    @Test
    public void testTransform() throws TransformException {
        final double[] srcPts = new double[] {λt, φt};   // in degrees
        final double[] dstPts = new double[2];

        // Linear operations (normalization) applied before NormalizedTransform.
        srcPts[0] = toRadians(srcPts[0]) - λ0;
        srcPts[1] = toRadians(srcPts[1]);
        srcPts[0] *= n;

        // The non-linear part of map projection (the "kernel").
        createNormalizedProjection(true);
        transform.transform(srcPts, 0, dstPts, 0, 1);

        // Linear operations (denormalization) applied after NormalizedTransform.
        dstPts[0] *= (k0 * 2*R);
        dstPts[1] *= (k0 * 2*R);
        dstPts[0] += FE;
        dstPts[1] += FN;

        assertEquals("Easting",  Et, dstPts[0], Formulas.LINEAR_TOLERANCE);
        assertEquals("Northing", Nt, dstPts[1], Formulas.LINEAR_TOLERANCE);
    }

    /**
     * Tests {@link ObliqueStereographic#inverseTransform(double[], int, double[], int)}
     * with the values given by the EPSG guide.
     *
     * @throws TransformException if an error occurred while projecting the coordinate.
     */
    @Test
    public void testInverseTransform() throws TransformException {
        final double[] srcPts = new double[] {Et, Nt};  // in metres
        final double[] dstPts = new double[2];

        // Linear operations (normalization) applied before NormalizedTransform.
        srcPts[0] -= FE;
        srcPts[1] -= FN;
        srcPts[0] /= (k0 * 2*R);
        srcPts[1] /= (k0 * 2*R);

        // The non-linear part of map projection (the "kernel").
        createNormalizedProjection(true);
        ((NormalizedProjection) transform).inverseTransform(srcPts, 0, dstPts, 0);

        // Linear operations (denormalization) applied after NormalizedTransform.
        dstPts[0] /= n;
        dstPts[0] = toDegrees(dstPts[0] + λ0);
        dstPts[1] = toDegrees(dstPts[1]);

        assertEquals("Longitude", λt, dstPts[0], Formulas.ANGULAR_TOLERANCE);
        assertEquals("Latitude",  φt, dstPts[1], Formulas.ANGULAR_TOLERANCE);
    }

    /**
     * Tests the <cite>Oblique Stereographic</cite> case (EPSG:9809).
     * This test is defined in GeoAPI conformance test suite.
     *
     * @throws FactoryException if an error occurred while creating the map projection.
     * @throws TransformException if an error occurred while projecting a coordinate.
     *
     * @see org.opengis.test.referencing.ParameterizedTransformTest#testObliqueStereographic()
     */
    @Test
    @DependsOnMethod({"testTransform", "testInverseTransform"})
    public void testObliqueStereographic() throws FactoryException, TransformException {
        createGeoApiTest(new org.apache.sis.internal.referencing.provider.ObliqueStereographic()).testObliqueStereographic();
    }

    /**
     * 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.
     *
     * @throws TransformException if an error occurred while projecting the coordinate.
     */
    @Test
    @DependsOnMethod("testTransform")
    public void testSphericalTransform() throws TransformException {
        final double[] srcPts = new double[] {λt, φt};  // in degrees
        final double[] dstPts = new double[2];
        final double[] refPts = new double[2];

        // Linear operations (normalization) applied before NormalizedTransform.
        srcPts[0] = toRadians(srcPts[0]) - λ0;
        srcPts[1] = toRadians(srcPts[1]);
        srcPts[0] *= n;

        // The non-linear part of map projection (the "kernel").
        createNormalizedProjection(false);
        transform.transform(srcPts, 0, refPts, 0, 1);

        // Linear operations (denormalization) applied after NormalizedTransform.
        refPts[0] *= (k0 * 2*R);
        refPts[1] *= (k0 * 2*R);
        refPts[0] += FE;
        refPts[1] += FN;

        // Transform the same point, now using the spherical implementation.
        ObliqueStereographic spherical = (ObliqueStereographic) transform;
        spherical = new ObliqueStereographic.Spherical(spherical);
        spherical.transform(srcPts, 0, dstPts, 0, 1);

        // Linear operations (denormalization) applied after NormalizedTransform.
        dstPts[0] *= (k0 * 2*R);
        dstPts[1] *= (k0 * 2*R);
        dstPts[0] += FE;
        dstPts[1] += FN;

        // Use a smaller tolerance because spherical and elliptical formulas should be equivalent in this case.
        assertArrayEquals("Spherical projection", refPts, dstPts, Formulas.LINEAR_TOLERANCE / 1E4);
    }

    /**
     * Verifies the consistency of spherical formulas with the elliptical formulas.
     * This test computes the inverse transform of the point given in the EPSG guide
     * and takes the result of the elliptical implementation as a reference.
     *
     * @throws TransformException if an error occurred while projecting the coordinate.
     */
    @Test
    @DependsOnMethod("testInverseTransform")
    public void testSphericalInverseTransform() throws TransformException {
        final double[] srcPts = new double[] {Et, Nt};  // in metres
        final double[] dstPts = new double[2];
        final double[] refPts = new double[2];

        // Linear operations (normalization) applied before NormalizedTransform.
        srcPts[0] -= FE;
        srcPts[1] -= FN;
        srcPts[0] /= (k0 * 2*R);
        srcPts[1] /= (k0 * 2*R);

        // The non-linear part of map projection (the "kernel").
        createNormalizedProjection(false);
        ((NormalizedProjection) transform).inverseTransform(srcPts, 0, refPts, 0);

        // Linear operations (denormalization) applied after NormalizedTransform.
        refPts[0] /= n;
        refPts[0] = toDegrees(refPts[0] + λ0);
        refPts[1] = toDegrees(refPts[1]);

        // Transform the same point, now using the spherical implementation.
        ObliqueStereographic spherical = (ObliqueStereographic) transform;
        spherical = new ObliqueStereographic.Spherical(spherical);
        spherical.inverseTransform(srcPts, 0, dstPts, 0);

        // Linear operations (denormalization) applied after NormalizedTransform.
        dstPts[0] /= n;
        dstPts[0] = toDegrees(dstPts[0] + λ0);
        dstPts[1] = toDegrees(dstPts[1]);

        // Use a smaller tolerance because spherical and elliptical formulas should be equivalent in this case.
        assertArrayEquals("Spherical inverse projection", refPts, dstPts, Formulas.ANGULAR_TOLERANCE / 1E6);
    }

    /**
     * Verifies the consistency of spherical formulas with the elliptical formulas.
     * This test computes the derivative at a point and takes the result of the elliptical
     * implementation as a reference.
     *
     * @throws TransformException if an error occurred while computing the derivative.
     */
    @Test
    @DependsOnMethod("testDerivative")
    public void testSphericalDerivative() throws TransformException {
        final double[] srcPts = new double[] {λt, φt};  // in degrees
        srcPts[0] = toRadians(srcPts[0]) - λ0;
        srcPts[1] = toRadians(srcPts[1]);
        srcPts[0] *= n;

        // Using elliptical implementation.
        createNormalizedProjection(false);
        final Matrix reference = ((NormalizedProjection) transform).transform(srcPts, 0, null, 0, true);

        // Using spherical implementation.
        ObliqueStereographic spherical = (ObliqueStereographic) transform;
        spherical = new ObliqueStereographic.Spherical(spherical);
        final Matrix derivative = spherical.transform(srcPts, 0, null, 0, true);

        tolerance = 1E-12;
        assertMatrixEquals("Spherical derivative", reference, derivative,
                new Matrix2(tolerance, tolerance,
                            tolerance, tolerance));
    }

    /**
     * Creates a projection and derivates a few points.
     *
     * @throws TransformException if an error occurred while computing the derivative.
     */
    @Test
    public void testDerivative() throws TransformException {
        createNormalizedProjection(true);
        tolerance = 1E-9;

        final double delta = toRadians(100.0 / 60) / 1852;      // Approximately 100 metres.
        derivativeDeltas = new double[] {delta, delta};
        verifyDerivative(toRadians( 0), toRadians( 0));
        verifyDerivative(toRadians(-3), toRadians(30));
        verifyDerivative(toRadians(+6), toRadians(60));
    }

    /**
     * Tests the delegation to {@link PolarStereographic} implementation when the latitude of origin is ±90°.
     *
     * @throws FactoryException if an error occurred while creating the map projection.
     * @throws TransformException if an error occurred while projecting a coordinate.
     */
    @Test
    public void testPolarStereographic() 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("inverse_flattening")            .setValue(298.2572236);
        p.parameter("Latitude of natural origin")    .setValue(90);
        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));
        tolerance = 0.01;
        verifyTransform(new double[] {44, 73}, new double[] {3320416.75, 632668.43});
    }
}
