/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2005-2013, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.referencing.operation.projection;
import static org.geotools.referencing.operation.projection.MapProjection.AbstractProvider.SEMI_MAJOR;
import static org.geotools.referencing.operation.projection.MapProjection.AbstractProvider.SEMI_MINOR;
import static org.junit.Assert.assertEquals;
import java.awt.geom.Point2D;
import org.geotools.referencing.ReferencingFactoryFinder;
import org.junit.Test;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.operation.MathTransformFactory;
import org.opengis.referencing.operation.TransformException;
/**
* Tests the {@link MapProjection} implementation.
*
* @source $URL$
* @version $Id$
* @author Frank Warmerdam
*/
public final class MapProjectionTest {
/**
* Make a simple spherical Mercator (Google Mercator) CRS. We just use this as
* a simple example of a MapProjection since that class is abstract.
*/
private static MapProjection createGoogleMercator() throws FactoryException {
MathTransformFactory mtFactory = ReferencingFactoryFinder.getMathTransformFactory(null);
final ParameterValueGroup parameters = mtFactory.getDefaultParameters("Mercator_1SP");
parameters.parameter(SEMI_MAJOR.getName().getCode()).setValue(6378137.0);
parameters.parameter(SEMI_MINOR.getName().getCode()).setValue(6378137.0);
return (MapProjection) mtFactory.createParameterizedTransform(parameters);
}
/**
* Sets of geographic coordinates to project.
*/
private static final double[] GEOGRAPHIC = {
47.0, -14.0,
48.38824840214492, -14.967538330290973,
};
/**
* Set of projected coordinates.
*/
private static final double[] PROJECTED = {
5232016.067283858, -1574216.548161465,
5386555.1725052055, -1685459.3322153771,
};
/**
* Test we can round trip well behaved points, and that checkReciprocal() works properly.
*/
@Test
public void testCheckReciprocal() throws TransformException, FactoryException {
final double[] dst = new double[PROJECTED.length];
MapProjection mt = createGoogleMercator();
mt.transform(GEOGRAPHIC, 0, dst, 0, PROJECTED.length/2);
for (int i=0; i<PROJECTED.length; i++) {
assertEquals(PROJECTED[i], dst[i], 0.1); // 10 cm precision
}
for (int i=0; i < PROJECTED.length/2; i++) {
Point2D src = new Point2D.Double(GEOGRAPHIC[i*2+0], GEOGRAPHIC[i*2+1]);
Point2D target = new Point2D.Double(PROJECTED[i*2+0], PROJECTED[i*2+1]);
assertEquals(true, mt.checkReciprocal(src, target, false));
assertEquals(true, mt.checkReciprocal(target, src, true));
}
mt.inverse().transform(PROJECTED, 0, dst, 0, PROJECTED.length/2);
for (int i=0; i<GEOGRAPHIC.length; i++) {
assertEquals(GEOGRAPHIC[i], dst[i], 0.0001); // About 10 m precision
}
}
/**
* Test that orthodromicDistance() works well for small and large distances.
*/
@Test
public void testOrthodromicDistance() throws FactoryException {
MapProjection mt = createGoogleMercator();
// Test some large distances
assertEquals(111319.49079,
mt.orthodromicDistance(new Point2D.Double(0.0, 0.0),
new Point2D.Double(0.0, 1.0)), 0.001);
assertEquals(111319.49079,
mt.orthodromicDistance(new Point2D.Double(0.0, 0.0),
new Point2D.Double(1.0, 0.0)), 0.001);
assertEquals(111319.49079,
mt.orthodromicDistance(new Point2D.Double(0.0, 89.0),
new Point2D.Double(0.0, 90.0)), 0.001);
assertEquals(1942.76834,
mt.orthodromicDistance(new Point2D.Double(0.0, 89.0),
new Point2D.Double(1.0, 89.0)), 0.001);
assertEquals(10018754.17139,
mt.orthodromicDistance(new Point2D.Double(0.0, 0.0),
new Point2D.Double(0.0, 90.0)), 0.001);
// Test some small distances.
Point2D src = new Point2D.Double(48.38824840214492, -14.967538330290973);
assertEquals(0.0, mt.orthodromicDistance(src, src), 0.000000001);
Point2D target = new Point2D.Double(src.getX(), src.getY()+0.0000001);
assertEquals(0.011131948840096939, mt.orthodromicDistance(src, target), 1E-12);
Point2D target2 = new Point2D.Double(src.getX(), src.getY()+0.000000000001);
assertEquals(1.1117412E-7, mt.orthodromicDistance(src, target2), 1E-12);
}
}