Search in sources :

Example 1 with Ellipsoid

use of org.opengis.referencing.datum.Ellipsoid in project sis by apache.

the class MapProjectionTestCase method parameters.

/**
 * Returns the parameters to use for instantiating the projection to test.
 * The parameters are initialized with the ellipse semi-axis lengths.
 *
 * @param  provider  the provider of the projection to test.
 * @param  ellipse   {@code false} for a sphere, or {@code true} for WGS84 ellipsoid.
 * @return the parameters to use for instantiating the projection.
 */
static Parameters parameters(final DefaultOperationMethod provider, final boolean ellipse) {
    final Parameters parameters = Parameters.castOrWrap(provider.getParameters().createValue());
    final Ellipsoid ellipsoid = (ellipse ? GeodeticDatumMock.WGS84 : GeodeticDatumMock.SPHERE).getEllipsoid();
    parameters.parameter(Constants.SEMI_MAJOR).setValue(ellipsoid.getSemiMajorAxis());
    parameters.parameter(Constants.SEMI_MINOR).setValue(ellipsoid.getSemiMinorAxis());
    if (ellipse) {
        parameters.parameter(Constants.INVERSE_FLATTENING).setValue(ellipsoid.getInverseFlattening());
    }
    return parameters;
}
Also used : Parameters(org.apache.sis.parameter.Parameters) Ellipsoid(org.opengis.referencing.datum.Ellipsoid)

Example 2 with Ellipsoid

use of org.opengis.referencing.datum.Ellipsoid in project sis by apache.

the class CoordinateOperationTest method testGeocentricTransform.

/**
 * Tests a "geographic to geocentric" conversion.
 *
 * @throws FactoryException if an error occurred while creating a test CRS.
 * @throws TransformException if an error occurred while testing a coordinate conversion.
 */
@Test
public void testGeocentricTransform() throws FactoryException, TransformException {
    final Random random = new Random(661597560);
    /*
         * Gets the math transform from WGS84 to a geocentric transform.
         */
    final Ellipsoid ellipsoid = CommonCRS.WGS84.ellipsoid();
    final CoordinateReferenceSystem sourceCRS = AbstractCRS.castOrCopy(CommonCRS.WGS84.geographic3D()).forConvention(AxesConvention.RIGHT_HANDED);
    final CoordinateReferenceSystem targetCRS = CommonCRS.WGS84.geocentric();
    final CoordinateOperation operation = opFactory.createOperation(sourceCRS, targetCRS);
    transform = operation.getMathTransform();
    final int dimension = transform.getSourceDimensions();
    assertEquals("Source dimension", 3, dimension);
    assertEquals("Target dimension", 3, transform.getTargetDimensions());
    assertSame("Inverse transform", transform, transform.inverse().inverse());
    validate();
    /*
         * Constructs an array of random points. The first 8 points
         * are initialized to know values. Other points are left random.
         */
    final double[] cartesianDistance = new double[4];
    final double[] orthodromicDistance = new double[4];
    // Must be divisible by 3.
    final double[] array0 = new double[900];
    for (int i = 0; i < array0.length; i++) {
        final int range;
        switch(i % 3) {
            // Longitude
            case 0:
                range = 360;
                break;
            // Latitidue
            case 1:
                range = 180;
                break;
            // Altitude
            case 2:
                range = 10000;
                break;
            // Should not happen
            default:
                range = 0;
                break;
        }
        array0[i] = random.nextDouble() * range - (range / 2);
    }
    // 24°N 35°E 8km
    array0[0] = 35.0;
    // 24°N 35°E 8km
    array0[1] = 24.0;
    // 24°N 35°E 8km
    array0[2] = 8000;
    // … about 80 km away
    array0[3] = 34.8;
    // … about 80 km away
    array0[4] = 24.7;
    // … about 80 km away
    array0[5] = 5000;
    cartesianDistance[0] = 80284.00;
    // Not really exact.
    orthodromicDistance[0] = 80302.99;
    array0[6] = 0;
    array0[7] = 0.0;
    array0[8] = 0;
    // Antipodes; distance should be 2*6378.137 km
    array0[9] = 180;
    // Antipodes; distance should be 2*6378.137 km
    array0[10] = 0.0;
    // Antipodes; distance should be 2*6378.137 km
    array0[11] = 0;
    cartesianDistance[1] = ellipsoid.getSemiMajorAxis() * 2;
    orthodromicDistance[1] = ellipsoid.getSemiMajorAxis() * PI;
    array0[12] = 0;
    array0[13] = -90;
    array0[14] = 0;
    // Antipodes; distance should be 2*6356.752 km
    array0[15] = 180;
    // Antipodes; distance should be 2*6356.752 km
    array0[16] = +90;
    // Antipodes; distance should be 2*6356.752 km
    array0[17] = 0;
    cartesianDistance[2] = ellipsoid.getSemiMinorAxis() * 2;
    orthodromicDistance[2] = 20003931.46;
    array0[18] = 95;
    array0[19] = -38;
    array0[20] = 0;
    // Antipodes
    array0[21] = -85;
    // Antipodes
    array0[22] = +38;
    // Antipodes
    array0[23] = 0;
    cartesianDistance[3] = 12740147.19;
    orthodromicDistance[3] = 20003867.86;
    /*
         * Transforms all points, and then inverse transform them. The resulting
         * array2 should be equal to array0 except for rounding errors. We tolerate
         * maximal error of 0.1 second in longitude or latitude and 1 cm in height.
         */
    final double[] array1 = new double[array0.length];
    final double[] array2 = new double[array0.length];
    transform.transform(array0, 0, array1, 0, array0.length / dimension);
    transform.inverse().transform(array1, 0, array2, 0, array1.length / dimension);
    for (int i = 0; i < array0.length; ) {
        assertEquals("Longitude", array2[i], array0[i], 0.1 / 3600);
        i++;
        assertEquals("Latitude", array2[i], array0[i], 0.1 / 3600);
        i++;
        assertEquals("Height", array2[i], array0[i], 0.01);
        i++;
    }
    /*
         * Compares the distances between "special" points with expected distances.
         * This tests the ellipsoid orthodromic distance computation as well.
         * We require a precision of 10 centimetres.
         */
    for (int i = 0; i < array0.length / 6; i++) {
        final int base = i * 6;
        final double cartesian = MathFunctions.magnitude(array1[base + 0] - array1[base + 3], array1[base + 1] - array1[base + 4], array1[base + 2] - array1[base + 5]);
        if (i < cartesianDistance.length) {
            assertEquals("Cartesian distance", cartesianDistance[i], cartesian, 0.1);
        }
        /*
             * Compares with orthodromic distance. Distance is computed using an ellipsoid
             * at the maximal altitude (i.e. the length of semi-major axis is increased to
             * fit the maximal altitude).
             */
        try {
            final double altitude = max(array0[base + 2], array0[base + 5]);
            final DefaultEllipsoid ellip = DefaultEllipsoid.createFlattenedSphere(Collections.singletonMap(Ellipsoid.NAME_KEY, "Temporary"), ellipsoid.getSemiMajorAxis() + altitude, ellipsoid.getInverseFlattening(), ellipsoid.getAxisUnit());
            double orthodromic = ellip.orthodromicDistance(array0[base + 0], array0[base + 1], array0[base + 3], array0[base + 4]);
            orthodromic = hypot(orthodromic, array0[base + 2] - array0[base + 5]);
            if (i < orthodromicDistance.length) {
                assertEquals("Orthodromic distance", orthodromicDistance[i], orthodromic, 0.1);
            }
            assertTrue("Distance consistency", cartesian <= orthodromic);
        } catch (ArithmeticException exception) {
        // Orthodromic distance computation didn't converge. Ignore...
        }
    }
}
Also used : Random(java.util.Random) DefaultEllipsoid(org.apache.sis.referencing.datum.DefaultEllipsoid) CoordinateOperation(org.opengis.referencing.operation.CoordinateOperation) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) DefaultEllipsoid(org.apache.sis.referencing.datum.DefaultEllipsoid) Ellipsoid(org.opengis.referencing.datum.Ellipsoid) Test(org.junit.Test)

Example 3 with Ellipsoid

use of org.opengis.referencing.datum.Ellipsoid in project sis by apache.

the class MolodenskyTransformTest method testIdentity.

/**
 * Verifies that creating a Molodensky operation with same source and target ellipsoid and zero translation
 * results in an identity affine transform.
 *
 * @throws FactoryException if an error occurred while creating a transform step.
 */
@Test
public void testIdentity() throws FactoryException {
    final Ellipsoid source = CommonCRS.WGS84.ellipsoid();
    transform = MolodenskyTransform.createGeodeticTransformation(DefaultFactories.forBuildin(MathTransformFactory.class), source, false, source, false, 0, 0, 0, false);
    assertInstanceOf("Expected optimized type.", LinearTransform.class, transform);
    assertTrue(transform.isIdentity());
    validate();
}
Also used : Ellipsoid(org.opengis.referencing.datum.Ellipsoid) GeocentricTranslationTest(org.apache.sis.internal.referencing.provider.GeocentricTranslationTest) Test(org.junit.Test)

Example 4 with Ellipsoid

use of org.opengis.referencing.datum.Ellipsoid in project sis by apache.

the class MolodenskyTransformTest method create.

/**
 * Creates a Molodensky transform for a datum shift from WGS84 to ED50.
 * Tolerance thresholds are also initialized.
 *
 * @throws FactoryException if an error occurred while creating a transform step.
 */
private void create(final boolean abridged) throws FactoryException {
    final Ellipsoid source = CommonCRS.WGS84.ellipsoid();
    final Ellipsoid target = CommonCRS.ED50.ellipsoid();
    transform = MolodenskyTransform.createGeodeticTransformation(DefaultFactories.forBuildin(MathTransformFactory.class), source, true, target, true, GeocentricTranslationTest.TX, GeocentricTranslationTest.TY, GeocentricTranslationTest.TZ, abridged);
    // Half the precision of target sample point
    tolerance = GeocentricTranslationTest.precision(1);
    // Required precision for h
    zTolerance = GeocentricTranslationTest.precision(3);
    assertFalse(transform.isIdentity());
    validate();
}
Also used : Ellipsoid(org.opengis.referencing.datum.Ellipsoid)

Example 5 with Ellipsoid

use of org.opengis.referencing.datum.Ellipsoid in project sis by apache.

the class WKTUtilities method suggestFractionDigits.

/**
 * Suggests an amount of fraction digits to use for formatting numbers in each column of the given sequence
 * of points. The number of fraction digits may be negative if we could round the numbers to 10, <i>etc</i>.
 *
 * @param  crs     the coordinate reference system for each points, or {@code null} if unknown.
 * @param  points  the sequence of points. It is not required that each point has the same dimension.
 * @return suggested amount of fraction digits as an array as long as the longest row.
 */
public static int[] suggestFractionDigits(final CoordinateReferenceSystem crs, final double[]... points) {
    final int[] fractionDigits = Numerics.suggestFractionDigits(points);
    final Ellipsoid ellipsoid = ReferencingUtilities.getEllipsoid(crs);
    if (ellipsoid != null) {
        /*
             * Use heuristic precisions for geodetic or projected CRS. We do not apply those heuristics
             * for other kind of CRS (e.g. engineering) because we do not know what could be the size
             * of the object attached to the CRS.
             */
        final CoordinateSystem cs = crs.getCoordinateSystem();
        final int dimension = Math.min(cs.getDimension(), fractionDigits.length);
        final double scale = Formulas.scaleComparedToEarth(ellipsoid);
        for (int i = 0; i < dimension; i++) {
            final Unit<?> unit = cs.getAxis(i).getUnit();
            double precision;
            if (Units.isLinear(unit)) {
                // In metres
                precision = Formulas.LINEAR_TOLERANCE * scale;
            } else if (Units.isAngular(unit)) {
                // In radians
                precision = Formulas.ANGULAR_TOLERANCE * (Math.PI / 180) * scale;
            } else if (Units.isTemporal(unit)) {
                // In seconds
                precision = Formulas.TEMPORAL_TOLERANCE;
            } else {
                continue;
            }
            // In units used by the coordinates.
            precision /= Units.toStandardUnit(unit);
            final int f = DecimalFunctions.fractionDigitsForDelta(precision, false);
            if (f > fractionDigits[i]) {
                // Use at least the heuristic precision.
                fractionDigits[i] = f;
            }
        }
    }
    return fractionDigits;
}
Also used : CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) DefaultEllipsoid(org.apache.sis.referencing.datum.DefaultEllipsoid) Ellipsoid(org.opengis.referencing.datum.Ellipsoid)

Aggregations

Ellipsoid (org.opengis.referencing.datum.Ellipsoid)9 Test (org.junit.Test)3 PrimeMeridian (org.opengis.referencing.datum.PrimeMeridian)3 DefaultEllipsoid (org.apache.sis.referencing.datum.DefaultEllipsoid)2 ParameterValueGroup (org.opengis.parameter.ParameterValueGroup)2 CoordinateSystem (org.opengis.referencing.cs.CoordinateSystem)2 EllipsoidalCS (org.opengis.referencing.cs.EllipsoidalCS)2 GeodeticDatum (org.opengis.referencing.datum.GeodeticDatum)2 URL (java.net.URL)1 Random (java.util.Random)1 Unit (javax.measure.Unit)1 Angle (javax.measure.quantity.Angle)1 GeocentricTranslationTest (org.apache.sis.internal.referencing.provider.GeocentricTranslationTest)1 Parameters (org.apache.sis.parameter.Parameters)1 BursaWolfParameters (org.apache.sis.referencing.datum.BursaWolfParameters)1 DefaultGeodeticDatum (org.apache.sis.referencing.datum.DefaultGeodeticDatum)1 UnavailableFactoryException (org.apache.sis.referencing.factory.UnavailableFactoryException)1 DependsOnMethod (org.apache.sis.test.DependsOnMethod)1 Identifier (org.opengis.metadata.Identifier)1 GeneralParameterValue (org.opengis.parameter.GeneralParameterValue)1