/* * Geotools 2 - OpenSource mapping toolkit * (C) 2003, Geotools Project Managment Committee (PMC) * (C) 2001, Institut de Recherche pour le Développement * * 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; either * version 2.1 of the License, or (at your option) any later version. * * 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. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.geotools.ct; // OpenGIS dependencies import java.io.Serializable; import org.geotools.pt.CoordinatePoint; import org.geotools.pt.Matrix; import org.geotools.resources.Utilities; import org.geotools.resources.i18n.Errors; import org.geotools.resources.i18n.ErrorKeys; import org.opengis.referencing.operation.NoninvertibleTransformException; import org.opengis.referencing.operation.TransformException; import org.opengis.spatialschema.geometry.MismatchedDimensionException; /** * Transform which passes through a subset of ordinates to another transform. * This allows transforms to operate on a subset of ordinates. For example, * if you have (latitude,longitude,height) * coordinates, then you may wish to convert the height values from feet to * meters without affecting the latitude and longitude values. * * @source $URL$ * @version 1.00 * @author Martin Desruisseaux * * @deprecated Replaced by {@link org.geotools.referencing.operation.transform.PassThroughTransform} * in the org.geotools.referencing.operation.transform package. */ final class PassThroughTransform extends AbstractMathTransform implements Serializable { /** * Serial number for interoperability with different versions. */ private static final long serialVersionUID = -1673997634240223449L; /** * Index of the first affected ordinate. */ protected final int firstAffectedOrdinate; /** * Number of unaffected ordinates after the affected ones. * Always 0 when used through the strict OpenGIS API. */ protected final int numTrailingOrdinates; /** * The sub transform. */ protected final MathTransform transform; /** * The inverse transform. This field * will be computed only when needed. */ private transient PassThroughTransform inverse; /** * Create a pass through transform. * * @param firstAffectedOrdinate Index of the first affected ordinate. * @param transform The sub transform. * @param numTrailingOrdinates Number of trailing ordinates to pass through. * Affected ordinates will range from firstAffectedOrdinate * inclusive to dimTarget-numTrailingOrdinates exclusive. */ public PassThroughTransform(final int firstAffectedOrdinate, final MathTransform transform, final int numTrailingOrdinates) { if (transform instanceof PassThroughTransform) { final PassThroughTransform passThrough = (PassThroughTransform) transform; this.firstAffectedOrdinate = passThrough.firstAffectedOrdinate + firstAffectedOrdinate; this.numTrailingOrdinates = passThrough.numTrailingOrdinates + numTrailingOrdinates; this.transform = passThrough.transform; } else { this.firstAffectedOrdinate = firstAffectedOrdinate; this.numTrailingOrdinates = numTrailingOrdinates; this.transform = transform; } } /** * Gets the dimension of input points. */ public int getDimSource() { return firstAffectedOrdinate + transform.getDimSource() + numTrailingOrdinates; } /** * Gets the dimension of output points. */ public int getDimTarget() { return firstAffectedOrdinate + transform.getDimTarget() + numTrailingOrdinates; } /** * Tests whether this transform does not move any points. */ public boolean isIdentity() { return transform.isIdentity(); } /** * Transforms a list of coordinate point ordinal values. */ public void transform(final float[] srcPts, int srcOff, final float[] dstPts, int dstOff, int numPts) throws TransformException { final int subDimSource = transform.getDimSource(); final int subDimTarget = transform.getDimTarget(); int srcStep = numTrailingOrdinates; int dstStep = numTrailingOrdinates; if (srcPts==dstPts && srcOff= 0) { System.arraycopy (srcPts, srcOff, dstPts, dstOff, firstAffectedOrdinate); transform.transform(srcPts, srcOff+=firstAffectedOrdinate, dstPts, dstOff+=firstAffectedOrdinate, 1); System.arraycopy (srcPts, srcOff+=subDimSource, dstPts, dstOff+=subDimTarget, numTrailingOrdinates); srcOff += srcStep; dstOff += dstStep; } } /** * Transforms a list of coordinate point ordinal values. */ public void transform(final double[] srcPts, int srcOff, final double[] dstPts, int dstOff, int numPts) throws TransformException { final int subDimSource = transform.getDimSource(); final int subDimTarget = transform.getDimTarget(); int srcStep = numTrailingOrdinates; int dstStep = numTrailingOrdinates; if (srcPts==dstPts && srcOff= 0) { System.arraycopy (srcPts, srcOff, dstPts, dstOff, firstAffectedOrdinate); transform.transform(srcPts, srcOff+=firstAffectedOrdinate, dstPts, dstOff+=firstAffectedOrdinate, 1); System.arraycopy (srcPts, srcOff+=subDimSource, dstPts, dstOff+=subDimTarget, numTrailingOrdinates); srcOff += srcStep; dstOff += dstStep; } } /** * Gets the derivative of this transform at a point. */ public Matrix derivative(final CoordinatePoint point) throws TransformException { final int nSkipped = firstAffectedOrdinate + numTrailingOrdinates; final int transDim = transform.getDimSource(); final int pointDim = point.getDimension(); if (pointDim != transDim+nSkipped) { throw new MismatchedDimensionException(Errors.format( ErrorKeys.MISMATCHED_DIMENSION_$2, new Integer(pointDim), new Integer(transDim+nSkipped))); } final CoordinatePoint subPoint = new CoordinatePoint(transDim); System.arraycopy(point.ord, firstAffectedOrdinate, subPoint.ord, 0, transDim); return expand(transform.derivative(subPoint), firstAffectedOrdinate, numTrailingOrdinates, 0); } /** * Create a pass through transform from a matrix. This method is invoked when the * sub-transform can be express as a matrix. It is also invoked for computing the * matrix returned by {@link #derivative}. * * @param subMatrix The sub-transform as a matrix. * @param firstAffectedOrdinate Index of the first affected ordinate. * @param numTrailingOrdinates Number of trailing ordinates to pass through. * @param affine 0 if the matrix do not contains translation terms, or 1 if * the matrix is an affine transform with translation terms. */ static Matrix expand(final Matrix subMatrix, final int firstAffectedOrdinate, final int numTrailingOrdinates, final int affine) { final int nSkipped = firstAffectedOrdinate + numTrailingOrdinates; final int numRow = subMatrix.getNumRow() - affine; final int numCol = subMatrix.getNumCol() - affine; final Matrix matrix = new Matrix(numRow + nSkipped + affine, numCol + nSkipped + affine); matrix.setZero(); // Set UL part to 1: [ 1 0 ] // [ 0 1 ] // [ ] // [ ] // [ ] for (int j=0; j