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: import java.util.List;
022:
023: // J2SE and extensions
024: import javax.vecmath.MismatchedSizeException;
025:
026: /**
027: * Builds {@linkplain org.opengis.referencing.operation.MathTransform
028: * MathTransform} setup as Similar transformation from a list of {@linkplain
029: * org.geotools.referencing.operation.builder.MappedPosition MappedPosition}.
030: * The The calculation uses least square method. The similar transform
031: * equation:<pre>
032: * [ x'] [ a -b Tx ] [ x ] [ a*x - b*y + Tx ]
033: * [ y'] = [ b a Ty ] [ y ] = [ b*x + a*y + Ty ] </pre>In the case
034: * that we have more identical points we can write it like this (in Matrix):
035: * <pre>
036: * [ x'<sub>1</sub> ] [ x<sub>1</sub> -y<sub>1</sub> 1 0 ] [ a ]
037: * [ x'<sub>2</sub> ] [ x<sub>2</sub> -y<sub>2</sub> 1 0 ] [ b ]
038: * [ . ] [ . ] [ Tx ]
039: * [ . ] [ . ] * [ Ty ]
040: * [ x'<sub>n</sub> ] = [ x<sub>n</sub> y<sub>n</sub> 1 0 ]
041: * [ y'<sub>1</sub> ] [ y<sub>1</sub> x<sub>1</sub> 0 1 ]
042: * [ y'<sub>2</sub> ] [ y<sub>2</sub> x<sub>2</sub> 0 1 ]
043: * [ . ] [ . ]
044: * [ . ] [ . ]
045: * [ y'<sub>n</sub> ] [ y<sub>n</sub> x<sub>n</sub> 0 1 ]
046: * x' = A*m </pre>Using the least square method we get this result:
047: * <pre><blockquote>
048: * m = (A<sup>T</sup>A)<sup>-1</sup> A<sup>T</sup>x' </blockquote> </pre>
049: *
050: * @since 2.4
051: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/operation/builder/SimilarTransformBuilder.java $
052: * @version $Id: SimilarTransformBuilder.java 24925 2007-03-27 20:12:08Z jgarnett $
053: * @author Jan Jezek
054: */
055: public class SimilarTransformBuilder extends ProjectiveTransformBuilder {
056: /**
057: * Creates SimilarTransformBuilder for the set of properties. The {@linkplain java.util.List List} of {@linkplain
058: * org.geotools.referencing.operation.builder.MappedPosition MappedPosition} is expected.
059: *
060: * @param vectors list of {@linkplain
061: * org.geotools.referencing.operation.builder.MappedPosition MappedPosition}
062: */
063: public SimilarTransformBuilder(List vectors)
064: throws MismatchedSizeException,
065: MismatchedDimensionException,
066: MismatchedReferenceSystemException {
067: super .setMappedPositions(vectors);
068: }
069:
070: protected void fillAMatrix() {
071: super .A = new GeneralMatrix(2 * getSourcePoints().length, 4);
072:
073: int numRow = getSourcePoints().length * 2;
074:
075: // Creates X matrix
076: for (int j = 0; j < (numRow / 2); j++) {
077: A.setRow(j, new double[] {
078: getSourcePoints()[j].getCoordinates()[0],
079: -getSourcePoints()[j].getCoordinates()[1], 1, 0 });
080: }
081:
082: for (int j = numRow / 2; j < numRow; j++) {
083: A.setRow(j, new double[] {
084: getSourcePoints()[j - (numRow / 2)]
085: .getCoordinates()[1],
086: getSourcePoints()[j - (numRow / 2)]
087: .getCoordinates()[0], 0, 1 });
088: }
089: }
090:
091: /**
092: * Returns the minimum number of points required by this builder,
093: * which is 2.
094: *
095: * @return Returns the minimum number of points required by this builder,
096: * which is 2.
097: */
098: public int getMinimumPointCount() {
099: return 2;
100: }
101:
102: /**
103: * Returns the matrix for Projective transformation setup as
104: * Affine. The M matrix looks like this:
105: * <pre>
106: * [ a -b Tx ]
107: * [ b a Ty ]
108: * [ 0 0 1 ]
109: * </pre>
110: *
111: * @return Matrix M.
112: */
113: protected GeneralMatrix getProjectiveMatrix() {
114: GeneralMatrix M = new GeneralMatrix(3, 3);
115: double[] param = calculateLSM();
116: double[] m0 = { param[0], -param[1], param[2] };
117: double[] m1 = { param[1], param[0], param[3] };
118: double[] m2 = { 0, 0, 1 };
119: M.setRow(0, m0);
120: M.setRow(1, m1);
121: M.setRow(2, m2);
122:
123: return M;
124: }
125: }
|