Java Code Examples for javax.measure.Unit#getConverterToAny()

The following examples show how to use javax.measure.Unit#getConverterToAny() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: DefaultParameterValue.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Returns the converter to be used by {@link #doubleValue(Unit)} and {@link #doubleValueList(Unit)}.
 */
private UnitConverter getConverterTo(final Unit<?> unit) {
    final Unit<?> source = getUnit();
    if (source == null) {
        throw new IllegalStateException(Resources.format(Resources.Keys.UnitlessParameter_1, Verifier.getDisplayName(descriptor)));
    }
    ensureNonNull("unit", unit);
    final short expectedID = Verifier.getUnitMessageID(source);
    if (Verifier.getUnitMessageID(unit) != expectedID) {
        throw new IllegalArgumentException(Errors.format(expectedID, unit));
    }
    try {
        return source.getConverterToAny(unit);
    } catch (IncommensurableException e) {
        throw new IllegalArgumentException(Errors.format(Errors.Keys.IncompatibleUnits_2, source, unit), e);
    }
}
 
Example 2
Source File: Axis.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Returns {@code true} if coordinates in this axis seem to map cell corner instead than cell center.
 * A {@code false} value does not necessarily means that the axis maps cell center; it can be unknown.
 * This method assumes a geographic CRS.
 *
 * <p>From CF-Convention: <cite>"If bounds are not provided, an application might reasonably assume the
 * grid points to be at the centers of the cells, but we do not require that in this standard."</cite>
 * We nevertheless tries to guess by checking if the "cell center" convention would result in coordinates
 * outside the range of longitude or latitude values.</p>
 */
final boolean isCellCorner() throws IOException, DataStoreException {
    double min;
    boolean wraparound;
    switch (abbreviation) {
        case 'λ': min = Longitude.MIN_VALUE; wraparound = true;  break;
        case 'φ': min =  Latitude.MIN_VALUE; wraparound = false; break;
        default: return false;
    }
    final Vector data = read();
    final int size = data.size();
    if (size != 0) {
        Unit<?> unit = getUnit();
        if (unit == null) {
            unit = Units.DEGREE;
        }
        try {
            final UnitConverter uc = unit.getConverterToAny(Units.DEGREE);
            if (wraparound && uc.convert(data.doubleValue(size - 1)) > Longitude.MAX_VALUE) {
                min = 0;            // Replace [-180 … +180]° longitude range by [0 … 360]°.
            }
            return uc.convert(data.doubleValue(0)) == min;
        } catch (IncommensurableException e) {
            warning(e, Errors.Keys.InconsistentUnitsForCS_1, unit);
        }
    }
    return false;
}
 
Example 3
Source File: ExtentsTest.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Tests {@link Extents#getVerticalRange(Extent)}.
 *
 * @throws IncommensurableException if a conversion between incompatible units were attempted.
 */
@Test
@SuppressWarnings("null")
public void testGetVerticalRange() throws IncommensurableException {
    final List<DefaultVerticalExtent> extents = Arrays.asList(
            new DefaultVerticalExtent( -200,  -100, VerticalCRSMock.HEIGHT),
            new DefaultVerticalExtent(  150,   300, VerticalCRSMock.DEPTH),
            new DefaultVerticalExtent(  0.1,   0.2, VerticalCRSMock.SIGMA_LEVEL),
            new DefaultVerticalExtent( -600,  -300, VerticalCRSMock.HEIGHT_ft), // [91.44 … 182.88] metres
            new DefaultVerticalExtent(10130, 20260, VerticalCRSMock.BAROMETRIC_HEIGHT)
    );
    Collections.shuffle(extents, TestUtilities.createRandomNumberGenerator());
    /*
     * Since we have shuffled the vertical extents in random order, the range that we will
     * test may be either in metres or in feet depending on which vertical extent is first.
     * So we need to check which linear unit is first.
     */
    Unit<?> unit = null;
    for (final DefaultVerticalExtent e : extents) {
        unit = e.getVerticalCRS().getCoordinateSystem().getAxis(0).getUnit();
        if (Units.isLinear(unit)) break;
    }
    final UnitConverter c = unit.getConverterToAny(Units.METRE);
    /*
     * The actual test. Arbitrarily compare the heights in metres, converting them if needed.
     */
    final DefaultExtent extent = new DefaultExtent();
    extent.setVerticalElements(extents);
    final MeasurementRange<Double> range = Extents.getVerticalRange(extent);
    assertNotNull("getVerticalRange", range);
    assertSame   ("unit",    unit,    range.unit());
    assertEquals ("minimum", -300,    c.convert(range.getMinDouble()), 0.001);
    assertEquals ("maximum", -91.44,  c.convert(range.getMaxDouble()), 0.001);
}
 
Example 4
Source File: Normalizer.java    From sis with Apache License 2.0 4 votes vote down vote up
/**
 * Returns a new axis with the same properties (except identifiers) than given axis,
 * but with normalized axis direction and unit of measurement.
 *
 * @param  axis     the axis to normalize.
 * @param  changes  the change to apply on axis direction and units.
 * @return an axis using normalized direction and units, or {@code axis} if there is no change.
 */
static CoordinateSystemAxis normalize(final CoordinateSystemAxis axis, final AxisFilter changes) {
    final Unit<?>       unit      = axis.getUnit();
    final AxisDirection direction = axis.getDirection();
    final Unit<?>       newUnit   = changes.getUnitReplacement(axis, unit);
    final AxisDirection newDir    = changes.getDirectionReplacement(axis, direction);
    /*
     * Reuse some properties (name, remarks, etc.) from the existing axis. If the direction changed,
     * then the axis name may need change too (e.g. "Westing" → "Easting"). The new axis name may be
     * set to "Unnamed", but the caller will hopefully be able to replace the returned instance by
     * an instance from the EPSG database with appropriate name.
     */
    final boolean sameDirection = newDir.equals(direction);
    if (sameDirection && newUnit.equals(unit)) {
        return axis;
    }
    final String abbreviation = axis.getAbbreviation();
    final String newAbbr = sameDirection ? abbreviation :
            AxisDirections.suggestAbbreviation(axis.getName().getCode(), newDir, newUnit);
    final Map<String,Object> properties = new HashMap<>(8);
    if (newAbbr.equals(abbreviation)) {
        properties.putAll(IdentifiedObjects.getProperties(axis, EXCLUDES));
    } else {
        properties.put(NAME_KEY, UNNAMED);
    }
    /*
     * Convert the axis range and build the new axis. The axis range will be converted only if
     * the axis direction is the same or the opposite, otherwise we do not know what should be
     * the new values. In the particular case of opposite axis direction, we need to reverse the
     * sign of minimum and maximum values.
     */
    if (sameDirection || newDir.equals(AxisDirections.opposite(direction))) {
        final UnitConverter c;
        try {
            c = unit.getConverterToAny(newUnit);
        } catch (IncommensurableException e) {
            // Use IllegalStateException because the public API is an AbstractCS member method.
            throw new IllegalStateException(Resources.format(Resources.Keys.IllegalUnitFor_2, "axis", unit), e);
        }
        double minimum = c.convert(axis.getMinimumValue());
        double maximum = c.convert(axis.getMaximumValue());
        if (!sameDirection) {
            final double tmp = minimum;
            minimum = -maximum;
            maximum = -tmp;
        }
        properties.put(DefaultCoordinateSystemAxis.MINIMUM_VALUE_KEY, minimum);
        properties.put(DefaultCoordinateSystemAxis.MAXIMUM_VALUE_KEY, maximum);
        properties.put(DefaultCoordinateSystemAxis.RANGE_MEANING_KEY, axis.getRangeMeaning());
    }
    return new DefaultCoordinateSystemAxis(properties, newAbbr, newDir, newUnit);
}
 
Example 5
Source File: CoordinateSystems.java    From sis with Apache License 2.0 2 votes vote down vote up
/**
     * Returns the EPSG code of a coordinate system using the units and directions of given axes.
     * This method ignores axis metadata (names, abbreviation, identifiers, remarks, <i>etc.</i>).
     * The axis minimum and maximum values are checked only if the
     * {@linkplain CoordinateSystemAxis#getRangeMeaning() range meaning} is "wraparound".
     * If no suitable coordinate system is known to Apache SIS, then this method returns {@code null}.
     *
     * <p>Current implementation uses a hard-coded list of known coordinate systems;
     * it does not yet scan the EPSG database (this may change in future Apache SIS version).
     * The current list of known coordinate systems is given below.</p>
     *
     * <table>
     *   <caption>Known coordinate systems (CS)</caption>
     *   <tr><th>EPSG</th> <th>CS type</th> <th colspan="3">Axis directions</th> <th>Horizontal unit</th></tr>
     *   <tr><td>6424</td> <td>Ellipsoidal</td> <td>east</td>  <td>north</td> <td></td>   <td>degree</td></tr>
     *   <tr><td>6422</td> <td>Ellipsoidal</td> <td>north</td> <td>east</td>  <td></td>   <td>degree</td></tr>
     *   <tr><td>6425</td> <td>Ellipsoidal</td> <td>east</td>  <td>north</td> <td></td>   <td>grads</td></tr>
     *   <tr><td>6403</td> <td>Ellipsoidal</td> <td>north</td> <td>east</td>  <td></td>   <td>grads</td></tr>
     *   <tr><td>6429</td> <td>Ellipsoidal</td> <td>east</td>  <td>north</td> <td></td>   <td>radian</td></tr>
     *   <tr><td>6428</td> <td>Ellipsoidal</td> <td>north</td> <td>east</td>  <td></td>   <td>radian</td></tr>
     *   <tr><td>6426</td> <td>Ellipsoidal</td> <td>east</td>  <td>north</td> <td>up</td> <td>degree</td></tr>
     *   <tr><td>6423</td> <td>Ellipsoidal</td> <td>north</td> <td>east</td>  <td>up</td> <td>degree</td></tr>
     *   <tr><td>6427</td> <td>Ellipsoidal</td> <td>east</td>  <td>north</td> <td>up</td> <td>grads</td></tr>
     *   <tr><td>6421</td> <td>Ellipsoidal</td> <td>north</td> <td>east</td>  <td>up</td> <td>grads</td></tr>
     *   <tr><td>6431</td> <td>Ellipsoidal</td> <td>east</td>  <td>north</td> <td>up</td> <td>radian</td></tr>
     *   <tr><td>6430</td> <td>Ellipsoidal</td> <td>north</td> <td>east</td>  <td>up</td> <td>radian</td></tr>
     *   <tr><td>4400</td> <td>Cartesian</td>   <td>east</td>  <td>north</td> <td></td>   <td>metre</td></tr>
     *   <tr><td>4500</td> <td>Cartesian</td>   <td>north</td> <td>east</td>  <td></td>   <td>metre</td></tr>
     *   <tr><td>4491</td> <td>Cartesian</td>   <td>west</td>  <td>north</td> <td></td>   <td>metre</td></tr>
     *   <tr><td>4501</td> <td>Cartesian</td>   <td>north</td> <td>west</td>  <td></td>   <td>metre</td></tr>
     *   <tr><td>6503</td> <td>Cartesian</td>   <td>west</td>  <td>south</td> <td></td>   <td>metre</td></tr>
     *   <tr><td>6501</td> <td>Cartesian</td>   <td>south</td> <td>west</td>  <td></td>   <td>metre</td></tr>
     *   <tr><td>1039</td> <td>Cartesian</td>   <td>east</td>  <td>north</td> <td></td>   <td>foot</td></tr>
     *   <tr><td>1029</td> <td>Cartesian</td>   <td>north</td> <td>east</td>  <td></td>   <td>foot</td></tr>
     *   <tr><td>4403</td> <td>Cartesian</td>   <td>east</td>  <td>north</td> <td></td>   <td>Clarke’s foot</td></tr>
     *   <tr><td>4502</td> <td>Cartesian</td>   <td>north</td> <td>east</td>  <td></td>   <td>Clarke’s foot</td></tr>
     *   <tr><td>4497</td> <td>Cartesian</td>   <td>east</td>  <td>north</td> <td></td>   <td>US survey foot</td></tr>
     * </table>
     *
     * @param  type  the type of coordinate system for which an EPSG code is desired, as a GeoAPI interface.
     * @param  axes  axes for which a coordinate system EPSG code is desired.
     * @return EPSG codes for a coordinate system using the given axes (ignoring metadata), or {@code null} if unknown
     *         to this method. Note that a null value does not mean that a more  extensive search in the EPSG database
     *         would not find a matching coordinate system.
     *
     * @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createCoordinateSystem(String)
     *
     * @since 1.0
     */
    @SuppressWarnings("fallthrough")
    public static Integer getEpsgCode(final Class<? extends CoordinateSystem> type, final CoordinateSystemAxis... axes) {
        ArgumentChecks.ensureNonNull("type", type);
        ArgumentChecks.ensureNonNull("axes", axes);
forDim: switch (axes.length) {
            case 3: {
                if (!Units.METRE.equals(axes[2].getUnit())) break;      // Restriction in our hard-coded list of codes.
                // Fall through
            }
            case 2: {
                final Unit<?> unit = axes[0].getUnit();
                if (unit != null && unit.equals(axes[1].getUnit())) {
                    final boolean isAngular = Units.isAngular(unit);
                    if ((isAngular && type.isAssignableFrom(EllipsoidalCS.class)) ||
                         Units.isLinear(unit) && type.isAssignableFrom(CartesianCS.class))
                    {
                        /*
                         * Current implementation defines EPSG codes for EllipsoidalCS and CartesianCS only.
                         * Those two coordinate system types can be differentiated by the unit of the two first axes.
                         * If a future implementation supports more CS types, above condition will need to be updated.
                         */
                        final AxisDirection[] directions = new AxisDirection[axes.length];
                        for (int i=0; i<directions.length; i++) {
                            final CoordinateSystemAxis axis = axes[i];
                            ArgumentChecks.ensureNonNullElement("axes", i, axis);
                            directions[i] = axis.getDirection();
                            if (isAngular && RangeMeaning.WRAPAROUND.equals(axis.getRangeMeaning())) try {
                                final UnitConverter uc = unit.getConverterToAny(Units.DEGREE);
                                final double min = uc.convert(axis.getMinimumValue());
                                final double max = uc.convert(axis.getMaximumValue());
                                if ((min > Double.NEGATIVE_INFINITY && Math.abs(min - Longitude.MIN_VALUE) > Formulas.ANGULAR_TOLERANCE) ||
                                    (max < Double.POSITIVE_INFINITY && Math.abs(max - Longitude.MAX_VALUE) > Formulas.ANGULAR_TOLERANCE))
                                {
                                    break forDim;
                                }
                            } catch (IncommensurableException e) {      // Should never happen since we checked that units are angular.
                                Logging.unexpectedException(Logging.getLogger(Modules.REFERENCING), CoordinateSystems.class, "getEpsgCode", e);
                                break forDim;
                            }
                        }
                        return getEpsgCode(unit, directions);
                    }
                }
            }
        }
        return null;
    }