use of org.opengis.referencing.crs.VerticalCRS in project sis by apache.
the class CoordinateOperationFinderTest method testIncompatibleVerticalCRS.
/**
* Tests that an exception is thrown on attempt to grab a transformation between incompatible vertical CRS.
*
* @throws FactoryException if an exception other than the expected one occurred.
*/
@Test
@DependsOnMethod("testIdentityTransform")
public void testIncompatibleVerticalCRS() throws FactoryException {
final VerticalCRS sourceCRS = CommonCRS.Vertical.NAVD88.crs();
final VerticalCRS targetCRS = CommonCRS.Vertical.MEAN_SEA_LEVEL.crs();
try {
finder.createOperation(sourceCRS, targetCRS);
fail("The operation should have failed.");
} catch (OperationNotFoundException e) {
final String message = e.getMessage();
assertTrue(message, message.contains("North American Vertical Datum"));
assertTrue(message, message.contains("Mean Sea Level"));
}
}
use of org.opengis.referencing.crs.VerticalCRS in project sis by apache.
the class CommonAuthorityFactoryTest method testCRS88.
/**
* Tests {@link CommonAuthorityFactory#createVerticalCRS(String)} with the {@code "CRS:88"} code.
*
* @throws FactoryException if an error occurred while creating a CRS.
*/
@Test
public void testCRS88() throws FactoryException {
VerticalCRS crs = factory.createVerticalCRS("CRS:88");
assertSame(crs, factory.createVerticalCRS("88"));
assertSame(crs, factory.createVerticalCRS("CRS88"));
assertSame(crs, factory.createVerticalCRS("CRS:CRS 88"));
assertAxisDirectionsEqual("CS", crs.getCoordinateSystem(), AxisDirection.UP);
}
use of org.opengis.referencing.crs.VerticalCRS in project sis by apache.
the class CRSBuilder method build.
// ////////////////////////////////////////////////////////////////////////////////////////////////
// ////// ////////
// ////// GeoKeys parsing ////////
// ////// ////////
// ////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Decodes all the given GeoTIFF keys, then creates a coordinate reference system.
* An overview of the key directory structure is given in {@linkplain CRSBuilder class javadoc}.
*
* @param keyDirectory the GeoTIFF keys to be associated to values. Can not be null.
* @param numericParameters a vector of {@code double} parameters, or {@code null} if none.
* @param asciiParameters the sequence of characters from which to build strings, or {@code null} if none.
* @return the coordinate reference system created from the given GeoTIFF keys.
*
* @throws NoSuchElementException if a mandatory value is missing.
* @throws NumberFormatException if a numeric value was stored as a string and can not be parsed.
* @throws ClassCastException if an object defined by an EPSG code is not of the expected type.
* @throws FactoryException if an error occurred during objects creation with the factories.
*/
@SuppressWarnings("null")
final CoordinateReferenceSystem build(final Vector keyDirectory, final Vector numericParameters, final String asciiParameters) throws FactoryException {
final int numberOfKeys;
final int directoryLength = keyDirectory.size();
if (directoryLength >= ENTRY_LENGTH) {
final int version = keyDirectory.intValue(0);
if (version != 1) {
warning(Resources.Keys.UnsupportedGeoKeyDirectory_1, version);
return null;
}
majorRevision = keyDirectory.shortValue(1);
minorRevision = keyDirectory.shortValue(2);
numberOfKeys = keyDirectory.intValue(3);
} else {
numberOfKeys = 0;
}
/*
* The key directory may be longer than needed for the amount of keys, but not shorter.
* If shorter, report a warning and stop the parsing since we have no way to know if the
* missing information were essentiel or not.
*
* (number of key + head) * 4 --- 1 entry = 4 short values.
*/
final int expectedLength = (numberOfKeys + 1) * ENTRY_LENGTH;
if (directoryLength < expectedLength) {
warning(Resources.Keys.ListTooShort_3, "GeoKeyDirectory", expectedLength, directoryLength);
return null;
}
final int numberOfDoubles = (numericParameters != null) ? numericParameters.size() : 0;
final int numberOfChars = (asciiParameters != null) ? asciiParameters.length() : 0;
/*
* Now iterate over all GeoKey values. The values are copied in a HashMap for convenience,
* because the CRS creation may use them out of order.
*/
for (int i = 1; i <= numberOfKeys; i++) {
final int p = i * ENTRY_LENGTH;
final short key = keyDirectory.shortValue(p);
final int tagLocation = keyDirectory.intValue(p + 1);
final int count = keyDirectory.intValue(p + 2);
final int valueOffset = keyDirectory.intValue(p + 3);
if (valueOffset < 0 || count < 0) {
missingValue(key);
continue;
}
final Object value;
switch(tagLocation) {
/*
* tagLocation == 0 means that 'valueOffset' actually contains the value,
* thus avoiding the need to allocate a separated storage location for it.
* The count should be 1.
*/
case 0:
{
switch(count) {
case 0:
continue;
// Expected value.
case 1:
break;
default:
warning(Resources.Keys.UnexpectedListOfValues_2, GeoKeys.name(key), count);
break;
}
value = valueOffset;
break;
}
/*
* Values of type 'short' are stored in the same vector than the key directory;
* the specification does not allocate a separated vector for them. We use the
* 'int' type if needed for allowing storage of unsigned short values.
*/
case Tags.GeoKeyDirectory & 0xFFFF:
{
if (valueOffset + count > keyDirectory.size()) {
missingValue(key);
continue;
}
switch(count) {
case 0:
continue;
case 1:
value = keyDirectory.get(valueOffset);
break;
default:
final int[] array = new int[count];
for (int j = 0; j < count; j++) {
array[j] = keyDirectory.intValue(valueOffset + j);
}
value = array;
break;
}
break;
}
/*
* Values of type 'double' are read from a separated vector, 'numericParameters'.
* Result is stored in a Double wrapper or in an array of type 'double[]'.
*/
case Tags.GeoDoubleParams & 0xFFFF:
{
if (valueOffset + count > numberOfDoubles) {
missingValue(key);
continue;
}
switch(count) {
case 0:
continue;
case 1:
value = numericParameters.get(valueOffset);
break;
default:
final double[] array = new double[count];
for (int j = 0; j < count; j++) {
array[j] = numericParameters.doubleValue(valueOffset + j);
}
value = array;
break;
}
break;
}
/*
* ASCII encoding use the pipe ('|') character as a replacement for the NUL character
* used in C/C++ programming languages. We need to omit those trailing characters.
*/
case Tags.GeoAsciiParams & 0xFFFF:
{
int upper = valueOffset + count;
if (upper > numberOfChars) {
missingValue(key);
continue;
}
upper = CharSequences.skipTrailingWhitespaces(asciiParameters, valueOffset, upper);
while (upper > valueOffset && asciiParameters.charAt(upper - 1) == SEPARATOR) {
// Skip trailing pipe, interpreted as C/C++ NUL character.
upper--;
}
// Use String.trim() for skipping C/C++ NUL character in addition of whitespaces.
final String s = asciiParameters.substring(valueOffset, upper).trim();
if (s.isEmpty())
continue;
value = s;
break;
}
/*
* GeoKeys are not expected to use other storage mechanism. If this happen anyway, report a warning
* and continue on the assumption that if the value that we are ignoring was critical information,
* it would have be stored in one of the standard GeoTIFF tags.
*/
default:
{
warning(Resources.Keys.UnsupportedGeoKeyStorage_1, GeoKeys.name(key));
continue;
}
}
geoKeys.put(key, value);
}
/*
* At this point we finished copying all GeoTIFF keys in 'CRSBuilder.geoKeys' map.
* First create the main coordinate reference system, as determined by 'ModelType'.
* Then if a vertical CRS exists and the main CRS is not geocentric (in which case
* adding a vertical CRS would make no sense), create a three-dimensional compound CRS.
*/
CoordinateReferenceSystem crs;
final int crsType = getAsInteger(GeoKeys.ModelType);
switch(crsType) {
case GeoCodes.undefined:
return null;
case GeoCodes.ModelTypeProjected:
crs = createProjectedCRS();
break;
// Ignore vertical CRS.
case GeoCodes.ModelTypeGeocentric:
return createGeocentricCRS();
case GeoCodes.ModelTypeGeographic:
{
crs = createGeographicCRS(true, createUnit(GeoKeys.AngularUnits, GeoKeys.AngularUnitSize, Angle.class, Units.DEGREE));
break;
}
default:
{
warning(Resources.Keys.UnsupportedCoordinateSystemKind_1, crsType);
return null;
}
}
final VerticalCRS vertical = createVerticalCRS();
if (vertical != null) {
crs = objectFactory().createCompoundCRS(Collections.singletonMap(IdentifiedObject.NAME_KEY, crs.getName()), crs, vertical);
}
return crs;
}
Aggregations