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

The following examples show how to use javax.measure.Unit#getSystemUnit() . 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: DefaultVerticalCS.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Returns {@code VALID} if the given argument values are allowed for this coordinate system,
 * or an {@code INVALID_*} error code otherwise. This method is invoked at construction time.
 * The current implementation accepts only temporal directions (i.e. {@link AxisDirection#UP}
 * and {@link AxisDirection#DOWN}).
 */
@Override
final int validateAxis(final AxisDirection direction, Unit<?> unit) {
    if (!AxisDirection.UP.equals(AxisDirections.absolute(direction))) {
        return INVALID_DIRECTION;
    }
    unit = unit.getSystemUnit();
    if (unit.equals(Units.METRE)   ||       // Most usual case.
        unit.equals(Units.PASCAL)  ||       // Height or depth estimated by the atmospheric or ocean pressure.
        unit.equals(Units.SECOND)  ||       // Depth estimated by the time needed for an echo to travel.
        unit.equals(Units.UNITY))           // Sigma-level (percentage from sea surface to ocean floor).
    {
        return VALID;
    }
    return INVALID_UNIT;
}
 
Example 2
Source File: SystemUnit.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Returns a converter of numeric values from this unit to another unit of same type.
 *
 * @param  unit  the unit of same type to which to convert the numeric values.
 * @return the converter from this unit to {@code that} unit.
 * @throws UnconvertibleException if the converter can not be constructed.
 */
@Override
public UnitConverter getConverterTo(final Unit<Q> unit) throws UnconvertibleException {
    ArgumentChecks.ensureNonNull("unit", unit);
    final Unit<Q> step = unit.getSystemUnit();
    if (step != this && !equalsIgnoreMetadata(step)) {
        // Should never occur unless parameterized type has been compromised.
        throw new UnconvertibleException(incompatible(unit));
    }
    if (step == unit) {
        return IdentityConverter.INSTANCE;
    }
    /*
     * At this point we know that the given units is not a system unit. Ask the conversion
     * FROM the given units (before to inverse it) instead than TO the given units because
     * in Apache SIS implementation, the former returns directly ConventionalUnit.toTarget
     * while the later implies a recursive call to this method.
     */
    return unit.getConverterTo(step).inverse();
}
 
Example 3
Source File: Quantities.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Returns the given quantity as an instance of the specific {@code Quantity} subtype.
 * For example this method can be used for converting a {@code Quantity<Length>} to a {@link Length}.
 * If the given quantity already implements the specific interface, then it is returned as-is.
 *
 * @param  <Q>      the quantity type (e.g. {@link Length}, {@link Angle}, {@link Time}, <i>etc.</i>), or {@code null}.
 * @param  quantity the quantity to convert to the specific subtype.
 * @return the given quantity as a specific subtype (may be {@code quantity} itself), or {@code null} if the given quantity was null.
 * @throws IllegalArgumentException if the unit class associated to the given quantity is not a supported implementation.
 */
@SuppressWarnings("unchecked")
public static <Q extends Quantity<Q>> Q castOrCopy(final Quantity<Q> quantity) {
    if (quantity != null) {
        final Unit<Q> unit   = quantity.getUnit();
        final Unit<Q> system = unit.getSystemUnit();
        if (!(system instanceof SystemUnit<?>)) {
            throw new IllegalArgumentException(Errors.format(Errors.Keys.UnsupportedImplementation_1, unit.getClass()));
        }
        final Class<Q> type = ((SystemUnit<Q>) system).quantity;
        if (!type.isInstance(quantity)) {
            final ScalarFactory<Q> factory = ((SystemUnit<Q>) system).factory;
            final double value = AbstractConverter.doubleValue(quantity.getValue());
            if (factory != null) {
                return factory.create(value, unit);
            } else {
                return ScalarFallback.factory(value, unit, type);
            }
        }
    }
    return (Q) quantity;
}
 
Example 4
Source File: ConventionalUnit.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Returns a converter of numeric values from this unit to another unit of same type.
 *
 * @param  that  the unit of same type to which to convert the numeric values.
 * @return the converter from this unit to {@code that} unit.
 * @throws UnconvertibleException if the converter can not be constructed.
 */
@Override
public UnitConverter getConverterTo(final Unit<Q> that) throws UnconvertibleException {
    if (that == this) {
        return IdentityConverter.INSTANCE;
    }
    ArgumentChecks.ensureNonNull("that", that);
    UnitConverter c = toTarget;
    if (target != that) {                           // Optimization for a common case.
        final Unit<Q> step = that.getSystemUnit();
        if (target != step && !target.isCompatible(step)) {
            // Should never occur unless parameterized type has been compromised.
            throw new UnconvertibleException(incompatible(that));
        }
        c = target.getConverterTo(step).concatenate(c);         // Usually leave 'c' unchanged.
        c =   step.getConverterTo(that).concatenate(c);
    }
    return c;
}
 
Example 5
Source File: ConventionalUnit.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Returns a converter from this unit to the specified unit of unknown type.
 * This method can be used when the quantity type of the specified unit is unknown at compile-time
 * or when dimensional analysis allows for conversion between units of different type.
 *
 * @param  that  the unit to which to convert the numeric values.
 * @return the converter from this unit to {@code that} unit.
 * @throws IncommensurableException if this unit is not {@linkplain #isCompatible(Unit) compatible} with {@code that} unit.
 *
 * @see #isCompatible(Unit)
 */
@Override
public UnitConverter getConverterToAny(final Unit<?> that) throws IncommensurableException {
    if (that == this) {
        return IdentityConverter.INSTANCE;
    }
    ArgumentChecks.ensureNonNull("that", that);
    UnitConverter c = toTarget;
    if (target != that) {                           // Optimization for a common case.
        final Unit<?> step = that.getSystemUnit();
        if (target != step && !target.isCompatible(step)) {
            throw new IncommensurableException(incompatible(that));
        }
        c = target.getConverterToAny(step).concatenate(c);      // Usually leave 'c' unchanged.
        c =   step.getConverterToAny(that).concatenate(c);
    }
    return c;
}
 
Example 6
Source File: SystemUnit.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Returns a converter from this unit to the specified unit of unknown type.
 * This method can be used when the quantity type of the specified unit is unknown at compile-time
 * or when dimensional analysis allows for conversion between units of different type.
 *
 * @param  unit  the unit to which to convert the numeric values.
 * @return the converter from this unit to {@code that} unit.
 * @throws IncommensurableException if this unit is not {@linkplain #isCompatible(Unit) compatible} with {@code that} unit.
 *
 * @see #isCompatible(Unit)
 */
@Override
public UnitConverter getConverterToAny(final Unit<?> unit) throws IncommensurableException {
    ArgumentChecks.ensureNonNull("unit", unit);
    final Unit<?> step = unit.getSystemUnit();
    if (step != this && !isCompatible(step)) {
        throw new IncommensurableException(incompatible(unit));
    }
    if (step == unit) {
        return IdentityConverter.INSTANCE;
    }
    // Same remark than in getConverterTo(Unit).
    return unit.getConverterToAny(step).inverse();
}
 
Example 7
Source File: SystemUnit.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Implementation of {@link #multiply(Unit)} and {@link #divide(Unit)} methods.
 *
 * @param  inverse  wether to use the inverse of {@code other}.
 */
private <T extends Quantity<T>> Unit<?> product(final Unit<T> other, final boolean inverse) {
    final Unit<T> intermediate = other.getSystemUnit();
    final Dimension dim = intermediate.getDimension();
    final UnitDimension newDimension;
    final char operation;
    if (inverse) {
        operation = DIVIDE;
        newDimension = dimension.divide(dim);
    } else {
        operation = MULTIPLY;
        newDimension = dimension.multiply(dim);
    }
    final boolean transformed = (intermediate != other);
    Unit<?> result = create(newDimension, operation, transformed ? null : other);
    if (transformed) {
        UnitConverter c = other.getConverterTo(intermediate);
        if (!c.isLinear()) {
            throw new IllegalArgumentException(Errors.format(Errors.Keys.NonRatioUnit_1, other));
        }
        if (!c.isIdentity()) {
            if (inverse) c = c.inverse();
            result = result.transform(c);
            /*
             * If the system unit product is an Apache SIS implementation, try to infer a unit symbol
             * to be given to our customized 'transform' method. Otherwise fallback on standard API.
             */
            result = inferSymbol(result, operation, other);
        }
    }
    return result;
}
 
Example 8
Source File: InterpolatedTransform.java    From sis with Apache License 2.0 4 votes vote down vote up
/**
 * Creates a transform for the given interpolation grid.
 * This {@code InterpolatedTransform} class works with coordinate values in <em>units of grid cell</em>
 * For example input coordinates (4,5) is the position of the center of the cell at grid index (4,5).
 * The output units are the same than the input units.
 *
 * <p>For converting geodetic coordinates, {@code InterpolatedTransform} instances need to be concatenated
 * with the following affine transforms:
 *
 * <ul>
 *   <li><cite>Normalization</cite> before {@code InterpolatedTransform}
 *     for converting the geodetic coordinates into grid coordinates.</li>
 *   <li><cite>Denormalization</cite> after {@code InterpolatedTransform}
 *     for converting grid coordinates into geodetic coordinates.</li>
 * </ul>
 *
 * After {@code InterpolatedTransform} construction,
 * the full conversion chain including the above affine transforms can be created by
 * <code>{@linkplain #getContextualParameters()}.{@linkplain ContextualParameters#completeTransform
 * completeTransform}(factory, this)}</code>.
 *
 * @param  <T>   dimension of the coordinate tuples and the translation unit.
 * @param  grid  the grid of datum shifts from source to target datum.
 * @throws NoninvertibleMatrixException if the conversion from geodetic coordinates
 *         to grid indices can not be inverted.
 *
 * @see #createGeodeticTransformation(MathTransformFactory, DatumShiftGrid)
 */
@SuppressWarnings( {"OverridableMethodCallDuringObjectConstruction", "fallthrough"})
protected <T extends Quantity<T>> InterpolatedTransform(final DatumShiftGrid<T,T> grid) throws NoninvertibleMatrixException {
    /*
     * Create the contextual parameters using the descriptor of the provider that created the datum shift grid.
     */
    super(grid.getParameterDescriptors(), grid);
    if (!grid.isCellValueRatio()) {
        throw new IllegalArgumentException(Resources.format(
                Resources.Keys.IllegalParameterValue_2, "isCellValueRatio", Boolean.FALSE));
    }
    final Unit<T> unit = grid.getTranslationUnit();
    if (unit != grid.getCoordinateUnit()) {
        throw new IllegalArgumentException(Resources.format(Resources.Keys.IllegalUnitFor_2, "translation", unit));
    }
    dimension = grid.getTranslationDimensions();
    /*
     * Set the normalization matrix to the conversion from source coordinates (e.g. seconds of angle)
     * to grid indices. This will allow us to invoke DatumShiftGrid.interpolateAtCell(x, y, vector)
     * directly in the transform(…) methods.
     */
    final MatrixSIS normalize = context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION);
    normalize.setMatrix(grid.getCoordinateToGrid().getMatrix());
    /*
     * NADCON and NTv2 datum shift grids expect geographic coordinates in seconds of angle, while
     * MathTransform instances created by DefaultMathTransformFactory.createParameterized(…) must
     * expect coordinates in standardized units (degrees of angle, metres, seconds, etc.).
     * We concatenate the unit conversion with above "coordinates to grid indices" conversion.
     */
    @SuppressWarnings("unchecked")
    final Unit<T> normalized = Units.isAngular(unit) ? (Unit<T>) Units.DEGREE : unit.getSystemUnit();
    if (!unit.equals(normalized)) {
        Number scale  = 1.0;
        Number offset = 0.0;
        final Number[] coefficients = Units.coefficients(normalized.getConverterTo(unit));
        switch (coefficients != null ? coefficients.length : -1) {
            case 2:  scale  = coefficients[1];                                      // Fall through
            case 1:  offset = coefficients[0];                                      // Fall through
            case 0:  break;
            default: throw new IllegalArgumentException(Resources.format(Resources.Keys.NonLinearUnitConversion_2, normalized, unit));
        }
        for (int j=0; j<dimension; j++) {
            normalize.convertBefore(j, scale, offset);
        }
    }
    /*
     * Denormalization is the inverse of all above conversions in the usual case (NADCON and NTv2) where the
     * source coordinate system is the same than the target coordinate system, for example with axis unit in
     * degrees. However we also use this InterpolatedTransform implementation for other operations, like the
     * one created by LocalizationGridBuilder. Those later operations may require a different denormalization
     * matrix. Consequently the call to `getParameterValues(…)` may overwrite the denormalization matrix as
     * a non-documented side effect.
     */
    Matrix denormalize = normalize.inverse();                   // Normal NACDON and NTv2 case.
    context.getMatrix(ContextualParameters.MatrixRole.DENORMALIZATION).setMatrix(denormalize);
    grid.getParameterValues(context);       // May overwrite `denormalize` (see above comment).
    inverse = createInverse();
}
 
Example 9
Source File: Formatter.java    From sis with Apache License 2.0 4 votes vote down vote up
/**
 * Appends a unit in a {@code Unit[…]} element or one of the specialized elements. Specialized elements are
 * {@code AngleUnit}, {@code LengthUnit}, {@code ScaleUnit}, {@code ParametricUnit} and {@code TimeUnit}.
 * By {@linkplain KeywordStyle#DEFAULT default}, specialized unit keywords are used with the
 * {@linkplain Convention#WKT2 WKT 2 convention}.
 *
 * <div class="note"><b>Example:</b>
 * {@code append(Units.KILOMETRE)} will append "{@code LengthUnit["km", 1000]}" to the WKT.</div>
 *
 * @param  unit  the unit to append to the WKT, or {@code null} if none.
 *
 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#35">WKT 2 specification §7.4</a>
 */
public void append(final Unit<?> unit) {
    if (unit != null) {
        final boolean isSimplified = (longKeywords == 0) ? convention.isSimplified() : (longKeywords < 0);
        final boolean isWKT1 = convention.majorVersion() == 1;
        final Unit<?> base = unit.getSystemUnit();
        final String keyword;
        if (base.equals(Units.METRE)) {
            keyword = isSimplified ? WKTKeywords.Unit : WKTKeywords.LengthUnit;
        } else if (base.equals(Units.RADIAN)) {
            keyword = isSimplified ? WKTKeywords.Unit : WKTKeywords.AngleUnit;
        } else if (base.equals(Units.UNITY)) {
            keyword = isSimplified ? WKTKeywords.Unit : WKTKeywords.ScaleUnit;
        } else if (base.equals(Units.SECOND)) {
            keyword = WKTKeywords.TimeUnit;  // "Unit" alone is not allowed for time units according ISO 19162.
        } else {
            keyword = WKTKeywords.ParametricUnit;
        }
        openElement(false, keyword);
        setColor(ElementKind.UNIT);
        final int fromIndex = buffer.appendCodePoint(symbols.getOpeningQuote(0)).length();
        unitFormat.format(unit, buffer, dummy);
        closeQuote(fromIndex);
        resetColor();
        final double conversion = Units.toStandardUnit(unit);
        if (Double.isNaN(conversion) && Units.isAngular(unit)) {
            appendExact(Math.PI / 180);                 // Presume that we have sexagesimal degrees (see below).
        } else {
            appendExact(conversion);
        }
        /*
         * The EPSG code in UNIT elements is generally not recommended. But we make an exception for sexagesimal
         * units (EPSG:9108, 9110 and 9111) because they can not be represented by a simple scale factor in WKT.
         * Those units are identified by a conversion factor set to NaN since the conversion is non-linear.
         */
        if (convention == Convention.INTERNAL || Double.isNaN(conversion)) {
            final Integer code = Units.getEpsgCode(unit, getEnclosingElement(1) instanceof CoordinateSystemAxis);
            if (code != null) {
                openElement(false, isWKT1 ? WKTKeywords.Authority : WKTKeywords.Id);
                append(Constants.EPSG, null);
                if (isWKT1) {
                    append(code.toString(), null);
                } else {
                    append(code);
                }
                closeElement(false);
            }
        }
        closeElement(false);
        /*
         * ISO 19162 requires the conversion factor to be positive.
         * In addition, keywords other than "Unit" are not valid in WKt 1.
         */
        if (!(conversion > 0) || (keyword != WKTKeywords.Unit && isWKT1)) {
            setInvalidWKT(Unit.class, null);
        }
    }
}