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();
}
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);
}
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;
}
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);
}
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;
}
Aggregations