/*
* Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package ucar.unidata.geoloc;
import org.junit.Assert;
import org.junit.Test;
import ucar.unidata.geoloc.projection.*;
import ucar.unidata.geoloc.projection.proj4.CylindricalEqualAreaProjection;
import ucar.unidata.geoloc.projection.proj4.EquidistantAzimuthalProjection;
import ucar.unidata.geoloc.projection.sat.MSGnavigation;
import ucar.unidata.geoloc.projection.proj4.AlbersEqualAreaEllipse;
import ucar.unidata.geoloc.projection.proj4.LambertConformalConicEllipse;
/**
* test methods projections have in common
*
* @author John Caron
*/
public class TestProjections {
boolean show = false;
int NTRIALS = 10000;
double tolerence = 5.0e-4;
private LatLonPoint doOne(ProjectionImpl proj, double lat, double lon, boolean show) {
LatLonPointImpl startL = new LatLonPointImpl(lat, lon);
ProjectionPoint p = proj.latLonToProj(startL);
if (Double.isNaN(p.getX()) || Double.isNaN(p.getY())) return LatLonPointImmutable.INVALID;
if (Double.isInfinite(p.getX()) || Double.isInfinite(p.getY())) return LatLonPointImmutable.INVALID;
LatLonPointImpl endL = (LatLonPointImpl) proj.projToLatLon(p);
if (show) {
System.out.println("start = " + startL.toString(8));
System.out.println("projection point = " + p.toString());
System.out.println("end = " + endL.toString(8));
}
return endL;
}
@Test
// java.lang.AssertionError: .072111263S 165.00490E expected:<-0.07211126381547306> but was:<39.99999999999999>
public void testTMproblem() {
double lat = -.072111263;
double lon = 165.00490;
LatLonPoint endL = doOne( new TransverseMercator(), lat, lon, true);
if (endL.equals(LatLonPointImmutable.INVALID)) return;
Assert.assertEquals(lat, endL.getLatitude(), tolerence);
Assert.assertEquals(lon, endL.getLongitude(), tolerence);
}
private void testProjection(ProjectionImpl proj) {
java.util.Random r = new java.util.Random((long) this.hashCode());
LatLonPointImpl startL = new LatLonPointImpl();
int countT1 = 0;
for (int i = 0; i < NTRIALS; i++) {
startL.setLatitude(180.0 * (r.nextDouble() - .5)); // random latlon point
startL.setLongitude(360.0 * (r.nextDouble() - .5));
ProjectionPoint p = proj.latLonToProj(startL);
if (Double.isNaN(p.getX()) || Double.isNaN(p.getY())) continue;
LatLonPoint endL = proj.projToLatLon(p);
if (Double.isNaN(endL.getLatitude()) ||
Double.isNaN(endL.getLongitude()) ||
endL.equals(LatLonPointImmutable.INVALID)) continue;
Assert.assertEquals(startL.toString(8), startL.getLatitude(), endL.getLatitude(), 1.0e-3);
Assert.assertEquals(startL.toString(8), startL.getLongitude(), endL.getLongitude(), 1.0e-3);
countT1++;
}
int countT2 = 0;
ProjectionPointImpl startP = new ProjectionPointImpl();
for (int i = 0; i < NTRIALS; i++) {
startP.setLocation(10000.0 * (r.nextDouble() - .5), // random proj point
10000.0 * (r.nextDouble() - .5));
LatLonPoint ll = proj.projToLatLon(startP);
if (Double.isNaN(ll.getLatitude()) || Double.isNaN(ll.getLongitude())) continue;
ProjectionPoint endP = proj.latLonToProj(ll);
if (Double.isNaN(endP.getX()) || Double.isNaN(endP.getY())) continue;
Assert.assertEquals(startP.toString(), startP.getX(), endP.getX(), tolerence);
Assert.assertEquals(startP.toString(), startP.getY(), endP.getY(), tolerence);
countT2++;
}
if (show)
System.out.printf("Tested %d, %d pts for projection %s %n", countT1,
countT2, proj.getClassName());
}
// must have lon within +/- lonMax, lat within +/- latMax
public void testProjectionLonMax(ProjectionImpl proj, double lonMax, double latMax) {
java.util.Random r = new java.util.Random((long) this.hashCode());
LatLonPointImpl startL = new LatLonPointImpl();
double minx = Double.MAX_VALUE;
double maxx = -Double.MAX_VALUE;
double miny = Double.MAX_VALUE;
double maxy = -Double.MAX_VALUE;
for (int i = 0; i < NTRIALS; i++) {
startL.setLatitude(latMax * (2 * r.nextDouble() - 1)); // random latlon point
startL.setLongitude(lonMax * (2 * r.nextDouble() - 1));
ProjectionPoint p = proj.latLonToProj(startL);
LatLonPoint endL = proj.projToLatLon(p);
if (show) {
System.out.println("startL = " + startL);
System.out.println("inter = " + p);
System.out.println("endL = " + endL);
}
Assert.assertEquals(startL.toString(8), startL.getLatitude(), endL.getLatitude(), tolerence);
Assert.assertEquals(startL.toString(8), startL.getLongitude(), endL.getLongitude(), tolerence);
minx = Math.min(minx, p.getX());
maxx = Math.max(maxx, p.getX());
miny = Math.min(miny, p.getY());
maxy = Math.max(maxy, p.getY());
}
double rangex = maxx - minx;
double rangey = maxy - miny;
if (show) {
System.out.printf("rangex = (%f,%f) %n", minx, maxx);
System.out.printf("rangey = (%f,%f) %n", miny, maxy);
}
startL.setLatitude(latMax / 2);
startL.setLongitude(lonMax / 2);
ProjectionPointImpl base = new ProjectionPointImpl();
proj.latLonToProj(startL, base);
ProjectionPointImpl startP = new ProjectionPointImpl();
for (int i = 0; i < NTRIALS; i++) {
double x = minx + rangex * r.nextDouble();
double y = miny + rangey * r.nextDouble();
startP.setLocation(x, y);
try {
LatLonPoint ll = proj.projToLatLon(startP);
ProjectionPoint endP = proj.latLonToProj(ll);
if (show) {
System.out.println("start = " + startP);
System.out.println("interL = " + ll);
System.out.println("end = " + endP);
}
Assert.assertEquals(startP.toString(), startP.getX(), endP.getX(), tolerence);
Assert.assertEquals(startP.toString(), startP.getY(), endP.getY(), tolerence);
} catch (IllegalArgumentException e) {
System.out.printf("IllegalArgumentException=%s%n", e.getMessage());
continue;
}
}
if (show)
System.out.println("Tested " + NTRIALS + " pts for projection " + proj
.getClassName());
}
// must have x within +/- xMax, y within +/- yMax
public void testProjectionProjMax(ProjectionImpl proj, double xMax,
double yMax) {
java.util.Random r = new java.util.Random((long) this.hashCode());
ProjectionPointImpl startP = new ProjectionPointImpl();
for (int i = 0; i < NTRIALS; i++) {
double x = xMax * (2 * r.nextDouble() - 1);
double y = yMax * (2 * r.nextDouble() - 1);
startP.setLocation(x, y);
try {
LatLonPoint ll = proj.projToLatLon(startP);
ProjectionPoint endP = proj.latLonToProj(ll);
if (show) {
System.out.println("start = " + startP);
System.out.println("interL = " + ll);
System.out.println("end = " + endP);
}
Assert.assertEquals(startP.toString(), startP.getX(), endP.getX(), tolerence);
Assert.assertEquals(startP.toString(), startP.getY(), endP.getY(), tolerence);
} catch (IllegalArgumentException e) {
System.out.printf("IllegalArgumentException=%s%n", e.getMessage());
continue;
}
}
if (show) System.out.println("Tested " + NTRIALS + " pts for projection " + proj.getClassName());
}
@Test
public void testLC() {
testProjection(new LambertConformal());
LambertConformal lc = new LambertConformal();
LambertConformal lc2 = (LambertConformal) lc.constructCopy();
assert lc.equals(lc2);
}
@Test
public void testLCseam() {
// test seam crossing
LambertConformal lc = new LambertConformal(40.0, 180.0, 20.0, 60.0);
ProjectionPointImpl p1 = (ProjectionPointImpl) lc.latLonToProj(new LatLonPointImpl(0.0, -1.0), new ProjectionPointImpl());
ProjectionPointImpl p2 = (ProjectionPointImpl) lc.latLonToProj(new LatLonPointImpl(0.0, 1.0), new ProjectionPointImpl());
if (show) {
System.out.printf(" p1= x=%f y=%f%n", p1.getX(), p1.getY());
System.out.printf(" p2= x=%f y=%f%n", p2.getX(), p2.getY());
}
assert lc.crossSeam(p1, p2);
}
@Test
public void testTM() {
testProjection(new TransverseMercator());
TransverseMercator p = new TransverseMercator();
TransverseMercator p2 = (TransverseMercator) p.constructCopy();
assert p.equals(p2);
}
@Test
public void testStereo() {
testProjection(new Stereographic());
Stereographic p = new Stereographic();
Stereographic p2 = (Stereographic) p.constructCopy();
assert p.equals(p2);
}
@Test
public void testLA() {
testProjection(new LambertAzimuthalEqualArea());
LambertAzimuthalEqualArea p = new LambertAzimuthalEqualArea();
LambertAzimuthalEqualArea p2 = (LambertAzimuthalEqualArea) p.constructCopy();
assert p.equals(p2);
}
@Test
public void testOrtho() {
testProjectionLonMax(new Orthographic(), 10, 10);
Orthographic p = new Orthographic();
Orthographic p2 = (Orthographic) p.constructCopy();
assert p.equals(p2);
}
@Test
public void testAEA() {
testProjection(new AlbersEqualArea());
AlbersEqualArea p = new AlbersEqualArea();
AlbersEqualArea p2 = (AlbersEqualArea) p.constructCopy();
assert p.equals(p2);
}
@Test
public void testCEA() {
testProjection(new CylindricalEqualAreaProjection());
CylindricalEqualAreaProjection p = new CylindricalEqualAreaProjection();
CylindricalEqualAreaProjection p2 = (CylindricalEqualAreaProjection) p.constructCopy();
assert p.equals(p2);
}
@Test
public void testEAP() {
testProjection(new EquidistantAzimuthalProjection());
EquidistantAzimuthalProjection p = new EquidistantAzimuthalProjection();
EquidistantAzimuthalProjection p2 = (EquidistantAzimuthalProjection) p.constructCopy();
assert p.equals(p2);
}
public void utestAEAE() {
testProjectionLonMax(new AlbersEqualAreaEllipse(), 180, 80);
AlbersEqualAreaEllipse p = new AlbersEqualAreaEllipse();
AlbersEqualAreaEllipse p2 = (AlbersEqualAreaEllipse) p.constructCopy();
assert p.equals(p2);
}
public void utestLCCE() {
testProjectionLonMax(new LambertConformalConicEllipse(), 360, 80);
LambertConformalConicEllipse p = new LambertConformalConicEllipse();
LambertConformalConicEllipse p2 = (LambertConformalConicEllipse) p.constructCopy();
assert p.equals(p2);
}
@Test
public void testFlatEarth() {
testProjectionProjMax(new FlatEarth(), 5000, 5000);
FlatEarth p = new FlatEarth();
FlatEarth p2 = (FlatEarth) p.constructCopy();
assert p.equals(p2);
}
@Test
public void testMercator() {
testProjection(new Mercator());
Mercator p = new Mercator();
Mercator p2 = (Mercator) p.constructCopy();
assert p.equals(p2);
}
private void showProjVal(ProjectionImpl proj, double lat, double lon) {
LatLonPointImpl startL = new LatLonPointImpl(lat, lon);
ProjectionPoint p = proj.latLonToProj(startL);
if (show)
System.out.printf("lat,lon= (%f, %f) x, y= (%f, %f) %n", lat, lon,
p.getX(), p.getY());
}
@Test
public void testMSG() {
doOne(new MSGnavigation(), 60, 60, true);
testProjection(new MSGnavigation());
MSGnavigation m = new MSGnavigation();
showProjVal(m, 0, 0);
showProjVal(m, 60, 0);
showProjVal(m, -60, 0);
showProjVal(m, 0, 60);
showProjVal(m, 0, -60);
}
@Test
public void testRotatedPole() {
testProjectionLonMax(new RotatedPole(37, 177), 360, 88);
RotatedPole p = new RotatedPole();
RotatedPole p2 = (RotatedPole) p.constructCopy();
assert p.equals(p2);
}
/*
grid_south_pole_latitude = -30.000001907348633
grid_south_pole_longitude = -15.000000953674316
grid_south_pole_angle = 0.0 */
@Test
public void testRotatedLatLon() {
// public RotatedLatLon(double southPoleLat, double southPoleLon, double southPoleAngle) {
testProjectionLonMax(new RotatedLatLon(-30, -15, 0), 360, 88);
RotatedLatLon p = new RotatedLatLon();
RotatedLatLon p2 = (RotatedLatLon) p.constructCopy();
assert p.equals(p2);
}
@Test
public void testSinusoidal() {
doOne(new Sinusoidal(0, 0, 0, 6371.007), 20, 40, true);
testProjection(new Sinusoidal(0, 0, 0, 6371.007));
Sinusoidal p = new Sinusoidal();
Sinusoidal p2 = (Sinusoidal) p.constructCopy();
assert p.equals(p2);
}
// UTM failing - no not use
@Test
public void testUTM() {
// The central meridian = (zone * 6 - 183) degrees, where zone in [1,60].
// zone = (lon + 183)/6
// 33.75N 15.25E end = 90.0N 143.4W
// doOne(new UtmProjection(10, true), 33.75, -122);
testProjectionUTM(-12.89, .07996);
testProjectionUTM(NTRIALS);
UtmProjection p = new UtmProjection();
UtmProjection p2 = (UtmProjection) p.constructCopy();
assert p.equals(p2); // */
}
private void testProjectionUTM(double lat, double lon) {
LatLonPointImpl startL = new LatLonPointImpl();
startL.setLatitude(lat);
startL.setLongitude(lon);
int zone = (int) ((lon + 183) / 6);
UtmProjection proj = new UtmProjection(zone, lat >= 0.0);
ProjectionPoint p = proj.latLonToProj(startL);
LatLonPoint endL = proj.projToLatLon(p);
if (show) {
System.out.println("startL = " + startL);
System.out.println("inter = " + p);
System.out.println("endL = " + endL);
}
Assert.assertEquals(startL.toString(8), startL.getLatitude(), endL.getLatitude(), 1.3e-4);
Assert.assertEquals(startL.toString(8), startL.getLongitude(), endL.getLongitude(), 1.3e-4);
}
private void testProjectionUTM(int n) {
java.util.Random r = new java.util.Random((long) this.hashCode());
LatLonPointImpl startL = new LatLonPointImpl();
for (int i = 0; i < n; i++) {
startL.setLatitude(180.0 * (r.nextDouble() - .5)); // random latlon point
startL.setLongitude(360.0 * (r.nextDouble() - .5));
double lat = startL.getLatitude();
double lon = startL.getLongitude();
int zone = (int) ((lon + 183) / 6);
UtmProjection proj = new UtmProjection(zone, lat >= 0.0);
ProjectionPoint p = proj.latLonToProj(startL);
LatLonPoint endL = proj.projToLatLon(p);
if (show) {
System.out.println("startL = " + startL);
System.out.println("inter = " + p);
System.out.println("endL = " + endL);
}
Assert.assertEquals(startL.toString(8), startL.getLatitude(), endL.getLatitude(), 1.0e-4);
Assert.assertEquals(startL.toString(8), startL.getLongitude(), endL.getLongitude(), .02);
}
/* ProjectionPointImpl startP = new ProjectionPointImpl();
for (int i = 0; i < NTRIALS; i++) {
startP.setLocation(10000.0 * (r.nextDouble() - .5), // random proj point
10000.0 * (r.nextDouble() - .5));
double lon = startL.getLongitude();
int zone = (int) ((lon + 183)/6);
UtmProjection proj = new UtmProjection(zone, lon >= 0.0);
LatLonPoint ll = proj.projToLatLon(startP);
ProjectionPoint endP = proj.latLonToProj(ll);
assert (TestAll.closeEnough(startP.getX(), endP.getX()));
assert (TestAll.closeEnough(startP.getY(), endP.getY()));
} */
if (show)
System.out.println("Tested " + n + " pts for UTM projection ");
}
public void utestVerticalPerspectiveView() {
testProjectionLonMax(new VerticalPerspectiveView(), 66, 60);
VerticalPerspectiveView p = new VerticalPerspectiveView();
VerticalPerspectiveView p2 = (VerticalPerspectiveView) p.constructCopy();
assert p.equals(p2);
}
}