From 01df928f3cd201d71d2e071aa2347b244b0a21a0 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Sat, 27 Jan 2024 03:22:53 +0100 Subject: [PATCH] Support RockSim booster importing --- .../file/rocksim/importt/PodHandler.java | 78 ++++++++++++++++++- .../rocketcomponent/RocketComponent.java | 2 +- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/core/src/net/sf/openrocket/file/rocksim/importt/PodHandler.java b/core/src/net/sf/openrocket/file/rocksim/importt/PodHandler.java index 267be2ec6..9344604bc 100644 --- a/core/src/net/sf/openrocket/file/rocksim/importt/PodHandler.java +++ b/core/src/net/sf/openrocket/file/rocksim/importt/PodHandler.java @@ -6,30 +6,43 @@ 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.ComponentAssembly; +import net.sf.openrocket.rocketcomponent.ParallelStage; import net.sf.openrocket.rocketcomponent.PodSet; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.position.AnglePositionable; import net.sf.openrocket.rocketcomponent.position.RadiusMethod; import org.xml.sax.SAXException; import java.util.HashMap; -public class PodHandler extends PositionDependentHandler { +public class PodHandler extends PositionDependentHandler { /** * The OpenRocket BodyTube. */ + private final RocketComponent parent; private final PodSet podSet; + private final ParallelStage parallelStage; // A RockSim podset can be an OpenRocket PodSet, or a ParallelStage if it is detachable + private boolean isDetachable = false; + private boolean isEjected = false; public PodHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) { super(context); if (c == null) { throw new IllegalArgumentException("The parent component of a pod set may not be null."); } + this.parent = c; podSet = new PodSet(); + parallelStage = new ParallelStage(); + podSet.addConfigListener(parallelStage); // The booster will now follow the same config changes as the podset podSet.setInstanceCount(1); // RockSim only supports one pod instance podSet.setRadiusMethod(RadiusMethod.FREE); // RockSim radial offset is relative to the center of the parent if (isCompatible(c, PodSet.class, warnings)) { c.addChild(podSet); } + if (isCompatible(c, ParallelStage.class, warnings)) { + c.addChild(parallelStage); + } } @Override @@ -52,10 +65,71 @@ public class PodHandler extends PositionDependentHandler { if (RockSimCommonConstants.RADIAL_LOC.equals(element)) { podSet.setRadiusOffset(Double.parseDouble(content) / RockSimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH); } + if (RockSimCommonConstants.DETACHABLE.equals(element)) { + int value = Integer.parseInt(content); + isDetachable = value == 1; + } + if (RockSimCommonConstants.REMOVED.equals(element)) { + int value = Integer.parseInt(content); + isEjected = value == 1; + } } @Override - protected PodSet getComponent() { + public void endHandler(String element, HashMap attributes, String content, WarningSet warnings) throws SAXException { + super.endHandler(element, attributes, content, warnings); + + // Since RockSim stores the angle offset of pod children in absolute coordinates (not relative to the parent pod set), + // we need to subtract the parent pod set angle offset from this component's offset + subtractAngleOffset(podSet, podSet.getAngleOffset()); + + if (isDetachable || isEjected) { + // The offsets of the parallel stage can change due to the children, so copy them from the podset and then apply + // it later + double axialOffset = podSet.getAxialOffset(); + double radiusOffset = podSet.getRadiusOffset(); + + // Copy the children from the pod to the booster + int childCount = podSet.getChildCount(); + for (int i = 0; i < childCount; i++) { + RocketComponent child = podSet.getChild(0); + podSet.removeChild(child); + if (parallelStage.isCompatible(child)) { + parallelStage.addChild(child); + } else { + warnings.add("The child component " + child.getName() + " of the podset " + podSet.getName() + " is not compatible with a parallel stage."); + } + } + + // Apply the offsets + parallelStage.setAxialOffset(axialOffset); + parallelStage.setRadiusOffset(radiusOffset); + + // Remove the podset from the parent + parent.removeChild(podSet); + + if (isEjected) { + parent.getRocket().getSelectedConfiguration()._setStageActive(parallelStage.getStageNumber(), false); + } + } else { + // It's a normal podset, so remove the booster placeholder + parent.removeChild(parallelStage); + } + } + + private void subtractAngleOffset(RocketComponent c, double angleOffset) { + for (RocketComponent child : c.getChildren()) { + if (child instanceof AnglePositionable anglePositionable) { + anglePositionable.setAngleOffset(anglePositionable.getAngleOffset() - angleOffset); + } + if (!(child instanceof ComponentAssembly)) { + subtractAngleOffset(child, angleOffset); + } + } + } + + @Override + protected ComponentAssembly getComponent() { return podSet; } diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index ca32e222f..4532d4cb2 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -2059,7 +2059,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab /** - * Move a child to another position. + * Move a child to another position within this component. * * @param component the component to move * @param index the component's new position