/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2014, 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.internal.image.io;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.opengis.referencing.operation.TransformException;
import org.apache.sis.referencing.operation.transform.AbstractMathTransform;
/**
* A modified Mercator projection used in some NetCDF files at IFREMER.
* This is a temporary patch until we get a better support for NetCDF grids.
* This class will not be ported to Apache SIS.
*/
@Deprecated
@SuppressWarnings("serial")
final class ModifiedMercator extends AbstractMathTransform {
/**
* Index of the latitude in a coordinate.
*/
private static final int DIM_φ = 1;
/**
* The Mercator projection to apply.
*/
private final AbstractMathTransform mercator;
/**
* North latitude threshold. Starting from the point, we replace the Mercator projection by a linear conversion.
* In the case of the IFREMER file for which we are creating this transform, it seems to be about 66.2°N.
*/
private final double thresholdNorth;
/**
* Scale and offset factors from values above {@link #thresholdNorth}, determined empirically from the
* latitude data in the NetCDF file.
*/
private final double scale, offset;
private transient MathTransform inverse;
/**
* Creates a new projection wrapping the given Mercator projection.
*/
ModifiedMercator(final AbstractMathTransform mercator) {
this(mercator, 66.2, 272866.03, -8171141.19);
}
private ModifiedMercator(final AbstractMathTransform mercator, final double thresholdNorth, final double scale, final double offset) {
this.mercator = mercator;
this.thresholdNorth = thresholdNorth;
this.scale = scale;
this.offset = offset;
}
@Override
public int getSourceDimensions() {
return 2;
}
@Override
public int getTargetDimensions() {
return 2;
}
@Override
public Matrix transform(final double[] srcPts, final int srcOff, final double[] dstPts, final int dstOff,
final boolean derivate) throws TransformException
{
final double φ = srcPts[srcOff + DIM_φ];
final Matrix matrix = mercator.transform(srcPts, srcOff, dstPts, dstOff, derivate);
if (φ >= thresholdNorth) {
dstPts[dstOff + DIM_φ] = φ * scale + offset;
if (matrix != null) {
matrix.setElement(DIM_φ, DIM_φ, scale);
matrix.setElement(DIM_φ, 2, offset);
}
}
return matrix;
}
@Override
public MathTransform inverse() throws NoninvertibleTransformException {
if (inverse == null) {
inverse = new ModifiedMercator((AbstractMathTransform) mercator.inverse(), 9894252, 1/scale, -offset/scale);
}
return inverse;
}
}