Search in sources :

Example 6 with MathTransform2D

use of org.opengis.referencing.operation.MathTransform2D in project sis by apache.

the class TransformTestCase method testTransformOverPole.

/**
 * Tests conversions of an envelope or rectangle over a pole using a coordinate operation.
 *
 * @throws FactoryException if an error occurred while creating the operation.
 * @throws TransformException if an error occurred while transforming the envelope.
 */
@Test
@DependsOnMethod("testTransform")
public final void testTransformOverPole() throws FactoryException, TransformException {
    final ProjectedCRS sourceCRS = (ProjectedCRS) CRS.fromWKT("PROJCS[“WGS 84 / Antarctic Polar Stereographic”,\n" + "  GEOGCS[“WGS 84”,\n" + "    DATUM[“World Geodetic System 1984”,\n" + "      SPHEROID[“WGS 84”, 6378137.0, 298.257223563]],\n" + "    PRIMEM[“Greenwich”, 0.0],\n" + "    UNIT[“degree”, 0.017453292519943295]],\n" + "  PROJECTION[“Polar Stereographic (variant B)”],\n" + "  PARAMETER[“standard_parallel_1”, -71.0],\n" + "  UNIT[“m”, 1.0]]");
    final GeographicCRS targetCRS = sourceCRS.getBaseCRS();
    final Conversion conversion = inverse(sourceCRS.getConversionFromBase());
    final MathTransform2D transform = (MathTransform2D) conversion.getMathTransform();
    /*
         * The rectangle to test, which contains the South pole.
         */
    G rectangle = createFromExtremums(sourceCRS, -3943612.4042124213, -4078471.954436003, 3729092.5890516187, 4033483.085688618);
    /*
         * This is what we get without special handling of singularity point.
         * Note that is does not include the South pole as we would expect.
         * The commented out values are what we get by projecting an arbitrary
         * larger amount of points.
         */
    G expected = createFromExtremums(targetCRS, // anti-regression values
    -179.8650137390031, // anti-regression values
    -88.99136583196396, // 178.8122742080059  -40.90577500420587]         // empirical values
    137.9769431693009, // anti-regression values
    -40.90577500420587);
    /*
         * Tests what we actually get. First, test using the method working on MathTransform.
         * Next, test again the same transform, but using the API on Envelope objects.
         */
    G actual = transform(targetCRS, transform, rectangle);
    assertGeometryEquals(expected, actual, ANGULAR_TOLERANCE, ANGULAR_TOLERANCE);
    /*
         * Using the transform(CoordinateOperation, …) method,
         * the singularity at South pole is taken in account.
         */
    expected = createFromExtremums(targetCRS, -180, -90, 180, -40.905775004205864);
    actual = transform(conversion, rectangle);
    assertGeometryEquals(expected, actual, ANGULAR_TOLERANCE, ANGULAR_TOLERANCE);
    /*
         * Another rectangle containing the South pole, but this time the south
         * pole is almost in a corner of the rectangle
         */
    rectangle = createFromExtremums(sourceCRS, -4000000, -4000000, 300000, 30000);
    expected = createFromExtremums(targetCRS, -180, -90, 180, -41.03163170198091);
    actual = transform(conversion, rectangle);
    assertGeometryEquals(expected, actual, ANGULAR_TOLERANCE, ANGULAR_TOLERANCE);
    /*
         * Another rectangle with the South pole close to the border.
         * This test should execute the step #3 in the transform method code.
         */
    rectangle = createFromExtremums(sourceCRS, -2000000, -1000000, 200000, 2000000);
    expected = createFromExtremums(targetCRS, -180, -90, 180, -64.3861643256928);
    actual = transform(conversion, rectangle);
    assertGeometryEquals(expected, actual, ANGULAR_TOLERANCE, ANGULAR_TOLERANCE);
}
Also used : ProjectedCRS(org.opengis.referencing.crs.ProjectedCRS) GeographicCRS(org.opengis.referencing.crs.GeographicCRS) MathTransform2D(org.opengis.referencing.operation.MathTransform2D) DefaultConversion(org.apache.sis.referencing.operation.DefaultConversion) Conversion(org.opengis.referencing.operation.Conversion) Test(org.junit.Test) DependsOnMethod(org.apache.sis.test.DependsOnMethod)

Example 7 with MathTransform2D

use of org.opengis.referencing.operation.MathTransform2D in project sis by apache.

the class TransformTestCase method testTransform.

/**
 * Tests the transformation of an envelope or rectangle. This is a relatively simple test case
 * working in the two-dimensional space only, with a coordinate operation of type "conversion"
 * (not a "transformation") and with no need to adjust for poles.
 *
 * @throws FactoryException if an error occurred while creating the operation.
 * @throws TransformException if an error occurred while transforming the envelope.
 */
@Test
public final void testTransform() throws FactoryException, TransformException {
    final ProjectedCRS targetCRS = CommonCRS.WGS84.universal(10, -123.5);
    final GeographicCRS sourceCRS = targetCRS.getBaseCRS();
    final Conversion conversion = targetCRS.getConversionFromBase();
    final MathTransform2D transform = (MathTransform2D) conversion.getMathTransform();
    /*
         * Transforms envelopes using MathTransform. Geographic coordinates are in (latitude, longitude) order.
         * Opportunistically check that the transform using a CoordinateOperation object produces the same result.
         */
    final G rectλφ = createFromExtremums(sourceCRS, -20, -126, 40, -120);
    final G rectXY = transform(targetCRS, transform, rectλφ);
    assertEquals("Conversion should produce the same result.", rectXY, transform(conversion, rectλφ));
    /*
         * Expected values are determined empirically by projecting many points.
         * Those values are the same than in EnvelopesTest.testTransform().
         */
    final G expected = createFromExtremums(targetCRS, 166021.56, -2214294.03, 833978.44, 4432069.06);
    assertGeometryEquals(expected, rectXY, LINEAR_TOLERANCE, LINEAR_TOLERANCE);
    /*
         * Test the inverse conversion.
         * Final envelope should be slightly bigger than the original.
         */
    final G rectBack = transform(sourceCRS, transform.inverse(), rectXY);
    assertTrue("Transformed envelope should not be smaller than the original one.", contains(rectBack, rectλφ));
    assertGeometryEquals(rectλφ, rectBack, 0.05, 1.0);
}
Also used : ProjectedCRS(org.opengis.referencing.crs.ProjectedCRS) GeographicCRS(org.opengis.referencing.crs.GeographicCRS) MathTransform2D(org.opengis.referencing.operation.MathTransform2D) DefaultConversion(org.apache.sis.referencing.operation.DefaultConversion) Conversion(org.opengis.referencing.operation.Conversion) Test(org.junit.Test)

Example 8 with MathTransform2D

use of org.opengis.referencing.operation.MathTransform2D in project sis by apache.

the class ConcatenatedTransform method create.

/**
 * Concatenates the two given transforms.
 * If the concatenation result works with two-dimensional input and output points,
 * then the returned transform will implement {@link MathTransform2D}.
 * Likewise if the concatenation result works with one-dimensional input and output points,
 * then the returned transform will implement {@link MathTransform1D}.
 *
 * <div class="note"><b>Implementation note:</b>
 * {@code ConcatenatedTransform} implementations are available in two versions: direct and non-direct.
 * The "non-direct" versions use an intermediate buffer when performing transformations; they are slower
 * and consume more memory. They are used only as a fallback when a "direct" version can not be created.</div>
 *
 * @param  tr1      the first math transform.
 * @param  tr2      the second math transform.
 * @param  factory  the factory which is (indirectly) invoking this method, or {@code null} if none.
 * @return the concatenated transform.
 *
 * @see MathTransforms#concatenate(MathTransform, MathTransform)
 */
public static MathTransform create(MathTransform tr1, MathTransform tr2, final MathTransformFactory factory) throws FactoryException, MismatchedDimensionException {
    final int dim1 = tr1.getTargetDimensions();
    final int dim2 = tr2.getSourceDimensions();
    if (dim1 != dim2) {
        throw new MismatchedDimensionException(Resources.format(Resources.Keys.CanNotConcatenateTransforms_2, getName(tr1), getName(tr2)) + ' ' + Errors.format(Errors.Keys.MismatchedDimension_2, dim1, dim2));
    }
    MathTransform mt = createOptimized(tr1, tr2, factory);
    if (mt != null) {
        return mt;
    }
    /*
         * If at least one math transform is an instance of ConcatenatedTransform and assuming
         * that MathTransforms are associatives, tries the following arrangements and select
         * the one with the fewest amount of steps:
         *
         *   Assuming :  tr1 = (A * B)
         *               tr2 = (C * D)
         *
         *   Current  :  (A * B) * (C * D)     Will be the selected one if nothing better.
         *   Try k=0  :  A * (B * (C * D))     Implies A * ((B * C) * D) through recursivity.
         *   Try k=1  :  ((A * B) * C) * D     Implies (A * (B * C)) * D through recursivity.
         *   Try k=2  :                        Tried only if try k=1 changed something.
         *
         * TODO: The same combination may be computed more than once (e.g. (B * C) above).
         *       Should not be a big deal if there is not two many steps. In the even where
         *       it would appears a performance issue, we could maintain a Map of combinations
         *       already computed. The map would be local to a "create" method execution.
         */
    int stepCount = getStepCount(tr1) + getStepCount(tr2);
    // Really 'true' because we want at least 2 iterations.
    boolean tryAgain = true;
    for (int k = 0; ; k++) {
        MathTransform c1 = tr1;
        MathTransform c2 = tr2;
        final boolean first = (k & 1) == 0;
        MathTransform candidate = first ? c1 : c2;
        while (candidate instanceof ConcatenatedTransform) {
            final ConcatenatedTransform ctr = (ConcatenatedTransform) candidate;
            if (first) {
                c1 = candidate = ctr.transform1;
                c2 = create(ctr.transform2, c2, factory);
            } else {
                c1 = create(c1, ctr.transform1, factory);
                c2 = candidate = ctr.transform2;
            }
            final int c = getStepCount(c1) + getStepCount(c2);
            if (c < stepCount) {
                tr1 = c1;
                tr2 = c2;
                stepCount = c;
                tryAgain = true;
            }
        }
        if (!tryAgain)
            break;
        tryAgain = false;
    }
    /*
         * Tries again the check for optimized cases (identity, etc.), because a
         * transform may have been simplified to identity as a result of the above.
         */
    mt = createOptimized(tr1, tr2, factory);
    if (mt != null) {
        return mt;
    }
    /*
         * Can not avoid the creation of a ConcatenatedTransform object.
         * Check for the type to create (1D, 2D, general case...)
         */
    final int dimSource = tr1.getSourceDimensions();
    final int dimTarget = tr2.getTargetDimensions();
    if (dimSource == 1 && dimTarget == 1) {
        /*
             * Result needs to be a MathTransform1D.
             */
        if (tr1 instanceof MathTransform1D && tr2 instanceof MathTransform1D) {
            return new ConcatenatedTransformDirect1D((MathTransform1D) tr1, (MathTransform1D) tr2);
        } else {
            return new ConcatenatedTransform1D(tr1, tr2);
        }
    } else if (dimSource == 2 && dimTarget == 2) {
        /*
             * Result needs to be a MathTransform2D.
             */
        if (tr1 instanceof MathTransform2D && tr2 instanceof MathTransform2D) {
            return new ConcatenatedTransformDirect2D((MathTransform2D) tr1, (MathTransform2D) tr2);
        } else {
            return new ConcatenatedTransform2D(tr1, tr2);
        }
    } else if (// dim1 = tr1.getTargetDimensions() and
    dimSource == tr1.getTargetDimensions() && // dim2 = tr2.getSourceDimensions() may not be true anymore.
    dimTarget == tr2.getSourceDimensions()) {
        return new ConcatenatedTransformDirect(tr1, tr2);
    } else {
        return new ConcatenatedTransform(tr1, tr2);
    }
}
Also used : MathTransform(org.opengis.referencing.operation.MathTransform) MathTransform1D(org.opengis.referencing.operation.MathTransform1D) MathTransform2D(org.opengis.referencing.operation.MathTransform2D) MismatchedDimensionException(org.opengis.geometry.MismatchedDimensionException)

Aggregations

MathTransform2D (org.opengis.referencing.operation.MathTransform2D)8 DefaultConversion (org.apache.sis.referencing.operation.DefaultConversion)2 Test (org.junit.Test)2 MismatchedDimensionException (org.opengis.geometry.MismatchedDimensionException)2 GeographicCRS (org.opengis.referencing.crs.GeographicCRS)2 ProjectedCRS (org.opengis.referencing.crs.ProjectedCRS)2 Conversion (org.opengis.referencing.operation.Conversion)2 MathTransform (org.opengis.referencing.operation.MathTransform)2 MathTransform1D (org.opengis.referencing.operation.MathTransform1D)2 Matrix (org.opengis.referencing.operation.Matrix)2 Shape (java.awt.Shape)1 Point2D (java.awt.geom.Point2D)1 Rectangle2D (java.awt.geom.Rectangle2D)1 GeneralEnvelope (org.apache.sis.geometry.GeneralEnvelope)1 IntervalRectangle (org.apache.sis.internal.referencing.j2d.IntervalRectangle)1 AbstractCoordinateOperation (org.apache.sis.referencing.operation.AbstractCoordinateOperation)1 DependsOnMethod (org.apache.sis.test.DependsOnMethod)1 After (org.junit.After)1 Envelope (org.opengis.geometry.Envelope)1 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)1