/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2008-2012, Open Source Geospatial Foundation (OSGeo) * (C) 2009-2012, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.referencing.operation.projection; import org.opengis.referencing.datum.Ellipsoid; import org.opengis.parameter.ParameterValueGroup; import org.opengis.parameter.ParameterDescriptorGroup; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.OperationMethod; import org.geotoolkit.factory.Hints; import org.geotoolkit.referencing.operation.transform.TransformTestBase; import org.apache.sis.parameter.Parameters; import org.apache.sis.referencing.CommonCRS; import org.apache.sis.referencing.operation.DefaultOperationMethod; import org.apache.sis.referencing.operation.projection.ProjectionException; import org.apache.sis.referencing.operation.transform.MathTransforms; import static java.lang.StrictMath.*; import static java.util.Collections.singletonMap; import static org.opengis.test.Assert.*; /** * Base class for tests of {@link UnitaryProjection} implementations. * * @author Martin Desruisseaux (Geomatys) * * @since 3.00 */ //@DependsOn({ProjectiveTransformTest.class, ConcatenatedTransformTest.class}) public abstract strictfp class ProjectionTestBase extends TransformTestBase { /** * The radius of the sphere used in sphere test cases. */ static final double SPHERE_RADIUS = CommonCRS.SPHERE.ellipsoid().getSemiMajorAxis(); /** * Creates a new test case using the given hints for fetching the factories. * * @param type The base class of the projection being tested. * @param hints The hints to use for fetching factories, or {@code null} for the default ones. */ protected ProjectionTestBase(final Class<? extends MathTransform> type, final Hints hints) { super(type, hints); } static OperationMethod wrap(final ParameterDescriptorGroup descriptor) { return new DefaultOperationMethod(singletonMap(DefaultOperationMethod.NAME_KEY, "Test"), 2, 2, descriptor); } /** * Returns default projection parameter for the given descriptor. * * @param descriptor The descriptor for which to create projection parameters. * @param ellipse {@code false} for a sphere, or {@code true} for WGS84 ellipsoid. * @param numStandardParallels Number of standard parallels (0, 1 or 2). * @return Newly created projection parameters. */ @SuppressWarnings("fallthrough") static Parameters parameters(final OperationMethod descriptor, final boolean ellipse, final int numStandardParallels) { final ParameterValueGroup values = descriptor.getParameters().createValue(); final Ellipsoid ellipsoid = (ellipse ? CommonCRS.WGS84 : CommonCRS.SPHERE).ellipsoid(); values.parameter("semi_major").setValue(ellipsoid.getSemiMajorAxis()); values.parameter("semi_minor").setValue(ellipsoid.getSemiMinorAxis()); switch (numStandardParallels) { default: fail("Unexpected number of standard parallels."); case 2: values.parameter("standard_parallel_2").setValue(0); case 1: values.parameter("standard_parallel_1").setValue(0); case 0: break; } return Parameters.castOrWrap(values); } /** * Returns the full projection from the given unitary projection. * * @param projection The unitary projection (or the "kernel"). * @return The complete projection, from degrees to linear units. */ static MathTransform concatenated(final UnitaryProjection projection) { try { return projection.createMapProjection( org.apache.sis.internal.system.DefaultFactories.forBuildin( org.opengis.referencing.operation.MathTransformFactory.class)); } catch (org.opengis.util.FactoryException e) { throw new AssertionError(e); // TODO } } /** * Projects the given latitude value. The longitude is fixed to zero. * This method is useful for testing the behavior close to poles in a * simple case. * * @param phi The latitude. * @return The northing. * @throws ProjectionException if the projection failed. */ final double transform(final double phi) throws ProjectionException { final double[] coordinate = new double[2]; coordinate[1] = phi; ((UnitaryProjection) transform).transform(coordinate, 0, coordinate, 0, false); final double y = coordinate[1]; if (!Double.isNaN(y) && !Double.isInfinite(y)) { assertEquals(0, coordinate[0], tolerance); } return y; } /** * Inverse projects the given northing value. The longitude is fixed to zero. * This method is useful for testing the behavior close to poles in a simple case. * * @param y The northing. * @return The latitude. * @throws ProjectionException if the projection failed. */ final double inverseTransform(final double y) throws ProjectionException { return inverseTransform(y, false); } /** * Same than {@link #inverseTransform(double)}, but said if the resulting longitude * is expected to be the anti-meridian. */ final double inverseTransform(final double y, final boolean antimeridian) throws ProjectionException { final double[] coordinate = new double[2]; coordinate[1] = y; ((UnitaryProjection) transform).inverseTransform(coordinate, 0, coordinate, 0); final double phi = coordinate[1]; if (!Double.isNaN(phi)) { final double lambda = coordinate[0]; assertEquals(antimeridian ? copySign(PI, lambda) : 0, lambda, tolerance); } return phi; } /** * Returns the unitary projection. */ private static UnitaryProjection unitary(final MathTransform transform) { for (final MathTransform step : MathTransforms.getSteps(transform)) { if (step instanceof UnitaryProjection) { return (UnitaryProjection) step; } } return null; } /** * Returns {@code true} if the given transform is one of the {@code Spherical} * inner classes. * * @param transform The transform to test. * @return {@code true} if the transform is spherical. */ static boolean isSpherical(final MathTransform transform) { return unitary(transform).getClass().getSimpleName().equals("Spherical"); } /** * Returns {@code true} if the current transform is one of the {@code Spherical} * inner classes. */ final boolean isSpherical() { return isSpherical(transform); } }