1 package net.sf.openrocket.unit;
3 import java.text.DecimalFormat;
5 import net.sf.openrocket.util.Chars;
7 public abstract class Unit {
9 /** No unit with 2 digit precision */
10 public static final Unit NOUNIT2 = new GeneralUnit(1,""+Chars.ZWSP, 2);
12 protected final double multiplier; // meters = units * multiplier
13 protected final String unit;
16 * Creates a new Unit with a given multiplier and unit name.
18 * Multiplier e.g. 1 in = 0.0254 meter
20 * @param multiplier The multiplier to use on the value, 1 this unit == multiplier SI units
21 * @param unit The unit's short form.
23 public Unit(double multiplier, String unit) {
25 throw new IllegalArgumentException("Unit has multiplier=0");
26 this.multiplier = multiplier;
31 * Converts from SI units to this unit. The default implementation simply divides by the
34 * @param value Value in SI unit
35 * @return Value in these units
37 public double toUnit(double value) {
38 return value/multiplier;
42 * Convert from this type of units to SI units. The default implementation simply
43 * multiplies by the multiplier.
45 * @param value Value in these units
46 * @return Value in SI units
48 public double fromUnit(double value) {
49 return value*multiplier;
54 * Return the unit name.
58 public String getUnit() {
63 * Whether the value and unit should be separated by a whitespace. This method
64 * returns true as most units have a space between the value and unit, but may be
67 * @return true if the value and unit should be separated
69 public boolean hasSpace() {
74 // Testcases for toString(double)
75 public static void main(String arg[]) {
76 System.out.println(NOUNIT2.toString(0.0049));
77 System.out.println(NOUNIT2.toString(0.0050));
78 System.out.println(NOUNIT2.toString(0.0051));
79 System.out.println(NOUNIT2.toString(0.00123));
80 System.out.println(NOUNIT2.toString(0.0123));
81 System.out.println(NOUNIT2.toString(0.1234));
82 System.out.println(NOUNIT2.toString(1.2345));
83 System.out.println(NOUNIT2.toString(12.345));
84 System.out.println(NOUNIT2.toString(123.456));
85 System.out.println(NOUNIT2.toString(1234.5678));
86 System.out.println(NOUNIT2.toString(12345.6789));
87 System.out.println(NOUNIT2.toString(123456.789));
88 System.out.println(NOUNIT2.toString(1234567.89));
89 System.out.println(NOUNIT2.toString(12345678.9));
91 System.out.println(NOUNIT2.toString(-0.0049));
92 System.out.println(NOUNIT2.toString(-0.0050));
93 System.out.println(NOUNIT2.toString(-0.0051));
94 System.out.println(NOUNIT2.toString(-0.00123));
95 System.out.println(NOUNIT2.toString(-0.0123));
96 System.out.println(NOUNIT2.toString(-0.1234));
97 System.out.println(NOUNIT2.toString(-1.2345));
98 System.out.println(NOUNIT2.toString(-12.345));
99 System.out.println(NOUNIT2.toString(-123.456));
100 System.out.println(NOUNIT2.toString(-1234.5678));
101 System.out.println(NOUNIT2.toString(-12345.6789));
102 System.out.println(NOUNIT2.toString(-123456.789));
103 System.out.println(NOUNIT2.toString(-1234567.89));
104 System.out.println(NOUNIT2.toString(-12345678.9));
110 public String toString() {
114 private static final DecimalFormat intFormat = new DecimalFormat("#");
115 private static final DecimalFormat decFormat = new DecimalFormat("0.##");
116 private static final DecimalFormat expFormat = new DecimalFormat("0.00E0");
119 * Format the given value (in SI units) to a string representation of the value in this
120 * units. An suitable amount of decimals for the unit are used in the representation.
121 * The unit is not appended to the numerical value.
123 * @param value Value in SI units.
124 * @return A string representation of the number in these units.
126 public String toString(double value) {
127 double val = toUnit(value);
129 if (Math.abs(val) > 1E6) {
130 return expFormat.format(val);
132 if (Math.abs(val) >= 100) {
133 return intFormat.format(val);
135 if (Math.abs(val) <= 0.005) {
139 double sign = Math.signum(val);
146 val = Math.rint(val)/mul * sign;
148 return decFormat.format(val);
153 * Return a string with the specified value and unit. The value is converted into
154 * this unit. If <code>value</code> is NaN, returns "N/A" (not applicable).
156 * @param value the value to print in SI units.
157 * @return the value and unit, or "N/A".
159 public String toStringUnit(double value) {
160 if (Double.isNaN(value))
163 String s = toString(value);
173 * Creates a new Value object with the specified value and this unit.
175 * @param value the value to set.
176 * @return a new Value object.
178 public Value toValue(double value) {
179 return new Value(value, this);
185 * Round the value (in the current units) to a precision suitable for rough valuing
186 * (approximately 2 significant numbers).
188 * @param value Value in current units
189 * @return Rounded value.
191 public abstract double round(double value);
194 * Return the next rounded value after the given value.
195 * @param value Value in these units.
196 * @return The next suitable rounded value.
198 public abstract double getNextValue(double value);
201 * Return the previous rounded value before the given value.
202 * @param value Value in these units.
203 * @return The previous suitable rounded value.
205 public abstract double getPreviousValue(double value);
207 //public abstract ArrayList<Tick> getTicks(double start, double end, double scale);
210 * Return ticks in the range start - end (in current units). minor is the minimum
211 * distance between minor, non-notable ticks and major the minimum distance between
212 * major non-notable ticks. The values are in current units, i.e. no conversion is
215 public abstract Tick[] getTicks(double start, double end, double minor, double major);
218 * Compares whether the two units are equal. Equality requires the unit classes,
219 * multiplier values and units to be equal.
222 public boolean equals(Object other) {
225 if (this.getClass() != other.getClass())
227 return ((this.multiplier == ((Unit)other).multiplier) &&
228 this.unit.equals(((Unit)other).unit));
232 public int hashCode() {
233 return this.getClass().hashCode() + this.unit.hashCode();