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