--- /dev/null
+Manufacturer,PartNo,Description,Type,OuterDiameter,Length,Material,Mass\r
+Semroc,BTC-5,Solid Balsa Tube Adapter - Series 5,BULK_HEAD,0.013081,0.01905,Balsa,0.000283495\r
+Semroc,BTC-7,Solid Balsa Tube Adapter - Series 7,BULK_HEAD,0.018161,0.0254,Balsa,0.000737087\r
+Semroc,BTC-8,Solid Balsa Tube Adapter - Series 8,BULK_HEAD,0.021971,0.0254,Balsa,0.001077281\r
+Semroc,BTC-8F,Solid Balsa Tube Adapter - Series 8F,BULK_HEAD,0.022479,0.0254,Balsa,0.001077281\r
+Semroc,BTC-9,Solid Balsa Tube Adapter - Series 9,BULK_HEAD,0.02413,0.0381,Balsa,0.001275727\r
+Semroc,BTC-10,Solid Balsa Tube Adapter - Series 10,BULK_HEAD,0.0254,0.0381,Balsa,0.001814368\r
+Semroc,BTC-11,Solid Balsa Tube Adapter - Series 11,BULK_HEAD,0.028702,0.0381,Balsa,0.001956115\r
+Semroc,BTC-13,Solid Balsa Tube Adapter - Series 13,BULK_HEAD,0.03302,0.04445,Balsa,0.003543687\r
+Semroc,BTC-16,Solid Balsa Tube Adapter - Series 16,BULK_HEAD,0.04064,0.04445,Balsa,0.004961161\r
+Semroc,BTC-18,Solid Balsa Tube Adapter - Series 18,BULK_HEAD,0.04572,0.04445,Balsa,0.005669899\r
+Semroc,BTC-20,Solid Balsa Tube Adapter - Series 20,BULK_HEAD,0.0508,0.05334,Balsa,0.007512616\r
+Semroc,BTC-085,Solid Balsa Tube Adapter - Series 85,BULK_HEAD,0.021971,0.0381,Balsa,0.001615921\r
+Semroc,BTC-115,Solid Balsa Tube Adapter - Series 115,BULK_HEAD,0.02921,0.04445,Balsa,0.003175143\r
+Semroc,BTC-125,Solid Balsa Tube Adapter - Series 125,BULK_HEAD,0.03175,0.0508,Balsa,0.004535919\r
+Semroc,BTC-150,Solid Balsa Tube Adapter - Series 150,BULK_HEAD,0.0381,0.0508,Balsa,0.006662131\r
+Semroc,BTC-175,Solid Balsa Tube Adapter - Series 175,BULK_HEAD,0.04445,0.05715,Balsa,0.00949708\r
+Semroc,BTC-225,Solid Balsa Tube Adapter - Series 225,BULK_HEAD,0.05715,0.0635,Balsa,0.018001928\r
+Semroc,BTC-275,Solid Balsa Tube Adapter - Series 275,BULK_HEAD,0.06985,0.0762,Balsa,0.032176674\r
+Semroc,NB-3,Solid Balsa Tube Adapter - Series BT-3,BULK_HEAD,0.0088646,0.01905,Balsa,0.000198446\r
+Semroc,NB-5,Solid Balsa Tube Adapter - Series BT-5,BULK_HEAD,0.013081,0.01905,Balsa,0.000283495\r
+Semroc,NB-20,Solid Balsa Tube Adapter - Series BT-20,BULK_HEAD,0.018034,0.01905,Balsa,0.00056699\r
+Semroc,NB-30,Solid Balsa Tube Adapter - Series BT-30,BULK_HEAD,0.018415,0.01905,Balsa,0.00056699\r
+Semroc,NB-40,Solid Balsa Tube Adapter - Series BT-40,BULK_HEAD,0.019431,0.0254,Balsa,0.000793786\r
+Semroc,NB-50,Solid Balsa Tube Adapter - Series BT-50,BULK_HEAD,0.02413,0.0254,Balsa,0.00113398\r
+Semroc,NB-50L,Solid Balsa Tube Adapter - Series BT-50,BULK_HEAD,0.02413,0.030226,Balsa,0.002182911\r
+Semroc,NB-55,Solid Balsa Tube Adapter - Series BT-55,BULK_HEAD,0.0325882,0.03175,Balsa,0.003260192\r
+Semroc,NB-60,Solid Balsa Tube Adapter - Series BT-60,BULK_HEAD,0.040513,0.0381,Balsa,0.004819414\r
+Semroc,NB-65,Solid Balsa Tube Adapter - Series BT-65,BULK_HEAD,0.04445,0.04445,Balsa,0.005953393\r
+Semroc,NB-70,Solid Balsa Tube Adapter - Series BT-70,BULK_HEAD,0.055245,0.0508,Balsa,0.006236888\r
+Semroc,NB-80,Solid Balsa Tube Adapter - Series BT-80,BULK_HEAD,0.0649732,0.0762,Balsa,0.010489312\r
import net.sf.openrocket.file.preset.PresetCSVReader;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.preset.ComponentPreset;
+import net.sf.openrocket.preset.ComponentPresetFactory;
import net.sf.openrocket.preset.InvalidComponentPresetException;
import net.sf.openrocket.preset.TypedPropertyMap;
import net.sf.openrocket.startup.Application;
List<TypedPropertyMap> list = parser.parse();
for( TypedPropertyMap o : list ) {
try {
- ComponentPreset preset = ComponentPreset.create(o);
+ ComponentPreset preset = ComponentPresetFactory.create(o);
if ( favorites.contains(preset.preferenceKey())) {
preset.setFavorite(true);
}
ComponentPreset.SHAPE,
ComponentPreset.FORE_OUTER_DIAMETER,
ComponentPreset.OUTER_DIAMETER,
- ComponentPreset.LENGTH
- } ) ;
+ ComponentPreset.LENGTH} ),
+
+ BULK_HEAD( new TypedKey<?>[] {
+ ComponentPreset.MANUFACTURER,
+ ComponentPreset.PARTNO,
+ ComponentPreset.DESCRIPTION,
+ ComponentPreset.OUTER_DIAMETER,
+ ComponentPreset.LENGTH} );
Type[] compatibleTypes;
TypedKey<?>[] displayedColumns;
keyMap.put(MASS.getName(), MASS);
}
- public static ComponentPreset create( TypedPropertyMap props ) throws InvalidComponentPresetException {
-
- ComponentPreset preset = new ComponentPreset();
- // First do validation.
- if ( !props.containsKey(TYPE)) {
- throw new InvalidComponentPresetException("No Type specified " + props.toString() );
- }
-
- if (!props.containsKey(MANUFACTURER)) {
- throw new InvalidComponentPresetException("No Manufacturer specified " + props.toString() );
- }
-
- if (!props.containsKey(PARTNO)) {
- throw new InvalidComponentPresetException("No PartNo specified " + props.toString() );
- }
-
- preset.properties.putAll(props);
-
- // Should check for various bits of each of the types.
- Type t = props.get(TYPE);
- switch ( t ) {
- case BODY_TUBE: {
-
- if ( !props.containsKey(LENGTH) ) {
- throw new InvalidComponentPresetException( "No Length specified for body tube preset " + props.toString());
- }
-
- BodyTube bt = new BodyTube();
-
- bt.setLength(props.get(LENGTH));
-
- // Need to verify contains 2 of OD, thickness, ID. Compute the third.
- boolean hasOd = props.containsKey(OUTER_DIAMETER);
- boolean hasId = props.containsKey(INNER_DIAMETER);
- boolean hasThickness = props.containsKey(THICKNESS);
-
- if ( hasOd ) {
- double outerRadius = props.get(OUTER_DIAMETER)/2.0;
- double thickness = 0;
- bt.setOuterRadius( outerRadius );
- if ( hasId ) {
- thickness = outerRadius - props.get(INNER_DIAMETER)/2.0;
- } else if ( hasThickness ) {
- thickness = props.get(THICKNESS);
- } else {
- throw new InvalidComponentPresetException("Body tube preset underspecified " + props.toString());
- }
- bt.setThickness( thickness );
- } else {
- if ( ! hasId && ! hasThickness ) {
- throw new InvalidComponentPresetException("Body tube preset underspecified " + props.toString());
- }
- double innerRadius = props.get(INNER_DIAMETER)/2.0;
- double thickness = props.get(THICKNESS);
- bt.setOuterRadius(innerRadius + thickness);
- bt.setThickness(thickness);
- }
-
- preset.properties.put(OUTER_DIAMETER, bt.getOuterRadius() *2.0);
- preset.properties.put(INNER_DIAMETER, bt.getInnerRadius() *2.0);
- preset.properties.put(THICKNESS, bt.getThickness());
-
- // Need to translate Mass to Density.
- if ( props.containsKey(MASS) ) {
- String materialName = "TubeCustom";
- if ( props.containsKey(MATERIAL) ) {
- materialName = props.get(MATERIAL).getName();
- }
- Material m = Material.newMaterial(Material.Type.BULK, materialName, props.get(MASS)/bt.getComponentVolume(), false);
- preset.properties.put(MATERIAL, m);
- }
-
- break;
- }
- case NOSE_CONE: {
-
- if ( !props.containsKey(LENGTH) ) {
- throw new InvalidComponentPresetException( "No Length specified for nose cone preset " + props.toString());
- }
- if ( !props.containsKey(SHAPE) ) {
- throw new InvalidComponentPresetException( "No Shape specified for nose cone preset " + props.toString());
- }
- if ( !props.containsKey(OUTER_DIAMETER) ) {
- throw new InvalidComponentPresetException( "No Outer Diameter specified for nose cone preset " + props.toString());
- }
-
- if ( props.containsKey(MASS) ) {
- // compute a density for this component
- double mass = props.get(MASS);
- NoseCone nc = new NoseCone();
- nc.loadPreset(preset);
- double density = mass / nc.getComponentVolume();
-
- String materialName = "NoseConeCustom";
- if ( props.containsKey(MATERIAL) ) {
- materialName = props.get(MATERIAL).getName();
- }
-
- Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
- preset.properties.put(MATERIAL, m);
-
- }
- break;
- }
- case TRANSITION: {
-
- if ( !props.containsKey(LENGTH) ) {
- throw new InvalidComponentPresetException( "No Length specified for transition preset " + props.toString());
- }
- if ( !props.containsKey(OUTER_DIAMETER) ) {
- throw new InvalidComponentPresetException( "No Outer Diameter specified for transition preset " + props.toString());
- }
- if ( !props.containsKey(FORE_OUTER_DIAMETER) ) {
- throw new InvalidComponentPresetException( "No Fore Outer Diameter specified for transition preset " + props.toString());
- }
-
- if ( props.containsKey(MASS) ) {
- // compute a density for this component
- double mass = props.get(MASS);
- Transition tr = new Transition();
- tr.loadPreset(preset);
- double density = mass / tr.getComponentVolume();
-
- String materialName = "TransitionCustom";
- if ( props.containsKey(MATERIAL) ) {
- materialName = props.get(MATERIAL).getName();
- }
-
- Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
- preset.properties.put(MATERIAL, m);
-
- }
- break;
- }
- }
-
- preset.computeDigest();
-
- return preset;
-
- }
-
- // Private constructor to encourage use of factory.
- private ComponentPreset() {
+ // package scope constructor to encourage use of factory.
+ ComponentPreset() {
}
/**
return properties.containsKey(key);
}
+ /**
+ * Package scope so the ComponentPresetFactory can call it.
+ * @param other
+ */
+ void putAll(TypedPropertyMap other) {
+ if (other == null) {
+ return;
+ }
+ properties.putAll(other);
+ }
+
+ /**
+ * Package scope so the ComponentPresetFactory can call it.
+ * @param key
+ * @param value
+ */
+ <T> void put( TypedKey<T> key, T value ) {
+ properties.put(key, value);
+ }
+
public <T> T get(TypedKey<T> key) {
T value = properties.get(key);
if (value == null) {
return get(MANUFACTURER).toString() + "|" + get(PARTNO);
}
- private void computeDigest() {
+ /**
+ * Package scope so the factory can call it.
+ */
+ void computeDigest() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
--- /dev/null
+package net.sf.openrocket.preset;
+
+import static net.sf.openrocket.preset.ComponentPreset.FORE_OUTER_DIAMETER;
+import static net.sf.openrocket.preset.ComponentPreset.INNER_DIAMETER;
+import static net.sf.openrocket.preset.ComponentPreset.LENGTH;
+import static net.sf.openrocket.preset.ComponentPreset.MANUFACTURER;
+import static net.sf.openrocket.preset.ComponentPreset.MASS;
+import static net.sf.openrocket.preset.ComponentPreset.MATERIAL;
+import static net.sf.openrocket.preset.ComponentPreset.OUTER_DIAMETER;
+import static net.sf.openrocket.preset.ComponentPreset.PARTNO;
+import static net.sf.openrocket.preset.ComponentPreset.SHAPE;
+import static net.sf.openrocket.preset.ComponentPreset.THICKNESS;
+import static net.sf.openrocket.preset.ComponentPreset.TYPE;
+import net.sf.openrocket.material.Material;
+import net.sf.openrocket.preset.ComponentPreset.Type;
+import net.sf.openrocket.rocketcomponent.BodyTube;
+import net.sf.openrocket.rocketcomponent.Bulkhead;
+import net.sf.openrocket.rocketcomponent.NoseCone;
+import net.sf.openrocket.rocketcomponent.Transition;
+
+public abstract class ComponentPresetFactory {
+
+ public static ComponentPreset create( TypedPropertyMap props ) throws InvalidComponentPresetException {
+
+ ComponentPreset preset = new ComponentPreset();
+ // First do validation.
+ if ( !props.containsKey(TYPE)) {
+ throw new InvalidComponentPresetException("No Type specified " + props.toString() );
+ }
+
+ if (!props.containsKey(MANUFACTURER)) {
+ throw new InvalidComponentPresetException("No Manufacturer specified " + props.toString() );
+ }
+
+ if (!props.containsKey(PARTNO)) {
+ throw new InvalidComponentPresetException("No PartNo specified " + props.toString() );
+ }
+
+ preset.putAll(props);
+
+ // Should check for various bits of each of the types.
+ Type t = props.get(TYPE);
+ switch ( t ) {
+ case BODY_TUBE: {
+ makeBodyTube(preset);
+ break;
+ }
+ case NOSE_CONE: {
+ makeNoseCone(preset);
+ break;
+ }
+ case TRANSITION: {
+ makeTransition(preset);
+ break;
+ }
+ case BULK_HEAD: {
+ makeBulkHead(preset);
+ break;
+ }
+ }
+
+ preset.computeDigest();
+
+ return preset;
+
+ }
+
+ private static void makeBodyTube( ComponentPreset preset ) throws InvalidComponentPresetException {
+
+ checkRequiredFields( preset, LENGTH );
+
+ BodyTube bt = new BodyTube();
+
+ bt.setLength(preset.get(LENGTH));
+
+ // Need to verify contains 2 of OD, thickness, ID. Compute the third.
+ boolean hasOd = preset.has(OUTER_DIAMETER);
+ boolean hasId = preset.has(INNER_DIAMETER);
+ boolean hasThickness = preset.has(THICKNESS);
+
+ if ( hasOd ) {
+ double outerRadius = preset.get(OUTER_DIAMETER)/2.0;
+ double thickness = 0;
+ bt.setOuterRadius( outerRadius );
+ if ( hasId ) {
+ thickness = outerRadius - preset.get(INNER_DIAMETER)/2.0;
+ } else if ( hasThickness ) {
+ thickness = preset.get(THICKNESS);
+ } else {
+ throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
+ }
+ bt.setThickness( thickness );
+ } else {
+ if ( ! hasId && ! hasThickness ) {
+ throw new InvalidComponentPresetException("Body tube preset underspecified " + preset.toString());
+ }
+ double innerRadius = preset.get(INNER_DIAMETER)/2.0;
+ double thickness = preset.get(THICKNESS);
+ bt.setOuterRadius(innerRadius + thickness);
+ bt.setThickness(thickness);
+ }
+
+ preset.put(OUTER_DIAMETER, bt.getOuterRadius() *2.0);
+ preset.put(INNER_DIAMETER, bt.getInnerRadius() *2.0);
+ preset.put(THICKNESS, bt.getThickness());
+
+ // Need to translate Mass to Density.
+ if ( preset.has(MASS) ) {
+ String materialName = "TubeCustom";
+ if ( preset.has(MATERIAL) ) {
+ materialName = preset.get(MATERIAL).getName();
+ }
+ Material m = Material.newMaterial(Material.Type.BULK, materialName, preset.get(MASS)/bt.getComponentVolume(), false);
+ preset.put(MATERIAL, m);
+ }
+
+
+ }
+
+ private static void makeNoseCone( ComponentPreset preset ) throws InvalidComponentPresetException {
+
+ checkRequiredFields( preset, LENGTH, SHAPE, OUTER_DIAMETER );
+
+ if ( preset.has(MASS) ) {
+ // compute a density for this component
+ double mass = preset.get(MASS);
+ NoseCone nc = new NoseCone();
+ nc.loadPreset(preset);
+ double density = mass / nc.getComponentVolume();
+
+ String materialName = "NoseConeCustom";
+ if ( preset.has(MATERIAL) ) {
+ materialName = preset.get(MATERIAL).getName();
+ }
+
+ Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
+ preset.put(MATERIAL, m);
+
+ }
+
+ }
+
+ private static void makeTransition( ComponentPreset preset ) throws InvalidComponentPresetException {
+ checkRequiredFields(preset, LENGTH, OUTER_DIAMETER, FORE_OUTER_DIAMETER);
+
+ if ( preset.has(MASS) ) {
+ // compute a density for this component
+ double mass = preset.get(MASS);
+ Transition tr = new Transition();
+ tr.loadPreset(preset);
+ double density = mass / tr.getComponentVolume();
+
+ String materialName = "TransitionCustom";
+ if ( preset.has(MATERIAL) ) {
+ materialName = preset.get(MATERIAL).getName();
+ }
+
+ Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
+ preset.put(MATERIAL, m);
+
+ }
+
+ }
+
+ private static void makeBulkHead( ComponentPreset preset ) throws InvalidComponentPresetException {
+ checkRequiredFields(preset, LENGTH, OUTER_DIAMETER );
+
+ if ( preset.has(MASS) ) {
+ // compute a density for this component
+ double mass = preset.get(MASS);
+ Bulkhead tr = new Bulkhead();
+ tr.loadPreset(preset);
+ // FIXME - Bulkhead.getComponentVolume does not exist!
+ // double density = mass / tr.getComponentVolume();
+
+ double volume = Math.pow(preset.get(OUTER_DIAMETER),2) * Math.PI / 4.0;
+ double density = mass / volume;
+
+ String materialName = "TransitionCustom";
+ if ( preset.has(MATERIAL) ) {
+ materialName = preset.get(MATERIAL).getName();
+ }
+
+ Material m = Material.newMaterial(Material.Type.BULK, materialName,density, false);
+ preset.put(MATERIAL, m);
+
+ }
+
+ }
+
+ private static void checkRequiredFields( ComponentPreset preset, TypedKey<?> ... keys ) throws InvalidComponentPresetException {
+ for( TypedKey<?> key: keys ) {
+ if (! preset.has(key) ) {
+ throw new InvalidComponentPresetException( "No " + key.getName() + " specified for " + preset.getType().name() + " preset " + preset.toString());
+ }
+ }
+ }
+
+}