diff --git a/core/src/net/sf/openrocket/file/rasaero/importt/BoatTailHandler.java b/core/src/net/sf/openrocket/file/rasaero/importt/BoatTailHandler.java index 6dd436935..b7fb91b84 100644 --- a/core/src/net/sf/openrocket/file/rasaero/importt/BoatTailHandler.java +++ b/core/src/net/sf/openrocket/file/rasaero/importt/BoatTailHandler.java @@ -2,18 +2,29 @@ package net.sf.openrocket.file.rasaero.importt; import net.sf.openrocket.aerodynamics.WarningSet; import net.sf.openrocket.file.DocumentLoadingContext; +import net.sf.openrocket.file.simplesax.AbstractElementHandler; import net.sf.openrocket.file.simplesax.ElementHandler; +import net.sf.openrocket.rocketcomponent.BodyTube; +import net.sf.openrocket.rocketcomponent.PodSet; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.Transition; +import net.sf.openrocket.rocketcomponent.position.AxialMethod; +import net.sf.openrocket.rocketcomponent.position.RadiusMethod; import org.xml.sax.SAXException; import java.util.HashMap; /** - * A handler for the boat tail element RASAero. This is just an OpenRocket transition. + * A handler for the boat tail element RASAero. + * A boat tail is just an OpenRocket transition, but because it can be recessed in next symmetric components + * (e.g. a body tube), we will add the boat tail using an inline pod set to the previous component. + * In case the previous component is a nose cone, we will first add a phantom body tube and then add the pod to + * that body tube. I know, not the most elegant solution, but it grants us the best cross-compatibility with RASAero. * * @author Sibo Van Gool */ public class BoatTailHandler extends TransitionHandler { + /** * Constructor * @@ -23,7 +34,46 @@ public class BoatTailHandler extends TransitionHandler { * @throws IllegalArgumentException if the parent component is null */ public BoatTailHandler(DocumentLoadingContext context, RocketComponent parent, WarningSet warnings) throws IllegalArgumentException { - super(context, parent, warnings); + super(context); + + if (parent == null) { + throw new IllegalArgumentException("The parent component of a boat tail may not be null."); + } + if (parent.getChildCount() == 0) { + throw new IllegalArgumentException("The parent component of a boat tail must have at least one child."); + } + + // Pod to add the boat tail to + PodSet pod = new PodSet(); + pod.setInstanceCount(1); + pod.setRadius(RadiusMethod.FREE, 0); + pod.setName("Boat tail pod"); + pod.setComment("Because boat tails in RASAero can be recessed, we will add the boat tail using an inline pod set to the previous component."); + + // Add the pod to the parent's last child, or to a phantom tube if the last child is a nose cone/transition + RocketComponent lastChild = parent.getChild(parent.getChildCount() - 1); + if (lastChild instanceof BodyTube) { + lastChild.addChild(pod); + pod.setAxialMethod(AxialMethod.BOTTOM); + pod.setAxialOffset(0); + } else if (lastChild instanceof Transition) { + BodyTube phantomBodyTube = new BodyTube(); + phantomBodyTube.setLength(0); + phantomBodyTube.setOuterRadiusAutomatic(true); + phantomBodyTube.setName("Boat tail phantom tube"); + ColorHandler.applyRASAeroColor(phantomBodyTube, null); // Set the color to the default RASAero color + parent.addChild(phantomBodyTube); + phantomBodyTube.addChild(pod); + pod.setAxialMethod(AxialMethod.TOP); + pod.setAxialOffset(0); + } else { + throw new IllegalArgumentException("Cannot add boat tail after component of type " + parent.getClass().getName()); + } + + pod.addChild(this.transition); + this.transition.setAftRadiusAutomatic(false); + this.transition.setShapeType(Transition.Shape.CONICAL); // RASAero only supports conical boat tails + this.transition.setName("Boat tail"); } @Override diff --git a/core/src/net/sf/openrocket/file/rasaero/importt/TransitionHandler.java b/core/src/net/sf/openrocket/file/rasaero/importt/TransitionHandler.java index 5efef4f95..88660244a 100644 --- a/core/src/net/sf/openrocket/file/rasaero/importt/TransitionHandler.java +++ b/core/src/net/sf/openrocket/file/rasaero/importt/TransitionHandler.java @@ -40,6 +40,10 @@ public class TransitionHandler extends BaseHandler { this.transition.setShapeType(Transition.Shape.CONICAL); // RASAero only supports conical transitions } + public TransitionHandler(DocumentLoadingContext context) { + super(context); + } + @Override public ElementHandler openElement(String element, HashMap attributes, WarningSet warnings) throws SAXException { return PlainTextHandler.INSTANCE;