You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by er...@apache.org on 2006/03/29 23:05:18 UTC
svn commit: r389891 [7/9] - in /incubator/felix/trunk/org.osgi.compendium:
./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/osgi/
src/main/java/org/osgi/service/ src/main/java/org/osgi/service/cm/
src/main/java/org/osgi/service/com...
Added: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Measurement.java
URL: http://svn.apache.org/viewcvs/incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Measurement.java?rev=389891&view=auto
==============================================================================
--- incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Measurement.java (added)
+++ incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Measurement.java Wed Mar 29 13:05:08 2006
@@ -0,0 +1,480 @@
+/*
+ * $Header: /cvshome/build/org.osgi.util.measurement/src/org/osgi/util/measurement/Measurement.java,v 1.12 2006/03/14 01:19:37 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2002, 2005). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.osgi.util.measurement;
+
+
+/**
+ * Represents a value with an error, a unit and a time-stamp.
+ *
+ * <p>
+ * A <code>Measurement</code> object is used for maintaining the tuple of value,
+ * error, unit and time-stamp. The value and error are represented as doubles
+ * and the time is measured in milliseconds since midnight, January 1, 1970 UTC.
+ *
+ * <p>
+ * Mathematic methods are provided that correctly calculate taking the error
+ * into account. A runtime error will occur when two measurements are used in an
+ * incompatible way. E.g., when a speed (m/s) is added to a distance (m). The
+ * measurement class will correctly track changes in unit during multiplication
+ * and division, always coercing the result to the most simple form. See
+ * {@link Unit}for more information on the supported units.
+ *
+ * <p>
+ * Errors in the measurement class are absolute errors. Measurement errors
+ * should use the P95 rule. Actual values must fall in the range value +/- error
+ * 95% or more of the time.
+ *
+ * <p>
+ * A <code>Measurement</code> object is immutable in order to be easily shared.
+ *
+ * <p>
+ * Note: This class has a natural ordering that is inconsistent with equals. See
+ * {@link #compareTo}.
+ *
+ * @version $Revision: 1.12 $
+ */
+public class Measurement implements Comparable {
+ /* package private so it can be accessed by Unit */
+ final double value;
+ final double error;
+ final long time;
+ final Unit unit;
+ private transient String name;
+
+ /**
+ * Create a new <code>Measurement</code> object.
+ *
+ * @param value The value of the <code>Measurement</code>.
+ * @param error The error of the <code>Measurement</code>.
+ * @param unit The <code>Unit</code> object in which the value is measured. If
+ * this argument is <code>null</code>, then the unit will be set to
+ * {@link Unit#unity}.
+ * @param time The time measured in milliseconds since midnight, January 1,
+ * 1970 UTC.
+ */
+ public Measurement(double value, double error, Unit unit, long time) {
+ this.value = value;
+ this.error = Math.abs(error);
+ this.unit = (unit != null) ? unit : Unit.unity;
+ this.time = time;
+ }
+
+ /**
+ * Create a new <code>Measurement</code> object with a time of zero.
+ *
+ * @param value The value of the <code>Measurement</code>.
+ * @param error The error of the <code>Measurement</code>.
+ * @param unit The <code>Unit</code> object in which the value is measured. If
+ * this argument is <code>null</code>, then the unit will be set to
+ * {@link Unit#unity}.
+ */
+ public Measurement(double value, double error, Unit unit) {
+ this(value, error, unit, 0l);
+ }
+
+ /**
+ * Create a new <code>Measurement</code> object with an error of 0.0 and a
+ * time of zero.
+ *
+ * @param value The value of the <code>Measurement</code>.
+ * @param unit The <code>Unit</code> in which the value is measured. If this
+ * argument is <code>null</code>, then the unit will be set to
+ * {@link Unit#unity}.
+ */
+ public Measurement(double value, Unit unit) {
+ this(value, 0.0d, unit, 0l);
+ }
+
+ /**
+ * Create a new <code>Measurement</code> object with an error of 0.0, a unit
+ * of {@link Unit#unity}and a time of zero.
+ *
+ * @param value The value of the <code>Measurement</code>.
+ */
+ public Measurement(double value) {
+ this(value, 0.0d, null, 0l);
+ }
+
+ /**
+ * Returns the value of this <code>Measurement</code> object.
+ *
+ * @return The value of this <code>Measurement</code> object as a double.
+ */
+ public final double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns the error of this <code>Measurement</code> object. The error is
+ * always a positive value.
+ *
+ * @return The error of this <code>Measurement</code> as a double.
+ */
+ public final double getError() {
+ return error;
+ }
+
+ /**
+ * Returns the <code>Unit</code> object of this <code>Measurement</code> object.
+ *
+ * @return The <code>Unit</code> object of this <code>Measurement</code> object.
+ *
+ * @see Unit
+ */
+ public final Unit getUnit() {
+ return unit;
+ }
+
+ /**
+ * Returns the time at which this <code>Measurement</code> object was taken.
+ * The time is measured in milliseconds since midnight, January 1, 1970 UTC,
+ * or zero when not defined.
+ *
+ * @return The time at which this <code>Measurement</code> object was taken or
+ * zero.
+ */
+ public final long getTime() {
+ return time;
+ }
+
+ /**
+ * Returns a new <code>Measurement</code> object that is the product of this
+ * object multiplied by the specified object.
+ *
+ * @param m The <code>Measurement</code> object that will be multiplied with
+ * this object.
+ * @return A new <code>Measurement</code> that is the product of this object
+ * multiplied by the specified object. The error and unit of the new
+ * object are computed. The time of the new object is set to the
+ * time of this object.
+ * @throws ArithmeticException If the <code>Unit</code> objects of this object
+ * and the specified object cannot be multiplied.
+ * @see Unit
+ */
+ public Measurement mul(Measurement m) {
+ double mvalue = m.value;
+ return new Measurement(value * mvalue, Math.abs(value) * m.error
+ + error * Math.abs(mvalue), unit.mul(m.unit), time);
+ }
+
+ /**
+ * Returns a new <code>Measurement</code> object that is the product of this
+ * object multiplied by the specified value.
+ *
+ * @param d The value that will be multiplied with this object.
+ * @param u The <code>Unit</code> of the specified value.
+ * @return A new <code>Measurement</code> object that is the product of this
+ * object multiplied by the specified value. The error and unit of
+ * the new object are computed. The time of the new object is set to
+ * the time of this object.
+ * @throws ArithmeticException If the units of this object and the specified
+ * value cannot be multiplied.
+ * @see Unit
+ */
+ public Measurement mul(double d, Unit u) {
+ return new Measurement(value * d, error * Math.abs(d), unit.mul(u),
+ time);
+ }
+
+ /**
+ * Returns a new <code>Measurement</code> object that is the product of this
+ * object multiplied by the specified value.
+ *
+ * @param d The value that will be multiplied with this object.
+ * @return A new <code>Measurement</code> object that is the product of this
+ * object multiplied by the specified value. The error of the new
+ * object is computed. The unit and time of the new object is set to
+ * the unit and time of this object.
+ */
+ public Measurement mul(double d) {
+ return new Measurement(value * d, error * Math.abs(d), unit, time);
+ }
+
+ /**
+ * Returns a new <code>Measurement</code> object that is the quotient of this
+ * object divided by the specified object.
+ *
+ * @param m The <code>Measurement</code> object that will be the divisor of
+ * this object.
+ * @return A new <code>Measurement</code> object that is the quotient of this
+ * object divided by the specified object. The error and unit of the
+ * new object are computed. The time of the new object is set to the
+ * time of this object.
+ * @throws ArithmeticException If the <code>Unit</code> objects of this object
+ * and the specified object cannot be divided.
+ * @see Unit
+ */
+ public Measurement div(Measurement m) {
+ double mvalue = m.value;
+ return new Measurement(value / mvalue,
+ (Math.abs(value) * m.error + error * Math.abs(mvalue))
+ / (mvalue * mvalue), unit.div(m.unit), time);
+ }
+
+ /**
+ * Returns a new <code>Measurement</code> object that is the quotient of this
+ * object divided by the specified value.
+ *
+ * @param d The value that will be the divisor of this object.
+ * @param u The <code>Unit</code> object of the specified value.
+ * @return A new <code>Measurement</code> that is the quotient of this object
+ * divided by the specified value. The error and unit of the new
+ * object are computed. The time of the new object is set to the
+ * time of this object.
+ * @throws ArithmeticException If the <code>Unit</code> objects of this object
+ * and the specified object cannot be divided.
+ * @see Unit
+ */
+ public Measurement div(double d, Unit u) {
+ return new Measurement(value / d, error / Math.abs(d), unit.div(u),
+ time);
+ }
+
+ /**
+ * Returns a new <code>Measurement</code> object that is the quotient of this
+ * object divided by the specified value.
+ *
+ * @param d The value that will be the divisor of this object.
+ * @return A new <code>Measurement</code> object that is the quotient of this
+ * object divided by the specified value. The error of the new
+ * object is computed. The unit and time of the new object is set to
+ * the <code>Unit</code> and time of this object.
+ */
+ public Measurement div(double d) {
+ return new Measurement(value / d, error / Math.abs(d), unit, time);
+ }
+
+ /**
+ * Returns a new <code>Measurement</code> object that is the sum of this
+ * object added to the specified object.
+ *
+ * The error and unit of the new object are computed. The time of the new
+ * object is set to the time of this object.
+ *
+ * @param m The <code>Measurement</code> object that will be added with this
+ * object.
+ * @return A new <code>Measurement</code> object that is the sum of this and
+ * m.
+ * @see Unit
+ * @throws ArithmeticException If the <code>Unit</code> objects of this object
+ * and the specified object cannot be added.
+ */
+ public Measurement add(Measurement m) {
+ return new Measurement(value + m.value, error + m.error, unit
+ .add(m.unit), time);
+ }
+
+ /**
+ * Returns a new <code>Measurement</code> object that is the sum of this
+ * object added to the specified value.
+ *
+ * @param d The value that will be added with this object.
+ * @param u The <code>Unit</code> object of the specified value.
+ * @return A new <code>Measurement</code> object that is the sum of this
+ * object added to the specified value. The unit of the new object
+ * is computed. The error and time of the new object is set to the
+ * error and time of this object.
+ * @throws ArithmeticException If the <code>Unit</code> objects of this object
+ * and the specified value cannot be added.
+ * @see Unit
+ */
+ public Measurement add(double d, Unit u) {
+ return new Measurement(value + d, error, unit.add(u), time);
+ }
+
+ /**
+ * Returns a new <code>Measurement</code> object that is the sum of this
+ * object added to the specified value.
+ *
+ * @param d The value that will be added with this object.
+ * @return A new <code>Measurement</code> object that is the sum of this
+ * object added to the specified value. The error, unit, and time of
+ * the new object is set to the error, <code>Unit</code> and time of
+ * this object.
+ */
+ public Measurement add(double d) {
+ return new Measurement(value + d, error, unit, time);
+ }
+
+ /**
+ * Returns a new <code>Measurement</code> object that is the subtraction of
+ * the specified object from this object.
+ *
+ * @param m The <code>Measurement</code> object that will be subtracted from
+ * this object.
+ * @return A new <code>Measurement</code> object that is the subtraction of
+ * the specified object from this object. The error and unit of the
+ * new object are computed. The time of the new object is set to the
+ * time of this object.
+ * @throws ArithmeticException If the <code>Unit</code> objects of this object
+ * and the specified object cannot be subtracted.
+ * @see Unit
+ */
+ public Measurement sub(Measurement m) {
+ return new Measurement(value - m.value, error + m.error, unit
+ .sub(m.unit), time);
+ }
+
+ /**
+ * Returns a new <code>Measurement</code> object that is the subtraction of
+ * the specified value from this object.
+ *
+ * @param d The value that will be subtracted from this object.
+ * @param u The <code>Unit</code> object of the specified value.
+ * @return A new <code>Measurement</code> object that is the subtraction of
+ * the specified value from this object. The unit of the new object
+ * is computed. The error and time of the new object is set to the
+ * error and time of this object.
+ * @throws ArithmeticException If the <code>Unit</code> objects of this object
+ * and the specified object cannot be subtracted.
+ * @see Unit
+ */
+ public Measurement sub(double d, Unit u) {
+ return new Measurement(value - d, error, unit.sub(u), time);
+ }
+
+ /**
+ * Returns a new <code>Measurement</code> object that is the subtraction of
+ * the specified value from this object.
+ *
+ * @param d The value that will be subtracted from this object.
+ * @return A new <code>Measurement</code> object that is the subtraction of
+ * the specified value from this object. The error, unit and time of
+ * the new object is set to the error, <code>Unit</code> object and
+ * time of this object.
+ */
+ public Measurement sub(double d) {
+ return new Measurement(value - d, error, unit, time);
+ }
+
+ /**
+ * Returns a <code>String</code> object representing this <code>Measurement</code>
+ * object.
+ *
+ * @return a <code>String</code> object representing this <code>Measurement</code>
+ * object.
+ */
+ public String toString() {
+ if (name == null) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(value);
+ if (error != 0.0d) {
+ sb.append(" +/- ");
+ sb.append(error);
+ }
+ String u = unit.toString();
+ if (u.length() > 0) {
+ sb.append(" ");
+ sb.append(u);
+ }
+ name = sb.toString();
+ }
+ return name;
+ }
+
+ /**
+ * Compares this object with the specified object for order. Returns a
+ * negative integer, zero, or a positive integer if this object is less
+ * than, equal to, or greater than the specified object.
+ *
+ * <p>
+ * Note: This class has a natural ordering that is inconsistent with equals.
+ * For this method, another <code>Measurement</code> object is considered
+ * equal if there is some <code>x</code> such that
+ *
+ * <pre>
+ * getValue() - getError() <= x <= getValue() + getError()
+ * </pre>
+ *
+ * for both <code>Measurement</code> objects being compared.
+ *
+ * @param obj The object to be compared.
+ * @return A negative integer, zero, or a positive integer if this object is
+ * less than, equal to, or greater than the specified object.
+ *
+ * @throws ClassCastException If the specified object is not of type
+ * <code>Measurement</code>.
+ * @throws ArithmeticException If the unit of the specified
+ * <code>Measurement</code> object is not equal to the <code>Unit</code>
+ * object of this object.
+ */
+ public int compareTo(Object obj) {
+ if (this == obj) {
+ return 0;
+ }
+ Measurement that = (Measurement) obj;
+ if (!unit.equals(that.unit)) {
+ throw new ArithmeticException("Cannot compare " + this + " and "
+ + that);
+ }
+ if (value == that.value) {
+ return 0;
+ }
+ if (value < that.value) {
+ if ((value + error) >= (that.value - that.error)) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
+ }
+ else {
+ if ((value - error) <= (that.value + that.error)) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+ }
+ }
+
+ /**
+ * Returns a hash code value for this object.
+ *
+ * @return A hash code value for this object.
+ */
+ public int hashCode() {
+ long bits = Double.doubleToLongBits(value + error);
+ return ((int) (bits ^ (bits >>> 32))) ^ unit.hashCode();
+ }
+
+ /**
+ * Returns whether the specified object is equal to this object. Two
+ * <code>Measurement</code> objects are equal if they have same value, error
+ * and <code>Unit</code>.
+ *
+ * <p>
+ * Note: This class has a natural ordering that is inconsistent with equals.
+ * See {@link #compareTo}.
+ *
+ * @param obj The object to compare with this object.
+ * @return <code>true</code> if this object is equal to the specified object;
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof Measurement)) {
+ return false;
+ }
+ Measurement that = (Measurement) obj;
+ return (value == that.value) && (error == that.error)
+ && unit.equals(that.unit);
+ }
+}
Propchange: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Measurement.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/State.java
URL: http://svn.apache.org/viewcvs/incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/State.java?rev=389891&view=auto
==============================================================================
--- incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/State.java (added)
+++ incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/State.java Wed Mar 29 13:05:08 2006
@@ -0,0 +1,145 @@
+/*
+ * $Header: /cvshome/build/org.osgi.util.measurement/src/org/osgi/util/measurement/State.java,v 1.7 2006/03/14 01:19:37 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2002, 2005). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.osgi.util.measurement;
+
+/**
+ * Groups a state name, value and timestamp.
+ *
+ * <p>
+ * The state itself is represented as an integer and the time is measured in
+ * milliseconds since midnight, January 1, 1970 UTC.
+ *
+ * <p>
+ * A <code>State</code> object is immutable so that it may be easily shared.
+ *
+ * @version $Revision: 1.7 $
+ */
+public class State {
+ final int value;
+ final long time;
+ final String name;
+
+ /**
+ * Create a new <code>State</code> object.
+ *
+ * @param value The value of the state.
+ * @param name The name of the state.
+ * @param time The time measured in milliseconds since midnight, January 1,
+ * 1970 UTC.
+ */
+ public State(int value, String name, long time) {
+ this.value = value;
+ this.name = name;
+ this.time = time;
+ }
+
+ /**
+ * Create a new <code>State</code> object with a time of 0.
+ *
+ * @param value The value of the state.
+ * @param name The name of the state.
+ */
+ public State(int value, String name) {
+ this(value, name, 0);
+ }
+
+ /**
+ * Returns the value of this <code>State</code>.
+ *
+ * @return The value of this <code>State</code> object.
+ */
+ public final int getValue() {
+ return value;
+ }
+
+ /**
+ * Returns the time with which this <code>State</code> was created.
+ *
+ * @return The time with which this <code>State</code> was created. The time
+ * is measured in milliseconds since midnight, January 1, 1970 UTC.
+ */
+ public final long getTime() {
+ return time;
+ }
+
+ /**
+ * Returns the name of this <code>State</code>.
+ *
+ * @return The name of this <code>State</code> object.
+ */
+ public final String getName() {
+ return name;
+ }
+
+ /**
+ * Returns a <code>String</code> object representing this object.
+ *
+ * @return a <code>String</code> object representing this object.
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(value);
+ if (name != null) {
+ sb.append(" \"");
+ sb.append(name);
+ sb.append("\"");
+ }
+ return (sb.toString());
+ }
+
+ /**
+ * Returns a hash code value for this object.
+ *
+ * @return A hash code value for this object.
+ */
+ public int hashCode() {
+ int hash = value;
+ if (name != null) {
+ hash ^= name.hashCode();
+ }
+ return hash;
+ }
+
+ /**
+ * Return whether the specified object is equal to this object. Two
+ * <code>State</code> objects are equal if they have same value and name.
+ *
+ * @param obj The object to compare with this object.
+ * @return <code>true</code> if this object is equal to the specified object;
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof State)) {
+ return false;
+ }
+ State that = (State) obj;
+ if (value != that.value) {
+ return false;
+ }
+ if (name == that.name) {
+ return true;
+ }
+ if (name == null) {
+ return false;
+ }
+ return name.equals(that.name);
+ }
+}
Propchange: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/State.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Unit.java
URL: http://svn.apache.org/viewcvs/incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Unit.java?rev=389891&view=auto
==============================================================================
--- incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Unit.java (added)
+++ incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Unit.java Wed Mar 29 13:05:08 2006
@@ -0,0 +1,525 @@
+/*
+ * $Header: /cvshome/build/org.osgi.util.measurement/src/org/osgi/util/measurement/Unit.java,v 1.14 2006/03/14 01:19:37 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2002, 2005). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.osgi.util.measurement;
+
+import java.util.Hashtable;
+
+/**
+ * A unit system for measurements.
+ *
+ * This class contains definitions of the most common SI units.
+ * <p>
+ *
+ * <p>
+ * This class only support exponents for the base SI units in the range -64 to
+ * +63. Any operation which produces an exponent outside of this range will
+ * result in a <code>Unit</code> object with undefined exponents.
+ *
+ * @version $Revision: 1.14 $
+ */
+/*
+ * This local class maintains the information about units. It can calculate new
+ * units when two values are multiplied, divided, added or subtracted. <p> The
+ * unit works with the 7 basic SI types + rad + up to 2^6 custom types. For each
+ * type, the unit keeps a bit mask with the exponents of the basic types. Eg.
+ * m/s is m = 1, s = -1. Multiplying one unit with another means that the bit
+ * masks are added, dividing means that the bit masks are subtracted. <p> This
+ * class can handle any reasonable combination of SI units. However, it will
+ * always try to coerce results back into the basic set. E.g. when you do V*A
+ * you should get W and not m2.kg/s3 . Only when the existing types do not match
+ * does the unit fallback to the expanded form. <p> This class uses offset
+ * arithmetic. This means that the exponents are stored in an long. The special
+ * field is used for units that should not be arithmetically divided or
+ * multiplied, like longitude and lattitude. These special units can however, be
+ * divided and multiplied by the basic 7 constants of the SI, e.g. deg/s.
+ */
+public class Unit {
+ private final static long UNITY = createType(0, 0, 0, 0, 0, 0, 0,
+ 0, 0);
+ private final static long ZERO = 0x40L;
+ private final static long MASK = 0x7fL;
+ private final static int m_SHIFT = 0;
+ private final static int s_SHIFT = 7;
+ private final static int kg_SHIFT = 14;
+ private final static int K_SHIFT = 21;
+ private final static int A_SHIFT = 28;
+ private final static int mol_SHIFT = 35;
+ private final static int cd_SHIFT = 42;
+ private final static int rad_SHIFT = 49;
+ private final static int x_SHIFT = 56;
+ private final static long x_MASK = MASK << x_SHIFT;
+ /** No Unit (Unity) */
+ public final static Unit unity = new Unit("", UNITY); // Unity
+ /* SI Base Units */
+ /** The length unit meter (m) */
+ public final static Unit m = new Unit("m", createType(0, 0, 0,
+ 0, 0, 0, 0, 0, 1)); // Distance
+ // meter
+ /** The time unit second (s) */
+ public final static Unit s = new Unit("s", createType(0, 0, 0,
+ 0, 0, 0, 0, 1, 0)); // Time
+ // Seconds
+ // s
+ /** The mass unit kilogram (kg) */
+ public final static Unit kg = new Unit("kg", createType(0, 0,
+ 0, 0, 0, 0, 1, 0, 0)); // Mass
+ // kilogram
+ // kg
+ /** The temperature unit kelvin (K) */
+ public final static Unit K = new Unit("K", createType(0, 0, 0,
+ 0, 0, 1, 0, 0, 0)); // Temperature
+ // kelvin
+ // K
+ /** The electric current unit ampere (A) */
+ public final static Unit A = new Unit("A", createType(0, 0, 0,
+ 0, 1, 0, 0, 0, 0)); // Current
+ // ampere
+ // A
+ /** The amount of substance unit mole (mol) */
+ public final static Unit mol = new Unit("mol", createType(0, 0,
+ 0, 1, 0, 0, 0, 0, 0)); // Substance
+ // mole
+ // mol
+ /** The luminous intensity unit candela (cd) */
+ public final static Unit cd = new Unit("cd", createType(0, 0,
+ 1, 0, 0, 0, 0, 0, 0)); // Light
+ // candela
+ // cd
+ /* SI Derived Units */
+ /** The speed unit meter per second (m/s) */
+ public final static Unit m_s = new Unit("m/s", createType(0, 0,
+ 0, 0, 0, 0, 0, -1, 1)); // Speed
+ // m/s
+ /** The acceleration unit meter per second squared (m/s <sup>2 </sup>) */
+ public final static Unit m_s2 = new Unit("m/s2", createType(0, 0,
+ 0, 0, 0, 0, 0, -2, 1)); // Acceleration
+ // m/s^2
+ /** The area unit square meter(m <sup>2 </sup>) */
+ public final static Unit m2 = new Unit("m2", createType(0, 0,
+ 0, 0, 0, 0, 0, 0, 2)); // Surface
+ // m^2
+ /** The volume unit cubic meter (m <sup>3 </sup>) */
+ public final static Unit m3 = new Unit("m3", createType(0, 0,
+ 0, 0, 0, 0, 0, 0, 3)); // Volume
+ // m^3
+ /**
+ * The frequency unit hertz (Hz).
+ * <p>
+ * hertz is expressed in SI units as 1/s
+ */
+ public final static Unit Hz = new Unit("Hz", createType(0, 0,
+ 0, 0, 0, 0, 0, -1, 0)); // Frequency
+ // 1/s
+ /**
+ * The force unit newton (N).
+ * <p>
+ * N is expressed in SI units as m·kg/s <sup>2 </sup>
+ */
+ public final static Unit N = new Unit("N", createType(0, 0, 0,
+ 0, 0, 0, 1, -2, 1)); // Force
+ // newton
+ // (m*kg)/s^2
+ /**
+ * The pressure unit pascal (Pa).
+ * <p>
+ * Pa is equal to N/m <sup>2 </sup> or is expressed in SI units as
+ * kg/m·s <sup>2 </sup>
+ */
+ public final static Unit Pa = new Unit("Pa", createType(0, 0,
+ 0, 0, 0, 0, 1, -2, -1)); // Pressure
+ // pascal
+ // kg/(m*s^2)
+ /**
+ * The energy unit joule (J).
+ * <p>
+ * joule is equal to N·m or is expressed in SI units as m <sup>2
+ * </sup>·kg/s <sup>2
+ */
+ public final static Unit J = new Unit("J", createType(0, 0, 0,
+ 0, 0, 0, 1, -2, 2)); // Energy
+ // joule
+ // (m^2*kg)/s^2
+ /**
+ * The power unit watt (W).
+ * <p>
+ * watt is equal to J/s or is expressed in SI units as m <sup>2
+ * </sup>·kg/s <sup>3 </sup>
+ */
+ public final static Unit W = new Unit("W", createType(0, 0, 0,
+ 0, 0, 0, 1, -3, 2)); // Power
+ // watt
+ // (m^2*kg)/s^3
+ /**
+ * The electric charge unit coulomb (C).
+ * <p>
+ * coulomb is expressed in SI units as s·A
+ */
+ public final static Unit C = new Unit("C", createType(0, 0, 0,
+ 0, 1, 0, 0, 1, 0)); // Charge
+ // coulumb
+ // s*A
+ /**
+ * The electric potential difference unit volt (V).
+ * <p>
+ * volt is equal to W/A or is expressed in SI units as m <sup>2
+ * </sup>·kg/s <sup>3 </sup>·A
+ */
+ public final static Unit V = new Unit("V", createType(0, 0, 0,
+ 0, -1, 0, 1, -3, 2)); // El.
+ // Potent.
+ // volt
+ // (m^2*kg)/(s^3*A)
+ /**
+ * The capacitance unit farad (F).
+ * <p>
+ * farad is equal to C/V or is expressed in SI units as s <sup>4
+ * </sup>·A <sup>2 </sup>/m <sup>2 </sup>·kg
+ */
+ public final static Unit F = new Unit("F", createType(0, 0, 0,
+ 0, 2, 0, -1, 4, -2)); // Capacitance
+ // farad
+ // (s^4*A^2)/(m^2*kg)
+ /**
+ * The electric resistance unit ohm.
+ * <p>
+ * ohm is equal to V/A or is expressed in SI units as m <sup>2
+ * </sup>·kg/s <sup>3 </sup>·A <sup>2 </sup>
+ */
+ public final static Unit Ohm = new Unit("Ohm", createType(0, 0,
+ 0, 0, -2, 0, 1, -3, 2)); // Resistance
+ // ohm
+ // (m^2*kg)/(s^3*A^2)
+ /**
+ * The electric conductance unit siemens (S).
+ * <p>
+ * siemens is equal to A/V or is expressed in SI units as s <sup>3
+ * </sup>·A <sup>2 </sup>/m <sup>2 </sup>·kg
+ */
+ public final static Unit S = new Unit("S", createType(0, 0, 0,
+ 0, 2, 0, -1, 3, -2)); // Conductance
+ // siemens
+ // (s^3*A^2)/(m^2*kg)
+ /**
+ * The magnetic flux unit weber (Wb).
+ * <p>
+ * weber is equal to V·s or is expressed in SI units as m <sup>2
+ * </sup>·kg/s <sup>2 </sup>·A
+ */
+ public final static Unit Wb = new Unit("Wb", createType(0, 0,
+ 0, 0, -1, 0, 1, -2, 2)); // Magn.
+ // Flux
+ // weber
+ // (m^2*kg)/(s^2*A)
+ /**
+ * The magnetic flux density unit tesla (T).
+ * <p>
+ * tesla is equal to Wb/m <sup>2 </sup> or is expressed in SI units as kg/s
+ * <sup>2 </sup>·A
+ */
+ public final static Unit T = new Unit("T", createType(0, 0, 0,
+ 0, -1, 0, 1, -2, 0)); // Magn.
+ // Flux
+ // Dens.
+ // tesla
+ // kg/(s^2*A)
+ /**
+ * The illuminance unit lux (lx).
+ * <p>
+ * lux is expressed in SI units as cd/m <sup>2 </sup>
+ */
+ public final static Unit lx = new Unit("lx", createType(0, 0,
+ 1, 0, 0, 0, 0, 0, -2)); // Illuminace
+ // lux
+ // cd/m^2
+ /**
+ * The absorbed dose unit gray (Gy).
+ * <p>
+ * Gy is equal to J/kg or is expressed in SI units as m <sup>2 </sup>/s
+ * <sup>2 </sup>
+ */
+ public final static Unit Gy = new Unit("Gy", createType(0, 0,
+ 0, 0, 0, 0, 0, -2, 2)); // Absorbed
+ // dose
+ // gray
+ // m^2/s^2
+ /**
+ * The catalytic activity unit katal (kat).
+ * <p>
+ * katal is expressed in SI units as mol/s
+ */
+ public final static Unit kat = new Unit("kat", createType(0, 0,
+ 0, 1, 0, 0, 0, -1, 0)); // Catalytic
+ // Act.
+ // katal
+ // mol/s
+ /** The angle unit radians (rad) */
+ public final static Unit rad = new Unit("rad", createType(0, 1,
+ 0, 0, 0, 0, 0, 0, 0)); // Angle
+ // radians
+ // rad
+ /**
+ * An array containing all units defined. The first seven items must be m,
+ * s, kg, K, A, mol, cd, rad in this order!
+ */
+ private final static Unit[] allUnits = new Unit[] {m, s, kg, K, A, mol,
+ cd, rad, m_s, m_s2, m2, m3, Hz, N, Pa, J, W, C, V, F, Ohm, S, Wb,
+ T, lx, Gy, kat, unity };
+ private static Hashtable base;
+ private String name;
+ private long type;
+
+ /**
+ * Creates a new <code>Unit</code> instance.
+ *
+ * @param name the name of the <code>Unit</code>
+ * @param type the type of the <code>Unit</code>
+ */
+ private Unit(String name, long type) {
+ this.name = name;
+ this.type = type;
+ //System.out.println( name + " " + Long.toHexString( type ) );
+ }
+
+ /**
+ * Create a type field from the base SI unit exponent values.
+ *
+ */
+ private static long createType(int x, int rad, int cd, int mol, int A,
+ int K, int kg, int s, int m) {
+ return (((ZERO + m) & MASK) << m_SHIFT)
+ | (((ZERO + s) & MASK) << s_SHIFT)
+ | (((ZERO + kg) & MASK) << kg_SHIFT)
+ | (((ZERO + K) & MASK) << K_SHIFT)
+ | (((ZERO + A) & MASK) << A_SHIFT)
+ | (((ZERO + mol) & MASK) << mol_SHIFT)
+ | (((ZERO + cd) & MASK) << cd_SHIFT)
+ | (((ZERO + rad) & MASK) << rad_SHIFT)
+ | (((long) x) << x_SHIFT);
+ }
+
+ /**
+ * Checks whether this <code>Unit</code> object is equal to the specified
+ * <code>Unit</code> object. The <code>Unit</code> objects are considered equal
+ * if their exponents are equal.
+ *
+ * @param obj the <code>Unit</code> object that should be checked for equality
+ *
+ * @return true if the specified <code>Unit</code> object is equal to this
+ * <code>Unit</code> object.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof Unit)) {
+ return false;
+ }
+ return ((Unit) obj).type == type;
+ }
+
+ /**
+ * Returns the hash code for this object.
+ *
+ * @return This object's hash code.
+ */
+ public int hashCode() {
+ return (int) ((type >>> 32) ^ type);
+ }
+
+ /**
+ * Returns a new <code>Unit</code> that is the multiplication of this
+ * <code>Unit</code> and the <code>Unit</code> specified
+ *
+ * @param that the <code>Unit</code> that will be multiplied with this
+ * <code>Unit</code>
+ *
+ * @return a new <code>Unit</code> that is the multiplication of this
+ * <code>Unit</code> and the <code>Unit</code> specified
+ *
+ * @throws RuntimeException if both <code>Unit</code> s are special
+ *
+ * @see Unit#isSpecial
+ */
+ Unit mul(Unit that) {
+ if (this.isSpecial() && that.isSpecial()) {
+ throw new ArithmeticException("Cannot multiply " + this + " with "
+ + that);
+ }
+ return find(this.type - UNITY + that.type);
+ }
+
+ /**
+ * Returns a new <code>Unit</code> that is the division of this <code>Unit</code>
+ * and the <code>Unit</code> specified
+ *
+ * @param that the <code>Unit</code> that this <code>Unit</code> will be divided
+ * with
+ * @return a new <code>Unit</code> that is the division of this <code>Unit</code>
+ * and the <code>Unit</code> specified
+ *
+ * @throws RuntimeException if both <code>Unit</code> s are special
+ *
+ * @see Unit#isSpecial
+ */
+ Unit div(Unit that) {
+ if (this.isSpecial() && that.isSpecial()) {
+ if (this.type == that.type) {
+ return Unit.unity;
+ }
+ throw new ArithmeticException("Cannot divide " + this + " by "
+ + that);
+ }
+ return find(this.type - that.type + UNITY);
+ }
+
+ /**
+ * Returns a new <code>Unit</code> that is the addition of this <code>Unit</code>
+ * and the <code>Unit</code> specified.
+ *
+ * @param that the <code>Unit</code> that should be added to this
+ * <code>Unit</code>
+ *
+ * @return a new <code>Unit</code> that is the addition of this <code>Unit</code>
+ * and the <code>Unit</code> specified.
+ *
+ * @throws RuntimeException if the two <code>Unit</code> s are not the same
+ */
+ Unit add(Unit that) {
+ if (!this.equals(that)) {
+ throw new ArithmeticException("Cannot add " + this + " to " + that);
+ }
+ return this;
+ }
+
+ /**
+ * Returns a new <code>Unit</code> that is the subtraction between this
+ * <code>Unit</code> and the <code>Unit</code> specified.
+ *
+ * @param that the <code>Unit</code> that will be subtracted from this
+ * <code>Unit</code>
+ * @return a new <code>Unit</code> that is the subtraction between this
+ * <code>Unit</code> and the <code>Unit</code> specified.
+ *
+ * @throws RuntimeException if the <code>Unit</code> specified is not the same
+ * as this <code>Unit</code>
+ */
+ Unit sub(Unit that) {
+ if (!this.equals(that)) {
+ throw new ArithmeticException("Cannot subtract " + that + " from "
+ + this);
+ }
+ return this;
+ }
+
+ /**
+ * Finds a <code>Unit</code> based on a type. If the <code>Unit</code> is not
+ * found, it will be created and added to the list of all units under a null
+ * name.
+ *
+ * @param type the type of the <code>Unit</code> to find
+ *
+ * @return the <code>Unit</code>
+ */
+ static Unit find(long type) {
+ if (base == null) {
+ synchronized (Unit.class) {
+ if (base == null) {
+ int size = allUnits.length;
+ base = new Hashtable(size << 1);
+ for (int i = 0; i < size; i++) {
+ base.put(allUnits[i], allUnits[i]);
+ }
+ }
+ }
+ }
+ Unit unit = new Unit(null, type);
+ Unit out = (Unit) base.get(unit);
+ if (out == null) {
+ base.put(unit, unit);
+ out = unit;
+ }
+ return out;
+ }
+
+ /**
+ * Returns a <code>String</code> object representing the <code>Unit</code>
+ *
+ * @return A <code>String</code> object representing the <code>Unit</code>
+ */
+ public String toString() {
+ if (name == null) {
+ int m = (int) (((type >> m_SHIFT) & MASK) - ZERO);
+ int s = (int) (((type >> s_SHIFT) & MASK) - ZERO);
+ int kg = (int) (((type >> kg_SHIFT) & MASK) - ZERO);
+ int K = (int) (((type >> K_SHIFT) & MASK) - ZERO);
+ int A = (int) (((type >> A_SHIFT) & MASK) - ZERO);
+ int mol = (int) (((type >> mol_SHIFT) & MASK) - ZERO);
+ int cd = (int) (((type >> cd_SHIFT) & MASK) - ZERO);
+ int rad = (int) (((type >> rad_SHIFT) & MASK) - ZERO);
+ StringBuffer numerator = new StringBuffer();
+ StringBuffer denominator = new StringBuffer();
+ addSIname(m, "m", numerator, denominator);
+ addSIname(s, "s", numerator, denominator);
+ addSIname(kg, "kg", numerator, denominator);
+ addSIname(K, "K", numerator, denominator);
+ addSIname(A, "A", numerator, denominator);
+ addSIname(mol, "mol", numerator, denominator);
+ addSIname(cd, "cd", numerator, denominator);
+ addSIname(rad, "rad", numerator, denominator);
+ if (denominator.length() > 0) {
+ if (numerator.length() == 0) {
+ numerator.append("1");
+ }
+ numerator.append("/");
+ numerator.append((Object) denominator); /*
+ * we use (Object) to
+ * avoid using new 1.4
+ * method
+ * append(StringBuffer)
+ */
+ }
+ name = numerator.toString();
+ }
+ return name;
+ }
+
+ private void addSIname(int si, String name, StringBuffer numerator,
+ StringBuffer denominator) {
+ if (si != 0) {
+ StringBuffer sb = (si > 0) ? numerator : denominator;
+ if (sb.length() > 0) {
+ sb.append("*");
+ }
+ sb.append(name);
+ int power = Math.abs(si);
+ if (power > 1) {
+ sb.append("^");
+ sb.append(power);
+ }
+ }
+ }
+
+ /**
+ * Checks whether the unit has a special type, i.e. not a SI unit.
+ *
+ * @return true if the type is special, otherwise false.
+ */
+ private boolean isSpecial() {
+ return (type & x_MASK) != 0;
+ }
+}
Propchange: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/Unit.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/package.html
URL: http://svn.apache.org/viewcvs/incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/package.html?rev=389891&view=auto
==============================================================================
--- incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/package.html (added)
+++ incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/package.html Wed Mar 29 13:05:08 2006
@@ -0,0 +1,10 @@
+<!-- $Header: /cvshome/build/org.osgi.util.measurement/src/org/osgi/util/measurement/package.html,v 1.4 2005/05/27 01:25:29 hargrave Exp $ -->
+<BODY>
+<P>The OSGi Measurement Package. Specification Version 1.0.
+<p>Bundles wishing to use this package must list the package
+in the Import-Package header of the bundle's manifest.
+For example:
+<pre>
+Import-Package: org.osgi.util.measurement; version=1.0
+</pre>
+</BODY>
Propchange: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/package.html
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/packageinfo
URL: http://svn.apache.org/viewcvs/incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/packageinfo?rev=389891&view=auto
==============================================================================
--- incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/packageinfo (added)
+++ incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/packageinfo Wed Mar 29 13:05:08 2006
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file
Propchange: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/measurement/packageinfo
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/Position.java
URL: http://svn.apache.org/viewcvs/incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/Position.java?rev=389891&view=auto
==============================================================================
--- incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/Position.java (added)
+++ incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/Position.java Wed Mar 29 13:05:08 2006
@@ -0,0 +1,236 @@
+/*
+ * $Header: /cvshome/build/org.osgi.util.position/src/org/osgi/util/position/Position.java,v 1.7 2006/03/14 01:20:44 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2002, 2005). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.osgi.util.position;
+
+import org.osgi.util.measurement.*;
+
+/**
+ * Position represents a geographic location, based on the WGS84 System (World
+ * Geodetic System 1984).
+ * <p>
+ * The <code>org.osgi.util.measurement.Measurement</code> class is used to
+ * represent the values that make up a position.
+ * <p>
+ * <p>
+ * A given position object may lack any of it's components, i.e. the altitude
+ * may not be known. Such missing values will be represented by null.
+ * <p>
+ * Position does not override the implementation of either equals() or
+ * hashCode() because it is not clear how missing values should be handled. It
+ * is up to the user of a position to determine how best to compare two position
+ * objects. A <code>Position</code> object is immutable.
+ */
+public class Position {
+ private Measurement altitude;
+ private Measurement longitude;
+ private Measurement latitude;
+ private Measurement speed;
+ private Measurement track;
+
+ /**
+ * Contructs a <code>Position</code> object with the given values.
+ *
+ * @param lat a <code>Measurement</code> object specifying the latitude in
+ * radians, or null
+ * @param lon a <code>Measurement</code> object specifying the longitude in
+ * radians, or null
+ * @param alt a <code>Measurement</code> object specifying the altitude in
+ * meters, or null
+ * @param speed a <code>Measurement</code> object specifying the speed in
+ * meters per second, or null
+ * @param track a <code>Measurement</code> object specifying the track in
+ * radians, or null
+ */
+ public Position(Measurement lat, Measurement lon, Measurement alt,
+ Measurement speed, Measurement track) {
+ if (lat != null) {
+ if (!Unit.rad.equals(lat.getUnit())) {
+ throw new IllegalArgumentException("Invalid Latitude");
+ }
+ this.latitude = lat;
+ }
+ if (lon != null) {
+ if (!Unit.rad.equals(lon.getUnit())) {
+ throw new IllegalArgumentException("Invalid Longitude");
+ }
+ this.longitude = lon;
+ }
+ normalizeLatLon();
+ if (alt != null) {
+ if (!Unit.m.equals(alt.getUnit())) {
+ throw new IllegalArgumentException("Invalid Altitude");
+ }
+ this.altitude = alt;
+ }
+ if (speed != null) {
+ if (!Unit.m_s.equals(speed.getUnit())) {
+ throw new IllegalArgumentException("Invalid Speed");
+ }
+ this.speed = speed;
+ }
+ if (track != null) {
+ if (!Unit.rad.equals(track.getUnit())) {
+ throw new IllegalArgumentException("Invalid Track");
+ }
+ this.track = normalizeTrack(track);
+ }
+ }
+
+ /**
+ * Returns the altitude of this position in meters.
+ *
+ * @return a <code>Measurement</code> object in <code>Unit.m</code> representing
+ * the altitude in meters above the ellipsoid <code>null</code> if the
+ * altitude is not known.
+ */
+ public Measurement getAltitude() {
+ return altitude;
+ }
+
+ /**
+ * Returns the longitude of this position in radians.
+ *
+ * @return a <code>Measurement</code> object in <code>Unit.rad</code>
+ * representing the longitude, or <code>null</code> if the longitude
+ * is not known.
+ */
+ public Measurement getLongitude() {
+ return longitude;
+ }
+
+ /**
+ * Returns the latitude of this position in radians.
+ *
+ * @return a <code>Measurement</code> object in <code>Unit.rad</code>
+ * representing the latitude, or <code>null</code> if the latitude is
+ * not known..
+ */
+ public Measurement getLatitude() {
+ return latitude;
+ }
+
+ /**
+ * Returns the ground speed of this position in meters per second.
+ *
+ * @return a <code>Measurement</code> object in <code>Unit.m_s</code>
+ * representing the speed, or <code>null</code> if the speed is not
+ * known..
+ */
+ public Measurement getSpeed() {
+ return speed;
+ }
+
+ /**
+ * Returns the track of this position in radians as a compass heading. The
+ * track is the extrapolation of previous previously measured positions to a
+ * future position.
+ *
+ * @return a <code>Measurement</code> object in <code>Unit.rad</code>
+ * representing the track, or <code>null</code> if the track is not
+ * known..
+ */
+ public Measurement getTrack() {
+ return track;
+ }
+
+ private static final double LON_RANGE = Math.PI;
+ private static final double LAT_RANGE = Math.PI / 2.0D;
+
+ /**
+ * Verify the longitude and latitude parameters so they fit the normal
+ * coordinate system. A latitude is between -90 (south) and +90 (north). A A
+ * longitude is between -180 (Western hemisphere) and +180 (eastern
+ * hemisphere). This method first normalizes the latitude and longitude
+ * between +/- 180. If the |latitude| > 90, then the longitude is added 180
+ * and the latitude is normalized to fit +/-90. (Example are with degrees
+ * though radians are used) <br>
+ * No normalization takes place when either lon or lat is null.
+ */
+ private void normalizeLatLon() {
+ if (longitude == null || latitude == null)
+ return;
+ double dlon = longitude.getValue();
+ double dlat = latitude.getValue();
+ if (dlon >= -LON_RANGE && dlon < LON_RANGE && dlat >= -LAT_RANGE
+ && dlat <= LAT_RANGE)
+ return;
+ dlon = normalize(dlon, LON_RANGE);
+ dlat = normalize(dlat, LAT_RANGE * 2.0D); // First over 180 degree
+ // Check if we have to move to other side of the earth
+ if (dlat > LAT_RANGE || dlat < -LAT_RANGE) {
+ dlon = normalize(dlon - LON_RANGE, LON_RANGE);
+ dlat = normalize((LAT_RANGE * 2.0D) - dlat, LAT_RANGE);
+ }
+ longitude = new Measurement(dlon, longitude.getError(), longitude
+ .getUnit(), longitude.getTime());
+ latitude = new Measurement(dlat, latitude.getError(), latitude
+ .getUnit(), latitude.getTime());
+ }
+
+ /**
+ * This function normalizes the a value according to a range. This is not
+ * simple modulo (as I thought when I started), but requires some special
+ * handling. For positive numbers we subtract 2*range from the number so
+ * that end up between -/+ range. For negative numbers we add this value.
+ * For example, if the value is 270 and the range is +/- 180. Then sign=1 so
+ * the (int) factor becomes 270+180/360 = 1. This means that 270-360=-90 is
+ * the result. (degrees are only used to make it easier to understand, this
+ * function is agnostic for radians/degrees). The result will be in
+ * [range,range> The algorithm is not very fast, but it handling the
+ * [> ranges made it very messy using integer arithmetic, and this is
+ * very readable. Note that it is highly unlikely that this method is called
+ * in normal situations. Normally input values to position are already
+ * normalized because they come from a GPS. And this is much more readable.
+ *
+ * @param value The value that needs adjusting
+ * @param range -range = < value < range
+ */
+ private double normalize(double value, double range) {
+ double twiceRange = 2.0D * range;
+ while (value >= range) {
+ value -= twiceRange;
+ }
+ while (value < -range) {
+ value += twiceRange;
+ }
+ return value;
+ }
+
+ private static final double TRACK_RANGE = Math.PI * 2.0D;
+
+ /**
+ * Normalize track to be a value such that: 0 <= value < +2PI. This
+ * corresponds to 0 deg to +360 deg. 0 is North 0.5*PI is East PI is South
+ * 1.5*PI is West
+ *
+ * @param track Value to be normalized
+ * @return Normalized value
+ */
+ private Measurement normalizeTrack(Measurement track) {
+ double value = track.getValue();
+ if ((0.0D <= value) && (value < TRACK_RANGE)) {
+ return track; /* value is already normalized */
+ }
+ value %= TRACK_RANGE;
+ if (value < 0.0D) {
+ value += TRACK_RANGE;
+ }
+ return new Measurement(value, track.getError(), track.getUnit(), track
+ .getTime());
+ }
+}
Propchange: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/Position.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/package.html
URL: http://svn.apache.org/viewcvs/incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/package.html?rev=389891&view=auto
==============================================================================
--- incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/package.html (added)
+++ incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/package.html Wed Mar 29 13:05:08 2006
@@ -0,0 +1,10 @@
+<!-- $Header: /cvshome/build/org.osgi.util.position/src/org/osgi/util/position/package.html,v 1.2 2004/12/01 19:00:53 hargrave Exp $ -->
+<BODY>
+<P>The OSGi Position Package. Specification Version 1.0.
+<p>Bundles wishing to use this package must list the package
+in the Import-Package header of the bundle's manifest.
+For example:
+<pre>
+Import-Package: org.osgi.util.position; version=1.0
+</pre>
+</BODY>
Propchange: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/package.html
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/packageinfo
URL: http://svn.apache.org/viewcvs/incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/packageinfo?rev=389891&view=auto
==============================================================================
--- incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/packageinfo (added)
+++ incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/packageinfo Wed Mar 29 13:05:08 2006
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file
Propchange: incubator/felix/trunk/org.osgi.compendium/src/main/java/org/osgi/util/position/packageinfo
------------------------------------------------------------------------------
svn:eol-style = native