1 package net.sf.openrocket.preset;
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;
21 public abstract class ComponentPresetFactory {
23 public static ComponentPreset create( TypedPropertyMap props ) throws InvalidComponentPresetException {
25 ComponentPreset preset = new ComponentPreset();
26 // First do validation.
27 if ( !props.containsKey(TYPE)) {
28 throw new InvalidComponentPresetException("No Type specified " + props.toString() );
31 if (!props.containsKey(MANUFACTURER)) {
32 throw new InvalidComponentPresetException("No Manufacturer specified " + props.toString() );
35 if (!props.containsKey(PARTNO)) {
36 throw new InvalidComponentPresetException("No PartNo specified " + props.toString() );
41 // Should check for various bits of each of the types.
42 Type t = props.get(TYPE);
53 makeTransition(preset);
61 makeTubeCoupler(preset);
66 preset.computeDigest();
72 private static void makeBodyTube( ComponentPreset preset ) throws InvalidComponentPresetException {
74 checkRequiredFields( preset, LENGTH );
76 BodyTube bt = new BodyTube();
78 bt.setLength(preset.get(LENGTH));
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);
86 double outerRadius = preset.get(OUTER_DIAMETER)/2.0;
88 bt.setOuterRadius( outerRadius );
90 thickness = outerRadius - preset.get(INNER_DIAMETER)/2.0;
91 } else if ( hasThickness ) {
92 thickness = preset.get(THICKNESS);
94 throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
96 bt.setThickness( thickness );
98 if ( ! hasId && ! hasThickness ) {
99 throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
101 double innerRadius = preset.get(INNER_DIAMETER)/2.0;
102 double thickness = preset.get(THICKNESS);
103 bt.setOuterRadius(innerRadius + thickness);
104 bt.setThickness(thickness);
107 preset.put(OUTER_DIAMETER, bt.getOuterRadius() *2.0);
108 preset.put(INNER_DIAMETER, bt.getInnerRadius() *2.0);
109 preset.put(THICKNESS, bt.getThickness());
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();
117 Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/bt.getComponentVolume(), false);
118 preset.put(MATERIAL, m);
124 private static void makeNoseCone( ComponentPreset preset ) throws InvalidComponentPresetException {
126 checkRequiredFields( preset, LENGTH, SHAPE, OUTER_DIAMETER );
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();
135 String materialName = "NoseConeCustom";
136 if ( preset.has(MATERIAL) ) {
137 materialName = preset.get(MATERIAL).getName();
140 Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
141 preset.put(MATERIAL, m);
147 private static void makeTransition( ComponentPreset preset ) throws InvalidComponentPresetException {
148 checkRequiredFields(preset, LENGTH, OUTER_DIAMETER, FORE_OUTER_DIAMETER);
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();
157 String materialName = "TransitionCustom";
158 if ( preset.has(MATERIAL) ) {
159 materialName = preset.get(MATERIAL).getName();
162 Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
163 preset.put(MATERIAL, m);
169 private static void makeBulkHead( ComponentPreset preset ) throws InvalidComponentPresetException {
170 checkRequiredFields(preset, LENGTH, OUTER_DIAMETER );
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();
180 double volume = Math.pow(preset.get(OUTER_DIAMETER),2) * Math.PI / 4.0;
181 double density = mass / volume;
183 String materialName = "TransitionCustom";
184 if ( preset.has(MATERIAL) ) {
185 materialName = preset.get(MATERIAL).getName();
188 Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
189 preset.put(MATERIAL, m);
195 private static void makeTubeCoupler( ComponentPreset preset ) throws InvalidComponentPresetException {
197 checkRequiredFields( preset, LENGTH );
199 // FIXME - TubeCoupler does not have getComponentVolume. So we use a BodyTube for this.
200 BodyTube bt = new BodyTube();
202 bt.setLength(preset.get(LENGTH));
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);
210 double outerRadius = preset.get(OUTER_DIAMETER)/2.0;
211 double thickness = 0;
212 bt.setOuterRadius( outerRadius );
214 thickness = outerRadius - preset.get(INNER_DIAMETER)/2.0;
215 } else if ( hasThickness ) {
216 thickness = preset.get(THICKNESS);
218 throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
220 bt.setThickness( thickness );
222 if ( ! hasId && ! hasThickness ) {
223 throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
225 double innerRadius = preset.get(INNER_DIAMETER)/2.0;
226 double thickness = preset.get(THICKNESS);
227 bt.setOuterRadius(innerRadius + thickness);
228 bt.setThickness(thickness);
231 preset.put(OUTER_DIAMETER, bt.getOuterRadius() *2.0);
232 preset.put(INNER_DIAMETER, bt.getInnerRadius() *2.0);
233 preset.put(THICKNESS, bt.getThickness());
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();
241 Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/bt.getComponentVolume(), false);
242 preset.put(MATERIAL, m);
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());