All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geotools.renderer.crs.GeographicOffsetWrapper Maven / Gradle / Ivy

/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 *
 *    (C) 2014, Open Source Geospatial Foundation (OSGeo)
 *
 *    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.geotools.renderer.crs;

import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.opengis.referencing.operation.TransformException;

/**
 * Wraps a datum shift math transform and makes sure we are not introducing dateline jumps when
 * applying the datum shift
 *
 * @author Andrea Aime - GeoSolutions
 */
class GeographicOffsetWrapper implements MathTransform {

    MathTransform delegate;

    public GeographicOffsetWrapper(MathTransform delegate) {
        this.delegate = delegate;
    }

    public int getSourceDimensions() {
        return delegate.getSourceDimensions();
    }

    public int getTargetDimensions() {
        return delegate.getTargetDimensions();
    }

    public DirectPosition transform(DirectPosition ptSrc, DirectPosition ptDst)
            throws MismatchedDimensionException, TransformException {
        return delegate.transform(ptSrc, ptDst);
    }

    public void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts)
            throws TransformException {
        double[] source = srcPts;
        if (srcPts == dstPts) {
            source = new double[srcPts.length];
            System.arraycopy(srcPts, 0, source, 0, srcPts.length);
        }
        delegate.transform(srcPts, srcOff, dstPts, dstOff, numPts);

        final int srcDimension = delegate.getSourceDimensions();
        final int dstDimension = delegate.getTargetDimensions();
        double lastSrcLon = source[srcOff];
        double lastDstLon = dstPts[dstOff];
        double offset = 0;
        for (int i = srcOff + srcDimension, j = dstOff + dstDimension, ptCount = 1;
                ptCount < numPts;
                i += srcDimension, j += dstDimension, ptCount++) {
            double srcLon = source[i];
            double dstLon = dstPts[j];

            double srcDelta = srcLon - lastSrcLon;
            double dstDelta = dstLon - lastDstLon;
            double difference = srcDelta - dstDelta;
            // did we jump over the dateline?
            if (difference > 180) {
                // from west to east
                offset += 360;
            } else if (difference < -180) {
                offset -= 360;
            }

            if (offset != 0) {
                dstPts[j] += offset;
            }

            lastDstLon = dstLon;
            lastSrcLon = srcLon;
        }
    }

    public void transform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts)
            throws TransformException {
        delegate.transform(srcPts, srcOff, dstPts, dstOff, numPts);

        int dimension = (srcPts.length - srcOff) / numPts;
        double lastSrcLon = srcPts[srcOff];
        double lastDstLon = dstPts[dstOff];
        float offset = 0;
        for (int i = srcOff + dimension, j = dstOff + dimension, ptCount = 0;
                ptCount < numPts;
                i += dimension, j += dimension, ptCount++) {
            double srcLon = srcPts[i];
            double dstLon = dstPts[j];

            double srcDelta = srcLon - lastSrcLon;
            double dstDelta = dstLon - lastDstLon;
            double difference = srcDelta - dstDelta;
            // did we jump over the dateline?
            if (difference > 180) {
                // from west to east
                offset += 360;
            } else if (difference < 180) {
                offset -= 360;
            }

            if (offset != 0) {
                dstPts[j] += offset;
            }

            lastDstLon = dstLon;
            lastSrcLon = srcLon;
        }
    }

    public void transform(float[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts)
            throws TransformException {
        delegate.transform(srcPts, srcOff, dstPts, dstOff, numPts);

        int dimension = (srcPts.length - srcOff) / numPts;
        double lastSrcLon = srcPts[srcOff];
        double lastDstLon = dstPts[dstOff];
        double offset = 0;
        for (int i = srcOff + dimension, j = dstOff + dimension, ptCount = 0;
                ptCount < numPts;
                i += dimension, j += dimension, ptCount++) {
            double srcLon = srcPts[i];
            double dstLon = dstPts[j];

            double srcDelta = srcLon - lastSrcLon;
            double dstDelta = dstLon - lastDstLon;
            double difference = srcDelta - dstDelta;
            // did we jump over the dateline?
            if (difference > 180) {
                // from west to east
                offset += 360;
            } else if (difference < 180) {
                offset -= 360;
            }

            if (offset != 0) {
                dstPts[j] += offset;
            }

            lastDstLon = dstLon;
            lastSrcLon = srcLon;
        }
    }

    public void transform(double[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts)
            throws TransformException {
        delegate.transform(srcPts, srcOff, dstPts, dstOff, numPts);

        int dimension = (srcPts.length - srcOff) / numPts;
        double lastSrcLon = srcPts[srcOff];
        double lastDstLon = dstPts[dstOff];
        float offset = 0;
        for (int i = srcOff + dimension, j = dstOff + dimension, ptCount = 0;
                ptCount < numPts;
                i += dimension, j += dimension, ptCount++) {
            double srcLon = srcPts[i];
            double dstLon = dstPts[j];

            double srcDelta = srcLon - lastSrcLon;
            double dstDelta = dstLon - lastDstLon;
            double difference = srcDelta - dstDelta;
            // did we jump over the dateline?
            if (difference > 180) {
                // from west to east
                offset += 360;
            } else if (difference < 180) {
                offset -= 360;
            }

            if (offset != 0) {
                dstPts[j] += offset;
            }

            lastDstLon = dstLon;
            lastSrcLon = srcLon;
        }
    }

    public Matrix derivative(DirectPosition point)
            throws MismatchedDimensionException, TransformException {
        return delegate.derivative(point);
    }

    public MathTransform inverse() throws NoninvertibleTransformException {
        MathTransform inverse = delegate.inverse();
        if (inverse instanceof GeographicOffsetWrapper) {
            return inverse;
        } else {
            return new GeographicOffsetWrapper(inverse);
        }
    }

    public boolean isIdentity() {
        return delegate.isIdentity();
    }

    public String toWKT() throws UnsupportedOperationException {
        return delegate.toWKT();
    }

    @Override
    public String toString() {
        return "GeographicOffsetWrapper[\n" + delegate.toString() + "\n]";
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy