274 lines
8.7 KiB
Java
274 lines
8.7 KiB
Java
/*
|
|
* JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
|
|
* Copyright (C) 2007 - JScience (http://jscience.org/)
|
|
* All rights reserved.
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software is
|
|
* freely granted, provided that this notice is preserved.
|
|
*/
|
|
package javax.measure;
|
|
|
|
import javax.measure.converter.UnitConverter;
|
|
import javax.measure.quantity.Quantity;
|
|
import javax.measure.unit.CompoundUnit;
|
|
import javax.measure.unit.Unit;
|
|
|
|
/**
|
|
* <p> This class represents a measurement vector of two or more dimensions.
|
|
* For example:[code]
|
|
* VectorMeasure<Length> dimension = VectorMeasure.valueOf(12.0, 30.0, 40.0, MILLIMETER);
|
|
* VectorMeasure<Velocity> v2d = VectorMeasure.valueOf(-2.2, -3.0, KNOTS);
|
|
* VectorMeasure<ElectricCurrent> c2d = VectorMeasure.valueOf(-7.3, 3.5, NANOAMPERE);
|
|
* [/code]
|
|
* </p>
|
|
*
|
|
* <p> Subclasses may provide fixed dimensions specializations:[code]
|
|
* class Velocity2D extends VectorMeasure<Velocity> {
|
|
* public Velocity2D(double x, double y, Unit<Velocity> unit) {
|
|
* ...
|
|
* }
|
|
* }
|
|
* [/code]</p>
|
|
*
|
|
* <p> Measurement vectors may use {@link CompoundUnit compound units}:[code]
|
|
* VectorMeasure<Angle> latLong = VectorMeasure.valueOf(12.345, 22.23, DEGREE_ANGLE);
|
|
* Unit<Angle> HOUR_MINUTE_SECOND_ANGLE = DEGREE_ANGLE.compound(MINUTE_ANGLE).compound(SECOND_ANGLE);
|
|
* System.out.println(latLong.to(HOUR_MINUTE_SECOND_ANGLE));
|
|
*
|
|
* > [12°19'42", 22°12'48"] [/code]</p>
|
|
*
|
|
* <p> Instances of this class (and sub-classes) are immutable.</p>
|
|
*
|
|
* @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
|
|
* @version 4.3, October 3, 2007
|
|
*/
|
|
public abstract class VectorMeasure<Q extends Quantity> extends Measure<double[], Q> {
|
|
|
|
/**
|
|
* Default constructor (for sub-classes).
|
|
*/
|
|
protected VectorMeasure() {
|
|
}
|
|
|
|
/**
|
|
* Returns a 2-dimensional measurement vector.
|
|
*
|
|
* @param x the first vector component value.
|
|
* @param y the second vector component value.
|
|
* @param unit the measurement unit.
|
|
*/
|
|
public static <Q extends Quantity> VectorMeasure<Q> valueOf(
|
|
double x, double y, Unit<Q> unit) {
|
|
return new TwoDimensional<Q>(x, y, unit);
|
|
}
|
|
|
|
/**
|
|
* Returns a 3-dimensional measurement vector.
|
|
*
|
|
* @param x the first vector component value.
|
|
* @param y the second vector component value.
|
|
* @param z the third vector component value.
|
|
* @param unit the measurement unit.
|
|
*/
|
|
public static <Q extends Quantity> VectorMeasure<Q> valueOf(
|
|
double x, double y, double z, Unit<Q> unit) {
|
|
return new ThreeDimensional<Q>(x, y, z, unit);
|
|
}
|
|
|
|
/**
|
|
* Returns a multi-dimensional measurement vector.
|
|
*
|
|
* @param components the vector component values.
|
|
* @param unit the measurement unit.
|
|
*/
|
|
public static <Q extends Quantity> VectorMeasure<Q> valueOf(double[] components,
|
|
Unit<Q> unit) {
|
|
return new MultiDimensional<Q>(components, unit);
|
|
}
|
|
|
|
/**
|
|
* Returns the measurement vector equivalent to this one but stated in the
|
|
* specified unit.
|
|
*
|
|
* @param unit the new measurement unit.
|
|
* @return the vector measure stated in the specified unit.
|
|
*/
|
|
public abstract VectorMeasure<Q> to(Unit<Q> unit);
|
|
|
|
/**
|
|
* Returns the norm of this measurement vector stated in the specified
|
|
* unit.
|
|
*
|
|
* @param unit the unit in which the norm is stated.
|
|
* @return <code>|this|</code>
|
|
*/
|
|
public abstract double doubleValue(Unit<Q> unit);
|
|
|
|
/**
|
|
* Returns the <code>String</code> representation of this measurement
|
|
* vector (for example <code>[2.3 m/s, 5.6 m/s]</code>).
|
|
*
|
|
* @return the textual representation of the measurement vector.
|
|
*/
|
|
public String toString() {
|
|
double[] values = getValue();
|
|
Unit<Q> unit = getUnit();
|
|
StringBuffer tmp = new StringBuffer();
|
|
tmp.append('[');
|
|
for (double v : values) {
|
|
if (tmp.length() > 1) {
|
|
tmp.append(", ");
|
|
}
|
|
if (unit instanceof CompoundUnit) {
|
|
MeasureFormat.DEFAULT.formatCompound(v, unit, tmp, null);
|
|
} else {
|
|
tmp.append(v).append(" ").append(unit);
|
|
}
|
|
}
|
|
tmp.append("] ");
|
|
return tmp.toString();
|
|
}
|
|
|
|
// Holds 2-dimensional implementation.
|
|
private static class TwoDimensional<Q extends Quantity> extends VectorMeasure<Q> {
|
|
|
|
private final double _x;
|
|
|
|
private final double _y;
|
|
|
|
private final Unit<Q> _unit;
|
|
|
|
private TwoDimensional(double x, double y, Unit<Q> unit) {
|
|
_x = x;
|
|
_y = y;
|
|
_unit = unit;
|
|
|
|
}
|
|
@Override
|
|
public double doubleValue(Unit<Q> unit) {
|
|
double norm = Math.sqrt(_x * _x + _y * _y);
|
|
if ((unit == _unit) || (unit.equals(_unit)))
|
|
return norm;
|
|
return _unit.getConverterTo(unit).convert(norm);
|
|
}
|
|
|
|
@Override
|
|
public Unit<Q> getUnit() {
|
|
return _unit;
|
|
}
|
|
|
|
@Override
|
|
public double[] getValue() {
|
|
return new double[] { _x, _y };
|
|
}
|
|
|
|
@Override
|
|
public TwoDimensional<Q> to(Unit<Q> unit) {
|
|
if ((unit == _unit) || (unit.equals(_unit)))
|
|
return this;
|
|
UnitConverter cvtr = _unit.getConverterTo(unit);
|
|
return new TwoDimensional<Q>(cvtr.convert(_x), cvtr.convert(_y), unit);
|
|
}
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
}
|
|
|
|
// Holds 3-dimensional implementation.
|
|
private static class ThreeDimensional<Q extends Quantity> extends VectorMeasure<Q> {
|
|
|
|
private final double _x;
|
|
|
|
private final double _y;
|
|
|
|
private final double _z;
|
|
|
|
private final Unit<Q> _unit;
|
|
|
|
private ThreeDimensional(double x, double y, double z, Unit<Q> unit) {
|
|
_x = x;
|
|
_y = y;
|
|
_z = z;
|
|
_unit = unit;
|
|
|
|
}
|
|
@Override
|
|
public double doubleValue(Unit<Q> unit) {
|
|
double norm = Math.sqrt(_x * _x + _y * _y + _z * _z);
|
|
if ((unit == _unit) || (unit.equals(_unit)))
|
|
return norm;
|
|
return _unit.getConverterTo(unit).convert(norm);
|
|
}
|
|
|
|
@Override
|
|
public Unit<Q> getUnit() {
|
|
return _unit;
|
|
}
|
|
|
|
@Override
|
|
public double[] getValue() {
|
|
return new double[] { _x, _y, _z };
|
|
}
|
|
|
|
@Override
|
|
public ThreeDimensional<Q> to(Unit<Q> unit) {
|
|
if ((unit == _unit) || (unit.equals(_unit)))
|
|
return this;
|
|
UnitConverter cvtr = _unit.getConverterTo(unit);
|
|
return new ThreeDimensional<Q>(cvtr.convert(_x), cvtr.convert(_y), cvtr.convert(_z), unit);
|
|
}
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
}
|
|
// Holds multi-dimensional implementation.
|
|
private static class MultiDimensional<Q extends Quantity> extends VectorMeasure<Q> {
|
|
|
|
private final double[] _components;
|
|
|
|
private final Unit<Q> _unit;
|
|
|
|
private MultiDimensional(double[] components, Unit<Q> unit) {
|
|
_components = components.clone();
|
|
_unit = unit;
|
|
}
|
|
|
|
@Override
|
|
public double doubleValue(Unit<Q> unit) {
|
|
double normSquare = _components[0] * _components[0];
|
|
for (int i=1, n=_components.length; i < n;) {
|
|
double d = _components[i++];
|
|
normSquare += d * d;
|
|
}
|
|
if ((unit == _unit) || (unit.equals(_unit)))
|
|
return Math.sqrt(normSquare);
|
|
return _unit.getConverterTo(unit).convert(Math.sqrt(normSquare));
|
|
}
|
|
|
|
@Override
|
|
public Unit<Q> getUnit() {
|
|
return _unit;
|
|
}
|
|
|
|
@Override
|
|
public double[] getValue() {
|
|
return _components.clone();
|
|
}
|
|
|
|
@Override
|
|
public MultiDimensional<Q> to(Unit<Q> unit) {
|
|
if ((unit == _unit) || (unit.equals(_unit)))
|
|
return this;
|
|
UnitConverter cvtr = _unit.getConverterTo(unit);
|
|
double[] newValues = new double[_components.length];
|
|
for (int i=0; i < _components.length; i++) {
|
|
newValues[i] = cvtr.convert(_components[i]);
|
|
}
|
|
return new MultiDimensional<Q>(newValues, unit);
|
|
}
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
}
|
|
}
|