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;
017:
018: // J2SE dependencies and extensions
019: import java.util.Collections;
020: import java.util.Map;
021: import javax.units.NonSI;
022:
023: // J2SE and JUnit dependencies
024: import javax.units.SI;
025: import junit.framework.Test;
026: import junit.framework.TestCase;
027: import junit.framework.TestSuite;
028:
029: // OpenGIS dependencies
030: import org.opengis.referencing.cs.*;
031: import org.opengis.referencing.crs.*;
032: import org.opengis.referencing.datum.*;
033: import org.opengis.referencing.operation.*;
034: import org.opengis.referencing.IdentifiedObject;
035: import org.opengis.referencing.FactoryException;
036: import org.opengis.parameter.ParameterValueGroup;
037:
038: // Geotools dependencies
039: import org.geotools.factory.Hints;
040: import org.geotools.referencing.ReferencingFactoryFinder;
041: import org.geotools.referencing.factory.ReferencingFactoryContainer;
042:
043: /**
044: * Tests of the {@code createProjectedCRS(...)} setting up the CRS with a 3D cartesian output for
045: * one test, and using a 2D + vertical CRS compound for the second test. This test constructs most
046: * objects using GeoAPI only (except for a few helper classes).
047: *
048: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/test/java/org/geotools/referencing/operation/Transform3DTest.java $
049: * @version $Id: Transform3DTest.java 27848 2007-11-12 13:10:32Z desruisseaux $
050: * @author Justin Couch
051: * @author Martin Desruisseaux
052: */
053: public final class Transform3DTest extends TestCase {
054: /**
055: * Run the suite from the command line.
056: */
057: public static void main(String[] args) {
058: org.geotools.util.logging.Logging.GEOTOOLS
059: .forceMonolineConsoleOutput();
060: junit.textui.TestRunner.run(suite());
061: }
062:
063: /**
064: * Returns the test suite.
065: */
066: public static Test suite() {
067: return new TestSuite(Transform3DTest.class);
068: }
069:
070: /**
071: * Construct a test case.
072: */
073: public Transform3DTest(String testName) {
074: super (testName);
075: }
076:
077: /**
078: * Convenience method returning a set of properties for a CRS with the specified name.
079: */
080: private static Map name(final String name) {
081: return Collections
082: .singletonMap(IdentifiedObject.NAME_KEY, name);
083: }
084:
085: /**
086: * Tests a 3D projected to geocentric transform.
087: */
088: public void testProjectedToGeocentric() throws FactoryException,
089: TransformException {
090: // ----------------------------------------------------------
091: // Gets factories to be used for all object creations
092: // ----------------------------------------------------------
093: final Hints hints = new Hints(null);
094: final CSFactory csFactory = ReferencingFactoryFinder
095: .getCSFactory(hints);
096: final CRSFactory crsFactory = ReferencingFactoryFinder
097: .getCRSFactory(hints);
098: final DatumFactory datumFactory = ReferencingFactoryFinder
099: .getDatumFactory(hints);
100: final MathTransformFactory mtFactory = ReferencingFactoryFinder
101: .getMathTransformFactory(hints);
102: final CoordinateOperationFactory opFactory = ReferencingFactoryFinder
103: .getCoordinateOperationFactory(hints);
104: final ReferencingFactoryContainer helper;
105:
106: hints.clear();
107: hints.put(Hints.DATUM_FACTORY, datumFactory);
108: hints.put(Hints.CS_FACTORY, csFactory);
109: hints.put(Hints.CRS_FACTORY, crsFactory);
110: hints.put(Hints.MATH_TRANSFORM_FACTORY, mtFactory);
111: helper = new ReferencingFactoryContainer(hints);
112:
113: // ----------------------------------------------------------
114: // Creates datum
115: // ----------------------------------------------------------
116: final PrimeMeridian greenwichMeridian = datumFactory
117: .createPrimeMeridian(name("Greenwich Meridian"), 0,
118: NonSI.DEGREE_ANGLE);
119: final Ellipsoid wgs84Ellipsoid = datumFactory
120: .createFlattenedSphere(name("WGS84 Ellipsoid"),
121: 6378137, 298.257223563, SI.METER);
122: final GeodeticDatum wgs84 = datumFactory.createGeodeticDatum(
123: name("WGS84 Datum"), wgs84Ellipsoid, greenwichMeridian);
124: final VerticalDatum wgs84_height = datumFactory
125: .createVerticalDatum(name("WGS84 Ellispoidal height"),
126: VerticalDatumType.ELLIPSOIDAL);
127:
128: // ----------------------------------------------------------
129: // Creates non-standard (in geodesy) geocentric axis
130: // ----------------------------------------------------------
131: final CoordinateSystemAxis x_axis = csFactory
132: .createCoordinateSystemAxis(name("X"), "X",
133: AxisDirection.OTHER, SI.METER);
134: final CoordinateSystemAxis y_axis = csFactory
135: .createCoordinateSystemAxis(name("Y"), "Y",
136: AxisDirection.WEST, SI.METER);
137: final CoordinateSystemAxis z_axis = csFactory
138: .createCoordinateSystemAxis(name("Z"), "Z",
139: AxisDirection.NORTH, SI.METER);
140:
141: // ----------------------------------------------------------
142: // Creates target CRS
143: // ----------------------------------------------------------
144: final CartesianCS world_cs = csFactory.createCartesianCS(
145: name("Rendered Cartesian CS"), x_axis, z_axis, y_axis);
146: final GeocentricCRS output_crs = crsFactory
147: .createGeocentricCRS(name("Output Cartesian CRS"),
148: wgs84, world_cs);
149:
150: // ----------------------------------------------------------
151: // Creates geographic and projected axis for source CRS
152: // ----------------------------------------------------------
153: final CoordinateSystemAxis latitude_axis = csFactory
154: .createCoordinateSystemAxis(name("Geodetic Latitude"),
155: "lat", AxisDirection.NORTH, NonSI.DEGREE_ANGLE);
156: final CoordinateSystemAxis longitude_axis = csFactory
157: .createCoordinateSystemAxis(name("Geodetic Longitude"),
158: "lon", AxisDirection.EAST, NonSI.DEGREE_ANGLE);
159: final CoordinateSystemAxis northing_axis = csFactory
160: .createCoordinateSystemAxis(name("Northing"), "N",
161: AxisDirection.NORTH, SI.METER);
162: final CoordinateSystemAxis easting_axis = csFactory
163: .createCoordinateSystemAxis(name("Easting"), "E",
164: AxisDirection.EAST, SI.METER);
165: final CoordinateSystemAxis height_axis = csFactory
166: .createCoordinateSystemAxis(name("Ellipsoidal height"),
167: "Up", AxisDirection.UP, SI.METER);
168:
169: // ----------------------------------------------------------
170: // Creates the geographic CRS
171: // ----------------------------------------------------------
172: final EllipsoidalCS ellipsoidal_2d_cs = csFactory
173: .createEllipsoidalCS(name("2D ellipsoidal"),
174: longitude_axis, latitude_axis);
175: final EllipsoidalCS ellipsoidal_3d_cs = csFactory
176: .createEllipsoidalCS(name("3D ellipsoidal"),
177: longitude_axis, latitude_axis, height_axis);
178: final GeographicCRS geographic_2d_crs = crsFactory
179: .createGeographicCRS(name("2D geographic CRS"), wgs84,
180: ellipsoidal_2d_cs);
181: final GeographicCRS geographic_3d_crs = crsFactory
182: .createGeographicCRS(name("3D geographic CRS"), wgs84,
183: ellipsoidal_3d_cs);
184:
185: // ----------------------------------------------------------
186: // Creates various coordinate systems for projected CRS
187: // ----------------------------------------------------------
188: final CartesianCS utm_cartesian_3d_cs = csFactory
189: .createCartesianCS(name("UTM 3D Cartesian CS"),
190: northing_axis, easting_axis, height_axis);
191: final CartesianCS utm_cartesian_2d_cs = csFactory
192: .createCartesianCS(name("UTM 2D Cartesian CS"),
193: northing_axis, easting_axis);
194: final VerticalCS utm_height_cs = csFactory.createVerticalCS(
195: name("Height CS"), height_axis);
196: final VerticalCRS height_crs = crsFactory.createVerticalCRS(
197: name("WGS84 Height CRS"), wgs84_height, utm_height_cs);
198:
199: // ----------------------------------------------------------
200: // Set the projection for UTM zone 12
201: // ----------------------------------------------------------
202: final int zone_num = 12;
203: final ParameterValueGroup parameters = mtFactory
204: .getDefaultParameters("Transverse_Mercator");
205: parameters.parameter("central_meridian").setValue(
206: -180 + zone_num * 6 - 3);
207: parameters.parameter("latitude_of_origin").setValue(0.0);
208: parameters.parameter("scale_factor").setValue(0.9996);
209: parameters.parameter("false_easting").setValue(500000.0);
210: parameters.parameter("false_northing").setValue(0.0);
211:
212: // ----------------------------------------------------------
213: // From here we create a 2D projected system and combine
214: // it with a height-only CRS to give it a full 3D transform
215: // ----------------------------------------------------------
216: final ProjectedCRS proj_2d = helper.createProjectedCRS(
217: name("WGS 84 / UTM Zone 12/ 2D"), geographic_2d_crs,
218: null, parameters, utm_cartesian_2d_cs);
219: final CompoundCRS compound_3d = crsFactory
220: .createCompoundCRS(
221: name("3D Compound WGS 84 / UTM Zone 12"),
222: new CoordinateReferenceSystem[] { proj_2d,
223: height_crs });
224: final double[] out1 = checkTransformation(opFactory
225: .createOperation(compound_3d, output_crs));
226:
227: // ----------------------------------------------------------
228: // From here we create a 3D projected system directly
229: // ----------------------------------------------------------
230: final ProjectedCRS proj_3d = helper.createProjectedCRS(
231: name("WGS 84 / UTM Zone 12/ 3D"), geographic_3d_crs,
232: null, parameters, utm_cartesian_3d_cs);
233: final double[] out2 = checkTransformation(opFactory
234: .createOperation(proj_3d, output_crs));
235:
236: // ----------------------------------------------------------
237: // The two set of transformed coordinates should be the same
238: // ----------------------------------------------------------
239: final int upper = out1.length;
240: assertEquals(upper, out2.length);
241: for (int i = 0; i < upper; i++) {
242: assertEquals(out1[i], out2[i], 1E-5);
243: }
244: }
245:
246: /**
247: * Tries to transforms some points using the specified operation.
248: * This method transforms two points from the projected CRS to the geocentric CRS.
249: * The first point is on the ellipsoid, and the second point is 10 km above the ellipsoid.
250: * After transformation to geocentric CRS using a cartesian CS, the two points should still
251: * ten kilometers apart each others.
252: *
253: * @return Transformed coordinates.
254: */
255: private static double[] checkTransformation(
256: final CoordinateOperation operation)
257: throws TransformException {
258: assertTrue(operation.getSourceCRS() instanceof ProjectedCRS);
259: assertTrue(operation.getTargetCRS() instanceof GeocentricCRS);
260: assertTrue(operation.getTargetCRS().getCoordinateSystem() instanceof CartesianCS);
261:
262: final MathTransform mt = operation.getMathTransform();
263:
264: // Now a couple of transforms to show it working or not working...
265: final double[] input = { 4145173, 572227, 0 };
266: final double[] output = new double[input.length * 2];
267:
268: mt.transform(input, 0, output, 0, 1);
269:
270: input[2] = 10000;
271: mt.transform(input, 0, output, input.length, 1);
272:
273: double distance = 0;
274: for (int i = 0; i < input.length; i++) {
275: final double delta = output[i] - output[input.length + i];
276: distance += delta * delta;
277: }
278: distance = Math.sqrt(distance);
279: assertEquals("Distance", 10000, distance, 1E-5);
280:
281: return output;
282: }
283: }
|