Added LaunchLug, Streamer and Parachute ComponentPresets.
[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.*;
4 import net.sf.openrocket.material.Material;
5 import net.sf.openrocket.preset.ComponentPreset.Type;
6 import net.sf.openrocket.rocketcomponent.NoseCone;
7 import net.sf.openrocket.rocketcomponent.Transition;
8
9 public abstract class ComponentPresetFactory {
10
11         public static ComponentPreset create( TypedPropertyMap props ) throws InvalidComponentPresetException {
12
13                 ComponentPreset preset = new ComponentPreset();
14                 // First do validation.
15                 if ( !props.containsKey(TYPE)) {
16                         throw new InvalidComponentPresetException("No Type specified " + props.toString() );
17                 }
18
19                 if (!props.containsKey(MANUFACTURER)) {
20                         throw new InvalidComponentPresetException("No Manufacturer specified " + props.toString() );
21                 }
22
23                 if (!props.containsKey(PARTNO)) {
24                         throw new InvalidComponentPresetException("No PartNo specified " + props.toString() );
25                 }
26
27                 preset.putAll(props);
28
29                 // Should check for various bits of each of the types.
30                 Type t = props.get(TYPE);
31                 switch ( t ) {
32                 case BODY_TUBE: {
33                         makeBodyTube(preset);
34                         break;
35                 }
36                 case NOSE_CONE: {
37                         makeNoseCone(preset);
38                         break;
39                 }
40                 case TRANSITION: {
41                         makeTransition(preset);
42                         break;
43                 }
44                 case BULK_HEAD: {
45                         makeBulkHead(preset);
46                         break;
47                 }
48                 case TUBE_COUPLER: {
49                         // For now TUBE_COUPLER is the same as BODY_TUBE
50                         makeBodyTube(preset);
51                         break;
52                 }
53                 case CENTERING_RING: {
54                         makeCenteringRing(preset);
55                         break;
56                 }
57                 case ENGINE_BLOCK: {
58                         makeEngineBlock(preset);
59                         break;
60                 }
61                 case LAUNCH_LUG: {
62                         // Same processing as BODY_TUBE
63                         makeBodyTube(preset);
64                         break;
65                 }
66                 case STREAMER: {
67                         makeStreamer(preset);
68                         break;
69                 }
70                 case PARACHUTE: {
71                         makeParachute(preset);
72                         break;
73                 }
74                 }
75
76                 preset.computeDigest();
77
78                 return preset;
79
80         }
81
82         private static void makeBodyTube( ComponentPreset preset ) throws InvalidComponentPresetException {
83                 
84                 checkRequiredFields( preset, LENGTH );
85
86                 checkDiametersAndThickness(preset);
87                 
88                 double volume = computeVolumeOfTube( preset );
89                 
90                 // Need to translate Mass to Density.
91                 if ( preset.has(MASS) ) {
92                         String materialName = "TubeCustom";
93                         if ( preset.has(MATERIAL) ) {
94                                 materialName = preset.get(MATERIAL).getName();
95                         }
96                         Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume, false);
97                         preset.put(MATERIAL, m);
98                 }
99
100
101         }
102
103         private static void makeNoseCone( ComponentPreset preset ) throws InvalidComponentPresetException {
104
105                 checkRequiredFields( preset, LENGTH, SHAPE, AFT_OUTER_DIAMETER );
106
107                 if ( preset.has(MASS) ) {
108                         // compute a density for this component
109                         double mass = preset.get(MASS);
110                         NoseCone nc = new NoseCone();
111                         nc.loadPreset(preset);
112                         double density = mass / nc.getComponentVolume();
113
114                         String materialName = "NoseConeCustom";
115                         if ( preset.has(MATERIAL) ) {
116                                 materialName = preset.get(MATERIAL).getName();
117                         }
118
119                         Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
120                         preset.put(MATERIAL, m);
121
122                 }
123
124         }
125
126         private static void makeTransition( ComponentPreset preset ) throws InvalidComponentPresetException {
127                 checkRequiredFields(preset, LENGTH, AFT_OUTER_DIAMETER, FORE_OUTER_DIAMETER);
128
129                 if ( preset.has(MASS) ) {
130                         // compute a density for this component
131                         double mass = preset.get(MASS);
132                         Transition tr = new Transition();
133                         tr.loadPreset(preset);
134                         double density = mass / tr.getComponentVolume();
135
136                         String materialName = "TransitionCustom";
137                         if ( preset.has(MATERIAL) ) {
138                                 materialName = preset.get(MATERIAL).getName();
139                         }
140
141                         Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
142                         preset.put(MATERIAL, m);
143
144                 }
145
146         }
147
148         private static void makeBulkHead( ComponentPreset preset ) throws InvalidComponentPresetException {
149                 checkRequiredFields(preset, LENGTH, OUTER_DIAMETER );
150
151                 if ( preset.has(MASS) ) {
152                         // compute a density for this component
153                         double mass = preset.get(MASS);
154
155                         double volume = computeVolumeOfTube(preset);
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 makeCenteringRing( ComponentPreset preset ) throws InvalidComponentPresetException {
171                 checkRequiredFields( preset, LENGTH );
172
173                 checkDiametersAndThickness( preset );
174
175                 double volume = computeVolumeOfTube( preset );
176
177                 // Need to translate Mass to Density.
178                 if ( preset.has(MASS) ) {
179                         String materialName = "CenteringRingCustom";
180                         if ( preset.has(MATERIAL) ) {
181                                 materialName = preset.get(MATERIAL).getName();
182                         }
183                         Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume, false);
184                         preset.put(MATERIAL, m);
185                 }
186
187         }
188         
189         private static void makeEngineBlock( 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 = "EngineBlockCustom";
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 makeStreamer( ComponentPreset preset ) throws InvalidComponentPresetException {
209                 checkRequiredFields( preset, LENGTH, WIDTH );
210         }
211
212         private static void makeParachute( ComponentPreset preset ) throws InvalidComponentPresetException {
213                 checkRequiredFields( preset, DIAMETER, LINE_COUNT, LINE_LENGTH );
214         }
215         
216
217         private static void checkRequiredFields( ComponentPreset preset, TypedKey<?> ... keys ) throws InvalidComponentPresetException {
218                 for( TypedKey<?> key: keys ) {
219                         if (! preset.has(key) ) {
220                                 throw new InvalidComponentPresetException( "No " + key.getName() + " specified for " + preset.getType().name() + " preset " + preset.toString());
221                         }
222                 }
223         }
224
225         private static void checkDiametersAndThickness( ComponentPreset preset ) throws InvalidComponentPresetException {
226                 // Need to verify contains 2 of OD, thickness, ID.  Compute the third.
227                 boolean hasOd = preset.has(OUTER_DIAMETER);
228                 boolean hasId = preset.has(INNER_DIAMETER);
229                 boolean hasThickness = preset.has(THICKNESS);
230
231                 double outerRadius;
232                 double innerRadius;
233                 double thickness;
234                 
235                 if ( hasOd ) {
236                         outerRadius = preset.get(OUTER_DIAMETER)/2.0;
237                         thickness = 0;
238                         if ( hasId ) {
239                                 innerRadius = preset.get(INNER_DIAMETER)/2.0;
240                                 thickness = outerRadius - innerRadius;
241                         } else if ( hasThickness ) {
242                                 thickness = preset.get(THICKNESS);
243                                 innerRadius = outerRadius - thickness;
244                         } else {
245                                 throw new InvalidComponentPresetException("Preset underspecified " + preset.toString());
246                         }
247                 } else {
248                         if ( ! hasId || ! hasThickness ) {
249                                 throw new InvalidComponentPresetException("Preset underspecified " + preset.toString());
250                         }
251                         innerRadius = preset.get(INNER_DIAMETER)/2.0;
252                         thickness = preset.get(THICKNESS);
253                         outerRadius = innerRadius + thickness;
254                 }
255
256                 preset.put(OUTER_DIAMETER, outerRadius *2.0);
257                 preset.put(INNER_DIAMETER, innerRadius *2.0);
258                 preset.put(THICKNESS, thickness );
259
260         }
261         
262         private static double computeVolumeOfTube(ComponentPreset preset) {
263                 double or = preset.get(OUTER_DIAMETER)/2.0;
264                 double ir = preset.has(INNER_DIAMETER) ? preset.get(INNER_DIAMETER)/2.0 : 0.0;
265                 double l = preset.get(LENGTH);
266                 return Math.PI * (or*or - ir*ir) * l;
267         }
268
269         
270 }