2 * MassObjectHandler.java
4 package net.sf.openrocket.file.rocksim.importt;
6 import net.sf.openrocket.aerodynamics.WarningSet;
7 import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
8 import net.sf.openrocket.file.simplesax.ElementHandler;
9 import net.sf.openrocket.file.simplesax.PlainTextHandler;
10 import net.sf.openrocket.material.Material;
11 import net.sf.openrocket.rocketcomponent.MassComponent;
12 import net.sf.openrocket.rocketcomponent.MassObject;
13 import net.sf.openrocket.rocketcomponent.RocketComponent;
14 import net.sf.openrocket.rocketcomponent.ShockCord;
15 import org.xml.sax.SAXException;
17 import java.util.HashMap;
20 * A SAX handler for Rocksim's MassObject XML type.
22 class MassObjectHandler extends PositionDependentHandler<MassObject> {
25 * The Rocksim Mass length fudge factor. Rocksim completely exaggerates the length of a mass object to the point
26 * that it looks ridiculous in OpenRocket. This fudge factor is here merely to get the typical mass object to
27 * render in the OpenRocket UI with it's bounds mostly inside it's parent. The odd thing about it is that
28 * Rocksim does not expose the length of a mass object in the UI and actually treats mass objects as point objects -
29 * not 3 or even 2 dimensional.
31 public static final int MASS_LEN_FUDGE_FACTOR = 100;
34 * The OpenRocket MassComponent - counterpart to the RS MassObject.
36 private final MassComponent mass;
39 * Reference to answer for getComponent().
41 private MassObject current;
46 private RocketComponent parent;
49 * 0 == General, 1 == Shock Cord
51 private int typeCode = 0;
56 * @param c the parent component
57 * @param warnings the warning set
59 * @throws IllegalArgumentException thrown if <code>c</code> is null
61 public MassObjectHandler(RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
63 throw new IllegalArgumentException("The parent component of a mass component may not be null.");
65 mass = new MassComponent();
71 public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
72 return PlainTextHandler.INSTANCE;
76 public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
78 super.closeElement(element, attributes, content, warnings);
80 if (RocksimCommonConstants.LEN.equals(element)) {
81 mass.setLength(Double.parseDouble(content) / (RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH));
83 if (RocksimCommonConstants.KNOWN_MASS.equals(element)) {
84 mass.setComponentMass(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_MASS);
86 if (RocksimCommonConstants.KNOWN_CG.equals(element)) {
87 //Setting the CG of the Mass Object to 0 is important because of the different ways that Rocksim and
88 //OpenRocket treat mass objects. Rocksim treats them as points (even though the data file contains a
89 //length) and because Rocksim sets the CG of the mass object to really be relative to the front of
90 //the parent. But that value is already assumed in the position and position value for the component.
91 //Thus it needs to be set to 0 to say that the mass object's CG is at the point of the mass object.
94 if (RocksimCommonConstants.TYPE_CODE.equals(element)) {
95 typeCode = Integer.parseInt(content);
97 if (RocksimCommonConstants.MATERIAL.equals(element)) {
98 setMaterialName(content);
101 catch (NumberFormatException nfe) {
102 warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
107 public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
108 if (typeCode == 0) { //General Mass Object
109 if (isCompatible(parent, MassComponent.class, warnings)) {
110 parent.addChild(mass);
112 super.endHandler(element, attributes, content, warnings);
114 else if (typeCode == 1) { //Shock Cord
115 ShockCord cord = new ShockCord();
117 if (isCompatible(parent, ShockCord.class, warnings)) {
118 parent.addChild(cord);
120 super.endHandler(element, attributes, content, warnings);
121 cord.setName(mass.getName());
123 setOverride(cord, mass.isMassOverridden(), mass.getOverrideMass(), mass.getOverrideCGX());
125 cord.setRadialDirection(mass.getRadialDirection());
126 cord.setRadialPosition(mass.getRadialPosition());
127 cord.setRadius(mass.getRadius());
129 //Rocksim does not distinguish between total length of the cord and the packed length. Fudge the
130 //packed length and set the real length.
131 cord.setCordLength(mass.getLength());
132 cord.setLength(cord.getCordLength()/MASS_LEN_FUDGE_FACTOR);
137 * Get the component this handler is working upon. This changes depending upon the type of mass object.
139 * @return a component
142 public MassObject getComponent() {
147 * Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
148 * public in all components.
150 * @param position the OpenRocket position
152 public void setRelativePosition(RocketComponent.Position position) {
153 current.setRelativePosition(position);
157 * Get the required type of material for this component. Does not apply to MassComponents, but does apply to Shock Cords.
162 public Material.Type getMaterialType() {
163 return Material.Type.LINE;