javax.measure.IncommensurableException Java Examples

The following examples show how to use javax.measure.IncommensurableException. 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: QuantityType.java    From openhab-core with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Convert this QuantityType to a new {@link QuantityType} using the given target unit.
 *
 * @param targetUnit the unit to which this {@link QuantityType} will be converted to.
 * @return the new {@link QuantityType} in the given {@link Unit} or {@code null} in case of a
 */
@SuppressWarnings("unchecked")
public @Nullable QuantityType<T> toUnit(Unit<?> targetUnit) {
    if (!targetUnit.equals(getUnit())) {
        try {
            UnitConverter uc = getUnit().getConverterToAny(targetUnit);
            Quantity<?> result = Quantities.getQuantity(uc.convert(quantity.getValue()), targetUnit);

            return new QuantityType<T>(result.getValue(), (Unit<T>) targetUnit);
        } catch (UnconvertibleException | IncommensurableException e) {
            logger.debug("Unable to convert unit from {} to {}", getUnit(), targetUnit);
            return null;
        }
    }
    return this;
}
 
Example #2
Source File: ConventionalUnitTest.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Tests the equivalence between litres and cubic metres.
 * The litre unit is handled as a special case, since it is not a SI unit but can have SI prefix.
 *
 * @throws IncommensurableException if {@link Unit#getConverterToAny(Unit)} failed.
 */
@Test
public void testVolumeEquivalences() throws IncommensurableException {
    assertEquivalent(  "L", Units.LITRE.divide  (1E+00),  "dm³", Units.CUBIC_METRE.divide  (1E+03));
    assertEquivalent( "mL", Units.LITRE.divide  (1E+03),  "cm³", Units.CUBIC_METRE.divide  (1E+06));
    assertEquivalent( "µL", Units.LITRE.divide  (1E+06),  "mm³", Units.CUBIC_METRE.divide  (1E+09));
    assertEquivalent( "fL", Units.LITRE.divide  (1E+15),  "µm³", Units.CUBIC_METRE.divide  (1E+18));
    assertEquivalent( "yL", Units.LITRE.divide  (1E+24),  "nm³", Units.CUBIC_METRE.divide  (1E+27));
    assertEquivalent( "kL", Units.LITRE.multiply(1E+03),   "m³", Units.CUBIC_METRE.divide  (1E+00));
    assertEquivalent( "ML", Units.LITRE.multiply(1E+06), "dam³", Units.CUBIC_METRE.multiply(1E+03));
    assertEquivalent( "GL", Units.LITRE.multiply(1E+09),  "hm³", Units.CUBIC_METRE.multiply(1E+06));
    assertEquivalent( "TL", Units.LITRE.multiply(1E+12),  "km³", Units.CUBIC_METRE.multiply(1E+09));
    assertEquivalent( "ZL", Units.LITRE.multiply(1E+21),  "Mm³", Units.CUBIC_METRE.multiply(1E+18));
    assertEquals    ( "dL", Units.LITRE.divide  (1E+01).getSymbol());
    assertEquals    ( "cL", Units.LITRE.divide  (1E+02).getSymbol());
    assertEquals    ( "nL", Units.LITRE.divide  (1E+09).getSymbol());
    assertEquals    ( "pL", Units.LITRE.divide  (1E+12).getSymbol());
    assertEquals    ( "aL", Units.LITRE.divide  (1E+18).getSymbol());
    assertEquals    ( "zL", Units.LITRE.divide  (1E+21).getSymbol());
    assertEquals    ("daL", Units.LITRE.multiply(1E+01).getSymbol());
    assertEquals    ( "hL", Units.LITRE.multiply(1E+02).getSymbol());
    assertEquals    ( "PL", Units.LITRE.multiply(1E+15).getSymbol());
    assertEquals    ( "EL", Units.LITRE.multiply(1E+18).getSymbol());
    assertEquals    ( "YL", Units.LITRE.multiply(1E+24).getSymbol());
}
 
Example #3
Source File: SystemUnitTest.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Tests {@link SystemUnit#getConverterToAny(Unit)}.
 *
 * @throws IncommensurableException if two units were not expected to be considered incompatible.
 */
@Test
@DependsOnMethod("testGetConverterTo")
public void testGetConverterToAny() throws IncommensurableException {
    assertTrue(Units.METRE .getConverterToAny(Units.METRE ).isIdentity());
    assertTrue(Units.SECOND.getConverterToAny(Units.SECOND).isIdentity());
    assertTrue(Units.RADIAN.getConverterToAny(Units.RADIAN).isIdentity());
    assertTrue(Units.RADIAN.getConverterToAny(Units.UNITY ).isIdentity());
    assertTrue(Units.UNITY .getConverterToAny(Units.RADIAN).isIdentity());
    try {
        Units.METRE.getConverterToAny(Units.SECOND);
        fail("Conversion should not have been allowed.");
    } catch (IncommensurableException e) {
        final String message = e.getMessage();
        assertTrue(message, message.contains("m"));     // metre unit symbol
        assertTrue(message, message.contains("s"));     // second unit symbol
    }
}
 
Example #4
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 #5
Source File: CoordinateSystemsTest.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Tests {@link CoordinateSystems#swapAndScaleAxes(CoordinateSystem, CoordinateSystem)} with a non-square matrix.
 *
 * @throws IncommensurableException if a conversion between incompatible units was attempted.
 */
@Test
@DependsOnMethod("testSwapAndScaleAxes")
public void testScaleAndSwapAxesNonSquare() throws IncommensurableException {
    final DefaultCartesianCS cs = new DefaultCartesianCS(singletonMap(NAME_KEY, "Test"),
            new DefaultCoordinateSystemAxis(getProperties(HardCodedAxes.SOUTHING), "y", AxisDirection.SOUTH, Units.CENTIMETRE),
            new DefaultCoordinateSystemAxis(getProperties(HardCodedAxes.EASTING),  "x", AxisDirection.EAST,  Units.MILLIMETRE));

    Matrix matrix = swapAndScaleAxes(HardCodedCS.CARTESIAN_2D, cs);
    assertMatrixEquals("(x,y) → (y,x)", Matrices.create(3, 3, new double[] {
            0,  -100,    0,
            1000,  0,    0,
            0,     0,    1
    }), matrix, STRICT);

    matrix = swapAndScaleAxes(HardCodedCS.CARTESIAN_3D, cs);
    assertMatrixEquals("(x,y,z) → (y,x)", Matrices.create(3, 4, new double[] {
            0,  -100,   0,   0,
            1000,  0,   0,   0,
            0,     0,   0,   1
    }), matrix, STRICT);
}
 
Example #6
Source File: CoordinateSystemsTest.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Tests {@link CoordinateSystems#swapAndScaleAxes(CoordinateSystem, CoordinateSystem)}
 * with a more arbitrary case, which include unit conversions.
 *
 * @throws IncommensurableException if a conversion between incompatible units was attempted.
 */
@Test
@DependsOnMethod("testSwapAndScaleAxes3D")
public void testSwapAndScaleAxes() throws IncommensurableException {
    final CoordinateSystem hxy = new DefaultCartesianCS(singletonMap(NAME_KEY, "(h,x,y)"),
            HardCodedAxes.HEIGHT_cm,
            HardCodedAxes.EASTING,
            HardCodedAxes.NORTHING);
    final CoordinateSystem yxh = new DefaultCartesianCS(singletonMap(NAME_KEY, "(y,x,h)"),
            HardCodedAxes.SOUTHING,
            HardCodedAxes.EASTING,
            HardCodedAxes.DEPTH);
    assertTrue(swapAndScaleAxes(hxy, hxy).isIdentity());
    assertTrue(swapAndScaleAxes(yxh, yxh).isIdentity());
    assertMatrixEquals("(h,x,y) → (y,x,h)", Matrices.create(4, 4, new double[] {
            0,    0,   -1,    0,
            0,    1,    0,    0,
           -0.01, 0,    0,    0,
            0,    0,    0,    1}), swapAndScaleAxes(hxy, yxh), STRICT);

    assertMatrixEquals("(y,x,h) → (h,x,y)", Matrices.create(4, 4, new double[] {
            0,    0, -100,    0,
            0,    1,    0,    0,
           -1,    0,    0,    0,
            0,    0,    0,    1}), swapAndScaleAxes(yxh, hxy), STRICT);
}
 
Example #7
Source File: CoordinateSystemsTest.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Tests {@link CoordinateSystems#swapAndScaleAxes(CoordinateSystem, CoordinateSystem)} for (λ,φ,h) ↔ (φ,λ,h).
 * This very common conversion is of critical importance to Apache SIS.
 *
 * @throws IncommensurableException if a conversion between incompatible units was attempted.
 */
@Test
@DependsOnMethod("testSwapAndScaleAxes2D")
public void testSwapAndScaleAxes3D() throws IncommensurableException {
    final CoordinateSystem λφh = new DefaultEllipsoidalCS(singletonMap(NAME_KEY, "(λ,φ,h)"),
            HardCodedAxes.GEODETIC_LONGITUDE,
            HardCodedAxes.GEODETIC_LATITUDE,
            HardCodedAxes.ELLIPSOIDAL_HEIGHT);
    final CoordinateSystem φλh = new DefaultEllipsoidalCS(singletonMap(NAME_KEY, "(φ,λ,h)"),
            HardCodedAxes.GEODETIC_LATITUDE,
            HardCodedAxes.GEODETIC_LONGITUDE,
            HardCodedAxes.ELLIPSOIDAL_HEIGHT);
    final Matrix expected = Matrices.create(4, 4, new double[] {
            0, 1, 0, 0,
            1, 0, 0, 0,
            0, 0, 1, 0,
            0, 0, 0, 1});
    assertTrue(swapAndScaleAxes(λφh, λφh).isIdentity());
    assertTrue(swapAndScaleAxes(φλh, φλh).isIdentity());
    assertMatrixEquals("(λ,φ,h) → (φ,λ,h)", expected, swapAndScaleAxes(λφh, φλh), STRICT);
    assertMatrixEquals("(φ,λ,h) → (λ,φ,h)", expected, swapAndScaleAxes(φλh, λφh), STRICT);
}
 
Example #8
Source File: CoordinateSystemsTest.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Tests {@link CoordinateSystems#swapAndScaleAxes(CoordinateSystem, CoordinateSystem)} for (λ,φ) ↔ (φ,λ).
 * This very common conversion is of critical importance to Apache SIS.
 *
 * @throws IncommensurableException if a conversion between incompatible units was attempted.
 */
@Test
public void testSwapAndScaleAxes2D() throws IncommensurableException {
    final CoordinateSystem λφ = new DefaultEllipsoidalCS(singletonMap(NAME_KEY, "(λ,φ)"),
            HardCodedAxes.GEODETIC_LONGITUDE,
            HardCodedAxes.GEODETIC_LATITUDE);
    final CoordinateSystem φλ = new DefaultEllipsoidalCS(singletonMap(NAME_KEY, "(φ,λ)"),
            HardCodedAxes.GEODETIC_LATITUDE,
            HardCodedAxes.GEODETIC_LONGITUDE);
    final Matrix expected = Matrices.create(3, 3, new double[] {
            0, 1, 0,
            1, 0, 0,
            0, 0, 1});
    assertTrue(swapAndScaleAxes(λφ, λφ).isIdentity());
    assertTrue(swapAndScaleAxes(φλ, φλ).isIdentity());
    assertMatrixEquals("(λ,φ) → (φ,λ)", expected, swapAndScaleAxes(λφ, φλ), STRICT);
    assertMatrixEquals("(φ,λ) → (λ,φ)", expected, swapAndScaleAxes(φλ, λφ), STRICT);
}
 
Example #9
Source File: CoordinateFormat.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Adjusts the resolution units for the given coordinate system axis. This methods select the units which
 * result in the smallest absolute value of {@link #resolution}.
 *
 * @param  maxValue  the maximal absolute value that a coordinate on the axis may have.
 * @param  axisUnit  {@link CoordinateSystemAxis#getUnit()}.
 * @return whether the given axis unit is compatible with the expected unit.
 */
boolean forAxis(double maxValue, final Unit<?> axisUnit) throws IncommensurableException {
    if (!axisUnit.isCompatible(unit)) {
        return false;
    }
    final UnitConverter c = unit.getConverterToAny(axisUnit);
    final double r = Math.abs(c.convert(resolution));
    if (r < resolution) {
        resolution = r;                                         // To units producing the smallest value.
        unit = axisUnit;
    } else {
        maxValue = Math.abs(c.inverse().convert(maxValue));     // From axis units to selected units.
    }
    if (maxValue > magnitude) {
        magnitude = maxValue;
    }
    return true;
}
 
Example #10
Source File: CoordinateOperationFinder.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Creates an operation between two vertical coordinate reference systems.
 * The default implementation checks if both CRS use the same datum, then
 * adjusts for axis direction and units.
 *
 * <p>This method returns only <em>one</em> step for a chain of concatenated operations (to be built by the caller).
 * But a list is returned because the same step may be implemented by different operation methods. Only one element
 * in the returned list should be selected (usually the first one).</p>
 *
 * @param  sourceCRS  input coordinate reference system.
 * @param  targetCRS  output coordinate reference system.
 * @return a coordinate operation from {@code sourceCRS} to {@code targetCRS}.
 * @throws FactoryException if the operation can not be constructed.
 *
 * @todo Needs to implement vertical datum shift.
 */
protected List<CoordinateOperation> createOperationStep(final VerticalCRS sourceCRS,
                                                        final VerticalCRS targetCRS)
        throws FactoryException
{
    final VerticalDatum sourceDatum = sourceCRS.getDatum();
    final VerticalDatum targetDatum = targetCRS.getDatum();
    if (!equalsIgnoreMetadata(sourceDatum, targetDatum)) {
        throw new OperationNotFoundException(notFoundMessage(sourceDatum, targetDatum));
    }
    final VerticalCS sourceCS = sourceCRS.getCoordinateSystem();
    final VerticalCS targetCS = targetCRS.getCoordinateSystem();
    final Matrix matrix;
    try {
        matrix = CoordinateSystems.swapAndScaleAxes(sourceCS, targetCS);
    } catch (IllegalArgumentException | IncommensurableException exception) {
        throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS), exception);
    }
    return asList(createFromAffineTransform(AXIS_CHANGES, sourceCRS, targetCRS, matrix));
}
 
Example #11
Source File: CoordinateOperationRegistry.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Returns an affine transform between two coordinate systems.
 * Only units and axes order are taken in account by this method.
 *
 * @param  sourceCRS  the source coordinate reference system.
 * @param  targetCRS  the target coordinate reference system.
 * @param  mtFactory  the math transform factory to use.
 * @return the transform from the given source to the given target CRS, or {@code null} if none is needed.
 * @throws IllegalArgumentException if the coordinate systems are not of the same type or axes do not match.
 * @throws IncommensurableException if the units are not compatible or a unit conversion is non-linear.
 * @throws FactoryException if an error occurred while creating a math transform.
 */
private static MathTransform swapAndScaleAxes(final CoordinateReferenceSystem sourceCRS,
                                              final CoordinateReferenceSystem targetCRS,
                                              final MathTransformFactory      mtFactory)
        throws IllegalArgumentException, IncommensurableException, FactoryException
{
    /*
     * Assertion: source and target CRS must be equals, ignoring change in axis order or units.
     * The first line is for disabling this check if the number of dimensions are not the same
     * (e.g. as in the "geographic 3D to geographic 2D" conversion) because ALLOW_VARIANT mode
     * still requires a matching number of dimensions.
     */
    assert ReferencingUtilities.getDimension(sourceCRS) != ReferencingUtilities.getDimension(targetCRS)
            || Utilities.deepEquals(sourceCRS, targetCRS, ComparisonMode.ALLOW_VARIANT);
    final Matrix m = CoordinateSystems.swapAndScaleAxes(sourceCRS.getCoordinateSystem(), targetCRS.getCoordinateSystem());
    return (m.isIdentity()) ? null : mtFactory.createAffineTransform(m);
}
 
Example #12
Source File: DefaultConversion.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Concatenates to the given transform the operation needed for swapping and scaling the axes.
 * The two coordinate systems must implement the same GeoAPI coordinate system interface.
 * For example if {@code sourceCRS} uses a {@code CartesianCS}, then {@code targetCRS} must use
 * a {@code CartesianCS} too.
 *
 * @param  transform  the transform to which to concatenate axis changes.
 * @param  sourceCRS  the first CRS of the pair for which to check for axes changes.
 * @param  targetCRS  the second CRS of the pair for which to check for axes changes.
 * @param  interpDim  the number of dimensions of the interpolation CRS, or 0 if none.
 * @param  isSource   {@code true} for pre-concatenating the changes, or {@code false} for post-concatenating.
 * @param  factory    the factory to use for performing axis changes.
 */
private static MathTransform swapAndScaleAxes(MathTransform transform,
        final CoordinateReferenceSystem sourceCRS,
        final CoordinateReferenceSystem targetCRS,
        final int interpDim, final boolean isSource,
        final MathTransformFactory factory) throws FactoryException
{
    if (sourceCRS != null && targetCRS != null && sourceCRS != targetCRS) try {
        Matrix m = CoordinateSystems.swapAndScaleAxes(sourceCRS.getCoordinateSystem(),
                                                      targetCRS.getCoordinateSystem());
        if (!m.isIdentity()) {
            if (interpDim != 0) {
                m = Matrices.createPassThrough(interpDim, m, 0);
            }
            final MathTransform s = factory.createAffineTransform(m);
            transform = factory.createConcatenatedTransform(isSource ? s : transform,
                                                            isSource ? transform : s);
        }
    } catch (IncommensurableException e) {
        throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2,
                (isSource ? "sourceCRS" : "targetCRS"),
                (isSource ?  sourceCRS  :  targetCRS).getName()), e);
    }
    return transform;
}
 
Example #13
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 #14
Source File: TransformCommand.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Computes the suggested precision for printing values in the given units.
 *
 * @throws IncommensurableException should never happen.
 */
private void computeNumFractionDigits(final CoordinateSystem cs) throws IncommensurableException {
    final int dimension = cs.getDimension();
    numFractionDigits = new int[dimension];
    thresholdForScientificNotation = new double[dimension];
    for (int i=0; i<dimension; i++) {
        final Unit<?> unit = cs.getAxis(0).getUnit();
        final Unit<?> source;
        double precision;
        if (Units.isLinear(unit)) {
            precision = Formulas.LINEAR_TOLERANCE;
            source = Units.METRE;
        } else if (Units.isAngular(unit)) {
            precision = Formulas.ANGULAR_TOLERANCE;
            source = Units.DEGREE;
        } else {
            precision = 0.001;
            source = unit;
        }
        precision = source.getConverterToAny(unit).convert(precision);
        if (precision > 0) {
            numFractionDigits[i] = Math.max(DecimalFunctions.fractionDigitsForDelta(precision, false) + 1, 0);
        }
        thresholdForScientificNotation[i] = MathFunctions.pow10(coordinateWidth - 1 - numFractionDigits[i]);
    }
}
 
Example #15
Source File: QuantityType.java    From smarthome with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Convert this QuantityType to a new {@link QuantityType} using the given target unit.
 *
 * @param targetUnit the unit to which this {@link QuantityType} will be converted to.
 * @return the new {@link QuantityType} in the given {@link Unit} or {@code null} in case of a
 */
@SuppressWarnings("unchecked")
public @Nullable QuantityType<T> toUnit(Unit<?> targetUnit) {
    if (!targetUnit.equals(getUnit())) {
        try {
            UnitConverter uc = getUnit().getConverterToAny(targetUnit);
            Quantity<?> result = Quantities.getQuantity(uc.convert(quantity.getValue()), targetUnit);

            return new QuantityType<T>(result.getValue(), (Unit<T>) targetUnit);
        } catch (UnconvertibleException | IncommensurableException e) {
            logger.debug("Unable to convert unit from {} to {}", getUnit(), targetUnit);
            return null;
        }
    }
    return this;
}
 
Example #16
Source File: Axis.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Returns the range of this wraparound axis, or {@link Double#NaN} if this axis is not a wraparound axis.
 */
@SuppressWarnings("fallthrough")
private double wraparoundRange() {
    if (isWraparound()) {
        double period = Longitude.MAX_VALUE - Longitude.MIN_VALUE;
        final Unit<?> unit = getUnit();
        if (unit != null) try {
            period = unit.getConverterToAny(Units.DEGREE).convert(period);
        } catch (IncommensurableException e) {
            warning(e, Errors.Keys.InconsistentUnitsForCS_1, unit);
            return Double.NaN;
        }
        return period;
    }
    return Double.NaN;
}
 
Example #17
Source File: ChannelDecoder.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Converts the given numerical values to date, using the information provided in the given unit symbol.
 * The unit symbol is typically a string like <cite>"days since 1970-01-01T00:00:00Z"</cite>.
 *
 * @param  values  the values to convert. May contain {@code null} elements.
 * @return the converted values. May contain {@code null} elements.
 */
@Override
public Date[] numberToDate(final String symbol, final Number... values) {
    final Date[] dates = new Date[values.length];
    final Matcher parts = Variable.TIME_UNIT_PATTERN.matcher(symbol);
    if (parts.matches()) try {
        final UnitConverter converter = Units.valueOf(parts.group(1)).getConverterToAny(Units.MILLISECOND);
        final long epoch = StandardDateFormat.toDate(StandardDateFormat.FORMAT.parse(parts.group(2))).getTime();
        for (int i=0; i<values.length; i++) {
            final Number value = values[i];
            if (value != null) {
                dates[i] = new Date(epoch + Math.round(converter.convert(value.doubleValue())));
            }
        }
    } catch (IncommensurableException | ParserException | DateTimeException | ArithmeticException e) {
        listeners.warning(e);
    }
    return dates;
}
 
Example #18
Source File: AbstractEnvelope.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the envelope span along the specified dimension, in terms of the given units.
 * The default implementation invokes {@link #getSpan(int)} and converts the result.
 *
 * @param  dimension  the dimension to query.
 * @param  unit  the unit for the return value.
 * @return the span in terms of the given unit.
 * @throws IndexOutOfBoundsException if the given index is out of bounds.
 * @throws IncommensurableException if the length can't be converted to the specified units.
 */
public double getSpan(final int dimension, final Unit<?> unit)
        throws IndexOutOfBoundsException, IncommensurableException
{
    double value = getSpan(dimension);
    final CoordinateSystemAxis axis = getAxis(getCoordinateReferenceSystem(), dimension);
    if (axis != null) {
        final Unit<?> source = axis.getUnit();
        if (source != null) {
            value = source.getConverterToAny(unit).convert(value);
        }
    }
    return value;
}
 
Example #19
Source File: MeasurementRange.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Casts the specified range to the specified type. If this class is associated to a unit of
 * measurement, then this method convert the {@code range} unit to the same unit than this
 * instance.
 *
 * @param  type  the class to cast to. Must be one of {@link Byte}, {@link Short},
 *               {@link Integer}, {@link Long}, {@link Float} or {@link Double}.
 * @return the casted range, or {@code range} if no cast is needed.
 */
@Override
<N extends Number & Comparable<? super N>>
NumberRange<N> convertAndCast(final NumberRange<?> range, final Class<N> type)
        throws IllegalArgumentException
{
    if (range instanceof MeasurementRange<?>) try {
        return ((MeasurementRange<?>) range).convertAndCast(type, unit);
    } catch (IncommensurableException e) {
        throw new IllegalArgumentException(Errors.format(Errors.Keys.IncompatibleUnits_2,
                ((MeasurementRange<?>) range).unit, unit), e);
    }
    return new MeasurementRange<>(type, range, unit);
}
 
Example #20
Source File: MeasurementRange.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * If the given range is an instance of {@code MeasurementRange}, converts that
 * range to the unit of this range. Otherwise returns the given range unchanged.
 *
 * @param  range  the range to convert.
 * @return the converted range.
 * @throws IllegalArgumentException if the given target unit is not compatible with the unit of this range.
 */
private <N extends E> Range<N> convert(final Range<N> range) throws IllegalArgumentException {
    if (range instanceof MeasurementRange<?>) try {
        return ((MeasurementRange<N>) range).convertAndCast(range.elementType, unit);
    } catch (IncommensurableException e) {
        throw new IllegalArgumentException(Errors.format(Errors.Keys.IncompatibleUnits_2,
                ((MeasurementRange<?>) range).unit, unit), e);
    }
    return range;
}
 
Example #21
Source File: MeasurementRange.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Casts this range to the specified type and converts to the specified unit.
 * This method is invoked on the {@code other} instance in expressions like
 * {@code this.operation(other)}.
 *
 * @param  type  the class to cast to. Must be one of {@link Byte}, {@link Short},
 *               {@link Integer}, {@link Long}, {@link Float} or {@link Double}.
 * @param  targetUnit the target unit, or {@code null} for no change.
 * @return the casted range, or {@code this}.
 * @throws IncommensurableException if the given target unit is not compatible with the unit of this range.
 */
@SuppressWarnings("unchecked")
private <N extends Number & Comparable<? super N>> MeasurementRange<N>
        convertAndCast(final Class<N> type, Unit<?> targetUnit) throws IncommensurableException
{
    if (targetUnit == null || targetUnit.equals(unit)) {
        if (elementType == type) {
            return (MeasurementRange<N>) this;
        }
        targetUnit = unit;
    } else if (unit != null) {
        final UnitConverter converter = unit.getConverterToAny(targetUnit);
        if (!converter.isIdentity()) {
            boolean minInc = isMinIncluded;
            boolean maxInc = isMaxIncluded;
            double minimum = converter.convert(getMinDouble());
            double maximum = converter.convert(getMaxDouble());
            if (minimum > maximum) {
                final double  td = minimum; minimum = maximum; maximum = td;
                final boolean tb = minInc;  minInc  = maxInc;  maxInc  = tb;
            }
            if (Numbers.isInteger(type)) {
                minInc &= (minimum == (minimum = Math.floor(minimum)));
                maxInc &= (maximum == (maximum = Math.ceil (maximum)));
            }
            return new MeasurementRange<>(type,
                    Numbers.cast(minimum, type), minInc,
                    Numbers.cast(maximum, type), maxInc, targetUnit);
        }
    }
    return new MeasurementRange<>(type, this, targetUnit);
}
 
Example #22
Source File: Angle.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the angular value of the axis having the given direction.
 * This helper method is used for subclass constructors expecting a {@link DirectPosition} argument.
 *
 * @param  position  the position from which to get an angular value.
 * @param  positive  axis direction of positive values.
 * @param  negative  axis direction of negative values.
 * @return angular value in degrees.
 * @throws IllegalArgumentException if the given coordinate it not associated to a CRS,
 *         or if no axis oriented toward the given directions is found, or if that axis
 *         does not use {@linkplain Units#isAngular angular units}.
 */
static double valueOf(final DirectPosition position, final AxisDirection positive, final AxisDirection negative) {
    final CoordinateReferenceSystem crs = position.getCoordinateReferenceSystem();
    if (crs == null) {
        throw new IllegalArgumentException(Errors.format(Errors.Keys.UnspecifiedCRS));
    }
    final CoordinateSystem cs = crs.getCoordinateSystem();
    final int dimension = cs.getDimension();
    IncommensurableException cause = null;
    for (int i=0; i<dimension; i++) {
        final CoordinateSystemAxis axis = cs.getAxis(i);
        final AxisDirection dir = axis.getDirection();
        final boolean isPositive = dir.equals(positive);
        if (isPositive || dir.equals(negative)) {
            double value = position.getOrdinate(i);
            if (!isPositive) value = -value;
            final Unit<?> unit = axis.getUnit();
            if (unit != Units.DEGREE) try {
                value = unit.getConverterToAny(Units.DEGREE).convert(value);
            } catch (IncommensurableException e) {
                cause = e;
                break;
            }
            return value;
        }
    }
    throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalCRSType_1,
            Classes.getLeafInterfaces(crs.getClass(), CoordinateReferenceSystem.class)[0]), cause);
}
 
Example #23
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 #24
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 #25
Source File: MetadataReader.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Fills one dimension of the geographic bounding box or vertical extent.
 * The extent values are written in the given {@code extent} array.
 *
 * @param  dim         the dimension for which to get the extent.
 * @param  targetUnit  the destination unit of the extent.
 * @param  positive    the direction considered positive, or {@code null} if the unit symbol is not expected to contain a direction.
 * @param  extent      where to store the minimum and maximum values.
 * @param  index       index where to store the minimum value in {@code extent}. The maximum value is stored at {@code index+1}.
 * @return {@code true} if a minimum or a maximum value has been found.
 */
private boolean fillExtent(final AttributeNames.Dimension dim, final Unit<?> targetUnit, final AxisDirection positive,
                           final double[] extent, final int index)
{
    double min = numericValue(dim.MINIMUM);
    double max = numericValue(dim.MAXIMUM);
    boolean hasExtent = !Double.isNaN(min) || !Double.isNaN(max);
    if (hasExtent) {
        final String symbol = stringValue(dim.UNITS);
        if (symbol != null) {
            try {
                final UnitConverter c = Units.valueOf(symbol).getConverterToAny(targetUnit);
                min = c.convert(min);
                max = c.convert(max);
            } catch (ParserException | IncommensurableException e) {
                warning(e);
            }
            boolean reverse = false;
            if (positive != null) {
                reverse = AxisDirections.opposite(positive).equals(Axis.direction(symbol));
            } else if (dim.POSITIVE != null) {
                // For now, only the vertical axis have a "positive" attribute.
                reverse = CF.POSITIVE_DOWN.equals(stringValue(dim.POSITIVE));
            }
            if (reverse) {
                final double tmp = min;
                min = -max;
                max = -tmp;
            }
        }
    }
    extent[index  ] = min;
    extent[index+1] = max;
    return hasExtent;
}
 
Example #26
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 #27
Source File: BursaWolfInfo.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Sets a Bursa-Wolf parameter from an EPSG parameter.
 * This method recognizes only the parameters that do not depend on time (EPSG:8605 to 8611).
 * This method does not recognize the time-dependent parameters (EPSG:1040 to 1046) because
 * they are not used in WKT 1 {@code TOWGS84} elements.
 *
 * @param  parameters  the Bursa-Wolf parameters to modify.
 * @param  code        the EPSG code for a parameter from the [PARAMETER_CODE] column.
 * @param  value       the value of the parameter from the [PARAMETER_VALUE] column.
 * @param  unit        the unit of the parameter value from the [UOM_CODE] column.
 * @param  locale      the locale, used only if an error message need to be formatted.
 * @throws FactoryDataException if the code is unrecognized.
 */
static void setBursaWolfParameter(final BursaWolfParameters parameters, final int code,
        double value, final Unit<?> unit, final Locale locale) throws FactoryDataException
{
    Unit<?> target = unit;
    if (code >= 8605) {
        if      (code <= 8607) target = Units.METRE;
        else if (code <= 8610) target = Units.ARC_SECOND;
        else if (code == 8611) target = Units.PPM;
    }
    if (target != unit) try {
        value = unit.getConverterToAny(target).convert(value);
    } catch (IncommensurableException e) {
        throw new FactoryDataException(Errors.getResources(locale).getString(Errors.Keys.IncompatibleUnit_1, unit), e);
    }
    switch (code) {
        case 8605: parameters.tX = value; break;
        case 8606: parameters.tY = value; break;
        case 8607: parameters.tZ = value; break;
        case 8608: parameters.rX = value; break;
        case 8609: parameters.rY = value; break;
        case 8610: parameters.rZ = value; break;
        case 8611: parameters.dS = value; break;
        default: throw new FactoryDataException(Errors.getResources(locale)
                            .getString(Errors.Keys.UnexpectedParameter_1, code));
    }
}
 
Example #28
Source File: MeasurementRangeTest.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Tests unit conversions by the {@link MeasurementRange#convertTo(Unit)} method.
 *
 * @throws IncommensurableException if a conversion between incompatible units were attempted.
 */
@Test
public void testConvertTo() throws IncommensurableException {
    final MeasurementRange<Float> range = MeasurementRange.create(1000f, true, 2000f, true, Units.METRE);
    assertSame(range, range.convertTo(Units.METRE));
    assertEquals(MeasurementRange.create(1f, true, 2f, true, Units.KILOMETRE), range.convertTo(Units.KILOMETRE));
}
 
Example #29
Source File: CoordinateOperationFinder.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates an operation between two temporal coordinate reference systems.
 * The default implementation checks if both CRS use the same datum, then
 * adjusts for axis direction, units and epoch.
 *
 * <p>This method returns only <em>one</em> step for a chain of concatenated operations (to be built by the caller).
 * But a list is returned because the same step may be implemented by different operation methods. Only one element
 * in the returned list should be selected (usually the first one).</p>
 *
 * @param  sourceCRS  input coordinate reference system.
 * @param  targetCRS  output coordinate reference system.
 * @return a coordinate operation from {@code sourceCRS} to {@code targetCRS}.
 * @throws FactoryException if the operation can not be constructed.
 */
protected List<CoordinateOperation> createOperationStep(final TemporalCRS sourceCRS,
                                                        final TemporalCRS targetCRS)
        throws FactoryException
{
    final TemporalDatum sourceDatum = sourceCRS.getDatum();
    final TemporalDatum targetDatum = targetCRS.getDatum();
    final TimeCS sourceCS = sourceCRS.getCoordinateSystem();
    final TimeCS targetCS = targetCRS.getCoordinateSystem();
    /*
     * Compute the epoch shift.  The epoch is the time "0" in a particular coordinate reference system.
     * For example, the epoch for java.util.Date object is january 1, 1970 at 00:00 UTC. We compute how
     * much to add to a time in 'sourceCRS' in order to get a time in 'targetCRS'. This "epoch shift" is
     * in units of 'targetCRS'.
     */
    final Unit<Time> targetUnit = targetCS.getAxis(0).getUnit().asType(Time.class);
    double epochShift = sourceDatum.getOrigin().getTime() -
                        targetDatum.getOrigin().getTime();
    epochShift = Units.MILLISECOND.getConverterTo(targetUnit).convert(epochShift);
    /*
     * Check axis directions. The method 'swapAndScaleAxes' should returns a matrix of size 2×2.
     * The element at index (0,0) may be +1 if source and target axes are in the same direction,
     * or -1 if there are in opposite direction ("PAST" vs "FUTURE"). The value may be something
     * else than ±1 if a unit conversion is applied too.  For example the value is 60 if time in
     * sourceCRS is in hours while time in targetCRS is in minutes.
     *
     * The "epoch shift" previously computed is a translation. Consequently, it is added to element (0,1).
     */
    final Matrix matrix;
    try {
        matrix = CoordinateSystems.swapAndScaleAxes(sourceCS, targetCS);
    } catch (IllegalArgumentException | IncommensurableException exception) {
        throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS), exception);
    }
    final int translationColumn = matrix.getNumCol() - 1;           // Paranoiac check: should always be 1.
    final double translation = matrix.getElement(0, translationColumn);
    matrix.setElement(0, translationColumn, translation + epochShift);
    return asList(createFromAffineTransform(AXIS_CHANGES, sourceCRS, targetCRS, matrix));
}
 
Example #30
Source File: UnitsTest.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Tests the conversion factor of {@link Units#DECIBEL}.
 *
 * @throws IncommensurableException if the conversion can not be applied.
 *
 * @see <a href="https://en.wikipedia.org/wiki/Decibel#Conversions">Decibel on Wikipedia</a>
 */
@Test
public void testDecibelConversionFactor() throws IncommensurableException {
    final Unit<?> bel = Units.valueOf("B");
    assertEquals(10,      bel.getConverterToAny(DECIBEL).convert(1), STRICT);
    assertEquals(0.1,     DECIBEL.getConverterToAny(bel).convert(1), STRICT);
    assertEquals(3.16228,     bel.getConverterToAny(UNITY).convert(1), 5E-6);
    assertEquals(1.12202, DECIBEL.getConverterToAny(UNITY).convert(1), 5E-6);
    /*
     * Reverse of last two lines above.
     */
    assertEquals(1, UNITY.getConverterToAny(bel)    .convert(3.16228), 2E-5);
    assertEquals(1, UNITY.getConverterToAny(DECIBEL).convert(1.12202), 2E-5);
}