/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2015, 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 org.geotools.geometry.DirectPosition2D;
import org.geotools.geometry.Envelope2D;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.junit.BeforeClass;
import org.junit.Test;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
public class GeostationarySatelliteTest {
public final static String sphericalGeosWKT =
"PROJCS[\"Geostationary_Satellite\"," +
" GEOGCS[\"Custom Geographic CS\"," +
" DATUM[\"Custom Datum\"," +
" SPHEROID[\"Sphere\",6367451.5, 0]]," +
" PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]," +
" PROJECTION[\"Geostationary_Satellite\"]," +
" PARAMETER[\"central_meridian\", -135]," +
" PARAMETER[\"satellite_height\",35832548.5]," +
" PARAMETER[\"false_easting\",0]," +
" PARAMETER[\"false_northing\",0]," +
" UNIT[\"meter\", 1]]";
public final static String ellipsoidalGeosWKT =
"PROJCS[\"Geostationary_Satellite\"," +
" GEOGCS[\"WGS 84\"," +
" DATUM[\"WGS_1984\"," +
" SPHEROID[\"WGS84\",6378137,298.257223563]]," +
" PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.01745329251994328]]," +
" PROJECTION[\"Geostationary_Satellite\"]," +
" PARAMETER[\"central_meridian\", -135]," +
" PARAMETER[\"satellite_height\",35785831.0]," +
" PARAMETER[\"false_easting\",0]," +
" PARAMETER[\"false_northing\",0]," +
" UNIT[\"meter\", 1]]";
static CoordinateReferenceSystem sphericalGeosCRS;
static MathTransform sphericalGeosToGeog;
static MathTransform geogToSphericalGeos;
static CoordinateReferenceSystem ellipsoidalGeosCRS;
static MathTransform ellipsoidalGeosToGeog;
static MathTransform geogToEllipsoidalGeos;
@BeforeClass
public static void setupClass() throws FactoryException, TransformException {
sphericalGeosCRS = CRS.parseWKT(sphericalGeosWKT);
sphericalGeosToGeog = CRS.findMathTransform(sphericalGeosCRS, CRS.getProjectedCRS(sphericalGeosCRS).getBaseCRS(), true);
geogToSphericalGeos = sphericalGeosToGeog.inverse();
ellipsoidalGeosCRS = CRS.parseWKT(ellipsoidalGeosWKT);
ellipsoidalGeosToGeog = CRS.findMathTransform(ellipsoidalGeosCRS, CRS.getProjectedCRS(ellipsoidalGeosCRS).getBaseCRS(), true);
geogToEllipsoidalGeos = ellipsoidalGeosToGeog.inverse();
}
@Test
public void testSpheroidalWKTParameters() {
ParameterValueGroup parameters = CRS.getMapProjection(sphericalGeosCRS).getParameterValues();
double satelliteHeight = parameters.parameter("satellite_height").doubleValue();
assertThat(satelliteHeight, is(35832548.5));
}
@Test
public void testEllipsoidalWKTParameters() {
ParameterValueGroup parameters = CRS.getMapProjection(ellipsoidalGeosCRS).getParameterValues();
double satelliteHeight = parameters.parameter("satellite_height").doubleValue();
assertThat(satelliteHeight, is(35785831.0));
}
@Test
public void testIsGeostationaryCRS() {
assertThat(GeostationarySatellite.isGeostationaryCRS(sphericalGeosCRS), is(true));
assertThat(GeostationarySatellite.isGeostationaryCRS(ellipsoidalGeosCRS), is(true));
assertThat(GeostationarySatellite.isGeostationaryCRS(DefaultGeographicCRS.WGS84), is(false));
assertThat(GeostationarySatellite.isGeostationaryCRS(null), is(false));
}
@Test
public void testCircumscribeFullDisk_Spheroidal() throws TransformException, FactoryException {
final Envelope2D circumscribed = GeostationarySatellite.circumscribeFullDisk(sphericalGeosCRS);
assertThat(circumscribed, is(notNullValue()));
final DirectPosition2D p = new DirectPosition2D();
p.setLocation(circumscribed.getCenterX(), circumscribed.getMaxY());
sphericalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToSphericalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
p.setLocation(circumscribed.getCenterX(), circumscribed.getMinY());
sphericalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToSphericalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
p.setLocation(circumscribed.getMaxX(), circumscribed.getCenterY());
sphericalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToSphericalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
p.setLocation(circumscribed.getMinX(), circumscribed.getCenterY());
sphericalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToSphericalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
// show that bounds of rectangle circumscribing full disk image is not
// transformable stepping 1 meter outside the X and Y extents along the
// orthogonal center axes
final double tickle = 1;
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getCenterX(), circumscribed.getMaxY() + tickle);
sphericalGeosToGeog.transform(p, p);
}});
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getCenterX(), circumscribed.getMinY() - tickle);
sphericalGeosToGeog.transform(p, p);
}});
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getMinX() - tickle, circumscribed.getCenterY());
sphericalGeosToGeog.transform(p, p);
}});
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getMaxX() + tickle, circumscribed.getCenterY());
sphericalGeosToGeog.transform(p, p);
}});
// show that bounds of rectangle circumscribing full disk image is not transformable
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getMaxX(), circumscribed.getMaxY());
sphericalGeosToGeog.transform(p, p);
}});
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getMaxX(), circumscribed.getMinY());
sphericalGeosToGeog.transform(p, p);
}});
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getMinX(), circumscribed.getMaxY());
sphericalGeosToGeog.transform(p, p);
}});
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getMinX(), circumscribed.getMinY());
sphericalGeosToGeog.transform(p, p);
}});
}
@Test
public void testCircumscribeFullDisk_Ellipsoidal() throws TransformException, FactoryException {
final Envelope2D circumscribed = GeostationarySatellite.circumscribeFullDisk(ellipsoidalGeosCRS);
assertThat(circumscribed, is(notNullValue()));
final DirectPosition2D p = new DirectPosition2D();
p.setLocation(circumscribed.getCenterX(), circumscribed.getMaxY());
ellipsoidalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToEllipsoidalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
p.setLocation(circumscribed.getCenterX(), circumscribed.getMinY());
ellipsoidalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToEllipsoidalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
p.setLocation(circumscribed.getMaxX(), circumscribed.getCenterY());
ellipsoidalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToEllipsoidalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
p.setLocation(circumscribed.getMinX(), circumscribed.getCenterY());
ellipsoidalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToEllipsoidalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
// show that bounds of rectangle circumscribing full disk image is not
// transformable stepping 1 meter outside the X and Y extents along the
// orthogonal center axes
final double tickle = 1;
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getCenterX(), circumscribed.getMaxY() + tickle);
ellipsoidalGeosToGeog.transform(p, p);
}});
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getCenterX(), circumscribed.getMinY() - tickle);
ellipsoidalGeosToGeog.transform(p, p);
}});
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getMinX() - tickle, circumscribed.getCenterY());
ellipsoidalGeosToGeog.transform(p, p);
}});
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getMaxX() + tickle, circumscribed.getCenterY());
ellipsoidalGeosToGeog.transform(p, p);
}});
// show that bounds of rectangle circumscribing full disk image is not transformable
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getMaxX(), circumscribed.getMaxY());
ellipsoidalGeosToGeog.transform(p, p);
}});
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getMaxX(), circumscribed.getMinY());
ellipsoidalGeosToGeog.transform(p, p);
}});
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getMinX(), circumscribed.getMaxY());
ellipsoidalGeosToGeog.transform(p, p);
}});
expectProjectionException(new Testable() { public void test() throws Exception {
p.setLocation(circumscribed.getMinX(), circumscribed.getMinY());
ellipsoidalGeosToGeog.transform(p, p);
}});
}
@Test
public void testInscribeFullDiskEstimate_Spheroidal() throws TransformException, FactoryException {
final Envelope2D inscribed = GeostationarySatellite.inscribeFullDiskEstimate(sphericalGeosCRS);
assertThat(inscribed, is(notNullValue()));
final DirectPosition2D p = new DirectPosition2D();
p.setLocation(inscribed.getMaxX(), inscribed.getMaxY());
sphericalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToSphericalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
p.setLocation(inscribed.getMaxX(), inscribed.getMinY());
sphericalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToSphericalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
p.setLocation(inscribed.getMinX(), inscribed.getMaxY());
sphericalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToSphericalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
p.setLocation(inscribed.getMinX(), inscribed.getMinY());
sphericalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToSphericalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
// Inscribed rectangle is smaller than largest inscribing rectangle, hence ESTIMATE
// final double tickle = 1;
// expectProjectionException(new Testable() { public void test() throws Exception {
// p.setLocation(inscribed.getMaxX() + tickle, inscribed.getMaxY() + tickle);
// sphericalGeosToGeog.transform(p, p);
// }});
// expectProjectionException(new Testable() { public void test() throws Exception {
// p.setLocation(inscribed.getMaxX() + tickle, inscribed.getMinY() - tickle);
// sphericalGeosToGeog.transform(p, p);
// }});
// expectProjectionException(new Testable() { public void test() throws Exception {
// p.setLocation(inscribed.getMinX() - tickle, inscribed.getMaxY() + tickle);
// sphericalGeosToGeog.transform(p, p);
// }});
// expectProjectionException(new Testable() { public void test() throws Exception {
// p.setLocation(inscribed.getMinX() - tickle, inscribed.getMinY() - tickle);
// sphericalGeosToGeog.transform(p, p);
// }});
}
@Test
public void testInscribeFullDiskEstimate_Ellipsoidal() throws TransformException, FactoryException {
final Envelope2D inscribed = GeostationarySatellite.inscribeFullDiskEstimate(ellipsoidalGeosCRS);
assertThat(inscribed, is(notNullValue()));
final DirectPosition2D p = new DirectPosition2D();
p.setLocation(inscribed.getMaxX(), inscribed.getMaxY());
ellipsoidalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToEllipsoidalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
p.setLocation(inscribed.getMaxX(), inscribed.getMinY());
ellipsoidalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToEllipsoidalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
p.setLocation(inscribed.getMinX(), inscribed.getMaxY());
ellipsoidalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToEllipsoidalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
p.setLocation(inscribed.getMinX(), inscribed.getMinY());
ellipsoidalGeosToGeog.transform(p, p);
assertThat(p, is(notNullValue()));
geogToEllipsoidalGeos.transform(p, p);
assertThat(p, is(notNullValue()));
// Inscribed rectangle is smaller than largest inscribing rectangle, hence ESTIMATE
// final double tickle = 1;
// expectProjectionException(new Testable() { public void test() throws Exception {
// p.setLocation(inscribed.getMaxX() + tickle, inscribed.getMaxY() + tickle);
// ellipsoidalGeosToGeog.transform(p, p);
// }});
// expectProjectionException(new Testable() { public void test() throws Exception {
// p.setLocation(inscribed.getMaxX() + tickle, inscribed.getMinY() - tickle);
// ellipsoidalGeosToGeog.transform(p, p);
// }});
// expectProjectionException(new Testable() { public void test() throws Exception {
// p.setLocation(inscribed.getMinX() - tickle, inscribed.getMaxY() + tickle);
// ellipsoidalGeosToGeog.transform(p, p);
// }});
// expectProjectionException(new Testable() { public void test() throws Exception {
// p.setLocation(inscribed.getMinX() - tickle, inscribed.getMinY() - tickle);
// ellipsoidalGeosToGeog.transform(p, p);
// }});
}
private void expectProjectionException(Testable testable) {
expectException(ProjectionException.class, testable);
}
private <T extends Exception> void expectException(Class<T> clazz, Testable testable) {
try {
testable.test();
fail(String.format("Expected exception, %s, but not thrown", clazz));
} catch (Exception e) {
if (!clazz.isInstance(e)) {
fail(String.format("Expected exception of %s but got %s", clazz, e.getClass()));
}
}
}
public interface Testable {
void test() throws Exception;
}
}