Support RockSim booster importing

This commit is contained in:
SiboVG 2024-01-27 03:22:53 +01:00
parent b5704c108c
commit 01df928f3c
2 changed files with 77 additions and 3 deletions

View File

@ -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<PodSet> {
public class PodHandler extends PositionDependentHandler<ComponentAssembly> {
/**
* 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<PodSet> {
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<String, String> 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;
}

View File

@ -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