org.opengis.referencing.operation.NoninvertibleTransformException Java Examples

The following examples show how to use org.opengis.referencing.operation.NoninvertibleTransformException. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: DefaultConcatenatedOperationTest.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Creates a “Tokyo to JGD2000” transformation.
 *
 * @see DefaultTransformationTest#createGeocentricTranslation()
 */
private static DefaultConcatenatedOperation createGeocentricTranslation() throws FactoryException, NoninvertibleTransformException {
    final MathTransformFactory mtFactory = DefaultFactories.forBuildin(MathTransformFactory.class);
    final DefaultTransformation op = DefaultTransformationTest.createGeocentricTranslation();

    final DefaultConversion before = new DefaultConversion(
            Collections.singletonMap(DefaultConversion.NAME_KEY, "Geographic to geocentric"),
            HardCodedCRS.TOKYO,             // SourceCRS
            op.getSourceCRS(),              // TargetCRS
            null,                           // InterpolationCRS
            DefaultOperationMethodTest.create("Geographic/geocentric conversions", "9602", "EPSG guidance note #7-2", 3),
            EllipsoidToCentricTransform.createGeodeticConversion(mtFactory, HardCodedDatum.TOKYO.getEllipsoid(), true));

    final DefaultConversion after = new DefaultConversion(
            Collections.singletonMap(DefaultConversion.NAME_KEY, "Geocentric to geographic"),
            op.getTargetCRS(),              // SourceCRS
            HardCodedCRS.JGD2000,           // TargetCRS
            null,                           // InterpolationCRS
            DefaultOperationMethodTest.create("Geographic/geocentric conversions", "9602", "EPSG guidance note #7-2", 3),
            EllipsoidToCentricTransform.createGeodeticConversion(mtFactory, HardCodedDatum.JGD2000.getEllipsoid(), true).inverse());

    return new DefaultConcatenatedOperation(
            Collections.singletonMap(DefaultConversion.NAME_KEY, "Tokyo to JGD2000"),
            new AbstractSingleOperation[] {before, op, after}, mtFactory);
}
 
Example #2
Source File: DatumShiftGridFile.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Creates a new datum shift grid for the given grid geometry.
 * The actual offset values need to be provided by subclasses.
 *
 * @param coordinateUnit    the unit of measurement of input values, before conversion to grid indices by {@code coordinateToGrid}.
 * @param translationUnit   the unit of measurement of output values.
 * @param isCellValueRatio  {@code true} if results of {@link #interpolateInCell interpolateInCell(…)} are divided by grid cell size.
 * @param x0                longitude in degrees of the center of the cell at grid index (0,0), positive east.
 * @param y0                latitude in degrees of the center of the cell at grid index (0,0), positive north.
 * @param Δx                increment in <var>x</var> value between cells at index <var>gridX</var> and <var>gridX</var> + 1.
 * @param Δy                increment in <var>y</var> value between cells at index <var>gridY</var> and <var>gridY</var> + 1.
 * @param nx                number of cells along the <var>x</var> axis in the grid.
 * @param ny                number of cells along the <var>y</var> axis in the grid.
 * @param descriptor        the parameter descriptor of the provider that created this grid.
 * @param files             the file(s) from which the grid has been loaded. This array is not cloned.
 */
DatumShiftGridFile(final Unit<C> coordinateUnit,
                   final Unit<T> translationUnit,
                   final boolean isCellValueRatio,
                   final double x0, final double y0,
                   final double Δx, final double Δy,
                   final int    nx, final int    ny,
                   final ParameterDescriptorGroup descriptor,
                   final Path... files) throws NoninvertibleTransformException
{
    super(coordinateUnit, new AffineTransform2D(Δx, 0, 0, Δy, x0, y0).inverse(),
          new int[] {nx, ny}, isCellValueRatio, translationUnit);
    this.descriptor     = descriptor;
    this.files          = files;
    this.scanlineStride = nx;
    if (Units.isAngular(coordinateUnit)) {
        periodX = Math.rint((Longitude.MAX_VALUE - Longitude.MIN_VALUE) / Math.abs(Δx));
    } else {
        periodX = 0;
        /*
         * Note: non-angular source coordinates are currently never used in this package.
         * If it continue to be like that in the future, we should remove the check for
         * Units.isAngular(…) and replace the C parameterized type by Angle directly.
         */
    }
}
 
Example #3
Source File: DatumShiftGridGroup.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Creates a new group for the given list of sub-grids. That list shall contain at least 2 elements.
 * The first sub-grid is taken as a template for setting parameter values such as filename (all list
 * elements should declare the same filename parameters, so the selected element should not matter).
 *
 * @param  tiles      the tiles computed by {@link TileOrganizer}.
 * @param  grids      sub-grids associated to tiles computed by {@link TileOrganizer}.
 * @param  gridToCRS  conversion from grid indices to "real world" coordinates.
 * @param  gridSize   number of cells along the <var>x</var> and <var>y</var> axes in the grid.
 * @throws IOException declared because {@link Tile#getRegion()} declares it, but should not happen.
 */
@SuppressWarnings({"rawtypes", "unchecked"})                        // For generic array creation.
private DatumShiftGridGroup(final Tile[] tiles,
                            final Map<Tile,DatumShiftGridFile<C,T>> grids,
                            final AffineTransform2D gridToCRS,
                            final Dimension gridSize)
        throws IOException, NoninvertibleTransformException
{
    super(grids.get(tiles[0]), gridToCRS, gridSize.width, gridSize.height);
    final int n = grids.size();
    regions  = new Region[n];
    subgrids = new DatumShiftGridFile[n];
    for (int i=0; i<n; i++) {
        final Tile tile = tiles[i];
        final DatumShiftGridFile<C,T> grid = grids.get(tile);
        regions [i] = new Region(tile);
        subgrids[i] = grid;
        if (grid.accuracy > accuracy) {
            accuracy = grid.accuracy;           // Conservatively set accuracy to the largest value.
        }
    }
}
 
Example #4
Source File: Projection.java    From gama with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void createTransformation(final MathTransform t) {
	if (t != null) {
		transformer = new GeometryCoordinateSequenceTransformer(new DefaultCoordinateSequenceTransformer(
				GeometryUtils.GEOMETRY_FACTORY.getCoordinateSequenceFactory()));
		// TODO see ConcatenatedTransformDirect2D
		transformer.setMathTransform(t);
		try {
			inverseTransformer = new GeometryCoordinateSequenceTransformer(new DefaultCoordinateSequenceTransformer(
					GeometryUtils.GEOMETRY_FACTORY.getCoordinateSequenceFactory()));
			inverseTransformer.setMathTransform(t.inverse());
		} catch (final NoninvertibleTransformException e) {
			e.printStackTrace();
		}
	}
}
 
Example #5
Source File: AbstractMathTransform.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Returns {@code true} if {@code tr1} is the inverse of {@code tr2}.
 * If this method is unsure, it conservatively returns {@code false}.
 * The transform that may be inverted is {@code tr1}.
 *
 * @param  tr1  the transform to inverse.
 * @param  tr2  the transform that may be the inverse of {@code tr1}.
 * @return whether this transform is the inverse of the given transform. If unsure, {@code false}.
 */
static boolean isInverseEquals(MathTransform tr1, final MathTransform tr2) {
    if (tr1.getSourceDimensions() != tr2.getTargetDimensions() ||
        tr1.getTargetDimensions() != tr2.getSourceDimensions())
    {
        return false;
    }
    try {
        tr1 = tr1.inverse();
    } catch (NoninvertibleTransformException e) {
        return false;
    }
    if (tr1 instanceof LenientComparable) {
        return ((LenientComparable) tr1).equals(tr2, ComparisonMode.APPROXIMATE);
    }
    if (tr2 instanceof LenientComparable) {
        return ((LenientComparable) tr2).equals(tr1, ComparisonMode.APPROXIMATE);
    }
    return tr1.equals(tr2);
}
 
Example #6
Source File: DatumShiftGridFileTest.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Creates a new grid using an affine transform as a reference.
 * An arbitrary non-uniform scale is applied on axes.
 *
 * @param  rotation  rotation angle in degrees to apply on affine transform.
 */
void init(final double rotation) throws NoninvertibleTransformException {
    reference = AffineTransform.getRotateInstance(StrictMath.toRadians(rotation), WIDTH/2, HEIGHT/2);
    reference.scale(2, 5);
    final DatumShiftGridFile.Float<Dimensionless,Dimensionless> grid = new DatumShiftGridFile.Float<>(
            2, Units.UNITY, Units.UNITY, true, 0, 0, 1, 1, WIDTH, HEIGHT, null);
    assertEquals(2, grid.offsets.length);
    final Point2D.Float point = new Point2D.Float();
    int i = 0;
    for (int y=0; y<HEIGHT; y++) {
        for (int x=0; x<WIDTH; x++) {
            point.x = x;
            point.y = y;
            assertSame(point, reference.transform(point, point));
            grid.offsets[0][i] = point.x - x;
            grid.offsets[1][i] = point.y - y;
            i++;
        }
    }
    assertEquals(grid.offsets[0].length, i);
    assertEquals(grid.offsets[1].length, i);
    this.grid = grid;
}
 
Example #7
Source File: Geographic3Dto2DTest.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Tests {@code Geographic3Dto2D.createMathTransform(…)}.
 *
 * @throws FactoryException should never happen.
 * @throws NoninvertibleTransformException should never happen.
 */
@Test
public void testCreateMathTransform() throws FactoryException, NoninvertibleTransformException {
    final Geographic3Dto2D provider = new Geographic3Dto2D();
    final MathTransform mt = provider.createMathTransform(null, null);
    assertSame("Expected cached instance.", mt, provider.createMathTransform(null, null));
    /*
     * Verify the full matrix. Note that the longitude offset is expected to be in degrees.
     * This conversion from grad to degrees is specific to Apache SIS and may be revised in
     * future version. See org.apache.sis.referencing.operation package javadoc.
     */
    assertInstanceOf("Shall be an affine transform.", LinearTransform.class, mt);
    assertMatrixEquals("Expected a Geographic 3D to 2D conversion.", Matrices.create(3, 4, new double[] {
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 0, 1}), ((LinearTransform) mt).getMatrix(), STRICT);
    assertMatrixEquals("Expected a Geographic 2D to 3D conversion.", Matrices.create(4, 3, new double[] {
            1, 0, 0,
            0, 1, 0,
            0, 0, 0,
            0, 0, 1}), ((LinearTransform) mt.inverse()).getMatrix(), STRICT);
}
 
Example #8
Source File: ConvertedGridCoverage.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Creates a new coverage with the same grid geometry than the given coverage and the given converted sample dimensions.
 */
private ConvertedGridCoverage(final GridCoverage packed, final List<SampleDimension> sampleDimensions, final List<SampleDimension> converted) {
    super(packed.getGridGeometry(), converted);
    final int numBands = sampleDimensions.size();
    toConverted = new MathTransform1D[numBands];
    toPacked    = new MathTransform1D[numBands];
    boolean isIdentity = true;
    final MathTransform1D identity = (MathTransform1D) MathTransforms.identity(1);
    for (int i = 0; i < numBands; i++) {
        MathTransform1D tr = sampleDimensions.get(i).getTransferFunction().orElse(identity);
        toConverted[i] = tr;
        isIdentity &= tr.isIdentity();
        try {
            tr = tr.inverse();
        } catch (NoninvertibleTransformException ex) {
            tr = (MathTransform1D) MathTransforms.linear(Double.NaN, 0.0);
        }
        toPacked[i] = tr;
    }
    this.isIdentity = isIdentity;
    this.packed     = packed;
}
 
Example #9
Source File: NormalizedProjection.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * If a sequence of 3 transforms are (inverse projection) → (affine) → (projection) where
 * the (projection) and (inverse projection) steps are the inverse of each other, returns
 * the matrix of the affine transform step. Otherwise returns {@code null}. This method
 * accepts also (projection) → (affine) → (inverse projection) sequence, but such sequences
 * should be much more unusual.
 *
 * @param  projection       either {@link NormalizedProjection} or {@link Inverse}.
 * @param  other            the arbitrary transforms to be concatenated with the given projection.
 * @param  applyOtherFirst  whether {@code other} is concatenated before {@code projection} or the converse.
 * @return the 3×3 matrix of the affine transform step, or {@code null} if none.
 */
private static Matrix getMiddleMatrix(final AbstractMathTransform projection, final MathTransform other,
        final boolean applyOtherFirst)
{
    final List<MathTransform> steps = MathTransforms.getSteps(other);
    if (steps.size() == 2) try {
        final int oi = applyOtherFirst ? 0 : 1;
        if (projection.equals(steps.get(oi).inverse(), ComparisonMode.IGNORE_METADATA)) {
            final Matrix m = MathTransforms.getMatrix(steps.get(oi ^ 1));
            if (Matrices.isAffine(m) && m.getNumRow() == DIMENSION+1 && m.getNumCol() == DIMENSION+1) {
                return m;
            }
        }
    } catch (NoninvertibleTransformException e) {
        Logging.recoverableException(Logging.getLogger(Loggers.COORDINATE_OPERATION),
                (projection instanceof NormalizedProjection) ? NormalizedProjection.class : projection.getClass(),
                "tryConcatenate", e);
    }
    return null;
}
 
Example #10
Source File: SpecializableTransform.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates the inverse of a specialized transform having the given properties.
 */
Inverse(final SpecializableTransform forward) throws NoninvertibleTransformException {
    this.forward = forward;
    this.global = forward.global.inverse();
    for (final SubArea domain : forward.roots()) {
        domain.createInverseTransform();
    }
}
 
Example #11
Source File: LocalizationGridBuilder.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a new builder for a localization grid inferred from the given provider of control points.
 * The {@linkplain LinearTransformBuilder#getSourceDimensions() number of source dimensions} in the
 * given {@code localizations} argument shall be 2. The {@code localization} can be used in two ways:
 *
 * <ul class="verbose">
 *   <li>If the {@code localizations} instance has been
 *     {@linkplain LinearTransformBuilder#LinearTransformBuilder(int...) created with a fixed grid size},
 *     then that instance is used as-is — it is not copied. It is okay to specify an empty instance and
 *     to provide control points later by calls to {@link #setControlPoint(int, int, double...)}.</li>
 *   <li>If the {@code localizations} instance has been
 *     {@linkplain LinearTransformBuilder#LinearTransformBuilder() created for a grid of unknown size},
 *     then this constructor tries to infer a grid size by inspection of the control points present in
 *     {@code localizations} at the time this constructor is invoked. Changes in {@code localizations}
 *     after construction will not be reflected in this new builder.</li>
 * </ul>
 *
 * @param  localizations  the provider of control points for which to create a localization grid.
 * @throws ArithmeticException if this constructor can not infer a reasonable grid size from the given localizations.
 *
 * @since 1.0
 */
public LocalizationGridBuilder(final LinearTransformBuilder localizations) {
    ArgumentChecks.ensureNonNull("localizations", localizations);
    int n = localizations.getGridDimensions();
    if (n == SOURCE_DIMENSION) {
        linear = localizations;
        sourceToGrid = MathTransforms.identity(SOURCE_DIMENSION);
    } else {
        if (n < 0) {
            final Vector[] sources = localizations.sources();
            n = sources.length;
            if (n == SOURCE_DIMENSION) {
                final Matrix fromGrid = new Matrix3();
                final int width  = infer(sources[0], fromGrid, 0);
                final int height = infer(sources[1], fromGrid, 1);
                linear = new LinearTransformBuilder(width, height);
                linear.setControlPoints(localizations.getControlPoints());
                try {
                    sourceToGrid = MathTransforms.linear(fromGrid).inverse();
                } catch (NoninvertibleTransformException e) {
                    throw (ArithmeticException) new ArithmeticException(e.getLocalizedMessage()).initCause(e);
                }
                linear.setLinearizers(localizations);
                return;
            }
        }
        throw new IllegalArgumentException(Resources.format(
                Resources.Keys.MismatchedTransformDimension_3, 0, SOURCE_DIMENSION, n));
    }
}
 
Example #12
Source File: PassThroughTransform.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates the inverse transform of this object.
 *
 * @return {@inheritDoc}
 * @throws NoninvertibleTransformException if the {@linkplain #subTransform sub-transform} is not invertible.
 */
@Override
public synchronized MathTransform inverse() throws NoninvertibleTransformException {
    if (inverse == null) {
        inverse = new PassThroughTransform(firstAffectedCoordinate, subTransform.inverse(), numTrailingCoordinates);
        inverse.inverse = this;
    }
    return inverse;
}
 
Example #13
Source File: PassThroughTransform2D.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates the inverse transform of this object.
 */
@Override
public synchronized MathTransform2D inverse() throws NoninvertibleTransformException {
    if (inverse == null) {
        inverse = new PassThroughTransform2D(firstAffectedCoordinate, subTransform.inverse(), numTrailingCoordinates);
        inverse.inverse = this;
    }
    return (MathTransform2D) inverse;
}
 
Example #14
Source File: AffineTransform2D.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates the inverse transform of this object.
 *
 * @throws NoninvertibleTransformException if this transform can not be inverted.
 */
@Override
public final AffineTransform2D inverse() throws NoninvertibleTransformException {
    if (inverse == null) {
        if (super.isIdentity()) {
            inverse = this;
        } else synchronized (this) {
            /*
             * Double check idiom. Was deprecated before Java 5 (couldn't work reliably).
             * Is okay with the new memory model since Java 5 provided that the field is
             * declared volatile (Joshua Bloch, "Effective Java" second edition).
             */
            if (inverse == null) {
                /*
                 * In a previous version, we were using the Java2D code as below:
                 *
                 *     AffineTransform2D work = new AffineTransform2D(this, true);
                 *     work.invert();
                 *     work.forcePositiveZeros();
                 *     work.freeze();
                 *
                 * Current version now uses the SIS code instead in order to get the double-double precision.
                 * It usually does not make a difference in the result of the matrix inversion, when ignoring
                 * the error terms.  But those error terms appear to be significant later, when the result of
                 * this matrix inversion is multiplied with other matrices: the double-double accuracy allows
                 * us to better detect the terms that are 0 or 1 after matrix concatenation.
                 */
                final AffineTransform2D work = new AffineTransform2D(
                        ((ExtendedPrecisionMatrix) Matrices.inverse(matrix)).getExtendedElements());
                work.inverse = this;
                inverse = work;                 // Set only on success.
            }
        }
    }
    return inverse;
}
 
Example #15
Source File: GeocentricToGeographic.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a transform from the specified group of parameter values.
 *
 * @param  factory  the factory to use for creating the transform.
 * @param  values   the parameter values that define the transform to create.
 * @return the conversion from geocentric to geographic coordinates.
 * @throws FactoryException if an error occurred while creating a transform.
 */
@Override
public MathTransform createMathTransform(final MathTransformFactory factory, final ParameterValueGroup values)
        throws FactoryException
{
    MathTransform tr = GeographicToGeocentric.create(factory, Parameters.castOrWrap(values));
    try {
        tr = tr.inverse();
    } catch (NoninvertibleTransformException e) {
        throw new FactoryException(e);                  // Should never happen with SIS implementation.
    }
    return tr;
}
 
Example #16
Source File: FranceGeocentricInterpolation.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a transform from the specified group of parameter values.
 * This method creates the transform from <em>target</em> to <em>source</em>
 * (which is the direction that use the interpolation grid directly without iteration),
 * then inverts the transform.
 *
 * @param  factory  the factory to use if this constructor needs to create other math transforms.
 * @param  values   the group of parameter values.
 * @return the created math transform.
 * @throws ParameterNotFoundException if a required parameter was not found.
 * @throws FactoryException if an error occurred while loading the grid.
 */
@Override
public MathTransform createMathTransform(final MathTransformFactory factory, final ParameterValueGroup values)
        throws ParameterNotFoundException, FactoryException
{
    boolean withHeights = false;
    final Parameters pg = Parameters.castOrWrap(values);
    final Integer dim = pg.getValue(Molodensky.DIMENSION);
    if (dim != null) switch (dim) {
        case 2:  break;
        case 3:  withHeights = true; break;
        default: throw new InvalidParameterValueException(Errors.format(
                        Errors.Keys.IllegalArgumentValue_2, "dim", dim), "dim", dim);
    }
    final Path file = pg.getMandatoryValue(FILE);
    final DatumShiftGridFile<Angle,Length> grid = getOrLoad(file,
            isRecognized(file) ? new double[] {TX, TY, TZ} : null, PRECISION);
    MathTransform tr = createGeodeticTransformation(factory,
            createEllipsoid(pg, Molodensky.TGT_SEMI_MAJOR,
                                Molodensky.TGT_SEMI_MINOR, CommonCRS.ETRS89.ellipsoid()),   // GRS 1980 ellipsoid
            createEllipsoid(pg, Molodensky.SRC_SEMI_MAJOR,
                                Molodensky.SRC_SEMI_MINOR, null),                           // Clarke 1880 (IGN) ellipsoid
            withHeights, grid);
    try {
        tr = tr.inverse();
    } catch (NoninvertibleTransformException e) {
        throw new FactoryException(e);                  // Should never happen.
    }
    return tr;
}
 
Example #17
Source File: FranceGeocentricInterpolation.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the grid of the given name. This method returns the cached instance if it still exists,
 * or load the grid otherwise.
 *
 * @param  file      name of the datum shift grid file to load.
 * @param  averages  an "average" value for the offset in each dimension, or {@code null} if unknown.
 * @param  scale     the factor by which to multiply each compressed value before to add to the average value.
 */
@SuppressWarnings("null")
static DatumShiftGridFile<Angle,Length> getOrLoad(final Path file, final double[] averages, final double scale)
        throws FactoryException
{
    final Path resolved = DataDirectory.DATUM_CHANGES.resolve(file).toAbsolutePath();
    DatumShiftGridFile<?,?> grid = DatumShiftGridFile.CACHE.peek(resolved);
    if (grid == null) {
        final Cache.Handler<DatumShiftGridFile<?,?>> handler = DatumShiftGridFile.CACHE.lock(resolved);
        try {
            grid = handler.peek();
            if (grid == null) {
                try (BufferedReader in = Files.newBufferedReader(resolved)) {
                    DatumShiftGridLoader.startLoading(FranceGeocentricInterpolation.class, file);
                    final DatumShiftGridFile.Float<Angle,Length> g = load(in, file);
                    grid = DatumShiftGridCompressed.compress(g, averages, scale);
                } catch (IOException | NoninvertibleTransformException | RuntimeException e) {
                    // NumberFormatException, ArithmeticException, NoSuchElementException, possibly other.
                    throw DatumShiftGridLoader.canNotLoad(HEADER, file, e);
                }
                grid = grid.useSharedData();
            }
        } finally {
            handler.putAndUnlock(grid);
        }
    }
    return grid.castTo(Angle.class, Length.class);
}
 
Example #18
Source File: NTv2.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the grid of the given name. This method returns the cached instance if it still exists,
 * or load the grid otherwise.
 *
 * @param  provider  the provider which is creating a transform.
 * @param  file      name of the datum shift grid file to load.
 * @param  version   the expected version (1 or 2).
 */
@SuppressWarnings("null")
static DatumShiftGridFile<Angle,Angle> getOrLoad(final Class<? extends AbstractProvider> provider,
        final Path file, final int version) throws FactoryException
{
    final Path resolved = DataDirectory.DATUM_CHANGES.resolve(file).toAbsolutePath();
    DatumShiftGridFile<?,?> grid = DatumShiftGridFile.CACHE.peek(resolved);
    if (grid == null) {
        final Cache.Handler<DatumShiftGridFile<?,?>> handler = DatumShiftGridFile.CACHE.lock(resolved);
        try {
            grid = handler.peek();
            if (grid == null) {
                try (ReadableByteChannel in = Files.newByteChannel(resolved)) {
                    DatumShiftGridLoader.startLoading(provider, file);
                    final Loader loader = new Loader(in, file, version);
                    grid = loader.readAllGrids();
                    loader.report(provider);
                } catch (IOException | NoninvertibleTransformException | RuntimeException e) {
                    throw DatumShiftGridLoader.canNotLoad(provider.getSimpleName(), file, e);
                }
                grid = grid.useSharedData();
            }
        } finally {
            handler.putAndUnlock(grid);
        }
    }
    return grid.castTo(Angle.class, Angle.class);
}
 
Example #19
Source File: GeocentricAffineBetweenGeographic.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a math transform from the specified group of parameter values.
 * This method wraps the affine operation into Geographic/Geocentric conversions.
 *
 * @param  factory  the factory to use for creating concatenated transforms.
 * @param  values   the group of parameter values.
 * @return the created math transform.
 * @throws FactoryException if a transform can not be created.
 */
@Override
public MathTransform createMathTransform(final MathTransformFactory factory, final ParameterValueGroup values)
        throws FactoryException
{
    final Parameters pv = Parameters.castOrWrap(values);
    final MathTransform affine = super.createMathTransform(factory, pv);
    /*
     * Create a "Geographic to Geocentric" conversion with ellipsoid axis length units converted to metres
     * (the unit implied by SRC_SEMI_MAJOR) because it is the unit of Bursa-Wolf parameters that we created above.
     */
    MathTransform toGeocentric = EllipsoidToCentricTransform.createGeodeticConversion(factory,
            pv.doubleValue(SRC_SEMI_MAJOR),
            pv.doubleValue(SRC_SEMI_MINOR),
            Units.METRE, getSourceDimensions() >= 3,
            EllipsoidToCentricTransform.TargetType.CARTESIAN);
    /*
     * Create a "Geocentric to Geographic" conversion with ellipsoid axis length units converted to metres
     * because this is the unit of the Geocentric CRS used above.
     */
    MathTransform toGeographic = EllipsoidToCentricTransform.createGeodeticConversion(factory,
            pv.doubleValue(TGT_SEMI_MAJOR),
            pv.doubleValue(TGT_SEMI_MINOR),
            Units.METRE, getTargetDimensions() >= 3,
            EllipsoidToCentricTransform.TargetType.CARTESIAN);
    try {
        toGeographic = toGeographic.inverse();
    } catch (NoninvertibleTransformException e) {
        throw new FactoryException(e);                  // Should never happen with SIS implementation.
    }
    /*
     * The  Geocentric → Affine → Geographic  chain.
     */
    return factory.createConcatenatedTransform(toGeocentric,
           factory.createConcatenatedTransform(affine, toGeographic));
}
 
Example #20
Source File: DatumShiftGridFile.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a new datum shift grid with the same configuration than the given grid,
 * except the size and transform which are set to the given values.
 * This is used for creating a {@link DatumShiftGridGroup} containing many grids,
 * using one grid as a template for setting parameter values.
 * The {@link #accuracy} is initialized to zero and should be updated by the caller.
 *
 * @param  other      the other datum shift grid from which to copy parameters.
 * @param  gridToCRS  conversion from grid indices to "real world" coordinates.
 * @param  nx         number of cells along the <var>x</var> axis in the grid.
 * @param  ny         number of cells along the <var>y</var> axis in the grid.
 */
DatumShiftGridFile(final DatumShiftGridFile<C,T> other, final AffineTransform2D gridToCRS, final int nx, final int ny)
        throws NoninvertibleTransformException
{
    super(other.getCoordinateUnit(), gridToCRS.inverse(), new int[] {nx, ny},
          other.isCellValueRatio(), other.getTranslationUnit());
    scanlineStride = nx;
    descriptor     = other.descriptor;
    files          = other.files;
    periodX        = (other.periodX == 0) ? 0 : Math.rint((Longitude.MAX_VALUE - Longitude.MIN_VALUE)
                                              / AffineTransforms2D.getScaleX0(gridToCRS));
    // Accuracy to be set by caller. Initial value needs to be zero.
}
 
Example #21
Source File: DatumShiftGridFile.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a new datum shift grid with the given grid geometry, filename and number of shift dimensions.
 * All {@code double} values given to this constructor will be converted from degrees to radians.
 *
 * @param  dim  number of dimensions of translation vectors.
 */
Float(final int dim,
      final Unit<C> coordinateUnit,
      final Unit<T> translationUnit,
      final boolean isCellValueRatio,
      final double x0, final double y0,
      final double Δx, final double Δy,
      final int    nx, final int    ny,
      final ParameterDescriptorGroup descriptor,
      final Path... files) throws NoninvertibleTransformException
{
    super(coordinateUnit, translationUnit, isCellValueRatio, x0, y0, Δx, Δy, nx, ny, descriptor, files);
    offsets = new float[dim][Math.multiplyExact(nx, ny)];
}
 
Example #22
Source File: DatumShiftGridFile.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a new datum shift grid with the given grid geometry, filename and number of shift dimensions.
 * All {@code double} values given to this constructor will be converted from degrees to radians.
 */
Double(final int dim,
       final Unit<C> coordinateUnit,
       final Unit<T> translationUnit,
       final boolean isCellValueRatio,
       final double x0, final double y0,
       final double Δx, final double Δy,
       final int    nx, final int    ny,
       final ParameterDescriptorGroup descriptor,
       final Path... files) throws NoninvertibleTransformException
{
    super(coordinateUnit, translationUnit, isCellValueRatio, x0, y0, Δx, Δy, nx, ny, descriptor, files);
    offsets = new double[dim][Math.multiplyExact(nx, ny)];
}
 
Example #23
Source File: MathTransformParser.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Parses an {@code "INVERSE_MT"} element. This element has the following pattern:
 *
 * {@preformat text
 *     INVERSE_MT[<math transform>]
 * }
 *
 * @param  parent  the parent element.
 * @return the {@code "INVERSE_MT"} element as an {@link MathTransform} object.
 * @throws ParseException if the {@code "INVERSE_MT"} element can not be parsed.
 */
private MathTransform parseInverseMT(final Element parent) throws ParseException {
    final Element element = parent.pullElement(FIRST, WKTKeywords.Inverse_MT);
    if (element == null) {
        return null;
    }
    MathTransform transform = parseMathTransform(element, true);
    try {
        transform = transform.inverse();
    } catch (NoninvertibleTransformException exception) {
        throw element.parseFailed(exception);
    }
    element.close(ignoredElements);
    return transform;
}
 
Example #24
Source File: Benchmark.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Prepares benchmarking for the map projection created by the given provider.
 */
private Benchmark(final AbstractProvider provider,
                  final double centralMeridian,
                  final double standardParallel1,
                  final double standardParallel2) throws FactoryException, NoninvertibleTransformException
{
    random = new Random();
    final Parameters values = Parameters.castOrWrap(provider.getParameters().createValue());
    values.parameter(Constants.SEMI_MAJOR)         .setValue(MapProjectionTestCase.WGS84_A);
    values.parameter(Constants.SEMI_MINOR)         .setValue(MapProjectionTestCase.WGS84_B);
    values.parameter(Constants.CENTRAL_MERIDIAN)   .setValue(centralMeridian);
    values.parameter(Constants.STANDARD_PARALLEL_1).setValue(standardParallel1);
    values.parameter(Constants.STANDARD_PARALLEL_2).setValue(standardParallel2);
    forward = new Transforms("Forward", new MathTransformFactoryMock(provider).createParameterizedTransform(values));
    inverse = new Transforms("Inverse", forward.projection.inverse());
    coordinates = new double[NUM_POINTS * DIMENSION];
    final double λmin = centralMeridian - 40;
    final double Δλ   = 80;
    final double φmin = standardParallel1 * 0.75;
    final double Δφ   = Math.min(standardParallel2 * 1.25, Latitude.MAX_VALUE) - φmin;
    for (int i=0; i<coordinates.length;) {
        coordinates[i++] = random.nextDouble() * Δλ + λmin;     // Longitude
        coordinates[i++] = random.nextDouble() * Δφ + φmin;     // Latitude
    }
    result = new double[coordinates.length];
    errors = new Statistics("Errors (cm)");
}
 
Example #25
Source File: MercatorTest.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Tests the WKT formatting of {@link NormalizedProjection}. For the Mercator projection, we expect only
 * the ellipsoid eccentricity. We expect nothing else because all other parameters are used
 * by the (de)normalization affine transforms instead than the {@link Mercator} class itself.
 *
 * @throws NoninvertibleTransformException if the transform can not be inverted.
 *
 * @see LambertConicConformalTest#testNormalizedWKT()
 */
@Test
public void testNormalizedWKT() throws NoninvertibleTransformException {
    createNormalizedProjection(true);
    assertWktEquals("PARAM_MT[“Mercator (radians domain)”,\n" +
                    "  PARAMETER[“eccentricity”, 0.0818191908426215]]");

    transform = transform.inverse();
    assertWktEquals("INVERSE_MT[\n" +
                    "  PARAM_MT[“Mercator (radians domain)”,\n" +
                    "    PARAMETER[“eccentricity”, 0.0818191908426215]]]");
}
 
Example #26
Source File: MercatorTest.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Tests WKT of a complete map projection.
 *
 * @throws FactoryException if an error occurred while creating the map projection.
 * @throws NoninvertibleTransformException if the transform can not be inverted.
 */
@Test
@DependsOnMethod("testNormalizedWKT")
public void testCompleteWKT() throws FactoryException, NoninvertibleTransformException {
    createCompleteProjection(new Mercator1SP(),
            WGS84_A,    // Semi-major axis length
            WGS84_B,    // Semi-minor axis length
            0.5,        // Central meridian
            NaN,        // Latitude of origin (none)
            NaN,        // Standard parallel 1 (none)
            NaN,        // Standard parallel 2 (none)
            0.997,      // Scale factor
            200,        // False easting
            100);       // False northing

    assertWktEquals("PARAM_MT[“Mercator_1SP”,\n" +
                    "  PARAMETER[“semi_major”, 6378137.0],\n" +
                    "  PARAMETER[“semi_minor”, 6356752.314245179],\n" +
                    "  PARAMETER[“central_meridian”, 0.5],\n" +
                    "  PARAMETER[“scale_factor”, 0.997],\n" +
                    "  PARAMETER[“false_easting”, 200.0],\n" +
                    "  PARAMETER[“false_northing”, 100.0]]");

    transform = transform.inverse();
    assertWktEquals("INVERSE_MT[\n" +
                    "  PARAM_MT[“Mercator_1SP”,\n" +
                    "    PARAMETER[“semi_major”, 6378137.0],\n" +
                    "    PARAMETER[“semi_minor”, 6356752.314245179],\n" +
                    "    PARAMETER[“central_meridian”, 0.5],\n" +
                    "    PARAMETER[“scale_factor”, 0.997],\n" +
                    "    PARAMETER[“false_easting”, 200.0],\n" +
                    "    PARAMETER[“false_northing”, 100.0]]]");
}
 
Example #27
Source File: DefaultConcatenatedOperationTest.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Tests WKT formatting. The WKT format used here is not defined in OGC/ISO standards;
 * this is a SIS-specific extension.
 *
 * @throws FactoryException if an error occurred while creating the test operation.
 * @throws NoninvertibleTransformException if an error occurred while creating the test operation.
 */
@Test
public void testWKT() throws FactoryException, NoninvertibleTransformException {
    final DefaultConcatenatedOperation op = createGeocentricTranslation();
    assertWktEquals(Convention.WKT2_SIMPLIFIED,                             // Pseudo-WKT actually.
            "ConcatenatedOperation[“Tokyo to JGD2000”,\n" +
            "  SourceCRS[GeodeticCRS[“Tokyo”,\n" +
            "    Datum[“Tokyo 1918”,\n" +
            "      Ellipsoid[“Bessel 1841”, 6377397.155, 299.1528128]],\n" +
            "    CS[ellipsoidal, 3],\n" +
            "      Axis[“Longitude (L)”, east, Unit[“degree”, 0.017453292519943295]],\n" +
            "      Axis[“Latitude (B)”, north, Unit[“degree”, 0.017453292519943295]],\n" +
            "      Axis[“Ellipsoidal height (h)”, up, Unit[“metre”, 1]]]],\n" +
            "  TargetCRS[GeodeticCRS[“JGD2000”,\n" +
            "    Datum[“Japanese Geodetic Datum 2000”,\n" +
            "      Ellipsoid[“GRS 1980”, 6378137.0, 298.257222101]],\n" +
            "    CS[ellipsoidal, 3],\n" +
            "      Axis[“Longitude (L)”, east, Unit[“degree”, 0.017453292519943295]],\n" +
            "      Axis[“Latitude (B)”, north, Unit[“degree”, 0.017453292519943295]],\n" +
            "      Axis[“Ellipsoidal height (h)”, up, Unit[“metre”, 1]]]],\n" +
            "  CoordinateOperationStep[“Geographic to geocentric”,\n" +
            "    Method[“Geographic/geocentric conversions”]],\n" +         // Omit non-EPSG parameters for EPSG method.
            "  CoordinateOperationStep[“Tokyo to JGD2000 (GSI)”,\n" +
            "    Method[“Geocentric translations”],\n" +
            "      Parameter[“X-axis translation”, -146.414],\n" +
            "      Parameter[“Y-axis translation”, 507.337],\n" +
            "      Parameter[“Z-axis translation”, 680.507]],\n" +
            "  CoordinateOperationStep[“Geocentric to geographic”,\n" +
            "    Method[“Geographic/geocentric conversions”],\n" +
            "      Parameter[“semi_major”, 6378137.0, Unit[“metre”, 1]],\n" +
            "      Parameter[“semi_minor”, 6356752.314140356, Unit[“metre”, 1]]]]", op);
}
 
Example #28
Source File: DatumShiftGridCompressedTest.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a new grid using an affine transform as a reference.
 *
 * @param  rotation  ignored.
 */
@Override
void init(final double rotation) throws NoninvertibleTransformException {
    super.init(0);      // No rotation in order to have integer values.
    grid = DatumShiftGridCompressed.compress((DatumShiftGridFile.Float<Dimensionless,Dimensionless>) grid, null, 0.5);
    assertInstanceOf("grid", DatumShiftGridCompressed.class, grid);
}
 
Example #29
Source File: GeodeticObjectParserTest.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the conversion from {@code north} to {@code south}.
 */
private static Matrix conversion(final ProjectedCRS north, final ProjectedCRS south)
        throws NoninvertibleTransformException
{
    final MathTransform transform = MathTransforms.concatenate(
            north.getConversionFromBase().getMathTransform().inverse(),
            south.getConversionFromBase().getMathTransform());
    assertInstanceOf("North to South", LinearTransform.class, transform);
    return ((LinearTransform) transform).getMatrix();
}
 
Example #30
Source File: GridDerivation.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the concatenation of all transformation steps from the given source to the given target.
 * The transform maps grid coordinates (not envelopes).
 *
 * @param  source     the source grid geometry.
 * @param  crsChange  the change of coordinate reference system, or {@code null} if none.
 * @param  target     the target grid geometry.
 * @param  anchor     whether we want the transform for cell corner or cell center.
 */
private static MathTransform path(final GridGeometry source, final CoordinateOperation crsChange,
        final GridGeometry target, final PixelInCell anchor) throws NoninvertibleTransformException
{
    MathTransform step1 = source.getGridToCRS(anchor);
    MathTransform step2 = target.getGridToCRS(anchor);
    if (crsChange != null) {
        step1 = MathTransforms.concatenate(step1, crsChange.getMathTransform());
    }
    if (step1.equals(step2)) {                                          // Optimization for a common case.
        return MathTransforms.identity(step1.getSourceDimensions());
    } else {
        return MathTransforms.concatenate(step1, step2.inverse());
    }
}