ed89d6bb20a7311c9abd40c162b581d6e9ce702f
[sw/motorsim] / src / com / billkuker / rocketry / motorsim / RocketScience.java
1 package com.billkuker.rocketry.motorsim;\r
2 \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.Set;\r
10 import java.util.prefs.Preferences;\r
11 \r
12 import javax.measure.quantity.Pressure;\r
13 import javax.measure.quantity.Quantity;\r
14 import javax.measure.unit.NonSI;\r
15 import javax.measure.unit.ProductUnit;\r
16 import javax.measure.unit.SI;\r
17 import javax.measure.unit.Unit;\r
18 import javax.measure.unit.UnitFormat;\r
19 \r
20 import org.jscience.physics.amount.Amount;\r
21 \r
22 public class RocketScience {\r
23         public static Unit<Pressure> PSI = new ProductUnit<Pressure>(NonSI.POUND_FORCE.divide(NonSI.INCH.pow(2)));\r
24         public static Unit<Impulse> NEWTON_SECOND = new ProductUnit<Impulse>(SI.NEWTON.times(SI.SECOND));\r
25         public static Unit<Impulse> POUND_SECOND = new ProductUnit<Impulse>(NonSI.POUND_FORCE.times(SI.SECOND));\r
26         static{\r
27                 UnitFormat.getInstance().label(PSI, "psi");\r
28                 UnitFormat.getInstance().label(NEWTON_SECOND, "Ns");\r
29         }\r
30 \r
31         public interface MolarWeight extends Quantity {\r
32                 public static final Unit<MolarWeight> UNIT = new ProductUnit<MolarWeight>(\r
33                                 SI.KILOGRAM.divide(SI.MOLE));\r
34         }\r
35         \r
36         public interface Impulse extends Quantity {\r
37                 public static Unit<Impulse> UNIT = NEWTON_SECOND;\r
38         }\r
39         \r
40         private static HashSet<WeakReference<UnitPreferenceListener>> prefListeners = new HashSet<WeakReference<UnitPreferenceListener>>();\r
41         public static interface UnitPreferenceListener{\r
42                 public void preferredUnitsChanged();\r
43         }\r
44         public static void addUnitPreferenceListener(UnitPreferenceListener l){\r
45                 prefListeners.add(new WeakReference<RocketScience.UnitPreferenceListener>(l));\r
46         }\r
47 \r
48         public static enum UnitPreference{\r
49                 SI(new Unit[]{\r
50                                 javax.measure.unit.SI.MILLIMETER.pow(2),\r
51                                 javax.measure.unit.SI.MILLIMETER,\r
52                                 javax.measure.unit.SI.MILLIMETER.divide(javax.measure.unit.SI.SECOND),\r
53                                 javax.measure.unit.SI.NEWTON,\r
54                                 javax.measure.unit.SI.GRAM,\r
55                                 javax.measure.unit.SI.MEGA(javax.measure.unit.SI.PASCAL),\r
56                                 NEWTON_SECOND\r
57                 }),\r
58                 NONSI(new Unit[]{\r
59                                 javax.measure.unit.NonSI.INCH.pow(2),\r
60                                 javax.measure.unit.NonSI.INCH,\r
61                                 javax.measure.unit.NonSI.POUND_FORCE,\r
62                                 javax.measure.unit.NonSI.OUNCE,\r
63                                 javax.measure.unit.NonSI.INCH.divide(javax.measure.unit.SI.SECOND),\r
64                                 PSI,\r
65                                 POUND_SECOND\r
66                 });\r
67                 \r
68                 private static UnitPreference preference = SI;\r
69 \r
70                 static {\r
71                         Preferences prefs = Preferences.userNodeForPackage(RocketScience.class);\r
72                         String p = prefs.get("PreferedUnits", "SI");\r
73                         preference = UnitPreference.valueOf(p);\r
74                 }\r
75                 \r
76                 public static UnitPreference getUnitPreference(){\r
77                         return preference;\r
78                 }\r
79                 \r
80                 public static void setUnitPreference( final UnitPreference up ){\r
81                         if ( preference == up )\r
82                                 return;\r
83                         preference = up;\r
84                         Preferences prefs = Preferences.userNodeForPackage(RocketScience.class);\r
85                         prefs.put("PreferedUnits", up.toString());\r
86                         for ( WeakReference<UnitPreferenceListener> weak : prefListeners ){\r
87                                 UnitPreferenceListener l = weak.get();\r
88                                 if ( l != null )\r
89                                         l.preferredUnitsChanged();\r
90                         }\r
91                 }\r
92                 \r
93                 protected Set<Unit<?>> units = new HashSet<Unit<?>>();\r
94                 \r
95                 UnitPreference( Unit<?> u[] ){\r
96                         for ( Unit<?> uu : u )\r
97                                 units.add(uu);\r
98                 }\r
99                 \r
100                 @SuppressWarnings("unchecked")\r
101                 public <T extends Quantity> Unit<T> getPreferredUnit(Unit<T> u){\r
102                         if ( units.contains(u) )\r
103                                 return u;\r
104                         for( Unit<?> ret : units ){\r
105                                 if ( ret.isCompatible(u) ){\r
106                                         return (Unit<T>) ret;\r
107                                 }\r
108                         }\r
109                         return u;\r
110                 }\r
111                 \r
112                 @SuppressWarnings("unchecked")\r
113                 public <T extends Quantity> Unit<T> getPreferredUnit(Class<T> q){\r
114                         for( Unit<?> u : units ){\r
115                                 try {\r
116                                         return u.asType(q); \r
117                                 } catch ( ClassCastException e ) {\r
118                                         //Not compatible\r
119                                 }\r
120                         }\r
121                         try {\r
122                                 Field f = q.getDeclaredField("UNIT");\r
123                                 if ( Modifier.isStatic(f.getModifiers()) ){\r
124                                         if ( Unit.class.isAssignableFrom(f.getType())){\r
125                                                 return (Unit<T>)f.get(null);\r
126                                         }\r
127                                 }\r
128                         } catch (SecurityException e) {\r
129                                 e.printStackTrace();\r
130                         } catch (NoSuchFieldException e) {\r
131                                 e.printStackTrace();\r
132                         } catch (IllegalArgumentException e) {\r
133                                 // TODO Auto-generated catch block\r
134                                 e.printStackTrace();\r
135                         } catch (IllegalAccessException e) {\r
136                                 // TODO Auto-generated catch block\r
137                                 e.printStackTrace();\r
138                         }\r
139                         return null;\r
140                 }\r
141         }\r
142 \r
143         public static <T extends Quantity> String ammountToString(Amount<T> a) {\r
144                 if ( a == null )\r
145                         return "Null";\r
146                 final NumberFormat nf = new DecimalFormat("##########.###");\r
147                 return nf.format(a.doubleValue(a.getUnit())) + " " + a.getUnit();\r
148         }\r
149         \r
150         public static <T extends Quantity> String ammountToRoundedString(Amount<T> a) {\r
151                 if (a == null)\r
152                         return "Null";\r
153                 Unit<T> u = RocketScience.UnitPreference.preference.getPreferredUnit(a\r
154                                 .getUnit());\r
155                 double d = a.doubleValue(u);\r
156 \r
157                 DecimalFormat df;\r
158 \r
159                 if (Math.abs(d) < 10.0) {\r
160                         df = new DecimalFormat("#.##");\r
161                 } else if (Math.abs(d) < 100.0) {\r
162                         df = new DecimalFormat("#.#");\r
163                 } else {\r
164                         df = new DecimalFormat("#");\r
165                 }\r
166 \r
167                 return df.format(d) + " " + u.toString();\r
168         }\r
169 \r
170 }\r