Added centering rings and engine blocks presets
[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                 case CENTERING_RING: {
65                         makeCenteringRing(preset);
66                         break;
67                 }
68                 case ENGINE_BLOCK: {
69                         makeEngineBlock(preset);
70                         break;
71                 }
72                 }
73
74                 preset.computeDigest();
75
76                 return preset;
77
78         }
79
80         private static void makeBodyTube( ComponentPreset preset ) throws InvalidComponentPresetException {
81                 
82                 checkRequiredFields( preset, LENGTH );
83
84                 checkDiametersAndThickness(preset);
85                 
86                 double volume = computeVolumeOfTube( preset );
87                 
88                 // Need to translate Mass to Density.
89                 if ( preset.has(MASS) ) {
90                         String materialName = "TubeCustom";
91                         if ( preset.has(MATERIAL) ) {
92                                 materialName = preset.get(MATERIAL).getName();
93                         }
94                         Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume, false);
95                         preset.put(MATERIAL, m);
96                 }
97
98
99         }
100
101         private static void makeNoseCone( ComponentPreset preset ) throws InvalidComponentPresetException {
102
103                 checkRequiredFields( preset, LENGTH, SHAPE, OUTER_DIAMETER );
104
105                 if ( preset.has(MASS) ) {
106                         // compute a density for this component
107                         double mass = preset.get(MASS);
108                         NoseCone nc = new NoseCone();
109                         nc.loadPreset(preset);
110                         double density = mass / nc.getComponentVolume();
111
112                         String materialName = "NoseConeCustom";
113                         if ( preset.has(MATERIAL) ) {
114                                 materialName = preset.get(MATERIAL).getName();
115                         }
116
117                         Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
118                         preset.put(MATERIAL, m);
119
120                 }
121
122         }
123
124         private static void makeTransition( ComponentPreset preset ) throws InvalidComponentPresetException {
125                 checkRequiredFields(preset, LENGTH, OUTER_DIAMETER, FORE_OUTER_DIAMETER);
126
127                 if ( preset.has(MASS) ) {
128                         // compute a density for this component
129                         double mass = preset.get(MASS);
130                         Transition tr = new Transition();
131                         tr.loadPreset(preset);
132                         double density = mass / tr.getComponentVolume();
133
134                         String materialName = "TransitionCustom";
135                         if ( preset.has(MATERIAL) ) {
136                                 materialName = preset.get(MATERIAL).getName();
137                         }
138
139                         Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
140                         preset.put(MATERIAL, m);
141
142                 }
143
144         }
145
146         private static void makeBulkHead( ComponentPreset preset ) throws InvalidComponentPresetException {
147                 checkRequiredFields(preset, LENGTH, OUTER_DIAMETER );
148
149                 if ( preset.has(MASS) ) {
150                         // compute a density for this component
151                         double mass = preset.get(MASS);
152                         // FIXME - Bulkhead.getComponentVolume does not exist!
153                         // double density = mass / tr.getComponentVolume();
154
155                         double volume = Math.pow(preset.get(OUTER_DIAMETER),2) * Math.PI / 4.0;
156                         double density = mass / volume;
157
158                         String materialName = "BulkHeadCustom";
159                         if ( preset.has(MATERIAL) ) {
160                                 materialName = preset.get(MATERIAL).getName();
161                         }
162
163                         Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
164                         preset.put(MATERIAL, m);
165
166                 }
167
168         }
169
170         private static void makeTubeCoupler( ComponentPreset preset ) throws InvalidComponentPresetException {
171                 
172                 checkRequiredFields( preset, LENGTH );
173
174                 checkDiametersAndThickness( preset );
175                 
176                 double volume = computeVolumeOfTube( preset );
177
178                 // Need to translate Mass to Density.
179                 if ( preset.has(MASS) ) {
180                         String materialName = "TubeCouplerCustom";
181                         if ( preset.has(MATERIAL) ) {
182                                 materialName = preset.get(MATERIAL).getName();
183                         }
184                         Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume, false);
185                         preset.put(MATERIAL, m);
186                 }
187         }
188
189         private static void makeCenteringRing( ComponentPreset preset ) throws InvalidComponentPresetException {
190                 checkRequiredFields( preset, LENGTH );
191
192                 checkDiametersAndThickness( preset );
193
194                 double volume = computeVolumeOfTube( preset );
195
196                 // Need to translate Mass to Density.
197                 if ( preset.has(MASS) ) {
198                         String materialName = "TubeCouplerCustom";
199                         if ( preset.has(MATERIAL) ) {
200                                 materialName = preset.get(MATERIAL).getName();
201                         }
202                         Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume, false);
203                         preset.put(MATERIAL, m);
204                 }
205
206         }
207         
208         private static void makeEngineBlock( ComponentPreset preset ) throws InvalidComponentPresetException {
209                 checkRequiredFields( preset, LENGTH );
210
211                 checkDiametersAndThickness( preset );
212
213                 double volume = computeVolumeOfTube( preset );
214
215                 // Need to translate Mass to Density.
216                 if ( preset.has(MASS) ) {
217                         String materialName = "TubeCouplerCustom";
218                         if ( preset.has(MATERIAL) ) {
219                                 materialName = preset.get(MATERIAL).getName();
220                         }
221                         Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume, false);
222                         preset.put(MATERIAL, m);
223                 }
224
225         }
226         
227         private static void checkRequiredFields( ComponentPreset preset, TypedKey<?> ... keys ) throws InvalidComponentPresetException {
228                 for( TypedKey<?> key: keys ) {
229                         if (! preset.has(key) ) {
230                                 throw new InvalidComponentPresetException( "No " + key.getName() + " specified for " + preset.getType().name() + " preset " + preset.toString());
231                         }
232                 }
233         }
234
235         private static void checkDiametersAndThickness( ComponentPreset preset ) throws InvalidComponentPresetException {
236                 // Need to verify contains 2 of OD, thickness, ID.  Compute the third.
237                 boolean hasOd = preset.has(OUTER_DIAMETER);
238                 boolean hasId = preset.has(INNER_DIAMETER);
239                 boolean hasThickness = preset.has(THICKNESS);
240
241                 double outerRadius;
242                 double innerRadius;
243                 double thickness;
244                 
245                 if ( hasOd ) {
246                         outerRadius = preset.get(OUTER_DIAMETER)/2.0;
247                         thickness = 0;
248                         if ( hasId ) {
249                                 innerRadius = preset.get(INNER_DIAMETER)/2.0;
250                                 thickness = outerRadius - innerRadius;
251                         } else if ( hasThickness ) {
252                                 thickness = preset.get(THICKNESS);
253                                 innerRadius = outerRadius - thickness;
254                         } else {
255                                 throw new InvalidComponentPresetException("Preset underspecified " + preset.toString());
256                         }
257                 } else {
258                         if ( ! hasId && ! hasThickness ) {
259                                 throw new InvalidComponentPresetException("Preset underspecified " + preset.toString());
260                         }
261                         innerRadius = preset.get(INNER_DIAMETER)/2.0;
262                         thickness = preset.get(THICKNESS);
263                         outerRadius = innerRadius + thickness;
264                 }
265
266                 preset.put(OUTER_DIAMETER, outerRadius *2.0);
267                 preset.put(INNER_DIAMETER, innerRadius *2.0);
268                 preset.put(THICKNESS, thickness );
269
270         }
271         
272         private static double computeVolumeOfTube(ComponentPreset preset) {
273                 double or = preset.get(OUTER_DIAMETER)/2.0;
274                 double ir = preset.get(INNER_DIAMETER)/2.0;
275                 double l = preset.get(LENGTH);
276                 return Math.PI * (or*or - ir*ir) * l;
277         }
278
279         
280 }