/* * ParachuteHandler.java */ package net.sf.openrocket.file.rocksim.importt; import java.util.HashMap; import net.sf.openrocket.aerodynamics.WarningSet; import net.sf.openrocket.file.DocumentLoadingContext; import net.sf.openrocket.file.rocksim.RocksimCommonConstants; import net.sf.openrocket.file.simplesax.ElementHandler; import net.sf.openrocket.file.simplesax.PlainTextHandler; import net.sf.openrocket.material.Material; import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.InnerTube; import net.sf.openrocket.rocketcomponent.Parachute; import net.sf.openrocket.rocketcomponent.RocketComponent; import org.xml.sax.SAXException; /** * A SAX handler for Rocksim's Parachute XML type. */ class ParachuteHandler extends RecoveryDeviceHandler<Parachute> { /** * The OpenRocket Parachute instance */ private final Parachute chute; /** * The shroud line density. */ private double shroudLineDensity = 0.0d; /** * Constructor. * * @param c the parent component * @param warnings the warning set * * @throws IllegalArgumentException thrown if <code>c</code> is null */ public ParachuteHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) throws IllegalArgumentException { super(context); if (c == null) { throw new IllegalArgumentException("The parent of a parachute may not be null."); } chute = new Parachute(); if (isCompatible(c, Parachute.class, warnings)) { c.addChild(chute); } } /** * {@inheritDoc} */ @Override public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) { return PlainTextHandler.INSTANCE; } /** * {@inheritDoc} */ @Override public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException { super.closeElement(element, attributes, content, warnings); try { if (RocksimCommonConstants.DIAMETER.equals(element)) { chute.setDiameter(Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH); /* Rocksim doesn't have a packed parachute radius, so we approximate it. */ double packed; RocketComponent parent = chute.getParent(); if (parent instanceof BodyTube) { packed = ((BodyTube) parent).getOuterRadius() * 0.9; } else if (parent instanceof InnerTube) { packed = ((InnerTube) parent).getInnerRadius() * 0.9; } else { packed = chute.getDiameter() * 0.025; } chute.setRadius(packed); } if (RocksimCommonConstants.SHROUD_LINE_COUNT.equals(element)) { chute.setLineCount(Math.max(0, Integer.parseInt(content))); } if (RocksimCommonConstants.SHROUD_LINE_LEN.equals(element)) { chute.setLineLength(Math.max(0, Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH)); } if (RocksimCommonConstants.SPILL_HOLE_DIA.equals(element)) { //Not supported in OpenRocket double spillHoleRadius = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_RADIUS; if (spillHoleRadius > 0) { warnings.add("Parachute spill holes are not supported. Ignoring."); } } if (RocksimCommonConstants.SHROUD_LINE_MASS_PER_MM.equals(element)) { shroudLineDensity = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LINE_DENSITY; } if (RocksimCommonConstants.SHROUD_LINE_MATERIAL.equals(element)) { chute.setLineMaterial(createCustomMaterial(Material.Type.LINE, content, shroudLineDensity)); } if (RocksimCommonConstants.DRAG_COEFFICIENT.equals(element)) { chute.setCD(Double.parseDouble(content)); } if (RocksimCommonConstants.MATERIAL.equals(element)) { setMaterialName(content); } } catch (NumberFormatException nfe) { warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number."); } } /** * Get the component this handler is working upon. * * @return a component */ public Parachute getComponent() { return chute; } }