| |
Package Name | Comment | javax.measure |
Provides strongly typed measurements to enforce compile-time
check of parameters consistency and avoid interface errors.
Let's take the following example:[code]
class Person {
void setWeight(double weight);
}[/code]
Should the weight be in pound, kilogram ??
Using measures there is no room for error:[code]
class Person {
void setWeight(Measurable weight);
}[/code]
Not only the interface is cleaner (the weight has to be of mass type);
but also there is no confusion on the measurement unit:[code]
double weightInKg = weight.doubleValue(KILOGRAM);
double weightInLb = weight.doubleValue(POUND);[/code]
Measurable work hand-in-hand with units (also parameterized).
For example, the following would result in compile-time error:[code]
double weightInLiter = weight.doubleValue(LITER); // Compile error, Unit required.
[/code]
Users may create their own {@link javax.measure.Measurable
Measurable} implementation:[code]
public class Period implements Measurable {
long nanoseconds;
...
}
public class Distance implements Measurable {
double meters;
...
}
public class Velocity3D implements Measurable {
double x, y, z; // In meters.
...
}
[/code]
Users may also combine a definite amount (scalar, vector, collection, etc.)
to a unit and make it a {@link javax.measure.Measure Measure} (and
a {@link javax.measure.Measurable Measurable} instance). For example:
[code]
// Scalar measurement (numerical).
person.setWeight(Measure.valueOf(180.0, POUND)); // Measure
timer.setPeriod(Measure.valueOf(20, MILLI(SECOND)); // Measure
circuit.setCurrent(Measure.valueOf(Complex.valueOf(2, -3), AMPERE); // (2 - 3i) A
bottle.setPression(Measure.valueOf(Rational.valueOf(20, 100), ATMOSPHERE)); // (20/100) Atm
// Vector measurement.
abstract class MeasureVector extends Measure {
... // doubleValue(Unit) returns vector norm.
}
MeasureVector v = MeasureVector.valueOf(METRE_PER_SECOND, 1.0, 2.0, 3.0);
plane.setVelocity(v);
// Statistical measurement.
class Average extends Measure{
... // doubleValue(Unit) returns average value.
}
sea.setTemperature(Average.valueOf(new double[] { 33.4, 44.55, 32.33} , CELCIUS));
// Measurement with uncertainty (and additional operations).
public class Amount extends Measurable {
public Amount(double value, double error, Unit unit) { ... }
public Amount plus(Amount that) {...}
public Amount> times(Amount> that) {...}
... // doubleValue(Unit) returns estimated value.
}
[/code]
| javax.measure.converter |
Provides support for unit conversion.
UML Diagram
| javax.measure.quantity |
Provides quantitative properties or attributes of thing such as
mass, time, distance, heat, and angular separation.
Each quantity sub-interface holds a static UNIT field
holding the standard unit for the quantity.
| javax.measure.unit |
Provides support for programatic unit handling.
Standart/NonStandard Units
Standard units and prefixes are provided by the
{@link javax.measure.unit.SI SI} class (Système International d'Unités) and
about 50 non-standard units are available through the
{@link javax.measure.unit.NonSI NonSI} class.
Usage examples:
[code]
import javax.measure.Scalar;
import javax.measure.Measure;
import javax.measure.unit.*;
import javax.measure.quantity.*;
import static javax.measure.unit.SI.*;
import static javax.measure.unit.NonSI.*;
import static javax.measure.unit.Dimension.*;
public class Main {
public void main(String[] args) {
// Conversion between units.
System.out.println(KILO(METRE).getConverterTo(MILE).convert(10));
// Retrieval of the system unit (identifies the measurement type).
System.out.println(REVOLUTION.divide(MINUTE).getSystemUnit());
// Dimension checking (allows/disallows conversions)
System.out.println(ELECTRON_VOLT.isCompatible(WATT.times(HOUR)));
// Retrieval of the unit dimension (depends upon the current model).
System.out.println(ELECTRON_VOLT.getDimension());
}
}
> 6.2137119223733395
> rad/s
> true
> [L]²·[M]/[T]²
[/code]
Unit Parameterization
Units are parameterized (<Q extends {@link javax.measure.quantity.Quantity Quantity}>) to
enforce compile-time checks of units/measures consistency, for example:[code]
Unit MINUTE = SECONDS.times(60); // Ok.
Unit MINUTE = METRE.times(60); // Compile error.
Unit HECTOPASCAL = HECTO(PASCAL); // Ok.
Unit HECTOPASCAL = HECTO(NEWTON); // Compile error.
Measurable duration = Measure.valueOf(2, MINUTE); // Ok.
Measurable duration = Measure.valueOf(2, CELSIUS); // Compile error.
long milliseconds = duration.longValue(MILLI(SECOND)); // Ok.
long milliseconds = duration.longValue(POUND); // Compile error.
[/code]
UML Diagram
| org.jscience |
Provides the library classes for versionning, self-tests and performance analysis.
| org.jscience.economics.money |
Provides support for monetary quantities and their currencies.
Conversions between quantities stated in different currencies is possible
if the exchange rates for the currencies have been set (otherwise
ConversionException is thrown).
Monetary quantities support the dynamic changes of the currencies exchange
rates as illustrated in the following example:[code]
import static javax.measure.units.SI.*;
import static javax.measure.units.NonSI.*;
import static org.jscience.economics.money.Currency.*;
///////////////////////////////////////////////////////////////////////
// Calculates the cost of a car trip in Europe for an American tourist.
///////////////////////////////////////////////////////////////////////
// Use currency symbols instead of ISO-4217 codes.
UnitFormat.getStandardInstance().label(USD, "$"); // Use "$" symbol instead of currency code ("USD")
UnitFormat.getStandardInstance().label(EUR, "€"); // Use "€" symbol instead of currency code ("EUR")
// Sets exchange rates.
Currency.setReferenceCurrency(USD);
EUR.setExchangeRate(1.17); // 1.0 € = 1.17 $
// Calculates trip cost.
Amount> carMileage = Amount.valueOf(20, MILE.divide(GALLON_LIQUID_US)); // 20 mi/gal.
Amount> gazPrice = Amount.valueOf(1.2, EUR.divide(LITER)); // 1.2 €/L
Amount tripDistance = Amount.valueOf(400, KILO(METRE)); // 400 km
Amount tripCost = tripDistance.divide(carMileage).times(gazPrice).to(USD);
// Displays cost.
System.out.println("Trip cost = " + tripCost + " (" + tripCost.to(EUR) + ")");
> Trip cost = 66.05 $ (56.45 €)
[/code]
The exchange rates between {@link org.jscience.economics.money.Currency currencies}
is {@link javolution.context.LocalContext context local}.
Application may use different sets of exchange rates concurrently (e.g. rates for buying and
rates for selling). For example:[code]
LocalContext.enter();
try {
EUR.setExchangeRate(1.22); // Buying rate.
Amount price = Amount.valueOf(9.99, EUR);
System.out.println("Price: " + price.to(USD);
} finally {
LocalContext.exit();
}
...
LocalContext.enter();
try {
EUR.setExchangeRate(1.18); // Selling rate.
Amount price = Amount.valueOf(14.99, USD);
System.out.println("Price: " + price.to(EUR);
} finally {
LocalContext.exit();
}[/code]
Like any {@link org.jscience.physics.amount.Amount amount},
money quantities can be exact or approximate (with an error known
and guaranteed).
[code]
Unit CENTS = Currency.USD.times(100);
Amount exactPrice = Amount.valueOf(1499, CENTS); // Integer value.
Amount apprxPrice = Amount.valueOf(14.99, USD); // Floating-Point IEEE 754 accuracy.
[/code]
| org.jscience.geography.coordinates |
Provides linear or angular {@link javax.measure.quantity quantities} which
designate the position that a point occupies in a given reference frame or system.
Coordinates are unambigous only when the {@link org.jscience.geography.coordinates.crs
coordinates reference system} to which those coordinates are related has
been fully defined.
Applications may create new types of coordinates either by extending
{@link org.jscience.geography.coordinates.Coordinates Coordinates}
(in which case they must provide a coordinates reference system) or simply by
{@link org.jscience.geography.coordinates.CompoundCoordinates combining}
existing coordinates together. For example:[code]
// High-Precision Coordinates.
class Position3D extends Coordinates {
public static final GeocentricCRS CRS = ...;
public GeocentricCRS getCoordinateReferenceSystem {
return CRS; // All instances use the same reference system.
}
public Real getX(Unit u) { ... }
public Real getY(Unit u) { ... }
public Real getZ(Unit u) { ... }
...
}
// Combining existing coordinates.
class LatLongHeight extends CompoundCoordinates { }
class HeightTime extends CompoundCoordinates { }
class UtmHeightTime extends CompoundCoordinates, Time> { }
[/code]
Conversion between coordinates is achieved through their coordinates
reference system. For example:[code]
// Converts UTM coordinates to Latitude/Longitude.
UTM utm = UTM.valueOf(17, 'E', 444.5, 556.44, METRE);
CoordinatesConverter utmToLatLong = UTM.CRS.getConverterTo(LatLong.CRS);
LatLong latLong = utmToLatLong.convert(utm);
// Converts compound coordinates to X/Y/Z geocentric coordinates.
CompoundCoordinates utmHeight = new CompoundCoordinates(utm, new Height(2330.55, FOOT));
XYZ xyz = new CompoundCRS(UTM.CRS, Height.CRS).getConverterTo(XYZ.CRS).convert(utmHeight);
// Converts any projected coordinates to Latitude/Longitude.
Coordinates coord2d;
LatLong latLong = coord2d.getCoordinateReferenceSystem().getConverterTo(LatLong.CRS).convert(coord2d);
[/code]
| org.jscience.geography.coordinates.crs |
Provides the Coordinate Reference Systems (CRS) specifying how
{@link org.jscience.geography.coordinates.Coordinates coordinates} are to
be assigned to spatial/temporal locations.
| org.jscience.mathematics.function |
Provides support for fairly simple symbolic math analysis
(to solve algebraic equations, integrate, differentiate, calculate
expressions, and so on).
{@link org.jscience.mathematics.function.Function Functions} defined in this package
can be {@link org.jscience.mathematics.function.Variable multivariate}
and operate on various kind of objects such as physical measurements,
vectors, matrices, all types of numbers or even the functions
themselves (functions of functions)!
Here is an example using {@link org.jscience.mathematics.number.Complex complex}
{@link org.jscience.mathematics.function.Polynomial polynomial} functions:[code]
// Defines two local variables (x, y).
Variable varX = new Variable.Local("x");
Variable varY = new Variable.Local("y");
// f(x) = ix² + 2x + 1
Polynomial x = Polynomial.valueOf(Complex.ONE, varX);
Polynomial fx = x.pow(2).times(Complex.I).plus(
x.times(Complex.valueOf(2, 0)).plus(Complex.ONE));
System.out.println(fx);
System.out.println(fx.pow(2));
System.out.println(fx.differentiate(varX));
System.out.println(fx.integrate(varY));
System.out.println(fx.compose(fx));
// Calculates expression.
varX.set(Complex.valueOf(2, 3));
System.out.println(fx.evaluate());
> [0.0 + 1.0i]x^2 + [2.0 + 0.0i]x + [1.0 + 0.0i]
> [-1.0 + 0.0i]x^4 + [0.0 + 4.0i]x^3 + [4.0 + 2.0i]x^2 + [4.0 + 0.0i]x + [1.0 + 0.0i]
> [0.0 + 2.0i]x + [2.0 + 0.0i]
> [0.0 + 1.0i]x^2y + [2.0 + 0.0i]xy + [1.0 + 0.0i]y
> [0.0 - 1.0i]x^4 + [-4.0 + 0.0i]x^3 + [-2.0 + 6.0i]x^2 + [4.0 + 4.0i]x + [3.0 + 1.0i]
> -7.0 + 1.0i
[/code]
| org.jscience.mathematics.number |
Provides common types of numbers most of them implementing the
{@link org.jscience.mathematics.structure.Field field} interface.
Although numbers defined in this package are not as fast as primitives types
(e.g. int or double ). They have many
advantages (such as arbitrary size for {@link org.jscience.mathematics.number.LargeInteger LargeInteger}
or precision for {@link org.jscience.mathematics.number.Real Real}) which
make them irreplaceable in some calculations. This can be illustrated with the following example:
double x = 10864;
double y = 18817;
double z = 9 * Math.pow(x, 4.0)- Math.pow(y, 4.0) + 2 * Math.pow(y, 2.0);
System.out.println("Result : " + z);
> Result : 2.0
The mathematically correct value is z=1. However, Java compilers
using ANSI/IEEE double precision numbers evaluate z=2. Not even the first
digit is correct! This is due to a rounding error occurring when subtracting
two nearly equal floating point numbers. Now, lets write the same formula
using {@link org.jscience.mathematics.number.Real Real} numbers:
int accuracy = 20; // 20 decimal zeros for integer values.
Real x = Real.valueOf(10864, accuracy);
Real y = Real.valueOf(18817, accuracy);
Real z = x.pow(4).times(9).plus(y.pow(4).opposite()).plus(y.pow(2).times(2));
System.out.println("Result : " + z);
> Result : 1.00000
Not only the correct result is returned, but this result is also guaranteed to be 1 ± 0.00001 .
Only exact digits are written out, for example the following displays the first exact
digits of sqrt(2) :
Real two = Real.valueOf(2, 100); // 2.0000..00 (100 zeros after decimal point).
Real sqrt2 = two.sqrt();
System.out.println("sqrt(2) = " + sqrt2);
System.out.println("Precision = " + sqrt2.getPrecision() + " digits.");
> sqrt(2) = 1.414213562373095048801688724209698078569671875376948
> Precision = 53 digits.
| org.jscience.mathematics.structure |
Provides mathematical sets (identified by the class parameter) associated to binary operations,
such as multiplication or addition, satisfying certain axioms.
For example,
{@link org.jscience.mathematics.number.Real Real} is a
{@link org.jscience.mathematics.structure.Field Field<Real>},
but
{@link org.jscience.mathematics.number.LargeInteger LargeInteger} is only a
{@link org.jscience.mathematics.structure.Ring Ring<LargeInteger>} as its
elements do not have multiplicative inverse (except for one).
To implement a structure means not only that some operations are now available
but also that some properties (such as associativity and distributivity) must be verified.
For example, the declaration: [code]class Quaternions implements Field[/code]
Indicates that addition (+), multiplication (·) and their respective inverses
are automatically defined for Quaternions objects; but also that (·) is distributive over (+),
both operations (+) and (·) are associative and (+) is commutative.
| org.jscience.mathematics.vector |
Provides support for linear algebra
in the form of {@link org.jscience.mathematics.vector.Matrix matrices} and
{@link org.jscience.mathematics.vector.Vector vectors}.
With the {@link org.jscience.mathematics.vector.Matrix Matrix} class,
you should be able to resolve linear systems of equations
involving any kind of elements such as
{@link org.jscience.mathematics.number.Rational Rational},
{@link org.jscience.mathematics.number.ModuloInteger ModuloInteger} (modulo operations),
{@link org.jscience.mathematics.number.Complex Complex},
{@link org.jscience.mathematics.function.RationalFunction RationalFunction}, etc.
The main requirement being that your element class implements the mathematical
{@link org.jscience.mathematics.structure.Field Field} interface.
Most {@link org.jscience.mathematics.number numbers} and even invertible matrices
themselves may implement this interface. Non-commutative multiplication is supported which
allows for the resolution of systems of equations with invertible matrix coefficients (matrices of matrices).
For classes embedding automatic error calculation (e.g.
{@link org.jscience.mathematics.number.Real Real} or {@link org.jscience.physics.amount.Amount Amount}),
the error on the solution obtained tells you if can trust that solution or not
(e.g. system close to singularity). The following example illustrates this point.
Let's say you have a simple electric circuit composed of 2 resistors in series
with a battery. You want to know the voltage (U1, U2) at the nodes of the
resistors and the current (I) traversing the circuit.[code]
import static org.jscience.physics.units.SI.*;
Amount R1 = Amount.valueOf(100, 1, OHM); // 1% precision.
Amount R2 = Amount.valueOf(300, 3, OHM); // 1% precision.
Amount U0 = Amount.valueOf(28, 0.01, VOLT); // ±0.01 V fluctuation.
// Equations: U0 = U1 + U2 |1 1 0 | |U1| |U0|
// U1 = R1 * I => |-1 0 R1| * |U2| = |0 |
// U2 = R2 * I |0 -1 R2| |I | |0 |
//
// A * X = B
//
DenseMatrix> A = DenseMatrix.valueOf(new Amount>[][] {
{ Amount.ONE, Amount.ONE, Amount.valueOf(0, OHM) },
{ Amount.ONE.opposite(), Amount.ZERO, R1 },
{ Amount.ZERO, Amount.ONE.opposite(), R2 } });
DenseVector> B = DenseVector.valueOf(new Amount>[]
{ U0, Amount.valueOf(0, VOLT), Amount.valueOf(0, VOLT) });
Vector> X = A.solve(B);
System.out.println(X);
System.out.println(X.get(2).to(MILLI(AMPERE)));
> {(7.0 ± 1.6E-1) V, (21.0 ± 1.5E-1) V, (7.0E-2 ± 7.3E-4) V/Ω}
> (70.0 ± 7.3E-1) mA
[/code]
Because the {@link org.jscience.physics.amount.Amount Amount} class guarantees
the accuracy/precision of its calculations. As long as the input resistances, voltage
stay within their specification range then the current is guaranteed
to be (70.0 ± 7.3E-1) mA . When the inputs have no error specified,
the error on the result corresponds to calculations numeric errors only
(which might increase significantly if the matrix is close to singularity).
| org.jscience.physics.amount |
Provides support for exact or arbitrary precision measurements.
Amount as {@link javax.measure.Measurable measurable} quantity:
The {@link org.jscience.physics.amount.Amount Amount}
base class is parameterized with the quantity onto which the measure applies
(Amount<Q extends Quantity>). If the quantity is not known then
<?> can be used. For example:[code]
Amount> carMileage = Amount.valueOf(20, MILE.divide(GALLON_LIQUID_US));
Amount> gazPrice = Amount.valueOf(1.2, EUR.divide(LITER)); // 1.2 €/L
[/code]
If the expected quantity result for a measure is known but has been lost
due to the calculations performed; better than using <?>, the measure can
be stated in a known unit for this quantity. It ensures dynamic check of
the measure dimension/unit and avoid compiler warnings. For example:[code]
// No problem here as the measure type is infered from the unit.
Amount tripDistance = Amount.valueOf(400, KILO(SI.METRE));
// Warning as the measure type is lost during calculation.
Amount tripCost = tripDistance.divide(carMileage).times(gazPrice);
// Better: Dimension check and no warning (USD is a Currency (Unit))
Amount tripCost = tripDistance.divide(carMileage).times(gazPrice).to(USD);
[/code]
It should be noted that this conversion is immediate if the specified
unit is the actual unit for the amount (which is then returned unchanged).
Error calculations:
Amount take into account measurement and calculation errors. For example:[code]
import static org.jscience.physics.units.SI.*;
...
Amount x = Amount.valueOf(1.0, METRE);
Amount v = Amount.valueOf(0.01, METRE_PER_SECOND);
Amount t = Amount.valueOf(1.0, MICRO(SECOND));
for (int i = 0; i < 10000000; i++) {
x = x.plus(v.times(t));
}
AmountFormat.setInstance(AmountFormat.getExactDigitsInstance());
System.out.println(x);
> 1.10000000 m
The exact value is guaranteed to be in the range: ]1.09999999 m, 1.10000001 m[
The same calculation using primitive double type would have display:
> 1.099999999392253
with no idea on the accuracy of the result.[/code]
Dimension checking.
The unit of an amount determinates its type.
For example, Amount.valueOf("1 µm") and Amount.valueOf("1.2 ft")
are Length amounts (both "µm" and "ft" units
are derived from SI.METRE ). Multiple physical models are supported (e.g. Standard ,
Relativistic , High-Energy , Quantum
and Natural ). The physical model sets which conversions are allowed or disallowed.
For example:[code]
RelativisticModel.select(); // Selects a relativistic model.
Amount x = Amount.valueOf(100, NonSI.INCH);
x = x.plus(Amount.valueOf("2.3 µs")).to(METRE); // Length and Duration can be added.
Amount m = Amount.valueOf("12 GeV").to(KILOGRAM); // Energy is compatible with mass (E=mc2)
System.out.println(x);
System.out.println(m);
> (692.06265340000008 ± 5.1E-13) m
> (2.1391940763025056E-26 ± 4.3E-42) kg[/code]
Physical Constants
Finally, this package holds the latest physical {@link org.jscience.physics.amount.Constants constants} measurements
with the best known accuracy (the more accurate the constant, the higher the precision of the calculations
making use of these constants).
| org.jscience.physics.model |
Provides models for physical quantities.
The difference between models lies in the assumptions each makes and,
in consequence,the operations each permits. For example, the summation
of a {@link javax.measure.quantity.Length length} and a {@link javax.measure.quantity.Duration duration}
is not allowed by the standard model, but is quite valid in a relativistic context.
Models are {@link javolution.context.LocalContext context-local}, allowing
multiple models to be used concurrently. For example:[code]
LocalContext.enter();
try {
RelativisticModel.select(); // Affects the current thread only.
...
} finally {
LocalContext.exit();
}[/code]
The names and characteristics of the models are presented in the following table:
Model |
Class |
Defining Characteristics |
Default Output Units |
Standard |
"StandardModel" |
per Système Internationale |
Length: m;
Mass: kg;
Duration: s;
ElectricCurrent: A;
Temperature: K;
AmountOfSubstance: mol;
LuminousIntensity: cd
|
Relativistic |
"RelativisticModel" |
1 = c |
Length,
Duration: s;
Mass: eV;
ElectricCurrent: A;
Temperature: K;
AmountOfSubstance: mol;
LuminousIntensity: cd
|
High-Energy |
"HighEnergyModel" |
1 = c
= k
= ePlus
|
Length,
Duration: ns;
Mass,
Temperature: GeV;
ElectricCurrent: 1/ns;
AmountOfSubstance: mol;
LuminousIntensity: cd
|
Quantum |
"QuantumModel" |
1 = c
= k
= µ0
= hBar
|
Length,
Duration: 1/GeV;
Mass,
Temperature,
ElectricCurrent: GeV;
AmountOfSubstance: mol;
LuminousIntensity: cd
|
Natural |
"NaturalModel" |
1 = c
= k
= µ0
= hBar
= G
|
Length,
Mass,
Duration,
ElectricCurrent,
Temperature: 1;
AmountOfSubstance: mol;
LuminousIntensity: cd
|
| org.opengis.referencing.cs | |
|