001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-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; either
009: * version 2.1 of the License, or (at your option) any later version.
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.transform;
017:
018: // J2SE dependencies
019: import java.awt.Point;
020: import java.awt.Rectangle;
021: import java.awt.geom.Point2D;
022: import java.awt.geom.AffineTransform;
023: import java.util.Random;
024:
025: // JUnit dependencies
026: import junit.framework.Test;
027: import junit.framework.TestCase;
028: import junit.framework.TestSuite;
029:
030: // JAI dependencies
031: import javax.media.jai.Warp;
032: import javax.media.jai.WarpAffine;
033: import javax.media.jai.WarpCubic;
034: import javax.media.jai.WarpQuadratic;
035: import javax.media.jai.WarpPolynomial;
036:
037: // OpenGIS dependencies
038: import org.opengis.referencing.operation.TransformException;
039:
040: // Geotools dependencies
041: import org.geotools.resources.Utilities;
042: import org.geotools.referencing.operation.transform.AffineTransform2D;
043:
044: /**
045: * Tests the {@link WarpTransform2D} and {@link WarpAdapter} classes.
046: *
047: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/test/java/org/geotools/referencing/operation/transform/WarpTransformTest.java $
048: * @version $Id: WarpTransformTest.java 24576 2007-02-24 00:07:40Z desruisseaux $
049: * @author Martin Desruisseaux
050: */
051: public final class WarpTransformTest extends TestCase {
052: /**
053: * Width and height of a pseudo-image source image.
054: */
055: private static final int WIDTH = 1000, HEIGHT = 2000;
056:
057: /**
058: * Runs the tests with the textual test runner.
059: */
060: public static void main(String args[]) {
061: junit.textui.TestRunner.run(suite());
062: }
063:
064: /**
065: * Returns the test suite.
066: */
067: public static Test suite() {
068: return new TestSuite(WarpTransformTest.class);
069: }
070:
071: /**
072: * Constructs a test case with the given name.
073: */
074: public WarpTransformTest(final String name) {
075: super (name);
076: }
077:
078: /**
079: * Transforms in place a point. This is used for testing
080: * affine, quadratic and cubic warp from know formulas.
081: */
082: private static interface Formula {
083: String message();
084:
085: void transform(Point point);
086: }
087:
088: /**
089: * Constructs a warp and tests the transformations. Coefficients will be tested later
090: * (by the caller).
091: */
092: private static WarpPolynomial executeTest(final Formula formula,
093: final int degree, final float EPS)
094: throws TransformException {
095: /*
096: * Creates a set of points and transform them according the formula supplied in argument.
097: */
098: final Random random = new Random(-854734760285695284L);
099: final Point[] sources = new Point[100];
100: final Point[] dest = new Point[sources.length];
101: for (int i = 0; i < dest.length; i++) {
102: Point p;
103: sources[i] = p = new Point(random.nextInt(WIDTH), random
104: .nextInt(HEIGHT));
105: dest[i] = p = new Point(p);
106: formula.transform(p);
107: }
108: /*
109: * Gets the transform. We specify a bounding box which contains all points.
110: */
111: final Point ext = new Point(WIDTH, HEIGHT);
112: formula.transform(ext);
113: final WarpTransform2D transform = new WarpTransform2D(
114: new Rectangle(0, 0, WIDTH, HEIGHT), sources, 0,
115: new Rectangle(0, 0, ext.x, ext.y), dest, 0,
116: sources.length, degree);
117: final WarpTransform2D inverse = (WarpTransform2D) transform
118: .inverse();
119: assertNotNull("WKT formatting test", transform.toString());
120: /*
121: * Checks Warp properties.
122: */
123: final Warp warp = transform.getWarp();
124: assertTrue("Expected a polynomial warp but got "
125: + Utilities.getShortClassName(warp),
126: warp instanceof WarpPolynomial);
127: final WarpPolynomial poly = (WarpPolynomial) warp;
128: /*
129: * Compares transformations to the expected points.
130: */
131: for (int i = 0; i < sources.length; i++) {
132: final String message = formula.message() + " Point #" + i;
133: final Point source = sources[i];
134: final Point expected = dest[i];
135: final Point2D computed = new Point2D.Double(source.x,
136: source.y);
137: assertSame(message, computed, transform.transform(computed,
138: computed));
139: assertEquals(message, expected.x, computed.getX(), EPS
140: * expected.x);
141: assertEquals(message, expected.y, computed.getY(), EPS
142: * expected.y);
143: //
144: // Try using transform(float[], ...)
145: //
146: if (true) {
147: final float[] array = new float[] { source.x, source.y };
148: transform.transform(array, 0, array, 0, 1);
149: assertEquals(message, expected.x, array[0], EPS
150: * expected.x);
151: assertEquals(message, expected.y, array[1], EPS
152: * expected.y);
153: }
154: //
155: // Try using transform(double[], ...)
156: //
157: if (true) {
158: final double[] array = new double[] { source.x,
159: source.y };
160: transform.transform(array, 0, array, 0, 1);
161: assertEquals(message, expected.x, array[0], EPS
162: * expected.x);
163: assertEquals(message, expected.y, array[1], EPS
164: * expected.y);
165: }
166: //
167: // Tests inverse transform
168: //
169: if (degree == 1) {
170: computed.setLocation(expected.x, expected.y);
171: assertSame(message, computed, inverse.transform(
172: computed, computed));
173: assertEquals(message, source.x, computed.getX(), EPS
174: * expected.x);
175: assertEquals(message, source.y, computed.getY(), EPS
176: * expected.y);
177: }
178: }
179: return poly;
180: }
181:
182: /**
183: * Tests an affine warp.
184: */
185: public void testAffine() throws TransformException {
186: final int[] scalesX = { 1, 2, 3, 4, 5, 6, 2, 7, 3, 1, 8 };
187: final int[] scalesY = { 1, 2, 3, 4, 5, 6, 6, 2, 5, 9, 1 };
188: for (int i = 0; i < scalesX.length; i++) {
189: final int scaleX = scalesX[i];
190: final int scaleY = scalesY[i];
191: final WarpPolynomial warp = executeTest(new Formula() {
192: public String message() {
193: return "WarpAffine[" + scaleX + ',' + scaleY + ']';
194: }
195:
196: public void transform(final Point point) {
197: point.x *= scaleX;
198: point.y *= scaleY;
199: }
200: }, 1, 1E-5f);
201: assertTrue("Expected an affine warp but got "
202: + Utilities.getShortClassName(warp),
203: warp instanceof WarpAffine);
204: }
205: }
206:
207: /**
208: * Tests a quadratic warp.
209: */
210: public void testQuadratic() throws TransformException {
211: final int[] scalesX = { 1, 2, 3, 4, 5, 6, 2, 7, 3, 1, 8 };
212: final int[] scalesY = { 1, 2, 3, 4, 5, 6, 6, 2, 5, 9, 1 };
213: for (int i = 0; i < scalesX.length; i++) {
214: final int scaleX = scalesX[i];
215: final int scaleY = scalesY[i];
216: final WarpPolynomial warp = executeTest(new Formula() {
217: public String message() {
218: return "WarpQuadratic[" + scaleX + ',' + scaleY
219: + ']';
220: }
221:
222: public void transform(final Point point) {
223: point.x *= scaleX * point.x;
224: point.y *= scaleY;
225: }
226: }, 2, 1E-2f);
227: assertTrue("Expected a quatratic warp but got "
228: + Utilities.getShortClassName(warp),
229: warp instanceof WarpQuadratic);
230: }
231: }
232:
233: /**
234: * Tests the {@link WarpAdapter} class using an affine transform.
235: */
236: public void testAdapter() {
237: final AffineTransform atr = AffineTransform.getScaleInstance(
238: 0.25, 0.5);
239: atr.translate(4, 2);
240: final AffineTransform2D transform = new AffineTransform2D(atr);
241: final WarpAffine warp = new WarpAffine(atr);
242: final WarpAdapter adapter = new WarpAdapter("test", transform);
243: final Random random = new Random(-854734760285695284L);
244: for (int i = 0; i < 200; i++) {
245: Point2D source = new Point2D.Double(
246: random.nextDouble() * 100,
247: random.nextDouble() * 100);
248: Point2D expected = warp.mapDestPoint(source);
249: Point2D computed = adapter.mapDestPoint(source);
250: assertEquals("X", expected.getX(), computed.getX(), 1E-5);
251: assertEquals("Y", expected.getY(), computed.getY(), 1E-5);
252:
253: // Try inverse transform.
254: expected = warp.mapSourcePoint(source);
255: computed = adapter.mapSourcePoint(source);
256: assertEquals("X", expected.getX(), computed.getX(), 1E-5);
257: assertEquals("Y", expected.getY(), computed.getY(), 1E-5);
258:
259: // Try warpPoint
260: final float[] exp = warp.warpPoint((int) source.getX(),
261: (int) source.getY(), null);
262: final float[] com = adapter.warpPoint((int) source.getX(),
263: (int) source.getY(), null);
264: assertEquals("X", exp[0], com[0], 1E-5);
265: assertEquals("Y", exp[1], com[1], 1E-5);
266: }
267: }
268: }
|