/* * 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 * * * This package contains documentation from OpenGIS specifications. * OpenGIS consortium's work is fully acknowledged here. */ package org.geotools.ct; // J2SE dependencies import java.awt.geom.Point2D; import java.io.Serializable; import java.util.Arrays; import javax.media.jai.ParameterList; import javax.media.jai.PerspectiveTransform; import javax.vecmath.GMatrix; import javax.vecmath.SingularMatrixException; import org.geotools.pt.CoordinatePoint; import org.geotools.pt.Matrix; import org.geotools.resources.i18n.ErrorKeys; import org.geotools.resources.i18n.Errors; import org.geotools.resources.i18n.VocabularyKeys; import org.geotools.resources.i18n.Vocabulary; import org.opengis.referencing.operation.NoninvertibleTransformException; /** * Transforms multi-dimensional coordinate points using a {@link Matrix}. * * @source $URL$ * @version $Id$ * @author OpenGIS (www.opengis.org) * @author Martin Desruisseaux * * @deprecated Replaced by {@link org.geotools.referencing.operation.ProjectiveTransform} * in the org.geotools.referencing.operation package. */ final class MatrixTransform extends AbstractMathTransform implements LinearTransform, Serializable { /** * Serial number for interoperability with different versions. */ private static final long serialVersionUID = -2104496465933824935L; /** * The number of rows. */ private final int numRow; /** * The number of columns. */ private final int numCol; /** * Elements of the matrix. Column indice vary fastest. */ private final double[] elt; /** * Construct a transform. */ protected MatrixTransform(final GMatrix matrix) { numRow = matrix.getNumRow(); numCol = matrix.getNumCol(); elt = new double[numRow*numCol]; int index = 0; for (int j=0; j{@link Matrix#getNumCol}-1. For example, * for square matrix of size 4×4, coordinate points are three-dimensional and * stored in the arrays starting at the specified offset (srcOff) in the order * [x0, y0, z0, * x1, y1, z1..., * xn, yn, zn]. * * The transformed points (x',y',z') are computed as below * (note that this computation is similar to {@link PerspectiveTransform}): * *
     * [ u ]     [ m00  m01  m02  m03 ] [ x ]
     * [ v ]  =  [ m10  m11  m12  m13 ] [ y ]
     * [ w ]     [ m20  m21  m22  m23 ] [ z ]
     * [ t ]     [ m30  m31  m32  m33 ] [ 1 ]
     *
     *   x' = u/t
     *   y' = v/t
     *   y' = w/t
     * 
* * @param srcPts The array containing the source point coordinates. * @param srcOff The offset to the first point to be transformed in the source array. * @param dstPts The array into which the transformed point coordinates are returned. * @param dstOff The offset to the location of the first transformed point that is stored * in the destination array. The source and destination array sections can * be overlaps. * @param numPts The number of points to be transformed */ public void transform(float[] srcPts, int srcOff, final float[] dstPts, int dstOff, int numPts) { final int inputDimension = numCol-1; // The last ordinate will be assumed equals to 1. final int outputDimension = numRow-1; final double[] buffer = new double[numRow]; if (srcPts==dstPts) { // We are going to write in the source array. Checks if // source and destination sections are going to clash. final int upperSrc = srcOff + numPts*inputDimension; if (upperSrc > dstOff) { if (inputDimension >= outputDimension ? dstOff > srcOff : dstOff + numPts*outputDimension > upperSrc) { // If source overlaps destination, then the easiest workaround is // to copy source data. This is not the most efficient however... srcPts = new float[numPts*inputDimension]; System.arraycopy(dstPts, srcOff, srcPts, 0, srcPts.length); srcOff = 0; } } } while (--numPts>=0) { int mix=0; for (int j=0; j{@link Matrix#getNumCol}-1. For example, * for square matrix of size 4×4, coordinate points are three-dimensional and * stored in the arrays starting at the specified offset (srcOff) in the order * [x0, y0, z0, * x1, y1, z1..., * xn, yn, zn]. * * The transformed points (x',y',z') are computed as below * (note that this computation is similar to {@link PerspectiveTransform}): * *
     * [ u ]     [ m00  m01  m02  m03 ] [ x ]
     * [ v ]  =  [ m10  m11  m12  m13 ] [ y ]
     * [ w ]     [ m20  m21  m22  m23 ] [ z ]
     * [ t ]     [ m30  m31  m32  m33 ] [ 1 ]
     *
     *   x' = u/t
     *   y' = v/t
     *   y' = w/t
     * 
* * @param srcPts The array containing the source point coordinates. * @param srcOff The offset to the first point to be transformed in the source array. * @param dstPts The array into which the transformed point coordinates are returned. * @param dstOff The offset to the location of the first transformed point that is stored * in the destination array. The source and destination array sections can * be overlaps. * @param numPts The number of points to be transformed */ public void transform(double[] srcPts, int srcOff, final double[] dstPts, int dstOff, int numPts) { final int inputDimension = numCol-1; // The last ordinate will be assumed equals to 1. final int outputDimension = numRow-1; final double[] buffer = new double[numRow]; if (srcPts==dstPts) { // We are going to write in the source array. Checks if // source and destination sections are going to clash. final int upperSrc = srcOff + numPts*inputDimension; if (upperSrc > dstOff) { if (inputDimension >= outputDimension ? dstOff > srcOff : dstOff + numPts*outputDimension > upperSrc) { // If source overlaps destination, then the easiest workaround is // to copy source data. This is not the most efficient however... srcPts = new double[numPts*inputDimension]; System.arraycopy(dstPts, srcOff, srcPts, 0, srcPts.length); srcOff = 0; } } } while (--numPts>=0) { int mix=0; for (int j=0; j=0;) { code = code*37 + Double.doubleToLongBits(elt[i]); } return (int)(code >>> 32) ^ (int)code; } /** * Compares the specified object with * this math transform for equality. */ public boolean equals(final Object object) { if (object==this) { // Slight optimization return true; } if (super.equals(object)) { final MatrixTransform that = (MatrixTransform) object; return this.numRow == that.numRow && this.numCol == that.numCol && Arrays.equals(this.elt, that.elt); } return false; } /** * Returns the WKT for this math transform. */ public String toString() { return toString(getMatrix()); } /** * Returns the WKT for an affine transform * using the specified matrix. */ static String toString(final Matrix matrix) { final int numRow = matrix.getNumRow(); final int numCol = matrix.getNumCol(); final StringBuffer buffer = paramMT("Affine"); final StringBuffer eltBuf = new StringBuffer("elt_"); addParameter(buffer, "num_row", numRow); addParameter(buffer, "num_col", numCol); for (int j=0; j