Search in sources :

Example 16 with VerticalCRS

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"));
    }
}
Also used : OperationNotFoundException(org.opengis.referencing.operation.OperationNotFoundException) VerticalCRS(org.opengis.referencing.crs.VerticalCRS) Test(org.junit.Test) DependsOnMethod(org.apache.sis.test.DependsOnMethod)

Example 17 with VerticalCRS

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);
}
Also used : VerticalCRS(org.opengis.referencing.crs.VerticalCRS) Test(org.junit.Test)

Example 18 with VerticalCRS

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;
}
Also used : Angle(javax.measure.quantity.Angle) VerticalCRS(org.opengis.referencing.crs.VerticalCRS) IdentifiedObject(org.opengis.referencing.IdentifiedObject) NilReferencingObject(org.apache.sis.internal.referencing.NilReferencingObject) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem)

Aggregations

VerticalCRS (org.opengis.referencing.crs.VerticalCRS)18 Test (org.junit.Test)9 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)9 TemporalCRS (org.opengis.referencing.crs.TemporalCRS)5 VerticalDatum (org.opengis.referencing.datum.VerticalDatum)5 DependsOnMethod (org.apache.sis.test.DependsOnMethod)4 GeographicCRS (org.opengis.referencing.crs.GeographicCRS)4 ProjectedCRS (org.opengis.referencing.crs.ProjectedCRS)4 CoordinateSystemAxis (org.opengis.referencing.cs.CoordinateSystemAxis)4 VerticalExtent (org.opengis.metadata.extent.VerticalExtent)3 CompoundCRS (org.opengis.referencing.crs.CompoundCRS)3 GeodeticCRS (org.opengis.referencing.crs.GeodeticCRS)3 CoordinateSystem (org.opengis.referencing.cs.CoordinateSystem)3 TransformException (org.opengis.referencing.operation.TransformException)3 DefaultGeographicBoundingBox (org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox)2 DefaultVerticalExtent (org.apache.sis.metadata.iso.extent.DefaultVerticalExtent)2 DefaultCompoundCRS (org.apache.sis.referencing.crs.DefaultCompoundCRS)2 DefaultTemporalCRS (org.apache.sis.referencing.crs.DefaultTemporalCRS)2 DefaultVerticalCRS (org.apache.sis.referencing.crs.DefaultVerticalCRS)2 DefaultVerticalCS (org.apache.sis.referencing.cs.DefaultVerticalCS)2