4 package net.sf.openrocket.file.rocksim;
6 import net.sf.openrocket.aerodynamics.WarningSet;
7 import net.sf.openrocket.file.simplesax.ElementHandler;
8 import net.sf.openrocket.file.simplesax.PlainTextHandler;
9 import net.sf.openrocket.material.Material;
10 import net.sf.openrocket.rocketcomponent.NoseCone;
11 import net.sf.openrocket.rocketcomponent.RocketComponent;
12 import net.sf.openrocket.rocketcomponent.Transition;
13 import org.xml.sax.SAXException;
15 import java.util.HashMap;
18 * The SAX nose cone handler for Rocksim NoseCones.
20 class NoseConeHandler extends BaseHandler<NoseCone> {
23 * The OpenRocket NoseCone.
25 private final NoseCone noseCone = new NoseCone();
28 * The wall thickness. Used for hollow nose cones.
30 private double thickness = 0d;
35 * @param c the parent component to the nosecone
36 * @throws IllegalArgumentException thrown if <code>c</code> is null
38 public NoseConeHandler(RocketComponent c) throws IllegalArgumentException {
40 throw new IllegalArgumentException("The parent component of a nose cone may not be null.");
43 noseCone.setAftRadiusAutomatic(false);
47 public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
48 //Nose cones in Rocksim may have attached parts - namely Mass Objects - as children.
49 if ("AttachedParts".equals(element)) {
50 return new AttachedPartsHandler(noseCone);
52 return PlainTextHandler.INSTANCE;
56 public void closeElement(String element, HashMap<String, String> attributes,
57 String content, WarningSet warnings) throws SAXException {
58 super.closeElement(element, attributes, content, warnings);
61 if ("ShapeCode".equals(element)) {
62 noseCone.setType(RocksimNoseConeCode.fromCode(Integer.parseInt(content)).asOpenRocket());
64 if ("Len".equals(element)) {
65 noseCone.setLength(Math.max(0, Double.parseDouble(content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH));
67 if ("BaseDia".equals(element)) {
68 noseCone.setAftRadius(Math.max(0, Double.parseDouble(content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS));
70 if ("WallThickness".equals(element)) {
71 thickness = Math.max(0, Double.parseDouble(content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH);
73 if ("ShoulderOD".equals(element)) {
74 noseCone.setAftShoulderRadius(Math.max(0, Double.parseDouble(
75 content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS));
77 if ("ShoulderLen".equals(element)) {
78 noseCone.setAftShoulderLength(Math.max(0, Double.parseDouble(
79 content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH));
81 if ("ShapeParameter".equals(element)) {
82 //The Rocksim ShapeParameter only applies to certain shapes, although it is included
83 //in the design file for all nose cones. Applying it when it should not be causes oddities so
84 //a check is made for the allowable shapes.
85 if (Transition.Shape.POWER.equals(noseCone.getType()) ||
86 Transition.Shape.HAACK.equals(noseCone.getType()) ||
87 Transition.Shape.PARABOLIC.equals(noseCone.getType())) {
88 noseCone.setShapeParameter(Double.parseDouble(content));
91 if ("ConstructionType".equals(element)) {
92 int typeCode = Integer.parseInt(content);
95 noseCone.setFilled(true);
97 else if (typeCode == 1) {
99 noseCone.setFilled(false);
102 if ("FinishCode".equals(element)) {
103 noseCone.setFinish(RocksimFinishCode.fromCode(Integer.parseInt(content)).asOpenRocket());
105 if ("Material".equals(element)) {
106 setMaterialName(content);
109 catch (NumberFormatException nfe) {
110 warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
115 public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
116 throws SAXException {
117 super.endHandler(element, attributes, content, warnings);
119 if (noseCone.isFilled()) {
120 noseCone.setAftShoulderThickness(noseCone.getAftShoulderRadius());
123 noseCone.setThickness(thickness);
124 noseCone.setAftShoulderThickness(thickness);
129 * Get the nose cone component this handler is working upon.
131 * @return a nose cone component
134 public NoseCone getComponent() {
139 * Get the required type of material for this component.
143 public Material.Type getMaterialType() {
144 return Material.Type.BULK;