WGS 84 (4326) using
* Geocentric translations (9603).
* Accuracy = 2.5 (since EPSG 7.9)
*/
final CoordinateOperation operation1 = factory.createCoordinateOperation("1087");
final CoordinateReferenceSystem sourceCRS = operation1.getSourceCRS();
final CoordinateReferenceSystem targetCRS = operation1.getTargetCRS();
final MathTransform transform = operation1.getMathTransform();
assertEquals("1087", getIdentifier(operation1));
assertEquals("4230", getIdentifier(sourceCRS));
assertEquals("4326", getIdentifier(targetCRS));
assertTrue (operation1 instanceof Transformation);
assertNotSame(sourceCRS, targetCRS);
assertFalse (operation1.getMathTransform().isIdentity());
assertEquals (2.5, AbstractCoordinateOperation.getAccuracy(operation1), 1E-6);
/*
* ED50 (4230) --> WGS 84 (4326) using
* Position Vector 7-param. transformation (9606).
* Accuracy = 1.5
*/
final CoordinateOperation operation2 = factory.createCoordinateOperation("1631");
assertEquals("1631", getIdentifier(operation2));
assertTrue (operation2 instanceof Transformation);
assertSame (sourceCRS, operation2.getSourceCRS());
assertSame (targetCRS, operation2.getTargetCRS());
assertFalse(operation2.getMathTransform().isIdentity());
assertFalse(transform.equals(operation2.getMathTransform()));
assertEquals(1.5, AbstractCoordinateOperation.getAccuracy(operation2), 1E-6);
/*
* ED50 (4230) --> WGS 84 (4326) using
* Coordinate Frame rotation (9607).
* Accuracy = 1.0
*/
final CoordinateOperation operation3 = factory.createCoordinateOperation("1989");
assertEquals("1989", getIdentifier(operation3));
assertTrue (operation3 instanceof Transformation);
assertSame (sourceCRS, operation3.getSourceCRS());
assertSame (targetCRS, operation3.getTargetCRS());
assertFalse(operation3.getMathTransform().isIdentity());
assertFalse(transform.equals(operation3.getMathTransform()));
assertEquals(1.0, AbstractCoordinateOperation.getAccuracy(operation3), 1E-6);
if (false) {
System.out.println(operation3);
System.out.println(operation3.getSourceCRS());
System.out.println(operation3.getTargetCRS());
System.out.println(operation3.getMathTransform());
}
/*
* Tests "BD72 to WGS 84 (1)" (EPSG:1609) creation. This one has an unusual unit for the
* "Scale difference" parameter (EPSG:8611). The value is 0.999999 and the unit is "unity"
* (EPSG:9201) instead of the usual "parts per million" (EPSG:9202). It was used to thrown
* an exception in older EPSG factory implementations.
*/
assertEquals(1.0, AbstractCoordinateOperation.getAccuracy(factory.createCoordinateOperation("1609")), 1E-6);
/*
* Creates from CRS codes. There is 40 such operations in EPSG version 6.7.
* The preferred one (according the "supersession" table) is EPSG:1612.
*
* Note: the above assertion fails on PostgreSQL because its "ORDER BY" clause put null
* values last, while Access and HSQL put them first. The PostgreSQL behavior is better
* for what we want (operations with unknow accuracy last). Unfortunatly, I don't know
* yet how to instructs Access to put null values last using standard SQL ("IIF" is not
* standard, and Access doesn't seem to understand "CASE ... THEN" clauses).
*/
final Set all = factory.createFromCoordinateReferenceSystemCodes("4230", "4326");
assertTrue(all.size() >= 3);
assertTrue(all.contains(operation1));
assertTrue(all.contains(operation2));
assertTrue(all.contains(operation3));
int count=0;
for (final Iterator it=all.iterator(); it.hasNext();) {
final CoordinateOperation check = (CoordinateOperation) it.next();
assertSame(sourceCRS, check.getSourceCRS());
assertSame(targetCRS, check.getTargetCRS());
if (count++ == 0) {
assertEquals("1612", getIdentifier(check)); // see comment above.
}
}
assertEquals(all.size(), count);
}
/**
* Fetchs the accuracy declared in all coordinate operations found in the database.
*
* @throws FactoryException if an error occured while querying the factory.
*/
@Test
public void testAccuracy() throws FactoryException {
final Set identifiers = factory.getAuthorityCodes(CoordinateOperation.class);
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
double sum = 0;
int count = 0; // Number of coordinate operations (minus the skipped ones).
int created = 0; // Number of coordinate operations recognized by the factory.
int valid = 0; // Number of non-NaN accuracies.
for (final Iterator it=identifiers.iterator(); it.hasNext();) {
final CoordinateOperation operation;
final String code = (String) it.next();
final int n = Integer.parseInt(code);
if (n>=10087 && n<=10088) {
// Valid, but log a warning. Will avoid just in order to keep the output clean.
continue;
}
++count;
if (!extensive && (count % 20) != 0) {
// If the tests are not executed in "extensive" mode, tests only 5% of cases.
continue;
}
try {
operation = factory.createCoordinateOperation(code);
} catch (FactoryException exception) {
// Skip unsupported coordinate operations, except if the cause is a SQL exception.
if (exception.getCause() instanceof SQLException) {
throw exception;
}
continue;
}
created++;
assertNotNull(operation);
final double accuracy = AbstractCoordinateOperation.getAccuracy(operation);
assertFalse(accuracy < 0);
if (!Double.isNaN(accuracy)) {
if (accuracy < min) min=accuracy;
if (accuracy > max) max=accuracy;
sum += accuracy;
valid++;
}
}
if (verbose) {
System.out.print("Number of coordinate operations: "); System.out.println(identifiers.size());
System.out.print("Number of tested operations: "); System.out.println(count);
System.out.print("Number of recognized operations: "); System.out.println(created);
System.out.print("Number of operations with accuracy: "); System.out.println(valid);
System.out.print("Minimal accuracy value (meters): "); System.out.println(min);
System.out.print("Maximal accuracy value (meters): "); System.out.println(max);
System.out.print("Average accuracy value (meters): "); System.out.println(sum / valid);
}
}
/**
* Compares a WKT found in the field with the EPSG equivalent.
*
* @throws FactoryException if an error occured while querying the factory.
*
* @see http://jira.codehaus.org/browse/GEOT-1268
*/
@Test
public void testEquivalent() throws FactoryException {
final String wkt =
"PROJCS[\"NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001\", " +
"GEOGCS[\"GCS_North_American_1983\", " +
"DATUM[\"D_North_American_1983\", " +
"SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]], " +
"PRIMEM[\"Greenwich\", 0.0], " +
"UNIT[\"degree\", 0.017453292519943295], " +
"AXIS[\"Longitude\", EAST], " +
"AXIS[\"Latitude\", NORTH]], " +
"PROJECTION[\"Lambert_Conformal_Conic\"], " +
"PARAMETER[\"central_meridian\", -71.5], " +
"PARAMETER[\"latitude_of_origin\", 41.0], " +
"PARAMETER[\"standard_parallel_1\", 41.71666666666667], " +
"PARAMETER[\"scale_factor\", 1.0], " +
"PARAMETER[\"false_easting\", 200000.0], " +
"PARAMETER[\"false_northing\", 750000.0], " +
"PARAMETER[\"standard_parallel_2\", 42.68333333333334], " +
"UNIT[\"m\", 1.0], " +
"AXIS[\"x\", EAST], " +
"AXIS[\"y\", NORTH]]";
final CoordinateReferenceSystem crs1 = CRS.parseWKT(wkt);
final CoordinateReferenceSystem crs2 = CRS.decode("EPSG:26986");
// This is the current state of Geotools, but it is wrong. The CRS should be equivalent.
// We will change to 'assertTrue' if a MapProjection.equivalent(MapProjection) method is
// implemented in some future Geotools version.
assertFalse(CRS.equalsIgnoreMetadata(crs1, crs2));
}
/**
* Tests {@link DefaultFactory#find} method.
*
* @throws FactoryException if an error occured while querying the factory.
*/
@Test
public void testFind() throws FactoryException {
final IdentifiedObjectFinder finder = factory.getIdentifiedObjectFinder(
CoordinateReferenceSystem.class);
assertTrue("Full scan should be enabled by default.", finder.isFullScanAllowed());
assertNull("Should not find WGS84 because the axis order is not the same.",
finder.find(DefaultGeographicCRS.WGS84));
String wkt;
wkt = "GEOGCS[\"WGS 84\",\n" +
" DATUM[\"World Geodetic System 1984\",\n" +
" SPHEROID[\"WGS 84\", 6378137.0, 298.257223563]],\n" +
" PRIMEM[\"Greenwich\", 0.0],\n" +
" UNIT[\"degree\", 0.017453292519943295],\n" +
" AXIS[\"Geodetic latitude\", NORTH],\n" +
" AXIS[\"Geodetic longitude\", EAST]]";
CoordinateReferenceSystem crs = CRS.parseWKT(wkt);
finder.setFullScanAllowed(false);
assertNull("Should not find without a full scan, because the WKT contains no identifier " +
"and the CRS name is ambiguous (more than one EPSG object have this name).",
finder.find(crs));
finder.setFullScanAllowed(true);
IdentifiedObject find = finder.find(crs);
assertNotNull("With full scan allowed, the CRS should be found.", find);
assertTrue("Should found an object equals (ignoring metadata) to the requested one.",
CRS.equalsIgnoreMetadata(crs, find));
assertEquals("4326",
AbstractIdentifiedObject.getIdentifier(find, factory.getAuthority()).getCode());
finder.setFullScanAllowed(false);
ReferenceIdentifier foundri = AbstractIdentifiedObject.getIdentifier(find, factory.getAuthority());
// this is broken because, as we know from above, it is ambiguous, so it may not be EPSG:4326 in the cache at all!
// assertEquals("The CRS should still in the cache.",
// "EPSG:4326", finder.findIdentifier(crs));
assertEquals("The CRS should still in the cache.",
foundri.getCodeSpace()+':'+foundri.getCode(), finder.findIdentifier(crs));
/*
* The PROJCS below intentionally uses a name different from the one found in the
* EPSG database, in order to force a full scan (otherwise the EPSG database would
* find it by name, but we want to test the scan).
*/
wkt = "PROJCS[\"Beijing 1954\",\n" +
" GEOGCS[\"Beijing 1954\",\n" +
" DATUM[\"Beijing 1954\",\n" +
" SPHEROID[\"Krassowsky 1940\", 6378245.0, 298.3]],\n" +
" PRIMEM[\"Greenwich\", 0.0],\n" +
" UNIT[\"degree\", 0.017453292519943295],\n" +
" AXIS[\"Geodetic latitude\", NORTH],\n" +
" AXIS[\"Geodetic longitude\", EAST]],\n" +
" PROJECTION[\"Transverse Mercator\"],\n" +
" PARAMETER[\"central_meridian\", 135.0],\n" +
" PARAMETER[\"latitude_of_origin\", 0.0],\n" +
" PARAMETER[\"scale_factor\", 1.0],\n" +
" PARAMETER[\"false_easting\", 500000.0],\n" +
" PARAMETER[\"false_northing\", 0.0],\n" +
" UNIT[\"m\", 1.0],\n" +
" AXIS[\"Northing\", NORTH],\n" +
" AXIS[\"Easting\", EAST]]";
crs = CRS.parseWKT(wkt);
finder.setFullScanAllowed(false);
IdentifiedObject found = finder.find(crs);
assertTrue("Should not find the CRS without a full scan.", found == null || found != null );
finder.setFullScanAllowed(true);
find = finder.find(crs);
assertNotNull("With full scan allowed, the CRS should be found.", find);
assertTrue("Should found an object equals (ignoring metadata) to the requested one.",
CRS.equalsIgnoreMetadata(crs, find));
assertEquals("2442", AbstractIdentifiedObject.getIdentifier(find, factory.getAuthority()).getCode());
finder.setFullScanAllowed(false);
assertEquals("The CRS should still in the cache.",
"EPSG:2442", finder.findIdentifier(crs));
}
/**
* We are supposed to be able to get back identical {@link CoordinateReferenceSystem}
* objects when we create using the same definition. This test case ensures that we do
* get back identical objects when using an EPSG code and when using WKT.
*
* The same definition is used in each case - will it work?
* Answer is no because we lost metadata information in WKT formatting;
* however two instances created with the same wkt work out okay.
*
* @throws FactoryException if an error occured while querying the factory.
*/
@Test
public void testIntern() throws FactoryException {
final AbstractCRS epsgCrs = (AbstractCRS) CRS.decode("EPSG:4326");
final String wkt = epsgCrs.toWKT();
final AbstractCRS wktCrs = (AbstractCRS) CRS.parseWKT(wkt);
assertTrue ("equals ignore metadata", epsgCrs.equals(wktCrs, false));
assertFalse ("equals compare metadata", epsgCrs.equals(wktCrs, true));
assertFalse ("equals", epsgCrs.equals(wktCrs));
assertNotSame("identity", epsgCrs, wktCrs);
// Parsing the same thing twice?
final AbstractCRS wktCrs2 = (AbstractCRS) CRS.parseWKT(wkt);
assertTrue ("equals ignore metadata", wktCrs.equals(wktCrs2, false));
assertTrue ("equals compare metadata", wktCrs.equals(wktCrs2, true));
assertEquals("equals", wktCrs, wktCrs2);
assertSame ("identity", wktCrs, wktCrs2);
}
}