001: /*
002: * Geotools2 - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2005, 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 junit.framework.Test;
019: import junit.framework.TestCase;
020: import junit.framework.TestSuite;
021: import org.geotools.geometry.DirectPosition2D;
022: import org.geotools.referencing.crs.DefaultEngineeringCRS;
023: import org.geotools.referencing.operation.builder.AffineTransformBuilder;
024: import org.geotools.referencing.operation.builder.MissingInfoException;
025: import org.geotools.referencing.operation.builder.ProjectiveTransformBuilder;
026: import org.geotools.referencing.operation.builder.RubberSheetBuilder;
027: import org.geotools.referencing.operation.builder.SimilarTransformBuilder;
028: import org.geotools.referencing.operation.builder.Quadrilateral;
029: import org.geotools.referencing.operation.builder.TriangulationException;
030: import org.geotools.referencing.operation.matrix.GeneralMatrix;
031: import org.opengis.referencing.FactoryException;
032: import org.opengis.referencing.crs.CoordinateReferenceSystem;
033: import org.opengis.referencing.operation.MathTransform;
034: import org.opengis.referencing.operation.TransformException;
035: import org.opengis.geometry.MismatchedDimensionException;
036: import java.util.ArrayList;
037: import java.util.List;
038: import java.util.Random;
039: import javax.vecmath.MismatchedSizeException;
040:
041: /**
042: * A test for the MathTransformBuilders.
043: *
044: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/test/java/org/geotools/referencing/operation/builder/MathTransformBuilderTest.java $
045: * @version $Id: MathTransformBuilderTest.java 28982 2008-01-28 16:27:33Z acuster $
046: * @author Jan Jezek
047: * @author Adrian Custer
048: */
049: public class MathTransformBuilderTest extends TestCase {
050: /**
051: * Run the suite from the command line.
052: *
053: * @param args
054: */
055: public static void main(String[] args) {
056: junit.textui.TestRunner.run(suite());
057: }
058:
059: /**
060: * Returns the test suite.
061: *
062: * @return DOCUMENT ME!
063: */
064: public static Test suite() {
065: return new TestSuite(MathTransformBuilderTest.class);
066: }
067:
068: /**
069: * Coordinates List generator.
070: *
071: * @param numberOfVertices count of generated points
072: * @param seed for random generating.
073: *
074: * @return points
075: */
076: private List generateCoords(int numberOfVertices, long seed) {
077: CoordinateReferenceSystem crs = DefaultEngineeringCRS.CARTESIAN_2D;
078:
079: return generateCoordsWithCRS(numberOfVertices, crs, seed, true);
080: }
081:
082: /**
083: * Coordinates List generator.
084: *
085: * @param numberOfVertices count of generated points
086: * @param seed for random generating.
087: * @param includeAccuracy set true to generate points with accuracy.
088: *
089: * @return points
090: */
091: private List generateCoords(int numberOfVertices, long seed,
092: boolean includeAccuracy) {
093: CoordinateReferenceSystem crs = DefaultEngineeringCRS.CARTESIAN_2D;
094:
095: return generateCoordsWithCRS(numberOfVertices, crs, seed,
096: includeAccuracy);
097: }
098:
099: /**
100: * Coordinates List generator.
101: *
102: * @param numberOfVertices count of generated points
103: * @param crs Coordinate Reference System of generated points
104: * @param seed seed for generate random numbers
105: * @param includeAccuracy set true to generate points with accuracy.
106: *
107: * @return points
108: */
109: private List generateCoordsWithCRS(int numberOfVertices,
110: CoordinateReferenceSystem crs, long seed,
111: boolean includeAccuracy) {
112: List vert = new ArrayList();
113:
114: Random randomCoord = new Random(seed);
115:
116: for (int i = 0; i < numberOfVertices; i++) {
117: double xs = randomCoord.nextDouble() * 1000;
118: double ys = randomCoord.nextDouble() * 1000;
119: double xd = randomCoord.nextDouble() * 1000;
120: double yd = randomCoord.nextDouble() * 1000;
121: MappedPosition p = new MappedPosition(new DirectPosition2D(
122: crs, xs, ys), new DirectPosition2D(crs, xd, yd));
123:
124: if (includeAccuracy) {
125: p.setAccuracy(randomCoord.nextDouble());
126: }
127:
128: vert.add(p);
129: }
130:
131: return vert;
132: }
133:
134: /**
135: * Test expected values against transformed values.
136: *
137: * @param mt mathTransform that will be tested
138: * @param pts MappedPositions of source and target values.
139: *
140: * @throws FactoryException
141: * @throws TransformException
142: */
143: private void transformTest(MathTransform mt, List pts)
144: throws FactoryException, TransformException {
145: double[] points = new double[pts.size() * 2];
146: double[] ptCalculated = new double[pts.size() * 2];
147:
148: for (int i = 0; i < pts.size(); i++) {
149: points[2 * i] = ((MappedPosition) pts.get(i)).getSource()
150: .getCoordinates()[0];
151: points[(2 * i) + 1] = ((MappedPosition) pts.get(i))
152: .getSource().getCoordinates()[1];
153: }
154:
155: mt.transform(points, 0, ptCalculated, 0, pts.size());
156:
157: for (int i = 0; i < pts.size(); i++) {
158: assertTrue((((MappedPosition) pts.get(i)).getTarget()
159: .getCoordinates()[0] - ptCalculated[2 * i]) < 0.001);
160: assertTrue((((MappedPosition) pts.get(i)).getTarget()
161: .getCoordinates()[1] - ptCalculated[(2 * i) + 1]) < 0.001);
162: }
163: }
164:
165: /**
166: * Test for {@linkplain RubberSheetBuilder RubberSheetBuilder}.
167: *
168: * @throws MismatchedSizeException
169: * @throws MismatchedDimensionException
170: * @throws FactoryException
171: * @throws TransformException
172: * @throws TriangulationException
173: */
174: public void testRubberBuilder() throws MismatchedSizeException,
175: MismatchedDimensionException, FactoryException,
176: TransformException, TriangulationException {
177: List pts = generateCoords(20, 8324);
178:
179: CoordinateReferenceSystem crs = DefaultEngineeringCRS.CARTESIAN_2D;
180:
181: List /*<DirectPosition>*/dpl = new ArrayList /*<DirectPosition>*/();
182: dpl.add(new DirectPosition2D(crs, 1000, 0));
183: dpl.add(new DirectPosition2D(crs, 0, 0));
184: dpl.add(new DirectPosition2D(crs, 0, 1000));
185: dpl.add(new DirectPosition2D(crs, 1000, 1000));
186: MathTransformBuilder ppc = new RubberSheetBuilder(pts, dpl);
187:
188: transformTest(ppc.getMathTransform(), pts);
189: assertTrue(ppc.getErrorStatistics().rms() < 0.00001);
190:
191: // Tests the formatting, but do not display to console for not polluting
192: // the output device. We just check that at least one axis title is
193: // there.
194: assertTrue(ppc.toString().indexOf(" x ") >= 0);
195: }
196:
197: /**
198: * Test for {@linkplain ProjectiveTransformBuilder ProjectiveTransformBuilder}.
199: *
200: * @throws MismatchedSizeException
201: * @throws MismatchedDimensionException
202: * @throws FactoryException
203: * @throws TransformException
204: */
205: public void testProjectiveBuilder() throws MismatchedSizeException,
206: MismatchedDimensionException, FactoryException,
207: TransformException {
208: List pts = generateCoords(4, 312243);
209:
210: MathTransformBuilder ppc = new ProjectiveTransformBuilder(pts);
211: transformTest(ppc.getMathTransform(), pts);
212:
213: assertTrue(ppc.getErrorStatistics().rms() < 0.0001);
214: }
215:
216: /**
217: * Test that all Matrixes are filled properly.
218: *
219: * @throws MismatchedSizeException
220: * @throws MismatchedDimensionException
221: * @throws FactoryException
222: * @throws TransformException
223: */
224: public void testLSMCalculation() throws MismatchedSizeException,
225: MismatchedDimensionException, FactoryException,
226: TransformException {
227: List pts = generateCoords(15, 3121123);
228: LSMTester buildTester = new LSMTester(pts);
229: buildTester.includeWeights(true);
230: buildTester.testLSM();
231: }
232:
233: /**
234: * Test for {@linkplain AffineTransformBuilder AffineTransformBuilder}.
235: * @throws MismatchedSizeException
236: * @throws MismatchedDimensionException
237: * @throws FactoryException
238: * @throws TransformException
239: */
240: public void testAffineBuilder() throws MismatchedSizeException,
241: MismatchedDimensionException, FactoryException,
242: TransformException {
243: List pts = generateCoords(3, 2345);
244: MathTransformBuilder ppc = new AffineTransformBuilder(pts);
245: transformTest(ppc.getMathTransform(), pts);
246: assertTrue(ppc.getErrorStatistics().rms() < 0.00001);
247: }
248:
249: /**
250: * Test for {@linkplain SimilarTransformBuilder SimilarTransformBuilder}.
251: * @throws MismatchedSizeException
252: * @throws MismatchedDimensionException
253: * @throws FactoryException
254: * @throws TransformException
255: */
256: public void testSimilarBuilder() throws MismatchedSizeException,
257: MismatchedDimensionException, FactoryException,
258: TransformException {
259: List pts = generateCoords(2, 24535);
260: MathTransformBuilder ppc = new SimilarTransformBuilder(pts);
261: transformTest(ppc.getMathTransform(), pts);
262: assertTrue(ppc.getErrorStatistics().rms() < 0.00001);
263: }
264:
265: /**
266: * Test for MismatchedSizeException.
267: * @throws TransformException
268: */
269: public void testMismatchedSizeException() throws TransformException {
270: // The exception should be thrown when the number of points is less than
271: // necessary
272: List pts = generateCoords(2, 2453655);
273:
274: try {
275: new AffineTransformBuilder(pts);
276: fail("Expected MismatchedSizeException");
277: } catch (MismatchedSizeException e) {
278: }
279: }
280:
281: /**
282: * Test for MissingInfoException.
283: * @throws FactoryException
284: */
285: public void testMissingInfoException() throws FactoryException {
286: // The exception should be thrown when the number of points is less than
287: // necessary
288: List pts = generateCoords(5, 2434765, false);
289:
290: try {
291: AffineTransformBuilder builder = new AffineTransformBuilder(
292: pts);
293: builder.includeWeights(true);
294: fail("Expected FactoryException");
295: } catch (MissingInfoException e) {
296: }
297: }
298:
299: /**
300: * Implements the method for testing the calculation of least
301: * square method. The main requirement of least square method is that
302: * A<sup>T<sup>PAx + A<sup>T<sup>PX = 0.
303: *
304: * @author jezekjas
305: *
306: */
307: class LSMTester extends ProjectiveTransformBuilder {
308: LSMTester(List pts) {
309: super (pts);
310: }
311:
312: public void testLSM() {
313: // fill Matrix by calculateLSM()
314: this .calculateLSM();
315:
316: GeneralMatrix AT = (GeneralMatrix) A.clone();
317: AT.transpose();
318:
319: GeneralMatrix ATP = new GeneralMatrix(AT.getNumRow(), P
320: .getNumCol());
321: GeneralMatrix ATPA = new GeneralMatrix(AT.getNumRow(), A
322: .getNumCol());
323: GeneralMatrix ATPX = new GeneralMatrix(AT.getNumRow(), 1);
324: GeneralMatrix x = new GeneralMatrix(A.getNumCol(), 1);
325: ATP.mul(AT, P); // ATP
326: ATPA.mul(ATP, A); // ATPA
327: ATPX.mul(ATP, X); // ATPX
328:
329: GeneralMatrix ATPAI = (GeneralMatrix) ATPA.clone();
330: ATPAI.invert();
331:
332: x.mul(ATPAI, ATPX);
333:
334: // assert the ATPAx + ATPX should be 0;.
335: x.mul(ATPA, x);
336: x.sub(ATPX);
337:
338: double[] tx = new double[x.getNumRow()];
339: x.getColumn(0, tx);
340:
341: for (int i = 0; i < tx.length; i++) {
342: assertTrue(tx[i] < 0.001);
343: }
344: }
345: }
346: }
|