2 * ParachuteHandler.java
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.BodyTube;
11 import net.sf.openrocket.rocketcomponent.InnerTube;
12 import net.sf.openrocket.rocketcomponent.Parachute;
13 import net.sf.openrocket.rocketcomponent.RocketComponent;
14 import org.xml.sax.SAXException;
16 import java.util.HashMap;
19 * A SAX handler for Rocksim's Parachute XML type.
22 class ParachuteHandler extends PositionDependentHandler<Parachute> {
24 * The OpenRocket Parachute instance
26 private final Parachute chute;
28 * The shroud line density.
30 private double shroudLineDensity = 0.0d;
35 * @param c the parent component
36 * @throws IllegalArgumentException thrown if <code>c</code> is null
38 public ParachuteHandler(RocketComponent c) throws IllegalArgumentException {
40 throw new IllegalArgumentException("The parent of a parachute may not be null.");
42 chute = new Parachute();
47 public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) {
48 return PlainTextHandler.INSTANCE;
52 public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings)
54 super.closeElement(element, attributes, content, warnings);
56 if ("Dia".equals(element)) {
57 chute.setDiameter(Double.parseDouble(content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH);
58 /* Rocksim doesn't have a packed parachute radius, so we approximate it. */
60 RocketComponent parent = chute.getParent();
61 if (parent instanceof BodyTube) {
62 packed = ((BodyTube) parent).getRadius() * 0.9;
64 else if (parent instanceof InnerTube) {
65 packed = ((InnerTube) parent).getInnerRadius() * 0.9;
68 packed = chute.getDiameter() * 0.025;
70 chute.setRadius(packed);
72 if ("ShroudLineCount".equals(element)) {
73 chute.setLineCount(Math.max(0, Integer.parseInt(content)));
75 if ("ShroudLineLen".equals(element)) {
76 chute.setLineLength(Math.max(0, Double.parseDouble(
77 content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_LENGTH));
79 if ("SpillHoleDia".equals(element)) {
80 //Not supported in OpenRocket
81 double spillHoleRadius = Double.parseDouble(content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_RADIUS;
82 warnings.add("Parachute spill holes are not supported. Ignoring.");
84 if ("ShroudLineMassPerMM".equals(element)) {
85 shroudLineDensity = Double.parseDouble(content) / RocksimHandler.ROCKSIM_TO_OPENROCKET_LINE_DENSITY;
87 if ("ShroudLineMaterial".equals(element)) {
88 chute.setLineMaterial(BaseHandler.createCustomMaterial(Material.Type.LINE, content, shroudLineDensity));
90 if ("DragCoefficient".equals(element)) {
91 chute.setCD(Double.parseDouble(content));
93 if ("Material".equals(element)) {
94 setMaterialName(content);
97 catch (NumberFormatException nfe) {
98 warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
103 * Get the component this handler is working upon.
105 * @return a component
107 public Parachute getComponent() {
112 * Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
113 * public in all components.
115 * @param position the OpenRocket position
117 public void setRelativePosition(RocketComponent.Position position) {
118 chute.setRelativePosition(position);
122 * Get the required type of material for this component.
127 public Material.Type getMaterialType() {
128 return Material.Type.SURFACE;