1 package net.sf.openrocket.preset;
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;
9 public abstract class ComponentPresetFactory {
11 public static ComponentPreset create( TypedPropertyMap props ) throws InvalidComponentPresetException {
13 InvalidComponentPresetException exceptions = new InvalidComponentPresetException("Invalid preset specification.");
15 ComponentPreset preset = new ComponentPreset();
16 // First do validation.
17 if (!props.containsKey(MANUFACTURER)) {
18 exceptions.addInvalidParameter(MANUFACTURER, "No Manufacturer specified");
20 if (!props.containsKey(PARTNO)) {
21 exceptions.addInvalidParameter(PARTNO,"No PartNo specified");
23 if ( !props.containsKey(TYPE)) {
24 exceptions.addInvalidParameter(TYPE, "No Type specified" );
25 // We can't do anything else without TYPE so throw immediately.
32 // Should check for various bits of each of the types.
33 Type t = props.get(TYPE);
36 makeBodyTube(exceptions,preset);
40 makeNoseCone(exceptions,preset);
44 makeTransition(exceptions,preset);
48 makeBulkHead(exceptions,preset);
52 // For now TUBE_COUPLER is the same as BODY_TUBE
53 makeBodyTube(exceptions,preset);
56 case CENTERING_RING: {
57 makeCenteringRing(exceptions,preset);
61 makeEngineBlock(exceptions,preset);
65 // Same processing as BODY_TUBE
66 makeBodyTube(exceptions,preset);
70 makeStreamer(exceptions,preset);
74 makeParachute(exceptions,preset);
79 if ( exceptions.hasProblems() ) {
83 preset.computeDigest();
89 private static void makeBodyTube( InvalidComponentPresetException exceptions, ComponentPreset preset ) throws InvalidComponentPresetException {
91 checkRequiredFields( exceptions, preset, LENGTH );
93 checkDiametersAndThickness(exceptions, preset);
95 double volume = computeVolumeOfTube( preset );
97 // Need to translate Mass to Density.
98 if ( preset.has(MASS) ) {
99 String materialName = "TubeCustom";
100 if ( preset.has(MATERIAL) ) {
101 materialName = preset.get(MATERIAL).getName();
103 Material m = Material.newUserMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume);
104 preset.put(MATERIAL, m);
110 private static void makeNoseCone( InvalidComponentPresetException exceptions, ComponentPreset preset ) {
112 checkRequiredFields( exceptions, preset, LENGTH, SHAPE, AFT_OUTER_DIAMETER );
114 if ( preset.has(MASS) ) {
115 // compute a density for this component
116 double mass = preset.get(MASS);
117 NoseCone nc = new NoseCone();
118 nc.loadPreset(preset);
119 double density = mass / nc.getComponentVolume();
121 String materialName = "NoseConeCustom";
122 if ( preset.has(MATERIAL) ) {
123 materialName = preset.get(MATERIAL).getName();
126 Material m = Material.newUserMaterial(Material.Type.BULK, materialName,density);
127 preset.put(MATERIAL, m);
133 private static void makeTransition( InvalidComponentPresetException exceptions, ComponentPreset preset ) {
134 checkRequiredFields(exceptions, preset, LENGTH, AFT_OUTER_DIAMETER, FORE_OUTER_DIAMETER);
136 if ( preset.has(MASS) ) {
137 // compute a density for this component
138 double mass = preset.get(MASS);
139 Transition tr = new Transition();
140 tr.loadPreset(preset);
141 double density = mass / tr.getComponentVolume();
143 String materialName = "TransitionCustom";
144 if ( preset.has(MATERIAL) ) {
145 materialName = preset.get(MATERIAL).getName();
148 Material m = Material.newUserMaterial(Material.Type.BULK, materialName,density);
149 preset.put(MATERIAL, m);
155 private static void makeBulkHead( InvalidComponentPresetException exceptions, ComponentPreset preset ) {
156 checkRequiredFields(exceptions, preset, LENGTH, OUTER_DIAMETER );
158 if ( preset.has(MASS) ) {
159 // compute a density for this component
160 double mass = preset.get(MASS);
162 double volume = computeVolumeOfTube(preset);
163 double density = mass / volume;
165 String materialName = "BulkHeadCustom";
166 if ( preset.has(MATERIAL) ) {
167 materialName = preset.get(MATERIAL).getName();
170 Material m = Material.newUserMaterial(Material.Type.BULK, materialName,density);
171 preset.put(MATERIAL, m);
177 private static void makeCenteringRing( InvalidComponentPresetException exceptions, ComponentPreset preset ) throws InvalidComponentPresetException {
178 checkRequiredFields( exceptions, preset, LENGTH );
180 checkDiametersAndThickness( exceptions, preset );
182 double volume = computeVolumeOfTube( preset );
184 // Need to translate Mass to Density.
185 if ( preset.has(MASS) ) {
186 String materialName = "CenteringRingCustom";
187 if ( preset.has(MATERIAL) ) {
188 materialName = preset.get(MATERIAL).getName();
190 Material m = Material.newUserMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume);
191 preset.put(MATERIAL, m);
196 private static void makeEngineBlock( InvalidComponentPresetException exceptions, ComponentPreset preset ) throws InvalidComponentPresetException {
197 checkRequiredFields( exceptions, preset, LENGTH );
199 checkDiametersAndThickness( exceptions, preset );
201 double volume = computeVolumeOfTube( preset );
203 // Need to translate Mass to Density.
204 if ( preset.has(MASS) ) {
205 String materialName = "EngineBlockCustom";
206 if ( preset.has(MATERIAL) ) {
207 materialName = preset.get(MATERIAL).getName();
209 Material m = Material.newUserMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume);
210 preset.put(MATERIAL, m);
215 private static void makeStreamer( InvalidComponentPresetException exceptions, ComponentPreset preset ) {
216 checkRequiredFields( exceptions, preset, LENGTH, WIDTH );
219 private static void makeParachute( InvalidComponentPresetException exceptions, ComponentPreset preset ) {
220 checkRequiredFields( exceptions, preset, DIAMETER, LINE_COUNT, LINE_LENGTH );
224 private static void checkRequiredFields( InvalidComponentPresetException exceptions, ComponentPreset preset, TypedKey<?> ... keys ) {
225 for( TypedKey<?> key: keys ) {
226 if (! preset.has(key) ) {
227 exceptions.addInvalidParameter(key, "No " + key.getName() + " specified");
232 private static void checkDiametersAndThickness( InvalidComponentPresetException exceptions, ComponentPreset preset ) throws InvalidComponentPresetException {
233 // Need to verify contains 2 of OD, thickness, ID. Compute the third.
234 boolean hasOd = preset.has(OUTER_DIAMETER);
235 boolean hasId = preset.has(INNER_DIAMETER);
236 boolean hasThickness = preset.has(THICKNESS);
243 outerRadius = preset.get(OUTER_DIAMETER)/2.0;
246 innerRadius = preset.get(INNER_DIAMETER)/2.0;
247 thickness = outerRadius - innerRadius;
248 } else if ( hasThickness ) {
249 thickness = preset.get(THICKNESS);
250 innerRadius = outerRadius - thickness;
252 exceptions.addMessage("Preset dimensions underspecified");
256 if ( ! hasId || ! hasThickness ) {
257 exceptions.addMessage("Preset dimensions underspecified");
260 innerRadius = preset.get(INNER_DIAMETER)/2.0;
261 thickness = preset.get(THICKNESS);
262 outerRadius = innerRadius + thickness;
265 preset.put(OUTER_DIAMETER, outerRadius *2.0);
266 preset.put(INNER_DIAMETER, innerRadius *2.0);
267 preset.put(THICKNESS, thickness );
271 private static double computeVolumeOfTube(ComponentPreset preset) {
272 double or = preset.get(OUTER_DIAMETER)/2.0;
273 double ir = preset.has(INNER_DIAMETER) ? preset.get(INNER_DIAMETER)/2.0 : 0.0;
274 double l = preset.get(LENGTH);
275 return Math.PI * (or*or - ir*ir) * l;