1 package net.sf.openrocket.unit;
3 import static net.sf.openrocket.util.Chars.*;
4 import static net.sf.openrocket.util.MathUtil.pow2;
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.HashMap;
10 import java.util.regex.Matcher;
11 import java.util.regex.Pattern;
13 import net.sf.openrocket.rocketcomponent.Configuration;
14 import net.sf.openrocket.rocketcomponent.Rocket;
18 * A group of units (eg. length, mass etc.). Contains a list of different units of a same
21 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
24 public class UnitGroup {
26 public static final UnitGroup UNITS_NONE;
28 public static final UnitGroup UNITS_MOTOR_DIMENSIONS;
29 public static final UnitGroup UNITS_LENGTH;
30 public static final UnitGroup UNITS_ALL_LENGTHS;
31 public static final UnitGroup UNITS_DISTANCE;
33 public static final UnitGroup UNITS_AREA;
34 public static final UnitGroup UNITS_STABILITY;
36 * This unit group contains only the caliber unit that never scales the originating "SI" value.
37 * It can be used in cases where the originating value is already in calibers to obtains the correct unit.
39 public static final UnitGroup UNITS_STABILITY_CALIBERS;
40 public static final UnitGroup UNITS_VELOCITY;
41 public static final UnitGroup UNITS_WINDSPEED;
42 public static final UnitGroup UNITS_ACCELERATION;
43 public static final UnitGroup UNITS_MASS;
44 public static final UnitGroup UNITS_INERTIA;
45 public static final UnitGroup UNITS_ANGLE;
46 public static final UnitGroup UNITS_DENSITY_BULK;
47 public static final UnitGroup UNITS_DENSITY_SURFACE;
48 public static final UnitGroup UNITS_DENSITY_LINE;
49 public static final UnitGroup UNITS_FORCE;
50 public static final UnitGroup UNITS_IMPULSE;
52 /** Time in the order of less than a second (time step etc). */
53 public static final UnitGroup UNITS_TIME_STEP;
55 /** Time in the order of seconds (motor delay etc). */
56 public static final UnitGroup UNITS_SHORT_TIME;
58 /** Time in the order of the flight time of a rocket. */
59 public static final UnitGroup UNITS_FLIGHT_TIME;
60 public static final UnitGroup UNITS_ROLL;
61 public static final UnitGroup UNITS_TEMPERATURE;
62 public static final UnitGroup UNITS_PRESSURE;
63 public static final UnitGroup UNITS_RELATIVE;
64 public static final UnitGroup UNITS_ROUGHNESS;
66 public static final UnitGroup UNITS_COEFFICIENT;
67 public static final UnitGroup UNITS_FREQUENCY;
69 public static final UnitGroup UNITS_ENERGY;
70 public static final UnitGroup UNITS_POWER;
71 public static final UnitGroup UNITS_MOMENTUM;
72 public static final UnitGroup UNITS_VOLTAGE;
73 public static final UnitGroup UNITS_CURRENT;
76 public static final Map<String, UnitGroup> UNITS; // keys such as "LENGTH", "VELOCITY"
77 public static final Map<String, UnitGroup> SIUNITS; // keys such a "m", "m/s"
81 * Note: Units may not use HTML tags.
83 * The scaling value "X" is obtained by "one of this unit is X of SI units"
84 * Type into Google for example: "1 in^2 in m^2"
87 UNITS_NONE = new UnitGroup();
88 UNITS_NONE.addUnit(Unit.NOUNIT2);
90 UNITS_ENERGY = new UnitGroup();
91 UNITS_ENERGY.addUnit(new GeneralUnit(1, "J"));
92 UNITS_ENERGY.addUnit(new GeneralUnit(1e-7, "erg"));
93 UNITS_ENERGY.addUnit(new GeneralUnit(1.055, "BTU"));
94 UNITS_ENERGY.addUnit(new GeneralUnit(4.184, "cal"));
95 UNITS_ENERGY.addUnit(new GeneralUnit(1.3558179483314, "ft"+DOT+"lbf"));
96 UNITS_ENERGY.setDefaultUnit(0);
98 UNITS_POWER = new UnitGroup();
99 UNITS_POWER.addUnit(new GeneralUnit(1e-3, "mW"));
100 UNITS_POWER.addUnit(new GeneralUnit(1, "W"));
101 UNITS_POWER.addUnit(new GeneralUnit(1e3, "kW"));
102 UNITS_POWER.addUnit(new GeneralUnit(1e-7, "ergs"));
103 UNITS_POWER.addUnit(new GeneralUnit(745.699872, "hp"));
104 UNITS_POWER.setDefaultUnit(1);
106 UNITS_MOMENTUM = new UnitGroup();
107 UNITS_MOMENTUM.addUnit(new GeneralUnit(1, "kg"+DOT+"m/s"));
108 UNITS_MOMENTUM.setDefaultUnit(0);
110 UNITS_VOLTAGE = new UnitGroup();
111 UNITS_VOLTAGE.addUnit(new GeneralUnit(1e-3, "mV"));
112 UNITS_VOLTAGE.addUnit(new GeneralUnit(1, "V"));
113 UNITS_VOLTAGE.setDefaultUnit(1);
115 UNITS_CURRENT = new UnitGroup();
116 UNITS_CURRENT.addUnit(new GeneralUnit(1e-3, "mA"));
117 UNITS_CURRENT.addUnit(new GeneralUnit(1, "A"));
118 UNITS_CURRENT.setDefaultUnit(1);
120 UNITS_LENGTH = new UnitGroup();
121 UNITS_LENGTH.addUnit(new GeneralUnit(0.001, "mm"));
122 UNITS_LENGTH.addUnit(new GeneralUnit(0.01, "cm"));
123 UNITS_LENGTH.addUnit(new GeneralUnit(1, "m"));
124 UNITS_LENGTH.addUnit(new GeneralUnit(0.0254, "in"));
125 UNITS_LENGTH.addUnit(new FractionalUnit(0.0254, "in/64", "in", 64, 1d / 16d, 0.5d / 64d));
126 UNITS_LENGTH.addUnit(new GeneralUnit(0.3048, "ft"));
127 UNITS_LENGTH.setDefaultUnit(1);
129 UNITS_MOTOR_DIMENSIONS = new UnitGroup();
130 UNITS_MOTOR_DIMENSIONS.addUnit(new GeneralUnit(1, "m")); // just added
131 UNITS_MOTOR_DIMENSIONS.addUnit(new GeneralUnit(0.001, "mm"));
132 UNITS_MOTOR_DIMENSIONS.addUnit(new GeneralUnit(0.01, "cm"));
133 UNITS_MOTOR_DIMENSIONS.addUnit(new GeneralUnit(0.0254, "in"));
134 UNITS_MOTOR_DIMENSIONS.setDefaultUnit(0);
136 UNITS_DISTANCE = new UnitGroup();
137 UNITS_DISTANCE.addUnit(new GeneralUnit(1, "m"));
138 UNITS_DISTANCE.addUnit(new GeneralUnit(1000, "km"));
139 UNITS_DISTANCE.addUnit(new GeneralUnit(0.3048, "ft"));
140 UNITS_DISTANCE.addUnit(new GeneralUnit(0.9144, "yd"));
141 UNITS_DISTANCE.addUnit(new GeneralUnit(1609.344, "mi"));
142 UNITS_DISTANCE.addUnit(new GeneralUnit(1852, "nmi"));
144 UNITS_ALL_LENGTHS = new UnitGroup();
145 UNITS_ALL_LENGTHS.addUnit(new GeneralUnit(0.001, "mm"));
146 UNITS_ALL_LENGTHS.addUnit(new GeneralUnit(0.01, "cm"));
147 UNITS_ALL_LENGTHS.addUnit(new GeneralUnit(1, "m"));
148 UNITS_ALL_LENGTHS.addUnit(new GeneralUnit(1000, "km"));
149 UNITS_ALL_LENGTHS.addUnit(new GeneralUnit(0.0254, "in"));
150 UNITS_ALL_LENGTHS.addUnit(new FractionalUnit(0.0254, "in/64", "in", 64, 1d / 16d, 0.5d / 64d));
151 UNITS_ALL_LENGTHS.addUnit(new GeneralUnit(0.3048, "ft"));
152 UNITS_ALL_LENGTHS.addUnit(new GeneralUnit(0.9144, "yd"));
153 UNITS_ALL_LENGTHS.addUnit(new GeneralUnit(1609.344, "mi"));
154 UNITS_ALL_LENGTHS.addUnit(new GeneralUnit(1852, "nmi"));
155 UNITS_ALL_LENGTHS.setDefaultUnit(2);
157 UNITS_AREA = new UnitGroup();
158 UNITS_AREA.addUnit(new GeneralUnit(pow2(0.001), "mm" + SQUARED));
159 UNITS_AREA.addUnit(new GeneralUnit(pow2(0.01), "cm" + SQUARED));
160 UNITS_AREA.addUnit(new GeneralUnit(1, "m" + SQUARED));
161 UNITS_AREA.addUnit(new GeneralUnit(pow2(0.0254), "in" + SQUARED));
162 UNITS_AREA.addUnit(new GeneralUnit(pow2(0.3048), "ft" + SQUARED));
163 UNITS_AREA.setDefaultUnit(1);
166 UNITS_STABILITY = new UnitGroup();
167 UNITS_STABILITY.addUnit(new GeneralUnit(1, "m"));
168 UNITS_STABILITY.addUnit(new GeneralUnit(0.001, "mm"));
169 UNITS_STABILITY.addUnit(new GeneralUnit(0.01, "cm"));
170 UNITS_STABILITY.addUnit(new GeneralUnit(0.0254, "in"));
171 UNITS_STABILITY.addUnit(new CaliberUnit((Rocket) null));
172 UNITS_STABILITY.setDefaultUnit(3);
174 UNITS_STABILITY_CALIBERS = new UnitGroup();
175 UNITS_STABILITY_CALIBERS.addUnit(new GeneralUnit(1, "cal"));
178 UNITS_VELOCITY = new UnitGroup();
179 UNITS_VELOCITY.addUnit(new GeneralUnit(1, "m/s"));
180 UNITS_VELOCITY.addUnit(new GeneralUnit(1 / 3.6, "km/h"));
181 UNITS_VELOCITY.addUnit(new GeneralUnit(0.3048, "ft/s"));
182 UNITS_VELOCITY.addUnit(new GeneralUnit(0.44704, "mph"));
184 UNITS_WINDSPEED = new UnitGroup();
185 UNITS_WINDSPEED.addUnit(new GeneralUnit(1, "m/s"));
186 UNITS_WINDSPEED.addUnit(new GeneralUnit(1 / 3.6, "km/h"));
187 UNITS_WINDSPEED.addUnit(new GeneralUnit(0.3048, "ft/s"));
188 UNITS_WINDSPEED.addUnit(new GeneralUnit(0.44704, "mph"));
190 UNITS_ACCELERATION = new UnitGroup();
191 UNITS_ACCELERATION.addUnit(new GeneralUnit(1, "m/s" + SQUARED));
192 UNITS_ACCELERATION.addUnit(new GeneralUnit(0.3048, "ft/s" + SQUARED));
193 UNITS_ACCELERATION.addUnit(new GeneralUnit(9.80665, "G"));
195 UNITS_MASS = new UnitGroup();
196 UNITS_MASS.addUnit(new GeneralUnit(0.001, "g"));
197 UNITS_MASS.addUnit(new GeneralUnit(1, "kg"));
198 UNITS_MASS.addUnit(new GeneralUnit(0.0283495231, "oz"));
199 UNITS_MASS.addUnit(new GeneralUnit(0.45359237, "lb"));
201 UNITS_INERTIA = new UnitGroup();
202 UNITS_INERTIA.addUnit(new GeneralUnit(0.0001, "kg" + DOT + "cm" + SQUARED));
203 UNITS_INERTIA.addUnit(new GeneralUnit(1, "kg" + DOT + "m" + SQUARED));
204 UNITS_INERTIA.addUnit(new GeneralUnit(1.82899783e-5, "oz" + DOT + "in" + SQUARED));
205 UNITS_INERTIA.addUnit(new GeneralUnit(0.000292639653, "lb" + DOT + "in" + SQUARED));
206 UNITS_INERTIA.addUnit(new GeneralUnit(0.0421401101, "lb" + DOT + "ft" + SQUARED));
207 UNITS_INERTIA.addUnit(new GeneralUnit(1.35581795, "lbf" + DOT + "ft" + DOT + "s" + SQUARED));
208 UNITS_INERTIA.setDefaultUnit(1);
210 UNITS_ANGLE = new UnitGroup();
211 UNITS_ANGLE.addUnit(new DegreeUnit());
212 UNITS_ANGLE.addUnit(new FixedPrecisionUnit("rad", 0.01));
213 UNITS_ANGLE.addUnit(new GeneralUnit(1.0 / 3437.74677078, "arcmin"));
215 UNITS_DENSITY_BULK = new UnitGroup();
216 UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1000, "g/cm" + CUBED));
217 UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1000, "kg/dm" + CUBED));
218 UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1, "kg/m" + CUBED));
219 UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1729.99404, "oz/in" + CUBED));
220 UNITS_DENSITY_BULK.addUnit(new GeneralUnit(16.0184634, "lb/ft" + CUBED));
222 UNITS_DENSITY_SURFACE = new UnitGroup();
223 UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(10, "g/cm" + SQUARED));
224 UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(0.001, "g/m" + SQUARED));
225 UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(1, "kg/m" + SQUARED));
226 UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(43.9418487, "oz/in" + SQUARED));
227 UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(0.305151727, "oz/ft" + SQUARED));
228 UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(4.88242764, "lb/ft" + SQUARED));
229 UNITS_DENSITY_SURFACE.setDefaultUnit(1);
231 UNITS_DENSITY_LINE = new UnitGroup();
232 UNITS_DENSITY_LINE.addUnit(new GeneralUnit(0.001, "g/m"));
233 UNITS_DENSITY_LINE.addUnit(new GeneralUnit(1, "kg/m"));
234 UNITS_DENSITY_LINE.addUnit(new GeneralUnit(0.0930102465, "oz/ft"));
236 UNITS_FORCE = new UnitGroup();
237 UNITS_FORCE.addUnit(new GeneralUnit(1, "N"));
238 UNITS_FORCE.addUnit(new GeneralUnit(4.44822162, "lbf"));
239 UNITS_FORCE.addUnit(new GeneralUnit(9.80665, "kgf"));
241 UNITS_IMPULSE = new UnitGroup();
242 UNITS_IMPULSE.addUnit(new GeneralUnit(1, "Ns"));
243 UNITS_IMPULSE.addUnit(new GeneralUnit(4.44822162, "lbf" + DOT + "s"));
245 UNITS_TIME_STEP = new UnitGroup();
246 UNITS_TIME_STEP.addUnit(new FixedPrecisionUnit("ms", 1, 0.001));
247 UNITS_TIME_STEP.addUnit(new FixedPrecisionUnit("s", 0.01));
248 UNITS_TIME_STEP.setDefaultUnit(1);
250 UNITS_SHORT_TIME = new UnitGroup();
251 UNITS_SHORT_TIME.addUnit(new GeneralUnit(1, "s"));
253 UNITS_FLIGHT_TIME = new UnitGroup();
254 UNITS_FLIGHT_TIME.addUnit(new GeneralUnit(1, "s"));
255 UNITS_FLIGHT_TIME.addUnit(new GeneralUnit(60, "min"));
257 UNITS_ROLL = new UnitGroup();
258 UNITS_ROLL.addUnit(new GeneralUnit(1, "rad/s"));
259 UNITS_ROLL.addUnit(new GeneralUnit(2 * Math.PI, "r/s"));
260 UNITS_ROLL.addUnit(new GeneralUnit(2 * Math.PI / 60, "rpm"));
261 UNITS_ROLL.setDefaultUnit(1);
263 UNITS_TEMPERATURE = new UnitGroup();
264 UNITS_TEMPERATURE.addUnit(new FixedPrecisionUnit("K", 1));
265 UNITS_TEMPERATURE.addUnit(new TemperatureUnit(1, 273.15, DEGREE + "C"));
266 UNITS_TEMPERATURE.addUnit(new TemperatureUnit(5.0 / 9.0, 459.67, DEGREE + "F"));
267 UNITS_TEMPERATURE.setDefaultUnit(1);
269 UNITS_PRESSURE = new UnitGroup();
270 UNITS_PRESSURE.addUnit(new FixedPrecisionUnit("mbar", 1, 1.0e2));
271 UNITS_PRESSURE.addUnit(new FixedPrecisionUnit("bar", 0.001, 1.0e5));
272 UNITS_PRESSURE.addUnit(new FixedPrecisionUnit("atm", 0.001, 1.01325e5));
273 UNITS_PRESSURE.addUnit(new GeneralUnit(101325.0 / 760.0, "mmHg"));
274 UNITS_PRESSURE.addUnit(new GeneralUnit(3386.389, "inHg"));
275 UNITS_PRESSURE.addUnit(new GeneralUnit(6894.75729, "psi"));
276 UNITS_PRESSURE.addUnit(new GeneralUnit(1, "Pa"));
278 UNITS_RELATIVE = new UnitGroup();
279 UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("" + ZWSP, 0.01, 1.0));
280 UNITS_RELATIVE.addUnit(new GeneralUnit(0.01, "%"));
281 UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("" + PERMILLE, 1, 0.001));
282 // UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("" + ZWSP, 0.01, 1.0));
283 // UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("%", 1, 0.01));
284 // UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("" + PERMILLE, 1, 0.001));
285 UNITS_RELATIVE.setDefaultUnit(1);
288 UNITS_ROUGHNESS = new UnitGroup();
289 UNITS_ROUGHNESS.addUnit(new GeneralUnit(1, "m")); // just added
290 UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.000001, MICRO + "m"));
291 UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.0000254, "mil"));
294 UNITS_COEFFICIENT = new UnitGroup();
295 UNITS_COEFFICIENT.addUnit(new FixedPrecisionUnit("" + ZWSP, 0.01)); // zero-width space
298 // This is not used by OpenRocket, and not extensively tested:
299 UNITS_FREQUENCY = new UnitGroup();
300 // UNITS_FREQUENCY.addUnit(new GeneralUnit(1, "s"));
301 // UNITS_FREQUENCY.addUnit(new GeneralUnit(0.001, "ms"));
302 // UNITS_FREQUENCY.addUnit(new GeneralUnit(0.000001, MICRO + "s"));
303 UNITS_FREQUENCY.addUnit(new FrequencyUnit(.001, "mHz"));
304 UNITS_FREQUENCY.addUnit(new FrequencyUnit(1, "Hz"));
305 UNITS_FREQUENCY.addUnit(new FrequencyUnit(1000, "kHz"));
306 UNITS_FREQUENCY.setDefaultUnit(1);
309 HashMap<String, UnitGroup> map = new HashMap<String, UnitGroup>();
310 map.put("NONE", UNITS_NONE);
311 map.put("LENGTH", UNITS_LENGTH);
312 map.put("ALL_LENGTHS", UNITS_ALL_LENGTHS);
313 map.put("MOTOR_DIMENSIONS", UNITS_MOTOR_DIMENSIONS);
314 map.put("DISTANCE", UNITS_DISTANCE);
315 map.put("VELOCITY", UNITS_VELOCITY);
316 map.put("ACCELERATION", UNITS_ACCELERATION);
317 map.put("AREA", UNITS_AREA);
318 map.put("STABILITY", UNITS_STABILITY);
319 map.put("MASS", UNITS_MASS);
320 map.put("INERTIA", UNITS_INERTIA);
321 map.put("ANGLE", UNITS_ANGLE);
322 map.put("DENSITY_BULK", UNITS_DENSITY_BULK);
323 map.put("DENSITY_SURFACE", UNITS_DENSITY_SURFACE);
324 map.put("DENSITY_LINE", UNITS_DENSITY_LINE);
325 map.put("FORCE", UNITS_FORCE);
326 map.put("IMPULSE", UNITS_IMPULSE);
327 map.put("TIME_STEP", UNITS_TIME_STEP);
328 map.put("SHORT_TIME", UNITS_SHORT_TIME);
329 map.put("FLIGHT_TIME", UNITS_FLIGHT_TIME);
330 map.put("ROLL", UNITS_ROLL);
331 map.put("TEMPERATURE", UNITS_TEMPERATURE);
332 map.put("PRESSURE", UNITS_PRESSURE);
333 map.put("RELATIVE", UNITS_RELATIVE);
334 map.put("ROUGHNESS", UNITS_ROUGHNESS);
335 map.put("COEFFICIENT", UNITS_COEFFICIENT);
336 map.put("VOLTAGE", UNITS_VOLTAGE);
337 map.put("CURRENT", UNITS_CURRENT);
338 map.put("ENERGY", UNITS_ENERGY);
339 map.put("POWER", UNITS_POWER);
340 map.put("MOMENTUM", UNITS_MOMENTUM);
341 map.put("FREQUENCY", UNITS_FREQUENCY);
343 UNITS = Collections.unmodifiableMap(map);
345 HashMap<String, UnitGroup> simap = new HashMap<String, UnitGroup>();
346 simap.put("m", UNITS_ALL_LENGTHS);
347 simap.put("m^2", UNITS_AREA);
348 simap.put("m/s", UNITS_VELOCITY);
349 simap.put("m/s^2", UNITS_ACCELERATION);
350 simap.put("kg", UNITS_MASS);
351 simap.put("kg m^2", UNITS_INERTIA);
352 simap.put("kg/m^3", UNITS_DENSITY_BULK);
353 simap.put("N", UNITS_FORCE);
354 simap.put("Ns", UNITS_IMPULSE);
355 simap.put("s", UNITS_FLIGHT_TIME);
356 simap.put("Pa", UNITS_PRESSURE);
357 simap.put("V", UNITS_VOLTAGE);
358 simap.put("A", UNITS_CURRENT);
359 simap.put("J", UNITS_ENERGY);
360 simap.put("W", UNITS_POWER);
361 simap.put("kg m/s", UNITS_MOMENTUM);
362 simap.put("Hz", UNITS_FREQUENCY);
363 simap.put("K", UNITS_TEMPERATURE);
365 SIUNITS = Collections.unmodifiableMap(simap);
368 public static void setDefaultMetricUnits() {
369 UNITS_LENGTH.setDefaultUnit("cm");
370 UNITS_MOTOR_DIMENSIONS.setDefaultUnit("mm");
371 UNITS_DISTANCE.setDefaultUnit("m");
372 UNITS_AREA.setDefaultUnit("cm" + SQUARED);
373 UNITS_STABILITY.setDefaultUnit("cal");
374 UNITS_VELOCITY.setDefaultUnit("m/s");
375 UNITS_ACCELERATION.setDefaultUnit("m/s" + SQUARED);
376 UNITS_MASS.setDefaultUnit("g");
377 UNITS_INERTIA.setDefaultUnit("kg" + DOT + "m" + SQUARED);
378 UNITS_ANGLE.setDefaultUnit("" + DEGREE);
379 UNITS_DENSITY_BULK.setDefaultUnit("g/cm" + CUBED);
380 UNITS_DENSITY_SURFACE.setDefaultUnit("g/m" + SQUARED);
381 UNITS_DENSITY_LINE.setDefaultUnit("g/m");
382 UNITS_FORCE.setDefaultUnit("N");
383 UNITS_IMPULSE.setDefaultUnit("Ns");
384 UNITS_TIME_STEP.setDefaultUnit("s");
385 UNITS_FLIGHT_TIME.setDefaultUnit("s");
386 UNITS_ROLL.setDefaultUnit("r/s");
387 UNITS_TEMPERATURE.setDefaultUnit(DEGREE + "C");
388 UNITS_WINDSPEED.setDefaultUnit("m/s");
389 UNITS_PRESSURE.setDefaultUnit("mbar");
390 UNITS_RELATIVE.setDefaultUnit("%");
391 UNITS_ROUGHNESS.setDefaultUnit(MICRO + "m");
394 public static void setDefaultImperialUnits() {
395 UNITS_LENGTH.setDefaultUnit("in");
396 UNITS_MOTOR_DIMENSIONS.setDefaultUnit("in");
397 UNITS_DISTANCE.setDefaultUnit("ft");
398 UNITS_AREA.setDefaultUnit("in" + SQUARED);
399 UNITS_STABILITY.setDefaultUnit("cal");
400 UNITS_VELOCITY.setDefaultUnit("ft/s");
401 UNITS_ACCELERATION.setDefaultUnit("ft/s" + SQUARED);
402 UNITS_MASS.setDefaultUnit("oz");
403 UNITS_INERTIA.setDefaultUnit("lb" + DOT + "ft" + SQUARED);
404 UNITS_ANGLE.setDefaultUnit("" + DEGREE);
405 UNITS_DENSITY_BULK.setDefaultUnit("oz/in" + CUBED);
406 UNITS_DENSITY_SURFACE.setDefaultUnit("oz/ft" + SQUARED);
407 UNITS_DENSITY_LINE.setDefaultUnit("oz/ft");
408 UNITS_FORCE.setDefaultUnit("N");
409 UNITS_IMPULSE.setDefaultUnit("Ns");
410 UNITS_TIME_STEP.setDefaultUnit("s");
411 UNITS_FLIGHT_TIME.setDefaultUnit("s");
412 UNITS_ROLL.setDefaultUnit("r/s");
413 UNITS_TEMPERATURE.setDefaultUnit(DEGREE + "F");
414 UNITS_WINDSPEED.setDefaultUnit("mph");
415 UNITS_PRESSURE.setDefaultUnit("mbar");
416 UNITS_RELATIVE.setDefaultUnit("%");
417 UNITS_ROUGHNESS.setDefaultUnit("mil");
422 * Return a UnitGroup for stability units based on the rocket.
424 * @param rocket the rocket from which to calculate the caliber
425 * @return the unit group
427 public static UnitGroup stabilityUnits(Rocket rocket) {
428 return new StabilityUnitGroup(rocket);
433 * Return a UnitGroup for stability units based on the rocket configuration.
435 * @param config the rocket configuration from which to calculate the caliber
436 * @return the unit group
438 public static UnitGroup stabilityUnits(Configuration config) {
439 return new StabilityUnitGroup(config);
444 * Return a UnitGroup for stability units based on a constant caliber.
446 * @param reference the constant reference length
447 * @return the unit group
449 public static UnitGroup stabilityUnits(double reference) {
450 return new StabilityUnitGroup(reference);
454 //////////////////////////////////////////////////////
457 protected ArrayList<Unit> units = new ArrayList<Unit>();
458 protected int defaultUnit = 0;
460 public int getUnitCount() {
464 public Unit getDefaultUnit() {
465 return units.get(defaultUnit);
468 public int getDefaultUnitIndex() {
472 public void setDefaultUnit(int n) {
473 if (n < 0 || n >= units.size()) {
474 throw new IllegalArgumentException("index out of range: " + n);
479 public Unit getSIUnit(){
480 for (Unit u : units){
481 if (u.multiplier == 1){
485 return UNITS_NONE.getDefaultUnit();
489 * Find a unit by approximate unit name. Only letters and (ordinary) numbers are
490 * considered in the matching. This method is mainly means for testing, allowing
491 * a simple means to obtain a particular unit.
493 * @param str the unit name.
494 * @return the corresponding unit, or <code>null</code> if not found.
496 public Unit findApproximate(String str) {
497 str = str.replaceAll("\\W", "").trim();
498 for (Unit u : units) {
499 String name = u.getUnit().replaceAll("\\W", "").trim();
500 if (str.equalsIgnoreCase(name))
507 * Set the default unit based on the unit name. Throws an exception if a
508 * unit with the provided name is not available.
510 * @param name the unit name.
511 * @throws IllegalArgumentException if the corresponding unit is not found in the group.
513 public void setDefaultUnit(String name) throws IllegalArgumentException {
514 for (int i = 0; i < units.size(); i++) {
515 if (units.get(i).getUnit().equals(name)) {
520 throw new IllegalArgumentException("name=" + name);
523 public Unit getUnit(String name) throws IllegalArgumentException {
524 for (int i = 0; i < units.size(); i++) {
525 if (units.get(i).getUnit().equals(name)) {
529 throw new IllegalArgumentException("name=" + name);
532 public Unit getUnit(int n) {
536 public int getUnitIndex(Unit u) {
537 return units.indexOf(u);
540 public void addUnit(Unit u) {
544 public boolean contains(Unit u) {
545 return units.contains(u);
548 public Unit[] getUnits() {
549 return units.toArray(new Unit[0]);
553 * Return the value in SI units from the default unit of this group.
554 * It is the same as calling <code>getDefaultUnit().fromUnit(value)</code>
556 * @param value the default unit value to convert
557 * @return the value in SI units.
558 * @see Unit#fromUnit(double)
560 public double fromUnit( double value ) {
561 return this.getDefaultUnit().fromUnit(value);
565 * Return the value formatted by the default unit of this group.
566 * It is the same as calling <code>getDefaultUnit().toString(value)</code>.
568 * @param value the SI value to format.
569 * @return the formatted string.
570 * @see Unit#toString(double)
572 public String toString(double value) {
573 return this.getDefaultUnit().toString(value);
578 * Return the value formatted by the default unit of this group including the unit.
579 * It is the same as calling <code>getDefaultUnit().toStringUnit(value)</code>.
581 * @param value the SI value to format.
582 * @return the formatted string.
583 * @see Unit#toStringUnit(double)
585 public String toStringUnit(double value) {
586 return this.getDefaultUnit().toStringUnit(value);
594 * Creates a new Value object with the specified value and the default unit of this group.
596 * @param value the value to set.
597 * @return a new Value object.
599 public Value toValue(double value) {
600 return this.getDefaultUnit().toValue(value);
604 public String toString(){
605 return this.getClass().getSimpleName()+":"+this.getSIUnit().toString();
609 public boolean equals(Object o){
610 UnitGroup u = (UnitGroup) o;
611 int size = units.size();
612 if (size != u.units.size()){
616 for (int i=0; i<size; i++){
617 if ( !units.get(i).equals(u.units.get(i)) ){
627 private static final Pattern STRING_PATTERN = Pattern.compile("^\\s*([0-9.,-]+)(.*?)$");
630 * Converts a string into an SI value. If the string has one of the units in this
631 * group appended to it, that unit will be used in conversion. Otherwise the default
632 * unit will be used. If an unknown unit is specified or the value does not parse
633 * with <code>Double.parseDouble</code> then a <code>NumberFormatException</code>
636 * This method is applicable only for simple units without e.g. powers.
638 * @param str the string to parse.
639 * @return the SI value.
640 * @throws NumberFormatException if the string cannot be parsed.
642 public double fromString(String str) {
643 Matcher matcher = STRING_PATTERN.matcher(str);
645 if (!matcher.matches()) {
646 throw new NumberFormatException("string did not match required pattern");
649 double value = Double.parseDouble(matcher.group(1));
650 String unit = matcher.group(2).trim();
652 if (unit.equals("")) {
653 value = this.getDefaultUnit().fromUnit(value);
656 for (i = 0; i < units.size(); i++) {
657 Unit u = units.get(i);
658 if (unit.equalsIgnoreCase(u.getUnit())) {
659 value = u.fromUnit(value);
663 if (i >= units.size()) {
664 throw new NumberFormatException("unknown unit " + unit);
672 ///////////////////////////
676 public int hashCode() {
678 for (Unit u : units){
679 code = code + u.hashCode();
685 * A private class that switches the CaliberUnit to a rocket-specific CaliberUnit.
686 * All other methods are passed through to UNITS_STABILITY.
688 private static class StabilityUnitGroup extends UnitGroup {
690 public StabilityUnitGroup(double ref) {
691 this(new CaliberUnit(ref));
694 public StabilityUnitGroup(Rocket rocket) {
695 this(new CaliberUnit(rocket));
698 public StabilityUnitGroup(Configuration config) {
699 this(new CaliberUnit(config));
702 private StabilityUnitGroup(CaliberUnit caliberUnit) {
703 this.units.addAll(UnitGroup.UNITS_STABILITY.units);
704 this.defaultUnit = UnitGroup.UNITS_STABILITY.defaultUnit;
705 for (int i = 0; i < units.size(); i++) {
706 if (units.get(i) instanceof CaliberUnit) {
707 units.set(i, caliberUnit);
714 public void setDefaultUnit(int n) {
715 super.setDefaultUnit(n);
716 UNITS_STABILITY.setDefaultUnit(n);