Search in sources :

Example 26 with UnitConverter

use of javax.measure.UnitConverter in project n2a by frothga.

the class ExportJob method biophysicalUnits.

public String biophysicalUnits(String value) {
    value = value.trim();
    int unitIndex = findUnits(value);
    // no number or no units, so probably something else
    if (unitIndex == 0 || unitIndex >= value.length())
        return value;
    String unitString = value.substring(unitIndex).trim();
    String numberString = value.substring(0, unitIndex);
    Unit<?> unit;
    try {
        unit = UCUM.parse(unitString);
    } catch (Exception e) {
        return value;
    }
    double v = 0;
    try {
        v = Double.valueOf(numberString);
    } catch (NumberFormatException error) {
        return value;
    }
    // Determine power in numberString itself
    double power = 1;
    if (v != 0)
        power = Math.pow(10, Math.floor((Math.getExponent(v) + 1) / baseRatio));
    // Find closest matching unit
    Entry<Unit<?>, String> closest = null;
    // like closest, but only ratios >= 1
    Entry<Unit<?>, String> closestAbove = null;
    double closestRatio = Double.POSITIVE_INFINITY;
    double closestAboveRatio = Double.POSITIVE_INFINITY;
    for (Entry<Unit<?>, String> e : nmlUnits.entrySet()) {
        Unit<?> u = e.getKey();
        if (u.isCompatible(unit)) {
            try {
                UnitConverter converter = unit.getConverterToAny(u);
                double ratio = converter.convert(power);
                if (ratio < 1) {
                    ratio = 1 / ratio;
                } else {
                    if (ratio < closestAboveRatio) {
                        closestAboveRatio = ratio;
                        closestAbove = e;
                    }
                }
                if (ratio < closestRatio) {
                    closestRatio = ratio;
                    closest = e;
                }
            } catch (UnconvertibleException | IncommensurableException e1) {
            }
        }
    }
    if (closest == null) {
        // completely give up on conversion
        return value;
    }
    if (closestAboveRatio <= 1000 + epsilon)
        closest = closestAbove;
    try {
        UnitConverter converter = unit.getConverterToAny(closest.getKey());
        v = converter.convert(v);
    } catch (Exception error) {
    }
    return print(v) + closest.getValue();
}
Also used : IncommensurableException(javax.measure.IncommensurableException) UnitConverter(javax.measure.UnitConverter) UnconvertibleException(javax.measure.UnconvertibleException) Unit(javax.measure.Unit) IncommensurableException(javax.measure.IncommensurableException) UnconvertibleException(javax.measure.UnconvertibleException) ParseException(gov.sandia.n2a.language.ParseException)

Example 27 with UnitConverter

use of javax.measure.UnitConverter in project unit-api by unitsofmeasurement.

the class TestUnit method getConverterToAny.

public UnitConverter getConverterToAny(Unit<?> that) throws IncommensurableException, UnconvertibleException {
    if (!isCompatible(that))
        throw new IncommensurableException(this + " is not compatible with " + that);
    // Since both units are
    TestUnit thatAbstr = (TestUnit) that;
    // compatible they must
    // be both test
    // units.
    Unit thisSystemUnit = this.getSystemUnit();
    UnitConverter thisToDimension = this.getSystemConverter();
    Unit thatSystemUnit = thatAbstr.getSystemUnit();
    UnitConverter thatToDimension = thatAbstr.getSystemConverter();
    return thatToDimension.inverse().concatenate(thisToDimension);
}
Also used : IncommensurableException(javax.measure.IncommensurableException) UnitConverter(javax.measure.UnitConverter) Unit(javax.measure.Unit) BaseUnit(javax.measure.test.unit.BaseUnit)

Example 28 with UnitConverter

use of javax.measure.UnitConverter in project sis by apache.

the class CoordinateFormat method parse.

/**
 * Parses a coordinate from the given character sequence.
 * This method presumes that the coordinate reference system is the {@linkplain #getDefaultCRS() default CRS}.
 * The parsing begins at the {@linkplain ParsePosition#getIndex() index} given by the {@code pos} argument.
 * If parsing succeeds, then the {@code pos} index is updated to the index after the last ordinate value and
 * the parsed coordinate is returned. Otherwise (if parsing fails), the {@code pos} index is left unchanged,
 * the {@code pos} {@linkplain ParsePosition#getErrorIndex() error index} is set to the index of the first
 * unparsable character and an exception is thrown with a similar {@linkplain ParseException#getErrorOffset()
 * error index}.
 *
 * @param  text  the character sequence for the coordinate to parse.
 * @param  pos   the index where to start the parsing.
 * @return the parsed coordinate (never {@code null}).
 * @throws ParseException if an error occurred while parsing the coordinate.
 */
@Override
public DirectPosition parse(final CharSequence text, final ParsePosition pos) throws ParseException {
    ArgumentChecks.ensureNonNull("text", text);
    ArgumentChecks.ensureNonNull("pos", pos);
    final int start = pos.getIndex();
    final int length = text.length();
    /*
         * The NumberFormat, DateFormat and AngleFormat work only on String values, not on CharSequence.
         * If the given text is not a String, we will convert an arbitrarily small section of the given
         * text. Note that this will require to adjust the ParsePosition indices.
         */
    final int offset;
    final String asString;
    final ParsePosition subPos;
    if (text instanceof String) {
        offset = 0;
        subPos = pos;
        asString = (String) text;
    } else {
        offset = start;
        subPos = new ParsePosition(0);
        asString = text.subSequence(start, Math.min(start + READ_AHEAD_LIMIT, length)).toString();
    }
    /*
         * The Format instances to be used for each ordinate values is determined by the default CRS.
         * If no such CRS has been specified, then we will parse everything as plain numbers.
         */
    if (lastCRS != defaultCRS) {
        initialize(defaultCRS);
    }
    final double[] ordinates;
    Format format;
    final Format[] formats = this.formats;
    if (formats != null) {
        format = null;
        ordinates = new double[formats.length];
    } else {
        format = getFormat(Number.class);
        ordinates = new double[DEFAULT_DIMENSION];
    }
    /*
         * For each ordinate value except the first one, we need to skip the separator.
         * If we do not find the separator, we may consider that we reached the coordinate
         * end ahead of time. We currently allow that only for coordinate without CRS.
         */
    for (int i = 0; i < ordinates.length; i++) {
        if (i != 0) {
            final int end = subPos.getIndex();
            int index = offset + end;
            while (!CharSequences.regionMatches(text, index, parseSeparator)) {
                if (index < length) {
                    final int c = Character.codePointAt(text, index);
                    if (Character.isSpaceChar(c)) {
                        index += Character.charCount(c);
                        continue;
                    }
                }
                if (formats == null) {
                    pos.setIndex(index);
                    return new GeneralDirectPosition(Arrays.copyOf(ordinates, i));
                }
                pos.setIndex(start);
                pos.setErrorIndex(index);
                throw new LocalizedParseException(getLocale(), Errors.Keys.UnexpectedCharactersAfter_2, new CharSequence[] { text.subSequence(start, end), CharSequences.token(text, index) }, index);
            }
            subPos.setIndex(index + parseSeparator.length() - offset);
        }
        /*
             * At this point 'subPos' is set to the beginning of the next ordinate to parse in 'asString'.
             * Parse the value as a number, angle or date, as determined from the coordinate system axis.
             */
        if (formats != null) {
            format = formats[i];
        }
        @SuppressWarnings("null") final Object object = format.parseObject(asString, subPos);
        if (object == null) {
            /*
                 * If we failed to parse, build an error message with the type that was expected for that ordinate.
                 * If the given CharSequence was not a String, we may need to update the error index since we tried
                 * to parse only a substring.
                 */
            Class<?> type = Number.class;
            if (types != null) {
                switch(types[i]) {
                    case LONGITUDE:
                        type = Longitude.class;
                        break;
                    case LATITUDE:
                        type = Latitude.class;
                        break;
                    case ANGLE:
                        type = Angle.class;
                        break;
                    case DATE:
                        type = Date.class;
                        break;
                }
            }
            pos.setIndex(start);
            if (subPos != pos) {
                pos.setErrorIndex(offset + subPos.getErrorIndex());
            }
            throw new LocalizedParseException(getLocale(), type, text, pos);
        }
        double value;
        if (object instanceof Angle) {
            value = ((Angle) object).degrees();
        } else if (object instanceof Date) {
            value = ((Date) object).getTime() - epochs[i];
        } else {
            value = ((Number) object).doubleValue();
        }
        /*
             * The conversions and sign reversal applied below shall be in exact reverse order than
             * in the 'format(…)' method. However we have one additional step compared to format(…):
             * the unit written after the ordinate value may not be the same than the unit declared
             * in the CRS axis, so we have to parse the unit and convert the value before to apply
             * the reverse of 'format(…)' steps.
             */
        if (units != null) {
            final Unit<?> target = units[i];
            if (target != null) {
                final int base = subPos.getIndex();
                int index = base;
                /*
                     * Skip whitespaces using Character.isSpaceChar(…), not Character.isWhitespace(…),
                     * because we need to skip also the non-breaking space (Characters.NO_BREAK_SPACE).
                     * If we can not parse the unit after those spaces, we will revert to the original
                     * position (absence of unit will not be considered an error).
                     */
                while (index < asString.length()) {
                    final int c = asString.codePointAt(index);
                    if (Character.isSpaceChar(c)) {
                        index += Character.charCount(c);
                        continue;
                    }
                    subPos.setIndex(index);
                    final Object unit = getFormat(Unit.class).parseObject(asString, subPos);
                    if (unit == null) {
                        subPos.setIndex(base);
                        subPos.setErrorIndex(-1);
                    } else
                        try {
                            value = ((Unit<?>) unit).getConverterToAny(target).convert(value);
                        } catch (IncommensurableException e) {
                            index += offset;
                            pos.setIndex(start);
                            pos.setErrorIndex(index);
                            throw (ParseException) new ParseException(e.getMessage(), index).initCause(e);
                        }
                    break;
                }
            }
        }
        if (toFormatUnit != null) {
            final UnitConverter c = toFormatUnit[i];
            if (c != null) {
                value = c.inverse().convert(value);
            }
        }
        if (isNegative(i)) {
            value = -value;
        }
        ordinates[i] = value;
    }
    final GeneralDirectPosition position = new GeneralDirectPosition(ordinates);
    position.setCoordinateReferenceSystem(defaultCRS);
    return position;
}
Also used : IncommensurableException(javax.measure.IncommensurableException) Unit(javax.measure.Unit) Date(java.util.Date) Format(java.text.Format) SimpleDateFormat(java.text.SimpleDateFormat) NumberFormat(java.text.NumberFormat) DateFormat(java.text.DateFormat) AngleFormat(org.apache.sis.measure.AngleFormat) CompoundFormat(org.apache.sis.io.CompoundFormat) DecimalFormat(java.text.DecimalFormat) LocalizedParseException(org.apache.sis.internal.util.LocalizedParseException) Angle(org.apache.sis.measure.Angle) UnitConverter(javax.measure.UnitConverter) ParseException(java.text.ParseException) LocalizedParseException(org.apache.sis.internal.util.LocalizedParseException) ParsePosition(java.text.ParsePosition)

Example 29 with UnitConverter

use of javax.measure.UnitConverter in project sis by apache.

the class SexagesimalConverterTest method checkConversion.

/**
 * Converts the given value to an other unit, compares with the expected value, and verify
 * the inverse conversion. Then tries again with the negative of the given values.
 */
private static <Q extends Quantity<Q>> void checkConversion(final double expected, final Unit<Q> unitExpected, final double actual, final Unit<Q> unitActual) {
    final UnitConverter converter = unitActual.getConverterTo(unitExpected);
    final UnitConverter inverse = converter.inverse();
    assertEquals(expected, converter.convert(actual), TOLERANCE);
    assertEquals(actual, inverse.convert(expected), TOLERANCE);
    assertEquals(-expected, converter.convert(-actual), TOLERANCE);
    assertEquals(-actual, inverse.convert(-expected), TOLERANCE);
}
Also used : UnitConverter(javax.measure.UnitConverter)

Example 30 with UnitConverter

use of javax.measure.UnitConverter in project sis by apache.

the class SystemUnit method combine.

/**
 * Implementation of {@link #multiply(Unit)} and {@link #divide(Unit)} methods.
 */
private <T extends Quantity<T>> Unit<?> combine(final Unit<T> other, final boolean divide) {
    final Unit<T> step = other.getSystemUnit();
    final Dimension dim = step.getDimension();
    Unit<?> result = create(divide ? dimension.divide(dim) : dimension.multiply(dim));
    if (step != other) {
        UnitConverter c = other.getConverterTo(step);
        if (!c.isLinear()) {
            throw new IllegalArgumentException(Errors.format(Errors.Keys.NonRatioUnit_1, other));
        }
        if (divide)
            c = c.inverse();
        result = result.transform(c);
    }
    return result;
}
Also used : UnitConverter(javax.measure.UnitConverter) Dimension(javax.measure.Dimension)

Aggregations

UnitConverter (javax.measure.UnitConverter)54 IncommensurableException (javax.measure.IncommensurableException)18 UnconvertibleException (javax.measure.UnconvertibleException)13 Test (org.junit.jupiter.api.Test)11 Test (org.junit.Test)9 RationalConverter (tech.units.indriya.function.RationalConverter)7 Unit (javax.measure.Unit)5 List (java.util.List)4 Mass (javax.measure.quantity.Mass)4 Date (java.util.Date)3 DateFormat (java.text.DateFormat)2 DecimalFormat (java.text.DecimalFormat)2 Format (java.text.Format)2 NumberFormat (java.text.NumberFormat)2 SimpleDateFormat (java.text.SimpleDateFormat)2 HashMap (java.util.HashMap)2 Dimension (javax.measure.Dimension)2 CompoundFormat (org.apache.sis.io.CompoundFormat)2 Angle (org.apache.sis.measure.Angle)2 AngleFormat (org.apache.sis.measure.AngleFormat)2