Merge branch 'openrocket:unstable' into fix-1702
This commit is contained in:
commit
3f73f694e2
@ -29,6 +29,8 @@ public class RockSimCommonConstants {
|
|||||||
public static final String DENSITY_TYPE = "DensityType";
|
public static final String DENSITY_TYPE = "DensityType";
|
||||||
public static final String RADIAL_LOC = "RadialLoc";
|
public static final String RADIAL_LOC = "RadialLoc";
|
||||||
public static final String RADIAL_ANGLE = "RadialAngle";
|
public static final String RADIAL_ANGLE = "RadialAngle";
|
||||||
|
public static final String AUTO_CALC_RADIAL_DISTANCE = "AutoCalcRadialDistance";
|
||||||
|
public static final String AUTO_CALC_RADIAL_ANGLE = "AutoCalcRadialAngle";
|
||||||
public static final String LOCATION_MODE = "LocationMode";
|
public static final String LOCATION_MODE = "LocationMode";
|
||||||
public static final String FINISH_CODE = "FinishCode";
|
public static final String FINISH_CODE = "FinishCode";
|
||||||
public static final String SERIAL_NUMBER = "SerialNo";
|
public static final String SERIAL_NUMBER = "SerialNo";
|
||||||
|
@ -11,6 +11,7 @@ import net.sf.openrocket.rocketcomponent.InnerTube;
|
|||||||
import net.sf.openrocket.rocketcomponent.LaunchLug;
|
import net.sf.openrocket.rocketcomponent.LaunchLug;
|
||||||
import net.sf.openrocket.rocketcomponent.MassObject;
|
import net.sf.openrocket.rocketcomponent.MassObject;
|
||||||
import net.sf.openrocket.rocketcomponent.Parachute;
|
import net.sf.openrocket.rocketcomponent.Parachute;
|
||||||
|
import net.sf.openrocket.rocketcomponent.PodSet;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.Streamer;
|
import net.sf.openrocket.rocketcomponent.Streamer;
|
||||||
import net.sf.openrocket.rocketcomponent.Transition;
|
import net.sf.openrocket.rocketcomponent.Transition;
|
||||||
@ -50,6 +51,7 @@ public class BodyTubeDTO extends BasePartDTO implements AttachableParts {
|
|||||||
@XmlElementRefs({
|
@XmlElementRefs({
|
||||||
@XmlElementRef(name = RockSimCommonConstants.BODY_TUBE, type = BodyTubeDTO.class),
|
@XmlElementRef(name = RockSimCommonConstants.BODY_TUBE, type = BodyTubeDTO.class),
|
||||||
@XmlElementRef(name = RockSimCommonConstants.BODY_TUBE, type = InnerBodyTubeDTO.class),
|
@XmlElementRef(name = RockSimCommonConstants.BODY_TUBE, type = InnerBodyTubeDTO.class),
|
||||||
|
@XmlElementRef(name = RockSimCommonConstants.TRANSITION, type = TransitionDTO.class),
|
||||||
@XmlElementRef(name = RockSimCommonConstants.RING, type = CenteringRingDTO.class),
|
@XmlElementRef(name = RockSimCommonConstants.RING, type = CenteringRingDTO.class),
|
||||||
@XmlElementRef(name = RockSimCommonConstants.LAUNCH_LUG, type = LaunchLugDTO.class),
|
@XmlElementRef(name = RockSimCommonConstants.LAUNCH_LUG, type = LaunchLugDTO.class),
|
||||||
@XmlElementRef(name = RockSimCommonConstants.FIN_SET, type = FinSetDTO.class),
|
@XmlElementRef(name = RockSimCommonConstants.FIN_SET, type = FinSetDTO.class),
|
||||||
@ -57,7 +59,8 @@ public class BodyTubeDTO extends BasePartDTO implements AttachableParts {
|
|||||||
@XmlElementRef(name = RockSimCommonConstants.TUBE_FIN_SET, type = TubeFinSetDTO.class),
|
@XmlElementRef(name = RockSimCommonConstants.TUBE_FIN_SET, type = TubeFinSetDTO.class),
|
||||||
@XmlElementRef(name = RockSimCommonConstants.STREAMER, type = StreamerDTO.class),
|
@XmlElementRef(name = RockSimCommonConstants.STREAMER, type = StreamerDTO.class),
|
||||||
@XmlElementRef(name = RockSimCommonConstants.PARACHUTE, type = ParachuteDTO.class),
|
@XmlElementRef(name = RockSimCommonConstants.PARACHUTE, type = ParachuteDTO.class),
|
||||||
@XmlElementRef(name = RockSimCommonConstants.MASS_OBJECT, type = MassObjectDTO.class)})
|
@XmlElementRef(name = RockSimCommonConstants.MASS_OBJECT, type = MassObjectDTO.class),
|
||||||
|
@XmlElementRef(name = RockSimCommonConstants.EXTERNAL_POD, type = PodSetDTO.class)})
|
||||||
List<BasePartDTO> attachedParts = new ArrayList<BasePartDTO>();
|
List<BasePartDTO> attachedParts = new ArrayList<BasePartDTO>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,6 +128,8 @@ public class BodyTubeDTO extends BasePartDTO implements AttachableParts {
|
|||||||
addAttachedPart(new FinSetDTO((FinSet) rocketComponents));
|
addAttachedPart(new FinSetDTO((FinSet) rocketComponents));
|
||||||
} else if (rocketComponents instanceof TubeFinSet) {
|
} else if (rocketComponents instanceof TubeFinSet) {
|
||||||
addAttachedPart(new TubeFinSetDTO((TubeFinSet) rocketComponents));
|
addAttachedPart(new TubeFinSetDTO((TubeFinSet) rocketComponents));
|
||||||
|
} else if (rocketComponents instanceof PodSet) {
|
||||||
|
addAttachedPart(new PodSetDTO((PodSet) rocketComponents));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
110
core/src/net/sf/openrocket/file/rocksim/export/PodSetDTO.java
Normal file
110
core/src/net/sf/openrocket/file/rocksim/export/PodSetDTO.java
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package net.sf.openrocket.file.rocksim.export;
|
||||||
|
|
||||||
|
import net.sf.openrocket.file.rocksim.RockSimCommonConstants;
|
||||||
|
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||||
|
import net.sf.openrocket.rocketcomponent.NoseCone;
|
||||||
|
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 javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
import javax.xml.bind.annotation.XmlElementRef;
|
||||||
|
import javax.xml.bind.annotation.XmlElementRefs;
|
||||||
|
import javax.xml.bind.annotation.XmlElementWrapper;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models the XML element for a RockSim pod.
|
||||||
|
*/
|
||||||
|
@XmlRootElement(name = RockSimCommonConstants.EXTERNAL_POD)
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
public class PodSetDTO extends BasePartDTO implements AttachableParts {
|
||||||
|
@XmlElement(name = RockSimCommonConstants.AUTO_CALC_RADIAL_DISTANCE)
|
||||||
|
private int autoCalcRadialDistance = 0;
|
||||||
|
@XmlElement(name = RockSimCommonConstants.AUTO_CALC_RADIAL_ANGLE)
|
||||||
|
private int autoCalcRadialAngle = 0;
|
||||||
|
@XmlElementWrapper(name = RockSimCommonConstants.ATTACHED_PARTS)
|
||||||
|
@XmlElementRefs({
|
||||||
|
@XmlElementRef(name = RockSimCommonConstants.BODY_TUBE, type = BodyTubeDTO.class),
|
||||||
|
@XmlElementRef(name = RockSimCommonConstants.NOSE_CONE, type = NoseConeDTO.class),
|
||||||
|
@XmlElementRef(name = RockSimCommonConstants.TRANSITION, type = TransitionDTO.class),
|
||||||
|
@XmlElementRef(name = RockSimCommonConstants.EXTERNAL_POD, type = PodSetDTO.class)})
|
||||||
|
List<BasePartDTO> attachedParts = new ArrayList<BasePartDTO>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*/
|
||||||
|
public PodSetDTO() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy constructor. Fully populates this instance with values taken from the OR PodSet.
|
||||||
|
*
|
||||||
|
* @param theORPodSet
|
||||||
|
*/
|
||||||
|
public PodSetDTO(PodSet theORPodSet) {
|
||||||
|
super(theORPodSet);
|
||||||
|
// OR should always override the radial angle and distance
|
||||||
|
setAutoCalcRadialDistance(false);
|
||||||
|
setAutoCalcRadialAngle(false);
|
||||||
|
setRadialAngle(theORPodSet.getAngleOffset());
|
||||||
|
setRadialLoc(theORPodSet.getRadiusMethod().getRadius(
|
||||||
|
theORPodSet.getParent(), theORPodSet,
|
||||||
|
theORPodSet.getRadiusOffset()) * RockSimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
|
||||||
|
setXb(theORPodSet.getAxialOffset(AxialMethod.TOP) * RockSimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
|
||||||
|
|
||||||
|
for (RocketComponent child : theORPodSet.getChildren()) {
|
||||||
|
if (child instanceof PodSet) {
|
||||||
|
addAttachedPart(new PodSetDTO((PodSet) child));
|
||||||
|
} else if (child instanceof BodyTube) {
|
||||||
|
addAttachedPart(new BodyTubeDTO((BodyTube) child));
|
||||||
|
} else if (child instanceof NoseCone) {
|
||||||
|
addAttachedPart(new NoseConeDTO((NoseCone) child));
|
||||||
|
} else if (child instanceof Transition) {
|
||||||
|
addAttachedPart(new TransitionDTO((Transition) child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAutoCalcRadialDistance() {
|
||||||
|
return autoCalcRadialDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutoCalcRadialDistance(boolean motorMount) {
|
||||||
|
if (motorMount) {
|
||||||
|
this.autoCalcRadialDistance = 1;
|
||||||
|
} else {
|
||||||
|
this.autoCalcRadialDistance = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAutoCalcRadialAngle() {
|
||||||
|
return autoCalcRadialAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutoCalcRadialAngle(boolean motorMount) {
|
||||||
|
if (motorMount) {
|
||||||
|
this.autoCalcRadialAngle = 1;
|
||||||
|
} else {
|
||||||
|
this.autoCalcRadialAngle = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAttachedPart(BasePartDTO part) {
|
||||||
|
if (!attachedParts.contains(part)) {
|
||||||
|
attachedParts.add(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAttachedPart(BasePartDTO part) {
|
||||||
|
attachedParts.remove(part);
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ import net.sf.openrocket.file.DocumentLoadingContext;
|
|||||||
import net.sf.openrocket.file.rocksim.RockSimCommonConstants;
|
import net.sf.openrocket.file.rocksim.RockSimCommonConstants;
|
||||||
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
|
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
|
||||||
import net.sf.openrocket.file.simplesax.ElementHandler;
|
import net.sf.openrocket.file.simplesax.ElementHandler;
|
||||||
|
import net.sf.openrocket.rocketcomponent.PodSet;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -68,23 +69,32 @@ class AttachedPartsHandler extends AbstractElementHandler {
|
|||||||
return new RingHandler(context, component, warnings);
|
return new RingHandler(context, component, warnings);
|
||||||
}
|
}
|
||||||
if (RockSimCommonConstants.BODY_TUBE.equals(element)) {
|
if (RockSimCommonConstants.BODY_TUBE.equals(element)) {
|
||||||
|
// Pods can have BodyTubes as attached parts, but not inner tubes. All other components can't have BodyTubes as
|
||||||
|
// attached parts.
|
||||||
|
if (component instanceof PodSet) {
|
||||||
|
return new BodyTubeHandler(context, component, warnings);
|
||||||
|
} else {
|
||||||
return new InnerBodyTubeHandler(context, component, warnings);
|
return new InnerBodyTubeHandler(context, component, warnings);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (RockSimCommonConstants.TRANSITION.equals(element)) {
|
if (RockSimCommonConstants.TRANSITION.equals(element)) {
|
||||||
return new TransitionHandler(context, component, warnings);
|
return new TransitionHandler(context, component, warnings);
|
||||||
}
|
}
|
||||||
|
if (RockSimCommonConstants.NOSE_CONE.equals(element)) {
|
||||||
|
return new NoseConeHandler(context, component, warnings);
|
||||||
|
}
|
||||||
if (RockSimCommonConstants.SUBASSEMBLY.equals(element)) {
|
if (RockSimCommonConstants.SUBASSEMBLY.equals(element)) {
|
||||||
return new SubAssemblyHandler(context, component);
|
return new SubAssemblyHandler(context, component);
|
||||||
}
|
}
|
||||||
if (RockSimCommonConstants.TUBE_FIN_SET.equals(element)) {
|
if (RockSimCommonConstants.TUBE_FIN_SET.equals(element)) {
|
||||||
return new TubeFinSetHandler(context, component, warnings);
|
return new TubeFinSetHandler(context, component, warnings);
|
||||||
}
|
}
|
||||||
|
if (RockSimCommonConstants.EXTERNAL_POD.equals(element)) {
|
||||||
|
return new PodHandler(context, component, warnings);
|
||||||
|
}
|
||||||
if (RockSimCommonConstants.RING_TAIL.equals(element)) {
|
if (RockSimCommonConstants.RING_TAIL.equals(element)) {
|
||||||
warnings.add("Ring tails are not currently supported. Ignoring.");
|
warnings.add("Ring tails are not currently supported. Ignoring.");
|
||||||
}
|
}
|
||||||
if (RockSimCommonConstants.EXTERNAL_POD.equals(element)) {
|
|
||||||
warnings.add("Pods are not currently supported. Ignoring.");
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ class BodyTubeHandler extends BaseHandler<BodyTube> {
|
|||||||
* The OpenRocket BodyTube.
|
* The OpenRocket BodyTube.
|
||||||
*/
|
*/
|
||||||
private final BodyTube bodyTube;
|
private final BodyTube bodyTube;
|
||||||
|
private int isInsideTube = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@ -80,6 +81,9 @@ class BodyTubeHandler extends BaseHandler<BodyTube> {
|
|||||||
if (RockSimCommonConstants.MATERIAL.equals(element)) {
|
if (RockSimCommonConstants.MATERIAL.equals(element)) {
|
||||||
setMaterialName(content);
|
setMaterialName(content);
|
||||||
}
|
}
|
||||||
|
if (RockSimCommonConstants.IS_INSIDE_TUBE.equals(element)) {
|
||||||
|
isInsideTube = Integer.parseInt(content);
|
||||||
|
}
|
||||||
} catch (NumberFormatException nfe) {
|
} catch (NumberFormatException nfe) {
|
||||||
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
|
warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number.");
|
||||||
}
|
}
|
||||||
@ -104,4 +108,11 @@ class BodyTubeHandler extends BaseHandler<BodyTube> {
|
|||||||
public Material.Type getMaterialType() {
|
public Material.Type getMaterialType() {
|
||||||
return Material.Type.BULK;
|
return Material.Type.BULK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns 0 if this is a body tube, 1 if it is an inside tube.
|
||||||
|
*/
|
||||||
|
public int isInsideTube() {
|
||||||
|
return isInsideTube;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
package net.sf.openrocket.file.rocksim.importt;
|
||||||
|
|
||||||
|
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.PodSet;
|
||||||
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
|
import net.sf.openrocket.rocketcomponent.position.RadiusMethod;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class PodHandler extends PositionDependentHandler<PodSet> {
|
||||||
|
/**
|
||||||
|
* The OpenRocket BodyTube.
|
||||||
|
*/
|
||||||
|
private final PodSet podSet;
|
||||||
|
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
podSet = new 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) throws SAXException {
|
||||||
|
if (RockSimCommonConstants.BODY_TUBE.equals(element)) { // RockSim pods allow body tubes, not inner tubes
|
||||||
|
return new BodyTubeHandler(context, podSet, warnings);
|
||||||
|
}
|
||||||
|
if (RockSimCommonConstants.ATTACHED_PARTS.equals(element)) {
|
||||||
|
return new AttachedPartsHandler(context, podSet);
|
||||||
|
}
|
||||||
|
return PlainTextHandler.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
|
||||||
|
super.closeElement(element, attributes, content, warnings);
|
||||||
|
if (RockSimCommonConstants.RADIAL_ANGLE.equals(element)) {
|
||||||
|
podSet.setAngleOffset(Double.parseDouble(content));
|
||||||
|
}
|
||||||
|
if (RockSimCommonConstants.RADIAL_LOC.equals(element)) {
|
||||||
|
podSet.setRadiusOffset(Double.parseDouble(content) / RockSimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PodSet getComponent() {
|
||||||
|
return podSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Material.Type getMaterialType() {
|
||||||
|
return Material.Type.BULK;
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,8 @@ import net.sf.openrocket.aerodynamics.WarningSet;
|
|||||||
import net.sf.openrocket.file.DocumentLoadingContext;
|
import net.sf.openrocket.file.DocumentLoadingContext;
|
||||||
import net.sf.openrocket.file.rocksim.RockSimCommonConstants;
|
import net.sf.openrocket.file.rocksim.RockSimCommonConstants;
|
||||||
import net.sf.openrocket.file.rocksim.RockSimLocationMode;
|
import net.sf.openrocket.file.rocksim.RockSimLocationMode;
|
||||||
|
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
|
||||||
|
import net.sf.openrocket.rocketcomponent.ParallelStage;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||||
|
|
||||||
@ -70,6 +72,10 @@ public abstract class PositionDependentHandler<C extends RocketComponent> extend
|
|||||||
* Set the axialMethod of a component.
|
* Set the axialMethod of a component.
|
||||||
*/
|
*/
|
||||||
protected void setLocation() {
|
protected void setLocation() {
|
||||||
|
if ((getComponent() instanceof ComponentAssembly || getComponent() instanceof ParallelStage) &&
|
||||||
|
getComponent().getParent() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
getComponent().setAxialMethod(axialMethod);
|
getComponent().setAxialMethod(axialMethod);
|
||||||
if (axialMethod.equals(AxialMethod.BOTTOM)) {
|
if (axialMethod.equals(AxialMethod.BOTTOM)) {
|
||||||
getComponent().setAxialOffset(-1d * positionValue);
|
getComponent().setAxialOffset(-1d * positionValue);
|
||||||
|
@ -350,6 +350,9 @@ class StageHandler extends AbstractElementHandler {
|
|||||||
if (RockSimCommonConstants.TRANSITION.equals(element)) {
|
if (RockSimCommonConstants.TRANSITION.equals(element)) {
|
||||||
return new TransitionHandler(context, component, warnings);
|
return new TransitionHandler(context, component, warnings);
|
||||||
}
|
}
|
||||||
|
if (RockSimCommonConstants.SUBASSEMBLY.equals(element)) {
|
||||||
|
return new SubAssemblyHandler(context, component);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,18 +10,21 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class handles Rocksim 'SubAssembly' elements. They are similar to 'AttachedParts' (which is why this class is subclassed from
|
* This class handles RockSim 'SubAssembly' elements. They are similar to 'AttachedParts' (which is why this class is subclassed from
|
||||||
* AttachedPartsHandler) with some key differences. In Rocksim, AttachedParts elements can contain SubAssembly elements, which can in turn
|
* AttachedPartsHandler) with some key differences. In RockSim, AttachedParts elements can contain SubAssembly elements, which can in turn
|
||||||
* contain AttachedParts elements. To represent them in OR, SubAssembly elements are treated as children of the stage - much like a nose cone or
|
* contain AttachedParts elements. To represent them in OR, SubAssembly elements are treated as children of the stage - much like a nose cone or
|
||||||
* external body tube.
|
* external body tube.
|
||||||
*/
|
*/
|
||||||
public class SubAssemblyHandler extends AttachedPartsHandler {
|
public class SubAssemblyHandler extends AttachedPartsHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param c the parent component
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
*/
|
||||||
public SubAssemblyHandler(final DocumentLoadingContext context, final RocketComponent c)
|
public SubAssemblyHandler(final DocumentLoadingContext context, final RocketComponent c)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException {
|
||||||
//A bit of a risk here, but assign the subassembly to the stage, not to the component. This is because typically the
|
super(context, c);
|
||||||
//first component within the subassembly will be an external component.
|
|
||||||
super(context, c.getStage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -33,9 +36,14 @@ public class SubAssemblyHandler extends AttachedPartsHandler {
|
|||||||
if (RockSimCommonConstants.ATTACHED_PARTS.equals(element)) {
|
if (RockSimCommonConstants.ATTACHED_PARTS.equals(element)) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
// The key override of this class - treat body tubes as external body tubes.
|
// The key override of this class - treat body tubes, transitions, and nose cones as external components.
|
||||||
|
// note: this will only work if the parent component is a stage.
|
||||||
else if (RockSimCommonConstants.BODY_TUBE.equals(element)) {
|
else if (RockSimCommonConstants.BODY_TUBE.equals(element)) {
|
||||||
return new BodyTubeHandler(getContext(), getComponent(), warnings);
|
return new BodyTubeHandler(getContext(), getComponent(), warnings);
|
||||||
|
} else if (RockSimCommonConstants.TRANSITION.equals(element)) {
|
||||||
|
return new TransitionHandler(getContext(), getComponent(), warnings);
|
||||||
|
} else if (RockSimCommonConstants.NOSE_CONE.equals(element)) {
|
||||||
|
return new NoseConeHandler(getContext(), getComponent(), warnings);
|
||||||
}
|
}
|
||||||
return super.openElement(element, attributes, warnings);
|
return super.openElement(element, attributes, warnings);
|
||||||
}
|
}
|
||||||
|
@ -121,13 +121,17 @@ public class PodSet extends ComponentAssembly implements RingInstanceable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getAxialOffset() {
|
public double getAxialOffset() {
|
||||||
|
return getAxialOffset(this.axialMethod);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public double getAxialOffset(AxialMethod method) {
|
||||||
double returnValue;
|
double returnValue;
|
||||||
|
|
||||||
if (this.isAfter()){
|
if (this.isAfter()){
|
||||||
// remember the implicit (this instanceof Stage)
|
// remember the implicit (this instanceof Stage)
|
||||||
throw new BugException("found a pod positioned via: AFTER, but is not on the centerline?!: " + this.getName() + " is " + this.getAxialMethod().name() );
|
throw new BugException("found a pod positioned via: AFTER, but is not on the centerline?!: " + this.getName() + " is " + this.getAxialMethod().name() );
|
||||||
} else {
|
} else {
|
||||||
returnValue = super.getAxialOffset(this.axialMethod);
|
returnValue = super.getAxialOffset(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MathUtil.EPSILON > Math.abs(returnValue)) {
|
if (MathUtil.EPSILON > Math.abs(returnValue)) {
|
||||||
|
@ -221,27 +221,18 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
// and thrust < THRUST_TUMBLE_CONDITION threshold
|
// and thrust < THRUST_TUMBLE_CONDITION threshold
|
||||||
|
|
||||||
if (!currentStatus.isTumbling()) {
|
if (!currentStatus.isTumbling()) {
|
||||||
final double t = currentStatus.getFlightData().getLast(FlightDataType.TYPE_THRUST_FORCE);
|
|
||||||
final double cp = currentStatus.getFlightData().getLast(FlightDataType.TYPE_CP_LOCATION);
|
final double cp = currentStatus.getFlightData().getLast(FlightDataType.TYPE_CP_LOCATION);
|
||||||
final double cg = currentStatus.getFlightData().getLast(FlightDataType.TYPE_CG_LOCATION);
|
final double cg = currentStatus.getFlightData().getLast(FlightDataType.TYPE_CG_LOCATION);
|
||||||
final double aoa = currentStatus.getFlightData().getLast(FlightDataType.TYPE_AOA);
|
final double aoa = currentStatus.getFlightData().getLast(FlightDataType.TYPE_AOA);
|
||||||
|
|
||||||
final boolean wantToTumble = (cg > cp && aoa > AOA_TUMBLE_CONDITION);
|
final boolean wantToTumble = (cg > cp && aoa > AOA_TUMBLE_CONDITION);
|
||||||
|
|
||||||
if (wantToTumble) {
|
|
||||||
final boolean tooMuchThrust = t > THRUST_TUMBLE_CONDITION;
|
|
||||||
final boolean isSustainer = currentStatus.getConfiguration().isStageActive(0);
|
final boolean isSustainer = currentStatus.getConfiguration().isStageActive(0);
|
||||||
final boolean isApogee = currentStatus.isApogeeReached();
|
final boolean isApogee = currentStatus.isApogeeReached();
|
||||||
if (tooMuchThrust) {
|
if (wantToTumble && (isApogee || !isSustainer)) {
|
||||||
currentStatus.getWarnings().add(Warning.TUMBLE_UNDER_THRUST);
|
|
||||||
} else if (isApogee || !isSustainer) {
|
|
||||||
addEvent(new FlightEvent(FlightEvent.Type.TUMBLE, currentStatus.getSimulationTime()));
|
addEvent(new FlightEvent(FlightEvent.Type.TUMBLE, currentStatus.getSimulationTime()));
|
||||||
currentStatus.setTumbling(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// If I'm on the ground and have no events in the queue, I'm done
|
// If I'm on the ground and have no events in the queue, I'm done
|
||||||
if (currentStatus.isLanded() && currentStatus.getEventQueue().isEmpty())
|
if (currentStatus.isLanded() && currentStatus.getEventQueue().isEmpty())
|
||||||
addEvent(new FlightEvent(FlightEvent.Type.SIMULATION_END, currentStatus.getSimulationTime()));
|
addEvent(new FlightEvent(FlightEvent.Type.SIMULATION_END, currentStatus.getSimulationTime()));
|
||||||
@ -535,6 +526,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
|
|
||||||
currentStatus.getFlightData().addEvent(event);
|
currentStatus.getFlightData().addEvent(event);
|
||||||
}
|
}
|
||||||
|
log.debug("deployed recovery devices: " + currentStatus.getDeployedRecoveryDevices().size() );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GROUND_HIT:
|
case GROUND_HIT:
|
||||||
@ -556,10 +548,19 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TUMBLE:
|
case TUMBLE:
|
||||||
if (!currentStatus.isLanded()) {
|
// Inhibit if we've deployed a parachute or we're on the ground
|
||||||
|
if ((currentStatus.getDeployedRecoveryDevices().size() > 0) || currentStatus.isLanded())
|
||||||
|
break;
|
||||||
|
|
||||||
currentStepper = tumbleStepper;
|
currentStepper = tumbleStepper;
|
||||||
currentStatus = currentStepper.initialize(currentStatus);
|
currentStatus = currentStepper.initialize(currentStatus);
|
||||||
|
|
||||||
|
final boolean tooMuchThrust = currentStatus.getFlightData().getLast(FlightDataType.TYPE_THRUST_FORCE) > THRUST_TUMBLE_CONDITION;
|
||||||
|
if (tooMuchThrust) {
|
||||||
|
currentStatus.getWarnings().add(Warning.TUMBLE_UNDER_THRUST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentStatus.setTumbling(true);
|
||||||
currentStatus.getFlightData().addEvent(event);
|
currentStatus.getFlightData().addEvent(event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,14 @@ import net.sf.openrocket.rocketcomponent.InnerTube;
|
|||||||
import net.sf.openrocket.rocketcomponent.MassComponent;
|
import net.sf.openrocket.rocketcomponent.MassComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.NoseCone;
|
import net.sf.openrocket.rocketcomponent.NoseCone;
|
||||||
import net.sf.openrocket.rocketcomponent.Parachute;
|
import net.sf.openrocket.rocketcomponent.Parachute;
|
||||||
|
import net.sf.openrocket.rocketcomponent.PodSet;
|
||||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.ShockCord;
|
import net.sf.openrocket.rocketcomponent.ShockCord;
|
||||||
import net.sf.openrocket.rocketcomponent.Streamer;
|
import net.sf.openrocket.rocketcomponent.Streamer;
|
||||||
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
import net.sf.openrocket.rocketcomponent.TubeCoupler;
|
||||||
|
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||||
|
import net.sf.openrocket.rocketcomponent.position.RadiusMethod;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -78,7 +81,7 @@ public class RockSimDocumentDTOTest extends RockSimTestBase {
|
|||||||
@Test
|
@Test
|
||||||
public void testRoundTrip() throws Exception {
|
public void testRoundTrip() throws Exception {
|
||||||
// TODO need checks here to validate that correct things were done
|
// TODO need checks here to validate that correct things were done
|
||||||
OpenRocketDocument ord = RockSimLoaderTest.loadRockSimRocket3(new RockSimLoader());
|
OpenRocketDocument ord = RockSimLoaderTest.loadRockSimRocket(new RockSimLoader(), "rocksimTestRocket3.rkt");
|
||||||
|
|
||||||
Assert.assertNotNull(ord);
|
Assert.assertNotNull(ord);
|
||||||
String result = new RockSimSaver().marshalToRockSim(ord);
|
String result = new RockSimSaver().marshalToRockSim(ord);
|
||||||
@ -94,6 +97,72 @@ public class RockSimDocumentDTOTest extends RockSimTestBase {
|
|||||||
output.delete();
|
output.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests exporting a rocket with pods, and whether importing that same file results in the same pod configuration.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testPodsExport() throws Exception {
|
||||||
|
OpenRocketDocument originalDocument = makePodsRocket();
|
||||||
|
Rocket originalRocket = originalDocument.getRocket();
|
||||||
|
|
||||||
|
// Convert to RockSim XML
|
||||||
|
String result = new RockSimSaver().marshalToRockSim(originalDocument);
|
||||||
|
|
||||||
|
// Write to .rkt file
|
||||||
|
Path output = Files.createTempFile("podsRocket", ".rkt");
|
||||||
|
Files.write(output, result.getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
// Read the file
|
||||||
|
RockSimLoader loader = new RockSimLoader();
|
||||||
|
InputStream stream = new FileInputStream(output.toFile());
|
||||||
|
Assert.assertNotNull("Could not open podsRocket.rkt", stream);
|
||||||
|
OpenRocketDocument importedDocument = OpenRocketDocumentFactory.createEmptyRocket();
|
||||||
|
DocumentLoadingContext context = new DocumentLoadingContext();
|
||||||
|
context.setOpenRocketDocument(importedDocument);
|
||||||
|
context.setMotorFinder(new DatabaseMotorFinder());
|
||||||
|
loader.loadFromStream(context, new BufferedInputStream(stream));
|
||||||
|
Rocket importedRocket = importedDocument.getRocket();
|
||||||
|
|
||||||
|
// Test children counts
|
||||||
|
List<RocketComponent> originalChildren = originalRocket.getAllChildren();
|
||||||
|
List<RocketComponent> importedChildren = importedRocket.getAllChildren();
|
||||||
|
assertEquals(" Number of total children doesn't match",
|
||||||
|
originalChildren.size(), importedChildren.size());
|
||||||
|
assertEquals(" Number of rocket children doesn't match", 1, importedRocket.getChildCount());
|
||||||
|
AxialStage stage = (AxialStage) importedRocket.getChild(0);
|
||||||
|
assertEquals(" Number of stage children doesn't match", 2, stage.getChildCount());
|
||||||
|
BodyTube tube = (BodyTube) stage.getChild(1);
|
||||||
|
assertEquals(" Number of body tube children doesn't match", 3, tube.getChildCount());
|
||||||
|
PodSet pod1 = (PodSet) tube.getChild(0);
|
||||||
|
assertEquals(" Number of pod 1 children doesn't match", 1, pod1.getChildCount());
|
||||||
|
PodSet pod2 = (PodSet) tube.getChild(1);
|
||||||
|
assertEquals(" Number of pod 2 children doesn't match", 2, pod2.getChildCount());
|
||||||
|
PodSet pod3 = (PodSet) tube.getChild(2);
|
||||||
|
assertEquals(" Number of pod 3 children doesn't match", 0, pod3.getChildCount());
|
||||||
|
|
||||||
|
// Test component names
|
||||||
|
for (int i = 1; i < originalChildren.size(); i++) {
|
||||||
|
assertEquals(" Child " + i + " does not match",
|
||||||
|
originalChildren.get(i).getName(), importedChildren.get(i).getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test pod parameters
|
||||||
|
assertEquals(-0.14, pod1.getAxialOffset(), 0.0001);
|
||||||
|
assertEquals(0.065, pod1.getRadiusOffset(), 0.0001);
|
||||||
|
assertEquals(Math.PI, pod1.getAngleOffset(), 0.0001);
|
||||||
|
assertEquals(1, pod1.getInstanceCount());
|
||||||
|
assertEquals(0.02, pod2.getAxialOffset(), 0.0001);
|
||||||
|
assertEquals(0.025, pod2.getRadiusOffset(), 0.0001);
|
||||||
|
assertEquals(- Math.PI / 2, pod2.getAngleOffset(), 0.0001);
|
||||||
|
assertEquals(1, pod2.getInstanceCount());
|
||||||
|
assertEquals(0.23, pod3.getAxialOffset(), 0.0001);
|
||||||
|
assertEquals(0.06, pod3.getRadiusOffset(), 0.0001);
|
||||||
|
assertEquals(Math.PI / 3, pod3.getAngleOffset(), 0.0001);
|
||||||
|
assertEquals(1, pod3.getInstanceCount());
|
||||||
|
|
||||||
|
stream.close();
|
||||||
|
Files.delete(output);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Tests exporting a design where a tube coupler has children, which is not supported by RockSim, so the children
|
* Tests exporting a design where a tube coupler has children, which is not supported by RockSim, so the children
|
||||||
* need to be moved outside the tube coupler.
|
* need to be moved outside the tube coupler.
|
||||||
@ -142,19 +211,91 @@ public class RockSimDocumentDTOTest extends RockSimTestBase {
|
|||||||
Files.delete(output);
|
Files.delete(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OpenRocketDocument makeTubeCouplerRocket() {
|
private OpenRocketDocument makePodsRocket() {
|
||||||
OpenRocketDocument document = OpenRocketDocumentFactory.createNewRocket();
|
OpenRocketDocument document = OpenRocketDocumentFactory.createNewRocket();
|
||||||
Rocket rocket = document.getRocket();
|
Rocket rocket = document.getRocket();
|
||||||
AxialStage stage = rocket.getStage(0);
|
AxialStage stage = rocket.getStage(0);
|
||||||
|
|
||||||
|
// Stage children
|
||||||
NoseCone noseCone = new NoseCone();
|
NoseCone noseCone = new NoseCone();
|
||||||
noseCone.setName("Nose Cone");
|
noseCone.setName("Nose Cone");
|
||||||
stage.addChild(noseCone);
|
stage.addChild(noseCone);
|
||||||
BodyTube tube = new BodyTube();
|
BodyTube tube = new BodyTube();
|
||||||
tube.setName("Body Tube");
|
tube.setName("Body Tube");
|
||||||
stage.addChild(tube);
|
stage.addChild(tube);
|
||||||
|
|
||||||
|
// Body tube children
|
||||||
|
PodSet pod1 = new PodSet();
|
||||||
|
pod1.setName("Pod 1");
|
||||||
|
tube.addChild(pod1);
|
||||||
|
PodSet pod2 = new PodSet();
|
||||||
|
pod2.setName("Pod 2");
|
||||||
|
tube.addChild(pod2);
|
||||||
|
PodSet pod3 = new PodSet();
|
||||||
|
pod2.setName("Pod 3");
|
||||||
|
tube.addChild(pod3);
|
||||||
|
|
||||||
|
// Pod 1 children
|
||||||
|
NoseCone noseCone1 = new NoseCone();
|
||||||
|
noseCone1.setName("Nose Cone 1");
|
||||||
|
pod1.addChild(noseCone1);
|
||||||
|
|
||||||
|
// Pod 2 children
|
||||||
|
NoseCone noseCone2 = new NoseCone();
|
||||||
|
noseCone2.setName("Nose Cone 2");
|
||||||
|
pod2.addChild(noseCone2);
|
||||||
|
BodyTube tube2 = new BodyTube();
|
||||||
|
tube2.setName("Body Tube 2");
|
||||||
|
pod2.addChild(tube2);
|
||||||
|
|
||||||
|
// Set pod parameters
|
||||||
|
pod1.setInstanceCount(1);
|
||||||
|
pod2.setInstanceCount(2);
|
||||||
|
pod3.setInstanceCount(3);
|
||||||
|
|
||||||
|
pod1.setAxialMethod(AxialMethod.ABSOLUTE);
|
||||||
|
pod1.setAxialOffset(0.01);
|
||||||
|
pod2.setAxialMethod(AxialMethod.TOP);
|
||||||
|
pod2.setAxialOffset(0.02);
|
||||||
|
pod3.setAxialMethod(AxialMethod.BOTTOM);
|
||||||
|
pod3.setAxialOffset(0.03);
|
||||||
|
|
||||||
|
pod1.setRadiusMethod(RadiusMethod.RELATIVE);
|
||||||
|
pod1.setRadiusOffset(0.015);
|
||||||
|
pod2.setRadiusMethod(RadiusMethod.FREE);
|
||||||
|
pod2.setRadiusOffset(0.025);
|
||||||
|
pod3.setRadiusMethod(RadiusMethod.RELATIVE);
|
||||||
|
pod3.setRadiusOffset(0.035);
|
||||||
|
|
||||||
|
pod1.setAngleOffset(Math.PI);
|
||||||
|
pod2.setAngleOffset(- Math.PI / 2);
|
||||||
|
pod3.setAngleOffset(Math.PI / 3);
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OpenRocketDocument makeTubeCouplerRocket() {
|
||||||
|
OpenRocketDocument document = OpenRocketDocumentFactory.createNewRocket();
|
||||||
|
Rocket rocket = document.getRocket();
|
||||||
|
AxialStage stage = rocket.getStage(0);
|
||||||
|
|
||||||
|
// Stage children
|
||||||
|
NoseCone noseCone = new NoseCone();
|
||||||
|
noseCone.setName("Nose Cone");
|
||||||
|
stage.addChild(noseCone);
|
||||||
|
BodyTube tube = new BodyTube();
|
||||||
|
tube.setName("Body Tube");
|
||||||
|
stage.addChild(tube);
|
||||||
|
|
||||||
|
// Body tube children
|
||||||
TubeCoupler coupler = new TubeCoupler();
|
TubeCoupler coupler = new TubeCoupler();
|
||||||
coupler.setName("Tube coupler 1");
|
coupler.setName("Tube coupler 1");
|
||||||
tube.addChild(coupler);
|
tube.addChild(coupler);
|
||||||
|
TubeCoupler coupler3 = new TubeCoupler();
|
||||||
|
coupler3.setName("Tube Coupler 3");
|
||||||
|
tube.addChild(coupler3);
|
||||||
|
|
||||||
|
// Tube coupler 1 children
|
||||||
InnerTube innerTube = new InnerTube();
|
InnerTube innerTube = new InnerTube();
|
||||||
innerTube.setName("Inner Tube");
|
innerTube.setName("Inner Tube");
|
||||||
coupler.addChild(innerTube);
|
coupler.addChild(innerTube);
|
||||||
@ -182,9 +323,8 @@ public class RockSimDocumentDTOTest extends RockSimTestBase {
|
|||||||
MassComponent massComponent = new MassComponent();
|
MassComponent massComponent = new MassComponent();
|
||||||
massComponent.setName("Mass Component");
|
massComponent.setName("Mass Component");
|
||||||
coupler.addChild(massComponent);
|
coupler.addChild(massComponent);
|
||||||
TubeCoupler coupler3 = new TubeCoupler();
|
|
||||||
coupler3.setName("Tube Coupler 3");
|
// Tube coupler 3 children
|
||||||
tube.addChild(coupler3);
|
|
||||||
Parachute parachute2 = new Parachute();
|
Parachute parachute2 = new Parachute();
|
||||||
parachute2.setName("Parachute 2");
|
parachute2.setName("Parachute 2");
|
||||||
coupler3.addChild(parachute2);
|
coupler3.addChild(parachute2);
|
||||||
|
@ -0,0 +1,483 @@
|
|||||||
|
<RockSimDocument>
|
||||||
|
<FileVersion>4</FileVersion>
|
||||||
|
<DesignInformation>
|
||||||
|
<RocketDesign>
|
||||||
|
<Name>Body Tube Children Test</Name>
|
||||||
|
<StageCount>1</StageCount>
|
||||||
|
<DisplayFlags>7</DisplayFlags>
|
||||||
|
<ViewType>0</ViewType>
|
||||||
|
<ViewStageCount>3</ViewStageCount>
|
||||||
|
<ViewTypeEdit>0</ViewTypeEdit>
|
||||||
|
<ViewStageCountEdit>3</ViewStageCountEdit>
|
||||||
|
<ZoomFactor>0.0</ZoomFactor>
|
||||||
|
<ZoomFactorEdit>0.0</ZoomFactorEdit>
|
||||||
|
<ScrollPosX>0</ScrollPosX>
|
||||||
|
<ScrollPosY>0</ScrollPosY>
|
||||||
|
<ScrollPosXEdit>0</ScrollPosXEdit>
|
||||||
|
<ScrollPosYEdit>0</ScrollPosYEdit>
|
||||||
|
<ThreeDFlags>0</ThreeDFlags>
|
||||||
|
<ThreeDFlagsEdit>0</ThreeDFlagsEdit>
|
||||||
|
<LastSerialNumber>18</LastSerialNumber>
|
||||||
|
<Stage3Mass>0.0</Stage3Mass>
|
||||||
|
<Stage2Mass>0.0</Stage2Mass>
|
||||||
|
<Stage1Mass>0.0</Stage1Mass>
|
||||||
|
<Stage3CG>426.6301716552979</Stage3CG>
|
||||||
|
<Stage2CGAlone>0.0</Stage2CGAlone>
|
||||||
|
<Stage1CGAlone>0.0</Stage1CGAlone>
|
||||||
|
<Stage321CG>0.0</Stage321CG>
|
||||||
|
<Stage32CG>0.0</Stage32CG>
|
||||||
|
<CPCalcFlags>1</CPCalcFlags>
|
||||||
|
<CPSimFlags>1</CPSimFlags>
|
||||||
|
<UseKnownMass>0</UseKnownMass>
|
||||||
|
<Stage3Parts>
|
||||||
|
<NoseCone>
|
||||||
|
<KnownMass>6.107306539734526</KnownMass>
|
||||||
|
<Density>1049.21</Density>
|
||||||
|
<Material>Polystyrene PS</Material>
|
||||||
|
<Name>Nose cone</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>0.0</Xb>
|
||||||
|
<CalcMass>6.107306539734526</CalcMass>
|
||||||
|
<CalcCG>53.68748632541546</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>76.2</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>1</SerialNo>
|
||||||
|
<ShapeCode>3</ShapeCode>
|
||||||
|
<ConstructionType>1</ConstructionType>
|
||||||
|
<WallThickness>1.00076</WallThickness>
|
||||||
|
<ShapeParameter>0.0</ShapeParameter>
|
||||||
|
<AttachedParts/>
|
||||||
|
<BaseDia>24.8006</BaseDia>
|
||||||
|
<ShoulderLen>19.1008</ShoulderLen>
|
||||||
|
<ShoulderOD>23.5991</ShoulderOD>
|
||||||
|
</NoseCone>
|
||||||
|
<BodyTube>
|
||||||
|
<KnownMass>15.040422946044567</KnownMass>
|
||||||
|
<Density>1121.29</Density>
|
||||||
|
<Material>Paper</Material>
|
||||||
|
<Name>Forward Body tube</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>0.0</Xb>
|
||||||
|
<CalcMass>15.040422946044567</CalcMass>
|
||||||
|
<CalcCG>228.6</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>457.2</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>2</SerialNo>
|
||||||
|
<OD>24.892</OD>
|
||||||
|
<ID>24.13</ID>
|
||||||
|
<IsMotorMount>0</IsMotorMount>
|
||||||
|
<MotorDia>24.13</MotorDia>
|
||||||
|
<EngineOverhang>0.0</EngineOverhang>
|
||||||
|
<IsInsideTube>0</IsInsideTube>
|
||||||
|
<AttachedParts>
|
||||||
|
<Ring>
|
||||||
|
<KnownMass>0.0</KnownMass>
|
||||||
|
<Density>1121.29</Density>
|
||||||
|
<Material>Paper</Material>
|
||||||
|
<Name>Tube coupler</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>120.65</Xb>
|
||||||
|
<CalcMass>0.0</CalcMass>
|
||||||
|
<CalcCG>31.75</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>63.5</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>3</SerialNo>
|
||||||
|
<OD>27.8892</OD>
|
||||||
|
<ID>27.8892</ID>
|
||||||
|
<UsageCode>4</UsageCode>
|
||||||
|
<AutoSize>0</AutoSize>
|
||||||
|
</Ring>
|
||||||
|
<Streamer>
|
||||||
|
<KnownMass>10.038912051168</KnownMass>
|
||||||
|
<Density>0.00664972</Density>
|
||||||
|
<Material>Mylar</Material>
|
||||||
|
<Name>Streamer</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>44.45</Xb>
|
||||||
|
<CalcMass>10.038912051168</CalcMass>
|
||||||
|
<CalcCG>57.15</CalcCG>
|
||||||
|
<DensityType>1</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>114.3</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>4</SerialNo>
|
||||||
|
<Width>114.3</Width>
|
||||||
|
<DragCoefficient>0.138</DragCoefficient>
|
||||||
|
</Streamer>
|
||||||
|
<MassObject>
|
||||||
|
<KnownMass>1.2996672000000002</KnownMass>
|
||||||
|
<Density>0.0</Density>
|
||||||
|
<Material></Material>
|
||||||
|
<Name>Shock Cord</Name>
|
||||||
|
<KnownCG>187.325</KnownCG>
|
||||||
|
<UseKnownCG>1</UseKnownCG>
|
||||||
|
<Xb>187.325</Xb>
|
||||||
|
<CalcMass>0.0</CalcMass>
|
||||||
|
<CalcCG>0.0</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>12.192000000000002</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>5</SerialNo>
|
||||||
|
<TypeCode>0</TypeCode>
|
||||||
|
</MassObject>
|
||||||
|
<MassObject>
|
||||||
|
<KnownMass>2.549</KnownMass>
|
||||||
|
<Density>0.0</Density>
|
||||||
|
<Material></Material>
|
||||||
|
<Name>Mass object - 2.549 g</Name>
|
||||||
|
<KnownCG>282.575</KnownCG>
|
||||||
|
<UseKnownCG>1</UseKnownCG>
|
||||||
|
<Xb>282.575</Xb>
|
||||||
|
<CalcMass>0.0</CalcMass>
|
||||||
|
<CalcCG>0.0</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>0.0</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>6</SerialNo>
|
||||||
|
<TypeCode>0</TypeCode>
|
||||||
|
</MassObject>
|
||||||
|
<Ring>
|
||||||
|
<KnownMass>1.1277286611933457</KnownMass>
|
||||||
|
<Density>1121.29</Density>
|
||||||
|
<Material>Paper</Material>
|
||||||
|
<Name>Centering ring</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>384.175</Xb>
|
||||||
|
<CalcMass>1.1277286611933457</CalcMass>
|
||||||
|
<CalcCG>3.175</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>6.35</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>7</SerialNo>
|
||||||
|
<OD>28.702</OD>
|
||||||
|
<ID>24.9428</ID>
|
||||||
|
<UsageCode>0</UsageCode>
|
||||||
|
<AutoSize>0</AutoSize>
|
||||||
|
</Ring>
|
||||||
|
<Ring>
|
||||||
|
<KnownMass>1.1277286611933457</KnownMass>
|
||||||
|
<Density>1121.29</Density>
|
||||||
|
<Material>Paper</Material>
|
||||||
|
<Name>Centering ring</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>358.775</Xb>
|
||||||
|
<CalcMass>1.1277286611933457</CalcMass>
|
||||||
|
<CalcCG>3.175</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>6.35</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>8</SerialNo>
|
||||||
|
<OD>28.702</OD>
|
||||||
|
<ID>24.9428</ID>
|
||||||
|
<UsageCode>0</UsageCode>
|
||||||
|
<AutoSize>0</AutoSize>
|
||||||
|
</Ring>
|
||||||
|
<Ring>
|
||||||
|
<KnownMass>1.1277286611933457</KnownMass>
|
||||||
|
<Density>1121.29</Density>
|
||||||
|
<Material>Paper</Material>
|
||||||
|
<Name>Centering ring</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>288.925</Xb>
|
||||||
|
<CalcMass>1.1277286611933457</CalcMass>
|
||||||
|
<CalcCG>3.175</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>6.35</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>9</SerialNo>
|
||||||
|
<OD>28.702</OD>
|
||||||
|
<ID>24.9428</ID>
|
||||||
|
<UsageCode>0</UsageCode>
|
||||||
|
<AutoSize>0</AutoSize>
|
||||||
|
</Ring>
|
||||||
|
</AttachedParts>
|
||||||
|
</BodyTube>
|
||||||
|
<BodyTube>
|
||||||
|
<KnownMass>13.498613632777841</KnownMass>
|
||||||
|
<Density>1121.29</Density>
|
||||||
|
<Material>Paper</Material>
|
||||||
|
<Name>Aft Body tube</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>0.0</Xb>
|
||||||
|
<CalcMass>13.498613632777841</CalcMass>
|
||||||
|
<CalcCG>165.1</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>330.2</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>10</SerialNo>
|
||||||
|
<OD>29.8704</OD>
|
||||||
|
<ID>29.083</ID>
|
||||||
|
<IsMotorMount>1</IsMotorMount>
|
||||||
|
<MotorDia>29.083</MotorDia>
|
||||||
|
<EngineOverhang>12.7</EngineOverhang>
|
||||||
|
<IsInsideTube>0</IsInsideTube>
|
||||||
|
<AttachedParts>
|
||||||
|
<Ring>
|
||||||
|
<KnownMass>1.25084668869137</KnownMass>
|
||||||
|
<Density>1121.29</Density>
|
||||||
|
<Material>Paper</Material>
|
||||||
|
<Name>Engine block</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>252.73000000000002</Xb>
|
||||||
|
<CalcMass>1.25084668869137</CalcMass>
|
||||||
|
<CalcCG>3.175</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>6.35</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>11</SerialNo>
|
||||||
|
<OD>29.083</OD>
|
||||||
|
<ID>24.9428</ID>
|
||||||
|
<UsageCode>2</UsageCode>
|
||||||
|
<AutoSize>0</AutoSize>
|
||||||
|
</Ring>
|
||||||
|
<FinSet>
|
||||||
|
<KnownMass>0.9977479979838839</KnownMass>
|
||||||
|
<Density>128.148</Density>
|
||||||
|
<Material>Balsa</Material>
|
||||||
|
<Name>Fin set-1</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>257.175</Xb>
|
||||||
|
<CalcMass>0.9977479979838839</CalcMass>
|
||||||
|
<CalcCG>54.72939060773481</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>0.0</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>12</SerialNo>
|
||||||
|
<FinCount>1</FinCount>
|
||||||
|
<RootChord>66.675</RootChord>
|
||||||
|
<TipChord>29.8704</TipChord>
|
||||||
|
<SemiSpan>50.8</SemiSpan>
|
||||||
|
<SweepDistance>67.4141</SweepDistance>
|
||||||
|
<Thickness>3.175</Thickness>
|
||||||
|
<ShapeCode>0</ShapeCode>
|
||||||
|
<TipShapeCode>0</TipShapeCode>
|
||||||
|
<TabLength>0.0</TabLength>
|
||||||
|
<TabDepth>0.0</TabDepth>
|
||||||
|
<TabOffset>0.0</TabOffset>
|
||||||
|
<SweepMode>1</SweepMode>
|
||||||
|
<CantAngle>0.0</CantAngle>
|
||||||
|
</FinSet>
|
||||||
|
<FinSet>
|
||||||
|
<KnownMass>2.8874580315239995</KnownMass>
|
||||||
|
<Density>128.148</Density>
|
||||||
|
<Material>Balsa</Material>
|
||||||
|
<Name>Fin set</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>146.05</Xb>
|
||||||
|
<CalcMass>2.8874580315239995</CalcMass>
|
||||||
|
<CalcCG>61.383333333333326</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.785398</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>0.0</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>13</SerialNo>
|
||||||
|
<FinCount>4</FinCount>
|
||||||
|
<RootChord>101.6</RootChord>
|
||||||
|
<TipChord>0.0</TipChord>
|
||||||
|
<SemiSpan>34.925</SemiSpan>
|
||||||
|
<SweepDistance>82.55</SweepDistance>
|
||||||
|
<Thickness>3.175</Thickness>
|
||||||
|
<ShapeCode>0</ShapeCode>
|
||||||
|
<TipShapeCode>0</TipShapeCode>
|
||||||
|
<TabLength>0.0</TabLength>
|
||||||
|
<TabDepth>0.0</TabDepth>
|
||||||
|
<TabOffset>0.0</TabOffset>
|
||||||
|
<SweepMode>1</SweepMode>
|
||||||
|
<CantAngle>0.0</CantAngle>
|
||||||
|
</FinSet>
|
||||||
|
<FinSet>
|
||||||
|
<KnownMass>0.9977479979838839</KnownMass>
|
||||||
|
<Density>128.148</Density>
|
||||||
|
<Material>Balsa</Material>
|
||||||
|
<Name>Fin set-2</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>257.175</Xb>
|
||||||
|
<CalcMass>0.9977479979838839</CalcMass>
|
||||||
|
<CalcCG>54.72939060773481</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>1.5708</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>0.0</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>14</SerialNo>
|
||||||
|
<FinCount>1</FinCount>
|
||||||
|
<RootChord>66.675</RootChord>
|
||||||
|
<TipChord>29.8704</TipChord>
|
||||||
|
<SemiSpan>50.8</SemiSpan>
|
||||||
|
<SweepDistance>67.4141</SweepDistance>
|
||||||
|
<Thickness>3.175</Thickness>
|
||||||
|
<ShapeCode>0</ShapeCode>
|
||||||
|
<TipShapeCode>0</TipShapeCode>
|
||||||
|
<TabLength>0.0</TabLength>
|
||||||
|
<TabDepth>0.0</TabDepth>
|
||||||
|
<TabOffset>0.0</TabOffset>
|
||||||
|
<SweepMode>1</SweepMode>
|
||||||
|
<CantAngle>0.0</CantAngle>
|
||||||
|
</FinSet>
|
||||||
|
<FinSet>
|
||||||
|
<KnownMass>0.9977479979838839</KnownMass>
|
||||||
|
<Density>128.148</Density>
|
||||||
|
<Material>Balsa</Material>
|
||||||
|
<Name>Fin set-3</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>257.175</Xb>
|
||||||
|
<CalcMass>0.9977479979838839</CalcMass>
|
||||||
|
<CalcCG>54.72939060773481</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>3.14159</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>0.0</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>15</SerialNo>
|
||||||
|
<FinCount>1</FinCount>
|
||||||
|
<RootChord>66.675</RootChord>
|
||||||
|
<TipChord>29.8704</TipChord>
|
||||||
|
<SemiSpan>50.8</SemiSpan>
|
||||||
|
<SweepDistance>67.4141</SweepDistance>
|
||||||
|
<Thickness>3.175</Thickness>
|
||||||
|
<ShapeCode>0</ShapeCode>
|
||||||
|
<TipShapeCode>0</TipShapeCode>
|
||||||
|
<TabLength>0.0</TabLength>
|
||||||
|
<TabDepth>0.0</TabDepth>
|
||||||
|
<TabOffset>0.0</TabOffset>
|
||||||
|
<SweepMode>1</SweepMode>
|
||||||
|
<CantAngle>0.0</CantAngle>
|
||||||
|
</FinSet>
|
||||||
|
<FinSet>
|
||||||
|
<KnownMass>0.9977479979838839</KnownMass>
|
||||||
|
<Density>128.148</Density>
|
||||||
|
<Material>Balsa</Material>
|
||||||
|
<Name>Fin set-4</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>257.175</Xb>
|
||||||
|
<CalcMass>0.9977479979838839</CalcMass>
|
||||||
|
<CalcCG>54.72939060773481</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>-1.5708</RadialAngle>
|
||||||
|
<LocationMode>0</LocationMode>
|
||||||
|
<Len>0.0</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>16</SerialNo>
|
||||||
|
<FinCount>1</FinCount>
|
||||||
|
<RootChord>66.675</RootChord>
|
||||||
|
<TipChord>29.8704</TipChord>
|
||||||
|
<SemiSpan>50.8</SemiSpan>
|
||||||
|
<SweepDistance>67.4141</SweepDistance>
|
||||||
|
<Thickness>3.175</Thickness>
|
||||||
|
<ShapeCode>0</ShapeCode>
|
||||||
|
<TipShapeCode>0</TipShapeCode>
|
||||||
|
<TabLength>0.0</TabLength>
|
||||||
|
<TabDepth>0.0</TabDepth>
|
||||||
|
<TabOffset>0.0</TabOffset>
|
||||||
|
<SweepMode>1</SweepMode>
|
||||||
|
<CantAngle>0.0</CantAngle>
|
||||||
|
</FinSet>
|
||||||
|
<Ring>
|
||||||
|
<KnownMass>1.1277286611933457</KnownMass>
|
||||||
|
<Density>1121.29</Density>
|
||||||
|
<Material>Paper</Material>
|
||||||
|
<Name>Centering ring</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>323.85</Xb>
|
||||||
|
<CalcMass>1.1277286611933457</CalcMass>
|
||||||
|
<CalcCG>3.175</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>2</LocationMode>
|
||||||
|
<Len>6.35</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>17</SerialNo>
|
||||||
|
<OD>28.702</OD>
|
||||||
|
<ID>24.9428</ID>
|
||||||
|
<UsageCode>0</UsageCode>
|
||||||
|
<AutoSize>0</AutoSize>
|
||||||
|
</Ring>
|
||||||
|
<Ring>
|
||||||
|
<KnownMass>1.1277286611933457</KnownMass>
|
||||||
|
<Density>1121.29</Density>
|
||||||
|
<Material>Paper</Material>
|
||||||
|
<Name>Centering ring</Name>
|
||||||
|
<KnownCG>0.0</KnownCG>
|
||||||
|
<UseKnownCG>0</UseKnownCG>
|
||||||
|
<Xb>282.575</Xb>
|
||||||
|
<CalcMass>1.1277286611933457</CalcMass>
|
||||||
|
<CalcCG>3.175</CalcCG>
|
||||||
|
<DensityType>0</DensityType>
|
||||||
|
<RadialLoc>0.0</RadialLoc>
|
||||||
|
<RadialAngle>0.0</RadialAngle>
|
||||||
|
<LocationMode>2</LocationMode>
|
||||||
|
<Len>6.35</Len>
|
||||||
|
<FinishCode>0</FinishCode>
|
||||||
|
<SerialNo>18</SerialNo>
|
||||||
|
<OD>28.702</OD>
|
||||||
|
<ID>24.9428</ID>
|
||||||
|
<UsageCode>0</UsageCode>
|
||||||
|
<AutoSize>0</AutoSize>
|
||||||
|
</Ring>
|
||||||
|
</AttachedParts>
|
||||||
|
</BodyTube>
|
||||||
|
</Stage3Parts>
|
||||||
|
<Stage2Parts/>
|
||||||
|
<Stage1Parts/>
|
||||||
|
</RocketDesign>
|
||||||
|
</DesignInformation>
|
||||||
|
</RockSimDocument>
|
1277
core/test/net/sf/openrocket/file/rocksim/importt/PodTest.rkt
Normal file
1277
core/test/net/sf/openrocket/file/rocksim/importt/PodTest.rkt
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,11 +7,18 @@ package net.sf.openrocket.file.rocksim.importt;
|
|||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
|
import net.sf.openrocket.rocketcomponent.Bulkhead;
|
||||||
|
import net.sf.openrocket.rocketcomponent.CenteringRing;
|
||||||
import net.sf.openrocket.rocketcomponent.FreeformFinSet;
|
import net.sf.openrocket.rocketcomponent.FreeformFinSet;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InnerTube;
|
||||||
|
import net.sf.openrocket.rocketcomponent.MassComponent;
|
||||||
|
import net.sf.openrocket.rocketcomponent.NoseCone;
|
||||||
|
import net.sf.openrocket.rocketcomponent.Parachute;
|
||||||
|
import net.sf.openrocket.rocketcomponent.PodSet;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.Transition;
|
import net.sf.openrocket.rocketcomponent.Transition;
|
||||||
|
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
@ -57,148 +64,10 @@ public class RockSimLoaderTest extends BaseTestCase {
|
|||||||
Assert.assertTrue(loader.getWarnings().size() == 2);
|
Assert.assertTrue(loader.getWarnings().size() == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method: loadFromStream(InputStream source)
|
|
||||||
*
|
|
||||||
* @throws Exception thrown if something goes awry
|
|
||||||
*/
|
|
||||||
@org.junit.Test
|
|
||||||
public void testLoadFromStream() throws Exception {
|
|
||||||
RockSimLoader loader = new RockSimLoader();
|
|
||||||
//Stupid single stage rocket
|
|
||||||
OpenRocketDocument doc = loadRockSimRocket(loader);
|
|
||||||
InputStream stream;
|
|
||||||
|
|
||||||
Assert.assertNotNull(doc);
|
|
||||||
Rocket rocket = doc.getRocket();
|
|
||||||
Assert.assertNotNull(rocket);
|
|
||||||
Assert.assertEquals("FooBar Test", doc.getRocket().getName());
|
|
||||||
Assert.assertTrue(loader.getWarnings().isEmpty());
|
|
||||||
|
|
||||||
stream = this.getClass().getResourceAsStream("rocksimTestRocket2.rkt");
|
|
||||||
Assert.assertNotNull("Could not open rocksimTestRocket2.rkt", stream);
|
|
||||||
|
|
||||||
doc = OpenRocketDocumentFactory.createEmptyRocket();
|
|
||||||
DocumentLoadingContext context = new DocumentLoadingContext();
|
|
||||||
context.setOpenRocketDocument(doc);
|
|
||||||
context.setMotorFinder(new DatabaseMotorFinder());
|
|
||||||
loader.loadFromStream(context, new BufferedInputStream(stream));
|
|
||||||
|
|
||||||
Assert.assertNotNull(doc);
|
|
||||||
rocket = doc.getRocket();
|
|
||||||
Assert.assertNotNull(rocket);
|
|
||||||
|
|
||||||
//Do some simple asserts; the important thing here is just validating that the mass and cg were
|
|
||||||
//not overridden for each stage.
|
|
||||||
Assert.assertEquals("Three Stage Everything Included Rocket", doc.getRocket().getName());
|
|
||||||
Assert.assertEquals(0, loader.getWarnings().size());
|
|
||||||
Assert.assertEquals(3, rocket.getStageCount());
|
|
||||||
AxialStage stage1 = (AxialStage) rocket.getChild(0);
|
|
||||||
Assert.assertFalse(stage1.isMassOverridden());
|
|
||||||
Assert.assertFalse(stage1.isCGOverridden());
|
|
||||||
AxialStage stage2 = (AxialStage) rocket.getChild(1);
|
|
||||||
Assert.assertFalse(stage2.isMassOverridden());
|
|
||||||
Assert.assertFalse(stage2.isCGOverridden());
|
|
||||||
AxialStage stage3 = (AxialStage) rocket.getChild(2);
|
|
||||||
Assert.assertFalse(stage3.isMassOverridden());
|
|
||||||
Assert.assertFalse(stage3.isCGOverridden());
|
|
||||||
|
|
||||||
stream = this.getClass().getResourceAsStream("rocksimTestRocket3.rkt");
|
|
||||||
Assert.assertNotNull("Could not open rocksimTestRocket3.rkt", stream);
|
|
||||||
|
|
||||||
doc = OpenRocketDocumentFactory.createEmptyRocket();
|
|
||||||
context = new DocumentLoadingContext();
|
|
||||||
context.setOpenRocketDocument(doc);
|
|
||||||
context.setMotorFinder(new DatabaseMotorFinder());
|
|
||||||
loader.loadFromStream(context, new BufferedInputStream(stream));
|
|
||||||
|
|
||||||
Assert.assertNotNull(doc);
|
|
||||||
rocket = doc.getRocket();
|
|
||||||
Assert.assertNotNull(rocket);
|
|
||||||
Assert.assertEquals("Three Stage Everything Included Rocket - Override Total Mass/CG", doc.getRocket().getName());
|
|
||||||
Assert.assertEquals(3, rocket.getStageCount());
|
|
||||||
stage1 = (AxialStage) rocket.getChild(0);
|
|
||||||
stage2 = (AxialStage) rocket.getChild(1);
|
|
||||||
stage3 = (AxialStage) rocket.getChild(2);
|
|
||||||
|
|
||||||
//Do some 1st level and simple asserts; the idea here is to not do a deep validation as that
|
|
||||||
//should have been covered elsewhere. Assert that the stage overrides are correct.
|
|
||||||
Assert.assertEquals(2, stage1.getChildCount());
|
|
||||||
Assert.assertEquals("Nose cone", stage1.getChild(0).getName());
|
|
||||||
Assert.assertEquals("Body tube", stage1.getChild(1).getName());
|
|
||||||
Assert.assertTrue(stage1.isMassOverridden());
|
|
||||||
Assert.assertEquals(0.185d, stage1.getOverrideMass(), 0.001);
|
|
||||||
Assert.assertTrue(stage1.isCGOverridden());
|
|
||||||
Assert.assertEquals(0.3d, stage1.getOverrideCG().x, 0.001);
|
|
||||||
Assert.assertEquals(3, loader.getWarnings().size());
|
|
||||||
|
|
||||||
Assert.assertEquals(1, stage2.getChildCount());
|
|
||||||
Assert.assertEquals("2nd Stage Tube", stage2.getChild(0).getName());
|
|
||||||
Assert.assertTrue(stage2.isMassOverridden());
|
|
||||||
Assert.assertEquals(0.21d, stage2.getOverrideMass(), 0.001);
|
|
||||||
Assert.assertTrue(stage2.isCGOverridden());
|
|
||||||
Assert.assertEquals(0.4d, stage2.getOverrideCG().x, 0.001);
|
|
||||||
|
|
||||||
BodyTube bt = (BodyTube) stage2.getChild(0);
|
|
||||||
LaunchLug ll = (LaunchLug) bt.getChild(6);
|
|
||||||
Assert.assertEquals(1.22d, ll.getAngleOffset(), 0.001);
|
|
||||||
|
|
||||||
Assert.assertEquals(2, stage3.getChildCount());
|
|
||||||
Assert.assertEquals("Transition", stage3.getChild(0).getName());
|
|
||||||
Assert.assertEquals("Body tube", stage3.getChild(1).getName());
|
|
||||||
Assert.assertTrue(stage2.isMassOverridden());
|
|
||||||
Assert.assertEquals(0.33d, stage3.getOverrideMass(), 0.001);
|
|
||||||
Assert.assertTrue(stage2.isCGOverridden());
|
|
||||||
Assert.assertEquals(0.5d, stage3.getOverrideCG().x, 0.001);
|
|
||||||
}
|
|
||||||
|
|
||||||
@org.junit.Test
|
|
||||||
public void testSubAssemblyRocket() throws IOException, RocketLoadException {
|
|
||||||
RockSimLoader loader = new RockSimLoader();
|
|
||||||
//Stupid single stage rocket
|
|
||||||
OpenRocketDocument doc = loadRockSimSubassemblyRocket(loader);
|
|
||||||
InputStream stream;
|
|
||||||
|
|
||||||
Assert.assertNotNull(doc);
|
|
||||||
Rocket rocket = doc.getRocket();
|
|
||||||
Assert.assertNotNull(rocket);
|
|
||||||
Assert.assertEquals("SubAssembly Element Test", doc.getRocket().getName());
|
|
||||||
Assert.assertTrue(loader.getWarnings().isEmpty());
|
|
||||||
|
|
||||||
stream = this.getClass().getResourceAsStream("SubAssemblyTest.rkt");
|
|
||||||
Assert.assertNotNull("Could not open SubAssemblyTest.rkt", stream);
|
|
||||||
|
|
||||||
doc = OpenRocketDocumentFactory.createEmptyRocket();
|
|
||||||
DocumentLoadingContext context = new DocumentLoadingContext();
|
|
||||||
context.setOpenRocketDocument(doc);
|
|
||||||
context.setMotorFinder(new DatabaseMotorFinder());
|
|
||||||
loader.loadFromStream(context, new BufferedInputStream(stream));
|
|
||||||
|
|
||||||
Assert.assertNotNull(doc);
|
|
||||||
rocket = doc.getRocket();
|
|
||||||
Assert.assertNotNull(rocket);
|
|
||||||
Assert.assertEquals(1, rocket.getStageCount());
|
|
||||||
AxialStage stage1 = (AxialStage) rocket.getChild(0);
|
|
||||||
Assert.assertEquals("Nose cone", stage1.getChild(0).getName());
|
|
||||||
Assert.assertEquals("Forward Body tube", stage1.getChild(1).getName());
|
|
||||||
Assert.assertEquals("Aft Body tube", stage1.getChild(2).getName());
|
|
||||||
|
|
||||||
BodyTube subassemblyBodyTube = (BodyTube)stage1.getChild(2);
|
|
||||||
Assert.assertEquals(8, subassemblyBodyTube.getChildCount());
|
|
||||||
Assert.assertEquals("Engine block", subassemblyBodyTube.getChild(0).getName());
|
|
||||||
Assert.assertEquals("Fin set-1", subassemblyBodyTube.getChild(1).getName());
|
|
||||||
Assert.assertEquals("Fin set", subassemblyBodyTube.getChild(2).getName());
|
|
||||||
Assert.assertEquals("Fin set-2", subassemblyBodyTube.getChild(3).getName());
|
|
||||||
Assert.assertEquals("Fin set-3", subassemblyBodyTube.getChild(4).getName());
|
|
||||||
Assert.assertEquals("Fin set-4", subassemblyBodyTube.getChild(5).getName());
|
|
||||||
Assert.assertEquals("Centering ring", subassemblyBodyTube.getChild(6).getName());
|
|
||||||
Assert.assertEquals("Centering ring", subassemblyBodyTube.getChild(7).getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFinsOnTransitions() throws IOException, RocketLoadException {
|
public void testFinsOnTransitions() throws IOException, RocketLoadException {
|
||||||
RockSimLoader loader = new RockSimLoader();
|
RockSimLoader loader = new RockSimLoader();
|
||||||
OpenRocketDocument doc = loadRockSimFinsOnTransitionsRocket(loader);
|
OpenRocketDocument doc = loadRockSimRocket(loader, "FinsOnTransitions.rkt");
|
||||||
|
|
||||||
Assert.assertNotNull(doc);
|
Assert.assertNotNull(doc);
|
||||||
Rocket rocket = doc.getRocket();
|
Rocket rocket = doc.getRocket();
|
||||||
@ -277,57 +146,337 @@ public class RockSimLoaderTest extends BaseTestCase {
|
|||||||
Assert.assertEquals(" Fin set 2 fin tab offset does not match", 0, freeformFinSet2.getTabOffset(), MathUtil.EPSILON);
|
Assert.assertEquals(" Fin set 2 fin tab offset does not match", 0, freeformFinSet2.getTabOffset(), MathUtil.EPSILON);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OpenRocketDocument loadRockSimRocket(RockSimLoader theLoader) throws IOException, RocketLoadException {
|
/**
|
||||||
InputStream stream = RockSimLoaderTest.class.getResourceAsStream("rocksimTestRocket1.rkt");
|
* Method: loadFromStream(InputStream source)
|
||||||
try {
|
*
|
||||||
Assert.assertNotNull("Could not open rocksimTestRocket1.rkt", stream);
|
* @throws Exception thrown if something goes awry
|
||||||
OpenRocketDocument doc = OpenRocketDocumentFactory.createEmptyRocket();
|
*/
|
||||||
|
@org.junit.Test
|
||||||
|
public void testLoadFromStream() throws Exception {
|
||||||
|
RockSimLoader loader = new RockSimLoader();
|
||||||
|
//Stupid single stage rocket
|
||||||
|
OpenRocketDocument doc = loadRockSimRocket(loader, "rocksimTestRocket1.rkt");
|
||||||
|
InputStream stream;
|
||||||
|
|
||||||
|
Assert.assertNotNull(doc);
|
||||||
|
Rocket rocket = doc.getRocket();
|
||||||
|
Assert.assertNotNull(rocket);
|
||||||
|
Assert.assertEquals("FooBar Test", doc.getRocket().getName());
|
||||||
|
Assert.assertTrue(loader.getWarnings().isEmpty());
|
||||||
|
|
||||||
|
stream = this.getClass().getResourceAsStream("rocksimTestRocket2.rkt");
|
||||||
|
Assert.assertNotNull("Could not open rocksimTestRocket2.rkt", stream);
|
||||||
|
|
||||||
|
doc = OpenRocketDocumentFactory.createEmptyRocket();
|
||||||
DocumentLoadingContext context = new DocumentLoadingContext();
|
DocumentLoadingContext context = new DocumentLoadingContext();
|
||||||
context.setOpenRocketDocument(doc);
|
context.setOpenRocketDocument(doc);
|
||||||
context.setMotorFinder(new DatabaseMotorFinder());
|
context.setMotorFinder(new DatabaseMotorFinder());
|
||||||
theLoader.loadFromStream(context, new BufferedInputStream(stream));
|
loader.loadFromStream(context, new BufferedInputStream(stream));
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static OpenRocketDocument loadRockSimRocket3(RockSimLoader theLoader) throws IOException, RocketLoadException {
|
Assert.assertNotNull(doc);
|
||||||
InputStream stream = RockSimLoaderTest.class.getResourceAsStream("rocksimTestRocket3.rkt");
|
rocket = doc.getRocket();
|
||||||
try {
|
Assert.assertNotNull(rocket);
|
||||||
|
|
||||||
|
//Do some simple asserts; the important thing here is just validating that the mass and cg were
|
||||||
|
//not overridden for each stage.
|
||||||
|
Assert.assertEquals("Three Stage Everything Included Rocket", doc.getRocket().getName());
|
||||||
|
Assert.assertEquals(0, loader.getWarnings().size());
|
||||||
|
Assert.assertEquals(3, rocket.getStageCount());
|
||||||
|
AxialStage stage1 = (AxialStage) rocket.getChild(0);
|
||||||
|
Assert.assertFalse(stage1.isMassOverridden());
|
||||||
|
Assert.assertFalse(stage1.isCGOverridden());
|
||||||
|
AxialStage stage2 = (AxialStage) rocket.getChild(1);
|
||||||
|
Assert.assertFalse(stage2.isMassOverridden());
|
||||||
|
Assert.assertFalse(stage2.isCGOverridden());
|
||||||
|
AxialStage stage3 = (AxialStage) rocket.getChild(2);
|
||||||
|
Assert.assertFalse(stage3.isMassOverridden());
|
||||||
|
Assert.assertFalse(stage3.isCGOverridden());
|
||||||
|
|
||||||
|
stream = this.getClass().getResourceAsStream("rocksimTestRocket3.rkt");
|
||||||
Assert.assertNotNull("Could not open rocksimTestRocket3.rkt", stream);
|
Assert.assertNotNull("Could not open rocksimTestRocket3.rkt", stream);
|
||||||
OpenRocketDocument doc = OpenRocketDocumentFactory.createEmptyRocket();
|
|
||||||
|
doc = OpenRocketDocumentFactory.createEmptyRocket();
|
||||||
|
context = new DocumentLoadingContext();
|
||||||
|
context.setOpenRocketDocument(doc);
|
||||||
|
context.setMotorFinder(new DatabaseMotorFinder());
|
||||||
|
loader.loadFromStream(context, new BufferedInputStream(stream));
|
||||||
|
|
||||||
|
Assert.assertNotNull(doc);
|
||||||
|
rocket = doc.getRocket();
|
||||||
|
Assert.assertNotNull(rocket);
|
||||||
|
Assert.assertEquals("Three Stage Everything Included Rocket - Override Total Mass/CG", doc.getRocket().getName());
|
||||||
|
Assert.assertEquals(3, rocket.getStageCount());
|
||||||
|
stage1 = (AxialStage) rocket.getChild(0);
|
||||||
|
stage2 = (AxialStage) rocket.getChild(1);
|
||||||
|
stage3 = (AxialStage) rocket.getChild(2);
|
||||||
|
|
||||||
|
//Do some 1st level and simple asserts; the idea here is to not do a deep validation as that
|
||||||
|
//should have been covered elsewhere. Assert that the stage overrides are correct.
|
||||||
|
Assert.assertEquals(2, stage1.getChildCount());
|
||||||
|
Assert.assertEquals("Nose cone", stage1.getChild(0).getName());
|
||||||
|
Assert.assertEquals("Body tube", stage1.getChild(1).getName());
|
||||||
|
Assert.assertTrue(stage1.isMassOverridden());
|
||||||
|
Assert.assertEquals(0.185d, stage1.getOverrideMass(), 0.001);
|
||||||
|
Assert.assertTrue(stage1.isCGOverridden());
|
||||||
|
Assert.assertEquals(0.3d, stage1.getOverrideCG().x, 0.001);
|
||||||
|
Assert.assertEquals(2, loader.getWarnings().size());
|
||||||
|
|
||||||
|
NoseCone nc = (NoseCone) stage1.getChild(0);
|
||||||
|
Assert.assertEquals(2, nc.getChildCount());
|
||||||
|
Assert.assertEquals("Clay", nc.getChild(0).getName());
|
||||||
|
RocketComponent it = nc.getChild(1);
|
||||||
|
Assert.assertEquals(InnerTube.class, it.getClass());
|
||||||
|
Assert.assertEquals("Attachment Rod", it.getName());
|
||||||
|
|
||||||
|
Assert.assertEquals(3, it.getChildCount());
|
||||||
|
RocketComponent c = it.getChild(0);
|
||||||
|
Assert.assertEquals(CenteringRing.class, c.getClass());
|
||||||
|
Assert.assertEquals("Plate", c.getName());
|
||||||
|
c = it.getChild(1);
|
||||||
|
Assert.assertEquals(CenteringRing.class, c.getClass());
|
||||||
|
Assert.assertEquals("Sleeve ", c.getName());
|
||||||
|
c = it.getChild(2);
|
||||||
|
Assert.assertEquals(Parachute.class, c.getClass());
|
||||||
|
Assert.assertEquals("Nose Cone Parachute", c.getName());
|
||||||
|
|
||||||
|
BodyTube bt1 = (BodyTube) stage1.getChild(1);
|
||||||
|
Assert.assertEquals(5, bt1.getChildCount());
|
||||||
|
Assert.assertEquals("Centering ring", bt1.getChild(0).getName());
|
||||||
|
Assert.assertEquals("Centering ring", bt1.getChild(1).getName());
|
||||||
|
c = bt1.getChild(2);
|
||||||
|
Assert.assertEquals(InnerTube.class, c.getClass());
|
||||||
|
Assert.assertEquals("Body tube", c.getName());
|
||||||
|
Assert.assertEquals("Launch lug", bt1.getChild(3).getName());
|
||||||
|
Assert.assertEquals("Pod", bt1.getChild(4).getName());
|
||||||
|
|
||||||
|
PodSet pod = (PodSet) bt1.getChild(4);
|
||||||
|
Assert.assertEquals(1, pod.getChildCount());
|
||||||
|
c = pod.getChild(0);
|
||||||
|
Assert.assertEquals(BodyTube.class, c.getClass());
|
||||||
|
Assert.assertEquals("Body tube", pod.getChild(0).getName());
|
||||||
|
|
||||||
|
Assert.assertEquals(1, stage2.getChildCount());
|
||||||
|
Assert.assertEquals("2nd Stage Tube", stage2.getChild(0).getName());
|
||||||
|
Assert.assertTrue(stage2.isMassOverridden());
|
||||||
|
Assert.assertEquals(0.21d, stage2.getOverrideMass(), 0.001);
|
||||||
|
Assert.assertTrue(stage2.isCGOverridden());
|
||||||
|
Assert.assertEquals(0.4d, stage2.getOverrideCG().x, 0.001);
|
||||||
|
|
||||||
|
BodyTube bt2 = (BodyTube) stage2.getChild(0);
|
||||||
|
LaunchLug ll = (LaunchLug) bt2.getChild(6);
|
||||||
|
Assert.assertEquals(1.22d, ll.getAngleOffset(), 0.001);
|
||||||
|
|
||||||
|
Assert.assertEquals(2, stage3.getChildCount());
|
||||||
|
Assert.assertEquals("Transition", stage3.getChild(0).getName());
|
||||||
|
Assert.assertEquals("Body tube", stage3.getChild(1).getName());
|
||||||
|
Assert.assertTrue(stage2.isMassOverridden());
|
||||||
|
Assert.assertEquals(0.33d, stage3.getOverrideMass(), 0.001);
|
||||||
|
Assert.assertTrue(stage2.isCGOverridden());
|
||||||
|
Assert.assertEquals(0.5d, stage3.getOverrideCG().x, 0.001);
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.Test
|
||||||
|
public void testBodyTubeChildrenRocket() throws IOException, RocketLoadException {
|
||||||
|
RockSimLoader loader = new RockSimLoader();
|
||||||
|
//Stupid single stage rocket
|
||||||
|
OpenRocketDocument doc = loadRockSimRocket(loader, "BodyTubeChildrenTest.rkt");
|
||||||
|
InputStream stream;
|
||||||
|
|
||||||
|
Assert.assertNotNull(doc);
|
||||||
|
Rocket rocket = doc.getRocket();
|
||||||
|
Assert.assertNotNull(rocket);
|
||||||
|
Assert.assertEquals("Body Tube Children Test", doc.getRocket().getName());
|
||||||
|
Assert.assertTrue(loader.getWarnings().isEmpty());
|
||||||
|
|
||||||
|
stream = this.getClass().getResourceAsStream("BodyTubeChildrenTest.rkt");
|
||||||
|
Assert.assertNotNull("Could not open BodyTubeChildrenTest.rkt", stream);
|
||||||
|
|
||||||
|
doc = OpenRocketDocumentFactory.createEmptyRocket();
|
||||||
DocumentLoadingContext context = new DocumentLoadingContext();
|
DocumentLoadingContext context = new DocumentLoadingContext();
|
||||||
context.setOpenRocketDocument(doc);
|
context.setOpenRocketDocument(doc);
|
||||||
context.setMotorFinder(new DatabaseMotorFinder());
|
context.setMotorFinder(new DatabaseMotorFinder());
|
||||||
theLoader.loadFromStream(context, new BufferedInputStream(stream));
|
loader.loadFromStream(context, new BufferedInputStream(stream));
|
||||||
return doc;
|
|
||||||
}
|
Assert.assertNotNull(doc);
|
||||||
finally {
|
rocket = doc.getRocket();
|
||||||
stream.close();
|
Assert.assertNotNull(rocket);
|
||||||
}
|
Assert.assertEquals(1, rocket.getStageCount());
|
||||||
|
AxialStage stage1 = (AxialStage) rocket.getChild(0);
|
||||||
|
Assert.assertEquals("Nose cone", stage1.getChild(0).getName());
|
||||||
|
Assert.assertEquals("Forward Body tube", stage1.getChild(1).getName());
|
||||||
|
Assert.assertEquals("Aft Body tube", stage1.getChild(2).getName());
|
||||||
|
|
||||||
|
BodyTube subassemblyBodyTube = (BodyTube)stage1.getChild(2);
|
||||||
|
Assert.assertEquals(8, subassemblyBodyTube.getChildCount());
|
||||||
|
Assert.assertEquals("Engine block", subassemblyBodyTube.getChild(0).getName());
|
||||||
|
Assert.assertEquals("Fin set-1", subassemblyBodyTube.getChild(1).getName());
|
||||||
|
Assert.assertEquals("Fin set", subassemblyBodyTube.getChild(2).getName());
|
||||||
|
Assert.assertEquals("Fin set-2", subassemblyBodyTube.getChild(3).getName());
|
||||||
|
Assert.assertEquals("Fin set-3", subassemblyBodyTube.getChild(4).getName());
|
||||||
|
Assert.assertEquals("Fin set-4", subassemblyBodyTube.getChild(5).getName());
|
||||||
|
Assert.assertEquals("Centering ring", subassemblyBodyTube.getChild(6).getName());
|
||||||
|
Assert.assertEquals("Centering ring", subassemblyBodyTube.getChild(7).getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OpenRocketDocument loadRockSimSubassemblyRocket(RockSimLoader theLoader) throws IOException, RocketLoadException {
|
@Test
|
||||||
InputStream stream = RockSimLoaderTest.class.getResourceAsStream("SubAssemblyTest.rkt");
|
public void testSubAssemblyRocket() throws IOException, RocketLoadException {
|
||||||
try {
|
RockSimLoader loader = new RockSimLoader();
|
||||||
|
OpenRocketDocument doc = loadRockSimRocket(loader, "SubAssemblyTest.rkt");
|
||||||
|
|
||||||
|
Assert.assertNotNull(doc);
|
||||||
|
Rocket rocket = doc.getRocket();
|
||||||
|
Assert.assertNotNull(rocket);
|
||||||
|
Assert.assertEquals("SubAssembly Test", doc.getRocket().getName());
|
||||||
|
Assert.assertEquals(2, loader.getWarnings().size()); // can't add BodyTube to NoseCone, and can't add Transition to Transition
|
||||||
|
|
||||||
|
InputStream stream = this.getClass().getResourceAsStream("SubAssemblyTest.rkt");
|
||||||
Assert.assertNotNull("Could not open SubAssemblyTest.rkt", stream);
|
Assert.assertNotNull("Could not open SubAssemblyTest.rkt", stream);
|
||||||
OpenRocketDocument doc = OpenRocketDocumentFactory.createEmptyRocket();
|
|
||||||
|
doc = OpenRocketDocumentFactory.createEmptyRocket();
|
||||||
DocumentLoadingContext context = new DocumentLoadingContext();
|
DocumentLoadingContext context = new DocumentLoadingContext();
|
||||||
context.setOpenRocketDocument(doc);
|
context.setOpenRocketDocument(doc);
|
||||||
context.setMotorFinder(new DatabaseMotorFinder());
|
context.setMotorFinder(new DatabaseMotorFinder());
|
||||||
theLoader.loadFromStream(context, new BufferedInputStream(stream));
|
loader.loadFromStream(context, new BufferedInputStream(stream));
|
||||||
return doc;
|
|
||||||
}
|
Assert.assertNotNull(doc);
|
||||||
finally {
|
rocket = doc.getRocket();
|
||||||
stream.close();
|
Assert.assertNotNull(rocket);
|
||||||
}
|
Assert.assertEquals(1, rocket.getStageCount());
|
||||||
|
AxialStage stage1 = (AxialStage) rocket.getChild(0);
|
||||||
|
|
||||||
|
Assert.assertEquals(5, stage1.getChildCount());
|
||||||
|
NoseCone noseCone1 = (NoseCone) stage1.getChild(0);
|
||||||
|
BodyTube bodyTube2 = (BodyTube) stage1.getChild(1);
|
||||||
|
Transition transition1 = (Transition) stage1.getChild(2);
|
||||||
|
Transition transition3 = (Transition) stage1.getChild(3);
|
||||||
|
BodyTube bodyTube3 = (BodyTube) stage1.getChild(4);
|
||||||
|
Assert.assertEquals("Nose cone 1", noseCone1.getName());
|
||||||
|
Assert.assertEquals("Body tube 2", bodyTube2.getName());
|
||||||
|
Assert.assertEquals("Transition 1", transition1.getName());
|
||||||
|
Assert.assertEquals("Transition 3", transition3.getName());
|
||||||
|
Assert.assertEquals("Body tube 3", bodyTube3.getName());
|
||||||
|
|
||||||
|
Assert.assertEquals(1, noseCone1.getChildCount());
|
||||||
|
Assert.assertEquals("Mass object 1", noseCone1.getChild(0).getName());
|
||||||
|
|
||||||
|
Assert.assertEquals(12, bodyTube2.getChildCount());
|
||||||
|
Assert.assertEquals("Mass object 2", bodyTube2.getChild(0).getName());
|
||||||
|
Assert.assertEquals("Launch lug 1", bodyTube2.getChild(1).getName());
|
||||||
|
Assert.assertEquals("Centering ring 1", bodyTube2.getChild(2).getName());
|
||||||
|
Assert.assertEquals("Tube coupler 1", bodyTube2.getChild(3).getName());
|
||||||
|
Assert.assertEquals("Fin set 1", bodyTube2.getChild(4).getName());
|
||||||
|
Assert.assertEquals("Fin set 2", bodyTube2.getChild(5).getName());
|
||||||
|
Assert.assertEquals("Parachute 1", bodyTube2.getChild(6).getName());
|
||||||
|
Assert.assertEquals("Streamer 1", bodyTube2.getChild(7).getName());
|
||||||
|
Assert.assertEquals("Bulkhead 1", bodyTube2.getChild(8).getName());
|
||||||
|
Assert.assertEquals("Engine block 1", bodyTube2.getChild(9).getName());
|
||||||
|
Assert.assertEquals("Tube fins 1", bodyTube2.getChild(10).getName());
|
||||||
|
Assert.assertEquals("Sleeve 1", bodyTube2.getChild(11).getName());
|
||||||
|
|
||||||
|
Assert.assertEquals(3, transition1.getChildCount());
|
||||||
|
Assert.assertEquals("Mass object 3", transition1.getChild(0).getName());
|
||||||
|
Assert.assertEquals("Fin set 3", transition1.getChild(1).getName());
|
||||||
|
Assert.assertEquals("Fin set 4", transition1.getChild(2).getName());
|
||||||
|
|
||||||
|
Assert.assertEquals(0, transition3.getChildCount());
|
||||||
|
|
||||||
|
Assert.assertEquals(0, bodyTube3.getChildCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OpenRocketDocument loadRockSimFinsOnTransitionsRocket(RockSimLoader theLoader) throws IOException, RocketLoadException {
|
@Test
|
||||||
try (InputStream stream = RockSimLoaderTest.class.getResourceAsStream("FinsOnTransitions.rkt")) {
|
public void testPodRocket() throws IOException, RocketLoadException{
|
||||||
Assert.assertNotNull("Could not open FinsOnTransitions.rkt", stream);
|
RockSimLoader loader = new RockSimLoader();
|
||||||
|
OpenRocketDocument doc = loadRockSimRocket(loader, "PodTest.rkt");
|
||||||
|
|
||||||
|
Assert.assertNotNull(doc);
|
||||||
|
Rocket rocket = doc.getRocket();
|
||||||
|
Assert.assertNotNull(rocket);
|
||||||
|
Assert.assertEquals("Pod Test", doc.getRocket().getName());
|
||||||
|
Assert.assertEquals(3, loader.getWarnings().size());
|
||||||
|
|
||||||
|
InputStream stream = this.getClass().getResourceAsStream("PodTest.rkt");
|
||||||
|
Assert.assertNotNull("Could not open PodTest.rkt", stream);
|
||||||
|
|
||||||
|
doc = OpenRocketDocumentFactory.createEmptyRocket();
|
||||||
|
DocumentLoadingContext context = new DocumentLoadingContext();
|
||||||
|
context.setOpenRocketDocument(doc);
|
||||||
|
context.setMotorFinder(new DatabaseMotorFinder());
|
||||||
|
loader.loadFromStream(context, new BufferedInputStream(stream));
|
||||||
|
|
||||||
|
Assert.assertNotNull(doc);
|
||||||
|
rocket = doc.getRocket();
|
||||||
|
Assert.assertNotNull(rocket);
|
||||||
|
Assert.assertEquals(1, rocket.getStageCount());
|
||||||
|
AxialStage stage1 = (AxialStage) rocket.getChild(0);
|
||||||
|
|
||||||
|
Assert.assertEquals(3, stage1.getChildCount());
|
||||||
|
RocketComponent noseCone1 = stage1.getChild(0);
|
||||||
|
RocketComponent bodyTube1 = stage1.getChild(1);
|
||||||
|
RocketComponent transition1 = stage1.getChild(2);
|
||||||
|
Assert.assertEquals(NoseCone.class, noseCone1.getClass());
|
||||||
|
Assert.assertEquals(BodyTube.class, bodyTube1.getClass());
|
||||||
|
Assert.assertEquals(Transition.class, transition1.getClass());
|
||||||
|
Assert.assertEquals("Nose cone 1", noseCone1.getName());
|
||||||
|
Assert.assertEquals("Body tube 1", bodyTube1.getName());
|
||||||
|
Assert.assertEquals("Transition 1", transition1.getName());
|
||||||
|
|
||||||
|
Assert.assertEquals(1, noseCone1.getChildCount());
|
||||||
|
RocketComponent component = noseCone1.getChild(0);
|
||||||
|
Assert.assertEquals(MassComponent.class, component.getClass());
|
||||||
|
Assert.assertEquals("Mass object 1", component.getName());
|
||||||
|
|
||||||
|
Assert.assertEquals(2, bodyTube1.getChildCount());
|
||||||
|
RocketComponent pod2 = bodyTube1.getChild(0);
|
||||||
|
Assert.assertEquals(PodSet.class, pod2.getClass());
|
||||||
|
Assert.assertEquals("Pod 2", pod2.getName());
|
||||||
|
component = bodyTube1.getChild(1);
|
||||||
|
Assert.assertEquals(Bulkhead.class, component.getClass());
|
||||||
|
Assert.assertEquals("Bulkhead 1", component.getName());
|
||||||
|
|
||||||
|
Assert.assertEquals(3, pod2.getChildCount());
|
||||||
|
RocketComponent noseCone2 = pod2.getChild(0);
|
||||||
|
Assert.assertEquals(NoseCone.class, noseCone2.getClass());
|
||||||
|
Assert.assertEquals("Nose cone 2", noseCone2.getName());
|
||||||
|
RocketComponent bodyTube2 = pod2.getChild(1);
|
||||||
|
Assert.assertEquals(BodyTube.class, bodyTube2.getClass());
|
||||||
|
Assert.assertEquals("Body tube 2", bodyTube2.getName());
|
||||||
|
component = pod2.getChild(2);
|
||||||
|
Assert.assertEquals(Transition.class, component.getClass());
|
||||||
|
Assert.assertEquals("Transition 2", component.getName());
|
||||||
|
|
||||||
|
Assert.assertEquals(1, noseCone2.getChildCount());
|
||||||
|
component = noseCone2.getChild(0);
|
||||||
|
Assert.assertEquals(MassComponent.class, component.getClass());
|
||||||
|
Assert.assertEquals("Mass object 2", component.getName());
|
||||||
|
|
||||||
|
Assert.assertEquals(3, bodyTube2.getChildCount());
|
||||||
|
component = bodyTube2.getChild(0);
|
||||||
|
Assert.assertEquals(TrapezoidFinSet.class, component.getClass());
|
||||||
|
Assert.assertEquals("Fin set 2", component.getName());
|
||||||
|
RocketComponent pod3 = bodyTube2.getChild(1);
|
||||||
|
Assert.assertEquals(PodSet.class, pod3.getClass());
|
||||||
|
Assert.assertEquals("Pod 3", pod3.getName());
|
||||||
|
component = bodyTube2.getChild(2);
|
||||||
|
Assert.assertEquals(LaunchLug.class, component.getClass());
|
||||||
|
Assert.assertEquals("Launch lug 1", component.getName());
|
||||||
|
|
||||||
|
Assert.assertEquals(1, pod3.getChildCount());
|
||||||
|
component = pod3.getChild(0);
|
||||||
|
Assert.assertEquals(BodyTube.class, component.getClass());
|
||||||
|
Assert.assertEquals("Body tube 3", component.getName());
|
||||||
|
Assert.assertEquals(0.04, pod3.getAxialOffset(), MathUtil.EPSILON);
|
||||||
|
Assert.assertEquals(Math.PI / 2, pod3.getAngleOffset(), 0.0001);
|
||||||
|
Assert.assertEquals(0.05, pod3.getRadiusOffset(), MathUtil.EPSILON);
|
||||||
|
|
||||||
|
Assert.assertEquals(1, transition1.getChildCount());
|
||||||
|
component = transition1.getChild(0);
|
||||||
|
Assert.assertEquals(MassComponent.class, component.getClass());
|
||||||
|
Assert.assertEquals("Mass object 3", component.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OpenRocketDocument loadRockSimRocket(RockSimLoader theLoader, String fileName) throws IOException, RocketLoadException {
|
||||||
|
try (InputStream stream = RockSimLoaderTest.class.getResourceAsStream(fileName)) {
|
||||||
|
Assert.assertNotNull("Could not open " + fileName, stream);
|
||||||
OpenRocketDocument doc = OpenRocketDocumentFactory.createEmptyRocket();
|
OpenRocketDocument doc = OpenRocketDocumentFactory.createEmptyRocket();
|
||||||
DocumentLoadingContext context = new DocumentLoadingContext();
|
DocumentLoadingContext context = new DocumentLoadingContext();
|
||||||
context.setOpenRocketDocument(doc);
|
context.setOpenRocketDocument(doc);
|
||||||
@ -336,5 +485,4 @@ public class RockSimLoaderTest extends BaseTestCase {
|
|||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -13,6 +13,7 @@ import javax.swing.SpinnerNumberModel;
|
|||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
|
import net.sf.openrocket.util.MathUtil;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -210,9 +211,16 @@ public class IntegerModel implements StateChangeListener {
|
|||||||
* Sets the value of the variable.
|
* Sets the value of the variable.
|
||||||
*/
|
*/
|
||||||
public void setValue(int v) {
|
public void setValue(int v) {
|
||||||
|
int clampedValue = MathUtil.clamp(v, minValue, maxValue);
|
||||||
|
if (clampedValue != v) {
|
||||||
|
log.debug("Clamped value " + v + " to " + clampedValue + " for " + this);
|
||||||
|
v = clampedValue;
|
||||||
|
}
|
||||||
|
|
||||||
log.debug("Setting value " + v + " for " + this);
|
log.debug("Setting value " + v + " for " + this);
|
||||||
try {
|
try {
|
||||||
setMethod.invoke(source, v);
|
setMethod.invoke(source, v);
|
||||||
|
fireStateChanged();
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
throw new BugException(e);
|
throw new BugException(e);
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
|
@ -17,6 +17,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -218,7 +219,7 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
selectedModifierTable.setDefaultRenderer(Double.class, new DoubleCellRenderer());
|
selectedModifierTable.setDefaultRenderer(Double.class, new DoubleCellRenderer());
|
||||||
selectedModifierTable.setRowSelectionAllowed(true);
|
selectedModifierTable.setRowSelectionAllowed(true);
|
||||||
selectedModifierTable.setColumnSelectionAllowed(false);
|
selectedModifierTable.setColumnSelectionAllowed(false);
|
||||||
selectedModifierTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
selectedModifierTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||||
|
|
||||||
// Make sure spinner editor fits into the cell height
|
// Make sure spinner editor fits into the cell height
|
||||||
selectedModifierTable.setRowHeight(new JSpinner().getPreferredSize().height - 4);
|
selectedModifierTable.setRowHeight(new JSpinner().getPreferredSize().height - 4);
|
||||||
@ -264,9 +265,9 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
addButton = new SelectColorButton(Chars.LEFT_ARROW + " " + trans.get("btn.add") + " ");
|
addButton = new SelectColorButton(Chars.LEFT_ARROW + " " + trans.get("btn.add") + " ");
|
||||||
addButton.setToolTipText(trans.get("btn.add.ttip"));
|
addButton.setToolTipText(trans.get("btn.add.ttip"));
|
||||||
addButton.addActionListener(e -> {
|
addButton.addActionListener(e -> {
|
||||||
SimulationModifier mod = getSelectedAvailableModifier();
|
List<SimulationModifier> mods = getSelectedAvailableModifiers();
|
||||||
if (mod != null) {
|
if (mods.size() > 0) {
|
||||||
addModifier(mod);
|
addModifiers(mods);
|
||||||
clearHistory();
|
clearHistory();
|
||||||
} else {
|
} else {
|
||||||
log.error("Attempting to add simulation modifier when none is selected");
|
log.error("Attempting to add simulation modifier when none is selected");
|
||||||
@ -281,8 +282,8 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
removeButton = new SelectColorButton(" " + trans.get("btn.delete") + " " + Chars.RIGHT_ARROW);
|
removeButton = new SelectColorButton(" " + trans.get("btn.delete") + " " + Chars.RIGHT_ARROW);
|
||||||
removeButton.setToolTipText(trans.get("btn.delete.ttip"));
|
removeButton.setToolTipText(trans.get("btn.delete.ttip"));
|
||||||
removeButton.addActionListener(e -> {
|
removeButton.addActionListener(e -> {
|
||||||
SimulationModifier mod = getSelectedModifier();
|
List<SimulationModifier> mods = getSelectedModifiers();
|
||||||
if (mod == null) {
|
if (mods.size() == 0) {
|
||||||
log.error("Attempting to remove simulation modifier when none is selected");
|
log.error("Attempting to remove simulation modifier when none is selected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -291,7 +292,7 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
selectedModifierTable.getCellEditor().stopCellEditing();
|
selectedModifierTable.getCellEditor().stopCellEditing();
|
||||||
}
|
}
|
||||||
|
|
||||||
removeModifier(mod);
|
removeModifiers(mods);
|
||||||
clearHistory();
|
clearHistory();
|
||||||
});
|
});
|
||||||
disableComponents.add(removeButton);
|
disableComponents.add(removeButton);
|
||||||
@ -328,9 +329,9 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
@Override
|
@Override
|
||||||
public void mousePressed(MouseEvent e) {
|
public void mousePressed(MouseEvent e) {
|
||||||
if (e.getClickCount() == 2) {
|
if (e.getClickCount() == 2) {
|
||||||
SimulationModifier mod = getSelectedAvailableModifier();
|
List<SimulationModifier> mods = getSelectedAvailableModifiers();
|
||||||
if (mod != null) {
|
if (mods.size() == 1) {
|
||||||
addModifier(mod);
|
addModifiers(mods);
|
||||||
clearHistory();
|
clearHistory();
|
||||||
} else {
|
} else {
|
||||||
log.info(Markers.USER_MARKER, "Double-clicked non-available option");
|
log.info(Markers.USER_MARKER, "Double-clicked non-available option");
|
||||||
@ -1027,20 +1028,30 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addModifier(SimulationModifier mod) {
|
private void addModifiers(List<SimulationModifier> mods) {
|
||||||
if (!selectedModifiers.contains(mod)) {
|
if (mods == null || mods.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (SimulationModifier mod : mods) {
|
||||||
|
if (selectedModifiers.contains(mod)) {
|
||||||
|
log.info(Markers.USER_MARKER, "Attempting to add an already existing simulation modifier " + mod);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
log.info(Markers.USER_MARKER, "Adding simulation modifier " + mod);
|
log.info(Markers.USER_MARKER, "Adding simulation modifier " + mod);
|
||||||
selectedModifiers.add(mod);
|
selectedModifiers.add(mod);
|
||||||
|
}
|
||||||
selectedModifierTableModel.fireTableDataChanged();
|
selectedModifierTableModel.fireTableDataChanged();
|
||||||
availableModifierTree.repaint();
|
availableModifierTree.repaint();
|
||||||
} else {
|
|
||||||
log.info(Markers.USER_MARKER, "Attempting to add an already existing simulation modifier " + mod);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeModifier(SimulationModifier mod) {
|
private void removeModifiers(List<SimulationModifier> mods) {
|
||||||
log.info(Markers.USER_MARKER, "Removing simulation modifier " + mod);
|
if (mods == null || mods.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.info(Markers.USER_MARKER, "Removing simulation modifiers " + mods);
|
||||||
|
for (SimulationModifier mod : mods) {
|
||||||
selectedModifiers.remove(mod);
|
selectedModifiers.remove(mod);
|
||||||
|
}
|
||||||
selectedModifierTableModel.fireTableDataChanged();
|
selectedModifierTableModel.fireTableDataChanged();
|
||||||
availableModifierTree.repaint();
|
availableModifierTree.repaint();
|
||||||
}
|
}
|
||||||
@ -1069,8 +1080,8 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "Add" button
|
// "Add" button
|
||||||
SimulationModifier mod = getSelectedAvailableModifier();
|
List<SimulationModifier> mods = getSelectedAvailableModifiers();
|
||||||
state = (mod != null && !selectedModifiers.contains(mod));
|
state = (mods.size() > 0 && !new HashSet<>(selectedModifiers).containsAll(mods));
|
||||||
log.debug("addButton enabled: " + state);
|
log.debug("addButton enabled: " + state);
|
||||||
addButton.setEnabled(state);
|
addButton.setEnabled(state);
|
||||||
|
|
||||||
@ -1122,9 +1133,9 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update description text
|
// Update description text
|
||||||
mod = getSelectedModifier();
|
List<SimulationModifier> selectedMods = getSelectedModifiers();
|
||||||
if (mod != null) {
|
if (selectedMods.size() == 1) {
|
||||||
selectedModifierDescription.setText(mod.getDescription());
|
selectedModifierDescription.setText(selectedMods.get(0).getDescription());
|
||||||
} else {
|
} else {
|
||||||
selectedModifierDescription.setText("");
|
selectedModifierDescription.setText("");
|
||||||
}
|
}
|
||||||
@ -1221,18 +1232,20 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the currently selected available simulation modifier from the modifier tree,
|
* Return the currently selected available simulation modifier from the modifier tree.
|
||||||
* or <code>null</code> if none selected.
|
|
||||||
*/
|
*/
|
||||||
private SimulationModifier getSelectedAvailableModifier() {
|
private List<SimulationModifier> getSelectedAvailableModifiers() {
|
||||||
TreePath treepath = availableModifierTree.getSelectionPath();
|
List<SimulationModifier> result = new ArrayList<>();
|
||||||
if (treepath != null) {
|
TreePath[] treepaths = availableModifierTree.getSelectionPaths();
|
||||||
Object o = ((DefaultMutableTreeNode) treepath.getLastPathComponent()).getUserObject();
|
if (treepaths != null) {
|
||||||
if (o instanceof SimulationModifier) {
|
for (TreePath treepath : treepaths) {
|
||||||
return (SimulationModifier) o;
|
Object obj = ((DefaultMutableTreeNode) treepath.getLastPathComponent()).getUserObject();
|
||||||
|
if (obj instanceof SimulationModifier) {
|
||||||
|
result.add((SimulationModifier) obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1257,17 +1270,17 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the currently selected simulation modifier from the table,
|
* Return the currently selected simulation modifiers from the table.
|
||||||
* or <code>null</code> if none selected.
|
* @return the selected modifier.
|
||||||
* @return the selected modifier or <code>null</code>.
|
|
||||||
*/
|
*/
|
||||||
private SimulationModifier getSelectedModifier() {
|
private List<SimulationModifier> getSelectedModifiers() {
|
||||||
int row = selectedModifierTable.getSelectedRow();
|
List<SimulationModifier> result = new ArrayList<>();
|
||||||
if (row < 0) {
|
int[] rows = selectedModifierTable.getSelectedRows();
|
||||||
return null;
|
for (int row : rows) {
|
||||||
|
int idx = selectedModifierTable.convertRowIndexToModel(row);
|
||||||
|
result.add(selectedModifiers.get(idx));
|
||||||
}
|
}
|
||||||
row = selectedModifierTable.convertRowIndexToModel(row);
|
return result;
|
||||||
return selectedModifiers.get(row);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -321,6 +321,8 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
|||||||
|
|
||||||
gl.glEnable(GL.GL_MULTISAMPLE);
|
gl.glEnable(GL.GL_MULTISAMPLE);
|
||||||
gl.glEnable(GLLightingFunc.GL_LIGHTING);
|
gl.glEnable(GLLightingFunc.GL_LIGHTING);
|
||||||
|
|
||||||
|
updateFigure();
|
||||||
}
|
}
|
||||||
rr.render(drawable, configuration, selection);
|
rr.render(drawable, configuration, selection);
|
||||||
|
|
||||||
|
@ -609,7 +609,11 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
|||||||
List<RocketComponent> selectedComponents = Arrays.stream(selectionModel.getSelectionPaths())
|
List<RocketComponent> selectedComponents = Arrays.stream(selectionModel.getSelectionPaths())
|
||||||
.map(c -> (RocketComponent) c.getLastPathComponent()).collect(Collectors.toList());
|
.map(c -> (RocketComponent) c.getLastPathComponent()).collect(Collectors.toList());
|
||||||
|
|
||||||
if (clicked == null || clicked.length == 0) return;
|
if (clicked == null || clicked.length == 0) {
|
||||||
|
selectionModel.setSelectionPaths(null);
|
||||||
|
ComponentConfigDialog.disposeDialog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check for double-click.
|
// Check for double-click.
|
||||||
// If the shift/meta key is not pressed and the component was not already selected, ignore the double click and treat it as a single click
|
// If the shift/meta key is not pressed and the component was not already selected, ignore the double click and treat it as a single click
|
||||||
|
Loading…
x
Reference in New Issue
Block a user