1 package net.sf.openrocket.unit;
3 import java.text.DecimalFormat;
5 public abstract class Unit {
7 /** No unit with 2 digit precision */
8 public static final Unit NOUNIT2 = new GeneralUnit(1,"\u200b", 2); // zero-width space
10 protected final double multiplier; // meters = units * multiplier
11 protected final String unit;
14 * Creates a new Unit with a given multiplier and unit name.
16 * Multiplier e.g. 1 in = 0.0254 meter
18 * @param multiplier The multiplier to use on the value, 1 this unit == multiplier SI units
19 * @param unit The unit's short form.
21 public Unit(double multiplier, String unit) {
23 throw new IllegalArgumentException("Unit has multiplier=0");
24 this.multiplier = multiplier;
29 * Converts from SI units to this unit. The default implementation simply divides by the
32 * @param value Value in SI unit
33 * @return Value in these units
35 public double toUnit(double value) {
36 return value/multiplier;
40 * Convert from this type of units to SI units. The default implementation simply
41 * multiplies by the multiplier.
43 * @param value Value in these units
44 * @return Value in SI units
46 public double fromUnit(double value) {
47 return value*multiplier;
52 * Return the unit name.
56 public String getUnit() {
61 * Whether the value and unit should be separated by a whitespace. This method
62 * returns true as most units have a space between the value and unit, but may be
65 * @return true if the value and unit should be separated
67 public boolean hasSpace() {
72 // Testcases for toString(double)
73 public static void main(String arg[]) {
74 System.out.println(NOUNIT2.toString(0.0049));
75 System.out.println(NOUNIT2.toString(0.0050));
76 System.out.println(NOUNIT2.toString(0.0051));
77 System.out.println(NOUNIT2.toString(0.00123));
78 System.out.println(NOUNIT2.toString(0.0123));
79 System.out.println(NOUNIT2.toString(0.1234));
80 System.out.println(NOUNIT2.toString(1.2345));
81 System.out.println(NOUNIT2.toString(12.345));
82 System.out.println(NOUNIT2.toString(123.456));
83 System.out.println(NOUNIT2.toString(1234.5678));
84 System.out.println(NOUNIT2.toString(12345.6789));
85 System.out.println(NOUNIT2.toString(123456.789));
86 System.out.println(NOUNIT2.toString(1234567.89));
87 System.out.println(NOUNIT2.toString(12345678.9));
89 System.out.println(NOUNIT2.toString(-0.0049));
90 System.out.println(NOUNIT2.toString(-0.0050));
91 System.out.println(NOUNIT2.toString(-0.0051));
92 System.out.println(NOUNIT2.toString(-0.00123));
93 System.out.println(NOUNIT2.toString(-0.0123));
94 System.out.println(NOUNIT2.toString(-0.1234));
95 System.out.println(NOUNIT2.toString(-1.2345));
96 System.out.println(NOUNIT2.toString(-12.345));
97 System.out.println(NOUNIT2.toString(-123.456));
98 System.out.println(NOUNIT2.toString(-1234.5678));
99 System.out.println(NOUNIT2.toString(-12345.6789));
100 System.out.println(NOUNIT2.toString(-123456.789));
101 System.out.println(NOUNIT2.toString(-1234567.89));
102 System.out.println(NOUNIT2.toString(-12345678.9));
108 public String toString() {
112 private static final DecimalFormat intFormat = new DecimalFormat("#");
113 private static final DecimalFormat decFormat = new DecimalFormat("0.##");
114 private static final DecimalFormat expFormat = new DecimalFormat("0.00E0");
117 * Format the given value (in SI units) to a string representation of the value in this
118 * units. An suitable amount of decimals for the unit are used in the representation.
119 * The unit is not appended to the numerical value.
121 * @param value Value in SI units.
122 * @return A string representation of the number in these units.
124 public String toString(double value) {
125 double val = toUnit(value);
127 if (Math.abs(val) > 1E6) {
128 return expFormat.format(val);
130 if (Math.abs(val) >= 100) {
131 return intFormat.format(val);
133 if (Math.abs(val) <= 0.005) {
137 double sign = Math.signum(val);
144 val = Math.rint(val)/mul * sign;
146 return decFormat.format(val);
151 * Return a string with the specified value and unit. The value is converted into
152 * this unit. If <code>value</code> is NaN, returns "N/A" (not applicable).
154 * @param value the value to print in SI units.
155 * @return the value and unit, or "N/A".
157 public String toStringUnit(double value) {
158 if (Double.isNaN(value))
161 String s = toString(value);
172 * Round the value (in the current units) to a precision suitable for rough valuing
173 * (approximately 2 significant numbers).
175 * @param value Value in current units
176 * @return Rounded value.
178 public abstract double round(double value);
181 * Return the next rounded value after the given value.
182 * @param value Value in these units.
183 * @return The next suitable rounded value.
185 public abstract double getNextValue(double value);
188 * Return the previous rounded value before the given value.
189 * @param value Value in these units.
190 * @return The previous suitable rounded value.
192 public abstract double getPreviousValue(double value);
194 //public abstract ArrayList<Tick> getTicks(double start, double end, double scale);
197 * Return ticks in the range start - end (in current units). minor is the minimum
198 * distance between minor, non-notable ticks and major the minimum distance between
199 * major non-notable ticks. The values are in current units, i.e. no conversion is
202 public abstract Tick[] getTicks(double start, double end, double minor, double major);
205 * Compares whether the two units are equal. Equality requires the unit classes,
206 * multiplier values and units to be equal.
209 public boolean equals(Object other) {
212 if (this.getClass() != other.getClass())
214 return ((this.multiplier == ((Unit)other).multiplier) &&
215 this.unit.equals(((Unit)other).unit));
219 public int hashCode() {
220 return this.getClass().hashCode() + this.unit.hashCode();