Added support for TubeCoupler.
[debian/openrocket] / core / src / net / sf / openrocket / preset / ComponentPresetFactory.java
1 package net.sf.openrocket.preset;
2
3 import static net.sf.openrocket.preset.ComponentPreset.FORE_OUTER_DIAMETER;
4 import static net.sf.openrocket.preset.ComponentPreset.INNER_DIAMETER;
5 import static net.sf.openrocket.preset.ComponentPreset.LENGTH;
6 import static net.sf.openrocket.preset.ComponentPreset.MANUFACTURER;
7 import static net.sf.openrocket.preset.ComponentPreset.MASS;
8 import static net.sf.openrocket.preset.ComponentPreset.MATERIAL;
9 import static net.sf.openrocket.preset.ComponentPreset.OUTER_DIAMETER;
10 import static net.sf.openrocket.preset.ComponentPreset.PARTNO;
11 import static net.sf.openrocket.preset.ComponentPreset.SHAPE;
12 import static net.sf.openrocket.preset.ComponentPreset.THICKNESS;
13 import static net.sf.openrocket.preset.ComponentPreset.TYPE;
14 import net.sf.openrocket.material.Material;
15 import net.sf.openrocket.preset.ComponentPreset.Type;
16 import net.sf.openrocket.rocketcomponent.BodyTube;
17 import net.sf.openrocket.rocketcomponent.Bulkhead;
18 import net.sf.openrocket.rocketcomponent.NoseCone;
19 import net.sf.openrocket.rocketcomponent.Transition;
20
21 public abstract class ComponentPresetFactory {
22
23         public static ComponentPreset create( TypedPropertyMap props ) throws InvalidComponentPresetException {
24
25                 ComponentPreset preset = new ComponentPreset();
26                 // First do validation.
27                 if ( !props.containsKey(TYPE)) {
28                         throw new InvalidComponentPresetException("No Type specified " + props.toString() );
29                 }
30
31                 if (!props.containsKey(MANUFACTURER)) {
32                         throw new InvalidComponentPresetException("No Manufacturer specified " + props.toString() );
33                 }
34
35                 if (!props.containsKey(PARTNO)) {
36                         throw new InvalidComponentPresetException("No PartNo specified " + props.toString() );
37                 }
38
39                 preset.putAll(props);
40
41                 // Should check for various bits of each of the types.
42                 Type t = props.get(TYPE);
43                 switch ( t ) {
44                 case BODY_TUBE: {
45                         makeBodyTube(preset);
46                         break;
47                 }
48                 case NOSE_CONE: {
49                         makeNoseCone(preset);
50                         break;
51                 }
52                 case TRANSITION: {
53                         makeTransition(preset);
54                         break;
55                 }
56                 case BULK_HEAD: {
57                         makeBulkHead(preset);
58                         break;
59                 }
60                 case TUBE_COUPLER: {
61                         makeTubeCoupler(preset);
62                         break;
63                 }
64                 }
65
66                 preset.computeDigest();
67
68                 return preset;
69
70         }
71
72         private static void makeBodyTube( ComponentPreset preset ) throws InvalidComponentPresetException {
73                 
74                 checkRequiredFields( preset, LENGTH );
75
76                 BodyTube bt = new BodyTube();
77
78                 bt.setLength(preset.get(LENGTH));
79
80                 // Need to verify contains 2 of OD, thickness, ID.  Compute the third.
81                 boolean hasOd = preset.has(OUTER_DIAMETER);
82                 boolean hasId = preset.has(INNER_DIAMETER);
83                 boolean hasThickness = preset.has(THICKNESS);
84
85                 if ( hasOd ) {
86                         double outerRadius = preset.get(OUTER_DIAMETER)/2.0;
87                         double thickness = 0;
88                         bt.setOuterRadius( outerRadius );
89                         if ( hasId ) {
90                                 thickness = outerRadius - preset.get(INNER_DIAMETER)/2.0;
91                         } else if ( hasThickness ) {
92                                 thickness = preset.get(THICKNESS);
93                         } else {
94                                 throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
95                         }
96                         bt.setThickness( thickness );
97                 } else {
98                         if ( ! hasId && ! hasThickness ) {
99                                 throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
100                         }
101                         double innerRadius = preset.get(INNER_DIAMETER)/2.0;
102                         double thickness = preset.get(THICKNESS);
103                         bt.setOuterRadius(innerRadius + thickness);
104                         bt.setThickness(thickness);
105                 }
106
107                 preset.put(OUTER_DIAMETER, bt.getOuterRadius() *2.0);
108                 preset.put(INNER_DIAMETER, bt.getInnerRadius() *2.0);
109                 preset.put(THICKNESS, bt.getThickness());
110
111                 // Need to translate Mass to Density.
112                 if ( preset.has(MASS) ) {
113                         String materialName = "TubeCustom";
114                         if ( preset.has(MATERIAL) ) {
115                                 materialName = preset.get(MATERIAL).getName();
116                         }
117                         Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/bt.getComponentVolume(), false);
118                         preset.put(MATERIAL, m);
119                 }
120
121
122         }
123
124         private static void makeNoseCone( ComponentPreset preset ) throws InvalidComponentPresetException {
125
126                 checkRequiredFields( preset, LENGTH, SHAPE, OUTER_DIAMETER );
127
128                 if ( preset.has(MASS) ) {
129                         // compute a density for this component
130                         double mass = preset.get(MASS);
131                         NoseCone nc = new NoseCone();
132                         nc.loadPreset(preset);
133                         double density = mass / nc.getComponentVolume();
134
135                         String materialName = "NoseConeCustom";
136                         if ( preset.has(MATERIAL) ) {
137                                 materialName = preset.get(MATERIAL).getName();
138                         }
139
140                         Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
141                         preset.put(MATERIAL, m);
142
143                 }
144
145         }
146
147         private static void makeTransition( ComponentPreset preset ) throws InvalidComponentPresetException {
148                 checkRequiredFields(preset, LENGTH, OUTER_DIAMETER, FORE_OUTER_DIAMETER);
149
150                 if ( preset.has(MASS) ) {
151                         // compute a density for this component
152                         double mass = preset.get(MASS);
153                         Transition tr = new Transition();
154                         tr.loadPreset(preset);
155                         double density = mass / tr.getComponentVolume();
156
157                         String materialName = "TransitionCustom";
158                         if ( preset.has(MATERIAL) ) {
159                                 materialName = preset.get(MATERIAL).getName();
160                         }
161
162                         Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
163                         preset.put(MATERIAL, m);
164
165                 }
166
167         }
168
169         private static void makeBulkHead( ComponentPreset preset ) throws InvalidComponentPresetException {
170                 checkRequiredFields(preset, LENGTH, OUTER_DIAMETER );
171
172                 if ( preset.has(MASS) ) {
173                         // compute a density for this component
174                         double mass = preset.get(MASS);
175                         Bulkhead tr = new Bulkhead();
176                         tr.loadPreset(preset);
177                         // FIXME - Bulkhead.getComponentVolume does not exist!
178                         // double density = mass / tr.getComponentVolume();
179
180                         double volume = Math.pow(preset.get(OUTER_DIAMETER),2) * Math.PI / 4.0;
181                         double density = mass / volume;
182
183                         String materialName = "TransitionCustom";
184                         if ( preset.has(MATERIAL) ) {
185                                 materialName = preset.get(MATERIAL).getName();
186                         }
187
188                         Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
189                         preset.put(MATERIAL, m);
190
191                 }
192
193         }
194
195         private static void makeTubeCoupler( ComponentPreset preset ) throws InvalidComponentPresetException {
196                 
197                 checkRequiredFields( preset, LENGTH );
198
199                 // FIXME - TubeCoupler does not have getComponentVolume.  So we use a BodyTube for this.
200                 BodyTube bt = new BodyTube();
201
202                 bt.setLength(preset.get(LENGTH));
203
204                 // Need to verify contains 2 of OD, thickness, ID.  Compute the third.
205                 boolean hasOd = preset.has(OUTER_DIAMETER);
206                 boolean hasId = preset.has(INNER_DIAMETER);
207                 boolean hasThickness = preset.has(THICKNESS);
208
209                 if ( hasOd ) {
210                         double outerRadius = preset.get(OUTER_DIAMETER)/2.0;
211                         double thickness = 0;
212                         bt.setOuterRadius( outerRadius );
213                         if ( hasId ) {
214                                 thickness = outerRadius - preset.get(INNER_DIAMETER)/2.0;
215                         } else if ( hasThickness ) {
216                                 thickness = preset.get(THICKNESS);
217                         } else {
218                                 throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
219                         }
220                         bt.setThickness( thickness );
221                 } else {
222                         if ( ! hasId && ! hasThickness ) {
223                                 throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
224                         }
225                         double innerRadius = preset.get(INNER_DIAMETER)/2.0;
226                         double thickness = preset.get(THICKNESS);
227                         bt.setOuterRadius(innerRadius + thickness);
228                         bt.setThickness(thickness);
229                 }
230
231                 preset.put(OUTER_DIAMETER, bt.getOuterRadius() *2.0);
232                 preset.put(INNER_DIAMETER, bt.getInnerRadius() *2.0);
233                 preset.put(THICKNESS, bt.getThickness());
234
235                 // Need to translate Mass to Density.
236                 if ( preset.has(MASS) ) {
237                         String materialName = "TubeCustom";
238                         if ( preset.has(MATERIAL) ) {
239                                 materialName = preset.get(MATERIAL).getName();
240                         }
241                         Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/bt.getComponentVolume(), false);
242                         preset.put(MATERIAL, m);
243                 }
244
245
246         }
247         
248         private static void checkRequiredFields( ComponentPreset preset, TypedKey<?> ... keys ) throws InvalidComponentPresetException {
249                 for( TypedKey<?> key: keys ) {
250                         if (! preset.has(key) ) {
251                                 throw new InvalidComponentPresetException( "No " + key.getName() + " specified for " + preset.getType().name() + " preset " + preset.toString());
252                         }
253                 }
254         }
255
256 }