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