001: /*
002: * Geotools2 - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, Geotools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.referencing.operation.builder;
017:
018: import org.geotools.referencing.operation.matrix.GeneralMatrix;
019: import org.opengis.geometry.MismatchedDimensionException;
020: import org.opengis.geometry.MismatchedReferenceSystemException;
021:
022: // J2SE and extensions
023: import java.util.List;
024: import javax.vecmath.MismatchedSizeException;
025:
026: /**
027: * Builds {@linkplain org.opengis.referencing.operation.MathTransform
028: * MathTransform} setup as Affine transformation from a list of {@linkplain
029: * MappedPosition MappedPosition}. The calculation uses least square method.
030: * The Affine transform equation:
031: * <pre>
032: * [ x'] [ m00 m01 m02 ] [ x ] [ m00x + m01y + m02 ]
033: * [ y'] = [ m10 m11 m12 ] [ y ] = [ m10x + m11y + m12 ]
034: * [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ]
035: * x' = m * x </pre>In the case that we have more identical points we can
036: * write it like this (in Matrix):<pre>
037: * [ x'<sub>1</sub> ] [ x<sub>1</sub> y<sub>1</sub> 1 0 0 0 ] [ m00 ]
038: * [ x'<sub>2</sub> ] [ x<sub>2</sub> y<sub>2</sub> 1 0 0 0 ] [ m01 ]
039: * [ . ] [ . ] [ m02 ]
040: * [ . ] [ . ] * [ m10 ]
041: * [ x'<sub>n</sub> ] = [ x<sub>n</sub> y<sub>n</sub> 1 0 0 0 ] [ m11 ]
042: * [ y'<sub>1</sub> ] [ 0 0 0 x<sub>1</sub> y<sub>1</sub> 1 ] [ m12 ]
043: * [ y'<sub>2</sub> ] [ 0 0 0 x<sub>2</sub> y<sub>2</sub> 1 ]
044: * [ . ] [ . ]
045: * [ . ] [ . ]
046: * [ y'<sub>n</sub> ] [ 0 0 0 x<sub>n</sub> y<sub>n</sub> 1 ]
047: * x' = A*m </pre>Using the least square method we get this result:
048: * <pre><blockquote>
049: * m = (A<sup>T</sup>A)<sup>-1</sup> A<sup>T</sup>x' </blockquote> </pre>
050: *
051: * @since 2.4
052: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/operation/builder/AffineTransformBuilder.java $
053: * @version $Id: AffineTransformBuilder.java 28982 2008-01-28 16:27:33Z acuster $
054: * @author Jan Jezek
055: */
056: public class AffineTransformBuilder extends ProjectiveTransformBuilder {
057: protected AffineTransformBuilder() {
058: }
059:
060: /**
061: * Creates AffineTransformBuilder for the set of properties.
062: *
063: * @param vectors list of {@linkplain
064: * MappedPosition MappedPosition}
065: */
066: public AffineTransformBuilder(List vectors)
067: throws MismatchedSizeException,
068: MismatchedDimensionException,
069: MismatchedReferenceSystemException {
070: super .setMappedPositions(vectors);
071: }
072:
073: /**
074: * Returns the minimum number of points required by this builder,
075: * which is 3.
076: *
077: * @return the minimum number of points required by this builder, which is
078: * 3.
079: */
080: public int getMinimumPointCount() {
081: return 3;
082: }
083:
084: /**
085: * Returns the matrix for Projective transformation setup as
086: * Affine. The M matrix looks like this:
087: * <pre>
088: * [ m00 m01 m02 ]
089: * [ m10 m11 m12 ]
090: * [ 0 0 1 ]
091: * </pre>
092: *
093: * @return Matrix M.
094: */
095: protected GeneralMatrix getProjectiveMatrix() {
096: GeneralMatrix M = new GeneralMatrix(3, 3);
097: double[] param = calculateLSM();
098: double[] m0 = { param[0], param[1], param[2] };
099: double[] m1 = { param[3], param[4], param[5] };
100: double[] m2 = { 0, 0, 1 };
101: M.setRow(0, m0);
102: M.setRow(1, m1);
103: M.setRow(2, m2);
104:
105: return M;
106: }
107:
108: protected void fillAMatrix() {
109:
110: super .A = new GeneralMatrix(2 * getSourcePoints().length, 6);
111:
112: int numRow = getSourcePoints().length * 2;
113:
114: // Creates X matrix
115: for (int j = 0; j < (numRow / 2); j++) {
116: A.setRow(j, new double[] {
117: getSourcePoints()[j].getCoordinates()[0],
118: getSourcePoints()[j].getCoordinates()[1], 1, 0, 0,
119: 0 });
120: }
121:
122: for (int j = numRow / 2; j < numRow; j++) {
123: A.setRow(j, new double[] {
124: 0,
125: 0,
126: 0,
127: getSourcePoints()[j - (numRow / 2)]
128: .getCoordinates()[0],
129: getSourcePoints()[j - (numRow / 2)]
130: .getCoordinates()[1], 1 });
131:
132: }
133: }
134: }
|