1 package com.billkuker.rocketry.motorsim;
\r
3 import java.lang.ref.WeakReference;
\r
4 import java.lang.reflect.Field;
\r
5 import java.lang.reflect.Modifier;
\r
6 import java.text.DecimalFormat;
\r
7 import java.text.NumberFormat;
\r
8 import java.util.HashSet;
\r
9 import java.util.Iterator;
\r
10 import java.util.Set;
\r
11 import java.util.prefs.Preferences;
\r
13 import javax.measure.quantity.Pressure;
\r
14 import javax.measure.quantity.Quantity;
\r
15 import javax.measure.unit.NonSI;
\r
16 import javax.measure.unit.ProductUnit;
\r
17 import javax.measure.unit.SI;
\r
18 import javax.measure.unit.Unit;
\r
19 import javax.measure.unit.UnitFormat;
\r
21 import org.apache.log4j.Logger;
\r
22 import org.jscience.physics.amount.Amount;
\r
24 public class RocketScience {
\r
25 private static final Logger log = Logger.getLogger(RocketScience.class);
\r
27 public static Unit<Pressure> PSI = new ProductUnit<Pressure>(NonSI.POUND_FORCE.divide(NonSI.INCH.pow(2)));
\r
28 public static Unit<Impulse> NEWTON_SECOND = new ProductUnit<Impulse>(SI.NEWTON.times(SI.SECOND));
\r
29 public static Unit<Impulse> POUND_SECOND = new ProductUnit<Impulse>(NonSI.POUND_FORCE.times(SI.SECOND));
\r
31 UnitFormat.getInstance().label(PSI, "psi");
\r
32 UnitFormat.getInstance().label(NEWTON_SECOND, "Ns");
\r
35 public interface MolarWeight extends Quantity {
\r
36 public static final Unit<MolarWeight> UNIT = new ProductUnit<MolarWeight>(
\r
37 SI.KILOGRAM.divide(SI.MOLE));
\r
40 public interface Impulse extends Quantity {
\r
41 public static Unit<Impulse> UNIT = NEWTON_SECOND;
\r
44 private static HashSet<WeakReference<UnitPreferenceListener>> prefListeners = new HashSet<WeakReference<UnitPreferenceListener>>();
\r
45 public static interface UnitPreferenceListener{
\r
46 public void preferredUnitsChanged();
\r
48 public static void addUnitPreferenceListener(UnitPreferenceListener l){
\r
49 prefListeners.add(new WeakReference<RocketScience.UnitPreferenceListener>(l));
\r
52 public static enum UnitPreference{
\r
54 javax.measure.unit.SI.METERS_PER_SECOND,
\r
55 javax.measure.unit.SI.MILLIMETER.pow(3),
\r
56 javax.measure.unit.SI.MILLIMETER.pow(2),
\r
57 javax.measure.unit.SI.MILLIMETER,
\r
58 javax.measure.unit.SI.MILLIMETER.divide(javax.measure.unit.SI.SECOND),
\r
59 javax.measure.unit.SI.NEWTON,
\r
60 javax.measure.unit.SI.GRAM,
\r
61 javax.measure.unit.SI.MEGA(javax.measure.unit.SI.PASCAL),
\r
65 javax.measure.unit.NonSI.MILES_PER_HOUR,
\r
66 javax.measure.unit.NonSI.INCH.pow(3),
\r
67 javax.measure.unit.NonSI.INCH.pow(2),
\r
68 javax.measure.unit.NonSI.INCH,
\r
69 javax.measure.unit.NonSI.POUND_FORCE,
\r
70 javax.measure.unit.NonSI.OUNCE,
\r
71 javax.measure.unit.NonSI.INCH.divide(javax.measure.unit.SI.SECOND),
\r
76 private static UnitPreference preference = SI;
\r
79 Preferences prefs = Preferences.userNodeForPackage(RocketScience.class);
\r
80 String p = prefs.get("PreferedUnits", "SI");
\r
81 preference = UnitPreference.valueOf(p);
\r
84 public static UnitPreference getUnitPreference(){
\r
88 public static void setUnitPreference( final UnitPreference up ){
\r
89 if ( preference == up )
\r
92 Preferences prefs = Preferences.userNodeForPackage(RocketScience.class);
\r
93 prefs.put("PreferedUnits", up.toString());
\r
94 Iterator<WeakReference<UnitPreferenceListener>> weakIter = prefListeners.iterator();
\r
95 while (weakIter.hasNext()) {
\r
96 WeakReference<UnitPreferenceListener> weak = weakIter.next();
\r
97 UnitPreferenceListener l = weak.get();
\r
99 l.preferredUnitsChanged();
\r
101 log.debug("Weak reference to UPE is null");
\r
107 protected Set<Unit<?>> units = new HashSet<Unit<?>>();
\r
109 UnitPreference( Unit<?> u[] ){
\r
110 for ( Unit<?> uu : u )
\r
114 @SuppressWarnings("unchecked")
\r
115 public <T extends Quantity> Unit<T> getPreferredUnit(Unit<T> u){
\r
116 if ( units.contains(u) )
\r
118 for( Unit<?> ret : units ){
\r
119 if ( ret.isCompatible(u) ){
\r
120 return (Unit<T>) ret;
\r
126 @SuppressWarnings("unchecked")
\r
127 public <T extends Quantity> Unit<T> getPreferredUnit(Class<T> q){
\r
128 for( Unit<?> u : units ){
\r
130 return u.asType(q);
\r
131 } catch ( ClassCastException e ) {
\r
136 Field f = q.getDeclaredField("UNIT");
\r
137 if ( Modifier.isStatic(f.getModifiers()) ){
\r
138 if ( Unit.class.isAssignableFrom(f.getType())){
\r
139 return (Unit<T>)f.get(null);
\r
142 } catch (SecurityException e) {
\r
143 e.printStackTrace();
\r
144 } catch (NoSuchFieldException e) {
\r
145 e.printStackTrace();
\r
146 } catch (IllegalArgumentException e) {
\r
148 } catch (IllegalAccessException e) {
\r
155 public static <T extends Quantity> String ammountToString(Amount<T> a) {
\r
158 final NumberFormat nf = new DecimalFormat("##########.###");
\r
159 return nf.format(a.doubleValue(a.getUnit())) + " " + a.getUnit();
\r
162 @SuppressWarnings("unchecked")
\r
163 public static <T extends Quantity> String ammountToRoundedString(Amount<T> a) {
\r
166 Unit<T> u = RocketScience.UnitPreference.preference.getPreferredUnit(a
\r
168 double d = a.doubleValue(u);
\r
172 if (u == SI.MILLIMETER && d > 1000.0) {
\r
173 u = (Unit<T>) SI.METER;
\r
175 } else if (u == NonSI.INCH && d > 12.0) {
\r
176 u = (Unit<T>) NonSI.FOOT;
\r
180 if (Math.abs(d) < 10.0) {
\r
181 df = new DecimalFormat("#.##");
\r
182 } else if (Math.abs(d) < 100.0) {
\r
183 df = new DecimalFormat("#.#");
\r
185 df = new DecimalFormat("#");
\r
188 return df.format(d) + " " + u.toString();
\r