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);
64 case CENTERING_RING: {
65 makeCenteringRing(preset);
69 makeEngineBlock(preset);
74 preset.computeDigest();
80 private static void makeBodyTube( ComponentPreset preset ) throws InvalidComponentPresetException {
82 checkRequiredFields( preset, LENGTH );
84 checkDiametersAndThickness(preset);
86 double volume = computeVolumeOfTube( preset );
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();
94 Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume, false);
95 preset.put(MATERIAL, m);
101 private static void makeNoseCone( ComponentPreset preset ) throws InvalidComponentPresetException {
103 checkRequiredFields( preset, LENGTH, SHAPE, OUTER_DIAMETER );
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();
112 String materialName = "NoseConeCustom";
113 if ( preset.has(MATERIAL) ) {
114 materialName = preset.get(MATERIAL).getName();
117 Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
118 preset.put(MATERIAL, m);
124 private static void makeTransition( ComponentPreset preset ) throws InvalidComponentPresetException {
125 checkRequiredFields(preset, LENGTH, OUTER_DIAMETER, FORE_OUTER_DIAMETER);
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();
134 String materialName = "TransitionCustom";
135 if ( preset.has(MATERIAL) ) {
136 materialName = preset.get(MATERIAL).getName();
139 Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
140 preset.put(MATERIAL, m);
146 private static void makeBulkHead( ComponentPreset preset ) throws InvalidComponentPresetException {
147 checkRequiredFields(preset, LENGTH, OUTER_DIAMETER );
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();
155 double volume = Math.pow(preset.get(OUTER_DIAMETER),2) * Math.PI / 4.0;
156 double density = mass / volume;
158 String materialName = "BulkHeadCustom";
159 if ( preset.has(MATERIAL) ) {
160 materialName = preset.get(MATERIAL).getName();
163 Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
164 preset.put(MATERIAL, m);
170 private static void makeTubeCoupler( ComponentPreset preset ) throws InvalidComponentPresetException {
172 checkRequiredFields( preset, LENGTH );
174 checkDiametersAndThickness( preset );
176 double volume = computeVolumeOfTube( preset );
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();
184 Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume, false);
185 preset.put(MATERIAL, m);
189 private static void makeCenteringRing( ComponentPreset preset ) throws InvalidComponentPresetException {
190 checkRequiredFields( preset, LENGTH );
192 checkDiametersAndThickness( preset );
194 double volume = computeVolumeOfTube( preset );
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();
202 Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume, false);
203 preset.put(MATERIAL, m);
208 private static void makeEngineBlock( ComponentPreset preset ) throws InvalidComponentPresetException {
209 checkRequiredFields( preset, LENGTH );
211 checkDiametersAndThickness( preset );
213 double volume = computeVolumeOfTube( preset );
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();
221 Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/volume, false);
222 preset.put(MATERIAL, m);
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());
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);
246 outerRadius = preset.get(OUTER_DIAMETER)/2.0;
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;
255 throw new InvalidComponentPresetException("Preset underspecified " + preset.toString());
258 if ( ! hasId && ! hasThickness ) {
259 throw new InvalidComponentPresetException("Preset underspecified " + preset.toString());
261 innerRadius = preset.get(INNER_DIAMETER)/2.0;
262 thickness = preset.get(THICKNESS);
263 outerRadius = innerRadius + thickness;
266 preset.put(OUTER_DIAMETER, outerRadius *2.0);
267 preset.put(INNER_DIAMETER, innerRadius *2.0);
268 preset.put(THICKNESS, thickness );
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;