[Major Refactor] Parallel stages are children of centerline stages

This commit is contained in:
Daniel_M_Williams 2015-07-24 16:44:10 -04:00
parent 2f42594acb
commit 5f42a10c20
14 changed files with 727 additions and 715 deletions

View File

@ -62,26 +62,12 @@ public class StageSaver extends ComponentAssemblySaver {
private Collection<? extends String> addStageReplicationParams(final Stage currentStage) {
List<String> elementsToReturn = new ArrayList<String>();
final String relTo_tag = "relativeto";
final String outside_tag = "outside";
final String instCt_tag = "instancecount";
final String radoffs_tag = "radialoffset";
final String startangle_tag = "angleoffset";
if (null != currentStage) {
// Save position unless "AFTER"
if (currentStage.getRelativePosition() != RocketComponent.Position.AFTER) {
// position type and offset are saved in superclass
// String type = currentStage.getRelativePositionMethod().name().toLowerCase(Locale.ENGLISH);
// double axialOffset = currentStage.getAxialPosition();
// elementsToReturn.add("<position type=\"" + type + "\">" + axialOffset + "</position>");
int relativeTo = currentStage.getRelativeToStage();
elementsToReturn.add("<" + relTo_tag + ">" + relativeTo + "</" + relTo_tag + ">");
}
boolean outsideFlag = currentStage.getOutside();
elementsToReturn.add("<" + outside_tag + ">" + outsideFlag + "</" + outside_tag + ">");
int instanceCount = currentStage.getInstanceCount();
elementsToReturn.add("<" + instCt_tag + ">" + instanceCount + "</" + instCt_tag + ">");
double radialOffset = currentStage.getRadialOffset();

View File

@ -664,6 +664,7 @@ public abstract class FinSet extends ExternalComponent {
finArea = -1;
cantRotation = null;
}
super.componentChanged(e);
}

View File

@ -77,7 +77,6 @@ public class Rocket extends RocketComponent {
flightConfigurationIDs.add(null);
}
// Does the rocket have a perfect finish (a notable amount of laminar flow)
private boolean perfectFinish = false;
@ -93,6 +92,8 @@ public class Rocket extends RocketComponent {
treeModID = modID;
functionalModID = modID;
defaultConfiguration = new Configuration(this);
Stage.resetStageCount();
}

View File

@ -79,12 +79,17 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
/**
* Parent component of the current component, or null if none exists.
*/
private RocketComponent parent = null;
protected RocketComponent parent = null;
/**
* previous child in parent's child list
*/
protected RocketComponent previousComponent = null;
/**
* List of child components of this component.
*/
private ArrayList<RocketComponent> children = new ArrayList<RocketComponent>();
protected ArrayList<RocketComponent> children = new ArrayList<RocketComponent>();
//////// Parameters common to all components:
@ -106,7 +111,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
* Offset of the position of this component relative to the normal position given by
* relativePosition. By default zero, i.e. no position change.
*/
// protected double position = 0;
protected double offset = 0;
/**
* Position of this component relative to it's parent.
@ -298,11 +303,11 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
protected void componentChanged(ComponentChangeEvent e) {
// No-op
checkState();
this.update();
}
/**
* Return the user-provided name of the component, or the component base
* name if the user-provided name is empty. This can be used in the UI.
@ -883,7 +888,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
* @param position the relative positioning.
*/
protected void setRelativePosition(RocketComponent.Position position) {
// this variable does not change the internal representation
// the relativePosition (method) is just the lens through which external code may view this component's position.
this.relativePosition = position;
@ -898,40 +902,41 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
*
* @return double position of the component relative to the parent, with respect to <code>position</code>
*/
public double asPositionValue(Position thePosition, RocketComponent relativeTo) {
double result = this.position.x; // relative
// this should be the usual case.... only 'Stage' classes should call this with anything else....
double relativeAxialPosition = this.position.x;
if (relativeTo != this.parent) {
Coordinate refAbsPos = relativeTo.getAbsolutePositionVector();
Coordinate curAbsPos = this.getAbsolutePositionVector();
relativeAxialPosition = (curAbsPos.x - refAbsPos.x);
public double asPositionValue(Position thePosition) {
if (null == this.parent) {
return 0.0;
}
if (relativeTo != null) {
double relLength = relativeTo.getLength();
double thisCenterX = this.position.x;
double relativeLength = this.parent.length;
double result = Double.NaN;
switch (thePosition) {
case AFTER:
result = relativeAxialPosition + (-relLength - this.getLength()) / 2;
if (null == this.previousComponent) {
result = thisCenterX + (relativeLength - this.getLength()) / 2;
} else {
double relativeAxialOffset = this.previousComponent.getRelativePositionVector().x;
relativeLength = this.previousComponent.getLength();
result = (thisCenterX - relativeAxialOffset) - (relativeLength + this.getLength()) / 2;
}
break;
case ABSOLUTE:
Coordinate curAbsPos = this.getAbsolutePositionVector();
result = curAbsPos.x;
result = this.getAbsolutePositionVector().x;
break;
case TOP:
result = relativeAxialPosition + (relLength - this.getLength()) / 2;
result = thisCenterX + (relativeLength - this.getLength()) / 2;
break;
case MIDDLE:
result = relativeAxialPosition;
result = thisCenterX;
break;
case BOTTOM:
result = relativeAxialPosition + (this.length - relLength) / 2;
result = thisCenterX + (this.length - relativeLength) / 2;
break;
default:
throw new BugException("Unknown position type: " + thePosition);
}
}
return result;
}
@ -948,7 +953,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
public double getAxialOffset() {
mutex.verify();
return this.asPositionValue(this.relativePosition, this.parent);
return this.asPositionValue(this.relativePosition);
}
/**
@ -990,72 +995,88 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
setAxialOffset(value);
}
public void setAxialOffset(double value) {
this.setAxialOffset(this.relativePosition, value, this.getParent());
public void setAxialOffset(double _value) {
this.setAxialOffset(this.relativePosition, _value);
this.fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
protected void setAxialOffset(Position positionMethod, double newOffset, RocketComponent referenceComponent) {
// if this is the root of a hierarchy, constrain the position to zeros.
// if referenceComponent is null, the function call is simply in error
protected void setAfter(RocketComponent referenceComponent) {
checkState();
if ((null == this.parent) || (referenceComponent == null)) {
double newAxialPosition;
double refLength;
if (null == referenceComponent) {
// if this is the first component in the stage, position from the top of the parent
if (null == this.parent) {
// Probably initialization order issue. Ignore a.t.t.
return;
} else {
refLength = this.parent.getLength();
newAxialPosition = (-refLength + this.length) / 2;
}
} else {
refLength = referenceComponent.getLength();
double refRelX = referenceComponent.getRelativePositionVector().x;
newAxialPosition = refRelX + (refLength + this.length) / 2;
}
//this.relativePosition = Position.AFTER;
this.position = new Coordinate(newAxialPosition, this.position.y, this.position.z);
}
protected void setAxialOffset(Position positionMethod, double newOffset) {
// if this is the root of a hierarchy, constrain the position to zero.
if (null == this.parent) {
return;
}
if (referenceComponent == this) {
throw new BugException("cannot move a component relative to itself!");
}
checkState();
// if (this instanceof Stage) {
// System.err.println(String.format(" Setting Stage X offs: type: %s pos: %f <== (%s,%f,%s)", this.relativePosition.name(), this.position.x,
// positionMethod.name(), newOffset, referenceComponent.getName()));
// }
this.relativePosition = positionMethod;
this.offset = newOffset;
double newAxialPosition = Double.NaN;
double refRelX = referenceComponent.position.x;
double refLength = referenceComponent.getLength();
if (referenceComponent.isAncestor(this)) {
referenceComponent = this.parent;
refRelX = 0;
}
double refLength = this.parent.getLength();
switch (positionMethod) {
case ABSOLUTE:
newAxialPosition = newOffset - this.parent.position.x;
break;
case AFTER:
newAxialPosition = refRelX + (refLength + this.length) / 2;
break;
this.setAfter(this.previousComponent);
return;
case TOP:
newAxialPosition = refRelX + (-refLength + this.length) / 2 + newOffset;
newAxialPosition = (-refLength + this.length) / 2 + newOffset;
break;
case MIDDLE:
newAxialPosition = refRelX + newOffset;
newAxialPosition = newOffset;
break;
case BOTTOM:
newAxialPosition = refRelX + (+refLength - this.length) / 2 + newOffset;
newAxialPosition = (+refLength - this.length) / 2 + newOffset;
break;
default:
throw new BugException("Unknown position type: " + positionMethod);
}
if (Double.NaN == newAxialPosition) {
throw new BugException("setAxialOffset is broken -- attempted to update as NaN: " + this.toDebugDetail());
}
this.position = new Coordinate(newAxialPosition, this.position.y, this.position.z);
}
// if ((this instanceof Stage) && (2 == this.getStageNumber())) {
// System.err.println(String.format(" Set Stage X offs: type: %s pos: %f", this.relativePosition.name(), this.position.x));
// }
protected void update() {
if (null == this.parent) {
return;
}
this.setAxialOffset(this.relativePosition, this.offset);
}
public Coordinate getRelativePositionVector() {
return this.position;
}
// disabled
// public void setRelativePositionVector(final Coordinate _newPos) {
// // this.setPosition( this.relativePosition, _newPos );
// }
public Coordinate getAbsolutePositionVector() {
if (null == this.parent) { // i.e. root / Rocket instance OR improperly initialized components
return new Coordinate();
@ -1364,6 +1385,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
throw new IllegalStateException("Component " + component.getComponentName() +
" not currently compatible with component " + getComponentName());
}
children.add(index, component);
component.parent = this;
@ -1556,23 +1578,24 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
*
* @return the stage number this component belongs to.
*/
public final int getStageNumber() {
public int getStageNumber() {
checkState();
if (parent == null) {
throw new IllegalArgumentException("getStageNumber() called for root component");
}
RocketComponent stage = this;
while (!(stage instanceof Stage)) {
stage = stage.parent;
if (stage == null || stage.parent == null) {
RocketComponent curComponent = this;
while (!(curComponent instanceof Stage)) {
curComponent = curComponent.parent;
if (curComponent == null || curComponent.parent == null) {
throw new IllegalStateException("getStageNumber() could not find parent " +
"stage.");
}
}
return stage.parent.getChildPosition(stage);
}
Stage stage = (Stage) curComponent;
return stage.getStageNumber();
}
/**
* Find a component with the given ID. The component tree is searched from this component
@ -2077,16 +2100,46 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
}
}
// Primarily for debug use
public void dumpTree(final boolean includeHeader, final String prefix) {
if (includeHeader) {
System.err.println(" [Name] [Length] [Rel Pos] [Abs Pos] ");
// multi-line output
protected StringBuilder toDebugDetail() {
StringBuilder buf = new StringBuilder();
StackTraceElement[] stackTrace = (new Exception()).getStackTrace();
buf.append(" >> Dumping Detailed Information from: " + stackTrace[1].getMethodName() + "\n");
buf.append(" current Component: " + this.getName() + " ofClass: " + this.getClass().getSimpleName() + "\n");
buf.append(" offset: " + this.offset + " via: " + this.relativePosition.name() + " => " + this.getAxialOffset() + "\n");
buf.append(" thisCenterX: " + this.position.x + "\n");
buf.append(" this length: " + this.length + "\n");
if (null == this.previousComponent) {
buf.append(" ..prevComponent: " + null + "\n");
} else {
RocketComponent refComp = this.previousComponent;
buf.append(" >>prevCompName: " + refComp.getName() + "\n");
buf.append(" ..prevCenterX: " + refComp.position.x + "\n");
buf.append(" ..prevLength: " + refComp.getLength() + "\n");
}
return buf;
}
System.err.println(String.format("%s >> %-24s %5.3f %24s %24s", prefix, this.getName(), this.getLength(), this.getRelativePositionVector(), this.getAbsolutePositionVector()));
// Primarily for debug use
public String toDebugTree() {
StringBuilder buffer = new StringBuilder();
buffer.append("\n ====== ====== ====== ====== ====== ====== ====== ====== ====== ====== ====== ======\n");
buffer.append(" [Name] [Length] [Rel Pos] [Abs Pos] \n");
this.dumpTreeHelper(buffer, "");
return buffer.toString();
}
public void toDebugTreeNode(final StringBuilder buffer, final String prefix) {
buffer.append(String.format("%s %-24s %5.3f %24s %24s\n", prefix, this.getName(), this.getLength(),
this.getRelativePositionVector(), this.getAbsolutePositionVector()));
}
public void dumpTreeHelper(StringBuilder buffer, final String prefix) {
this.toDebugTreeNode(buffer, prefix);
Iterator<RocketComponent> iterator = this.children.iterator();
while (iterator.hasNext()) {
iterator.next().dumpTree(false, prefix + " ");
iterator.next().dumpTreeHelper(buffer, prefix + " ");
}
}
}

View File

@ -17,76 +17,27 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
private FlightConfigurationImpl<StageSeparationConfiguration> separationConfigurations;
private boolean outside = false;
private boolean centerline = true;
private double angularPosition_rad = 0;
private double radialPosition_m = 0;
private Stage stageRelativeTo = null;
private int count = 1;
private double angularSeparation = Math.PI;
private int stageNumber;
private static int stageCount;
public Stage() {
this.separationConfigurations = new FlightConfigurationImpl<StageSeparationConfiguration>(this, ComponentChangeEvent.EVENT_CHANGE, new StageSeparationConfiguration());
this.relativePosition = Position.AFTER;
}
@Override
protected void componentChanged(ComponentChangeEvent e) {
checkState();
if (e.isAerodynamicChange() || e.isMassChange()) {
// System.err.println(">> in (" + this.getStageNumber() + ")" + this.getName());
// update this component
this.updateBounds();
this.updateCenter();
// now update children relative to this
int childIndex = 0;
int childCount = this.getChildCount();
RocketComponent prevComp = null;
while (childIndex < childCount) {
RocketComponent curComp = this.getChild(childIndex);
// System.err.println(" updating position of " + curComp + " via (AFTER, O, " + prevComp + ")");
if (0 == childIndex) {
curComp.setAxialOffset(Position.TOP, 0, this);
} else {
if (Position.AFTER != curComp.getRelativePositionMethod()) {
throw new IllegalStateException(" direct children of a Stage are expected to be positioned via AFTER.");
}
curComp.setAxialOffset(Position.AFTER, 0, prevComp);
}
// System.err.println(" position updated to: " + curComp.getAxialOffset());
prevComp = curComp;
childIndex++;
}
}
stageNumber = Stage.stageCount;
Stage.stageCount++;
}
protected String toPositionString() {
return ">> " + this.getName() + " rel: " + this.getRelativePositionVector().x + " abs: " + this.getAbsolutePositionVector().x;
}
protected void dumpDetail() {
StackTraceElement[] stackTrace = (new Exception()).getStackTrace();
System.err.println(" >> Dumping Stage Detailed Information from: " + stackTrace[1].getMethodName());
System.err.println(" curStageName: " + this.getName());
System.err.println(" method: " + this.relativePosition.name());
System.err.println(" thisCenterX: " + this.position.x);
System.err.println(" this length: " + this.length);
if (-1 == this.getRelativeToStage()) {
System.err.println(" ..refStageName: " + null);
} else {
Stage refStage = this.stageRelativeTo;
System.err.println(" ..refStageName: " + refStage.getName());
System.err.println(" ..refCenterX: " + refStage.position.x);
System.err.println(" ..refLength: " + refStage.getLength());
}
}
@Override
public String getComponentName() {
@ -103,6 +54,30 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
return true;
}
@Override
public void toDebugTreeNode(final StringBuilder buffer, final String prefix) {
String thisLabel = this.getName() + " (" + this.getStageNumber() + ")";
buffer.append(String.format("%s %-24s %5.3f %24s %24s", prefix, thisLabel, this.getLength(),
this.getRelativePositionVector(), this.getAbsolutePositionVector()));
if (this.isCenterline()) {
buffer.append("\n");
} else {
buffer.append(String.format(" %4.1f//%s \n", this.getAxialOffset(), this.relativePosition.name()));
Coordinate componentAbsolutePosition = this.getAbsolutePositionVector();
Coordinate[] instanceCoords = new Coordinate[] { componentAbsolutePosition };
instanceCoords = this.shiftCoordinates(instanceCoords);
for (int instance = 0; instance < this.count; instance++) {
Coordinate instanceAbsolutePosition = instanceCoords[instance];
buffer.append(String.format("%s [instance %2d of %2d] %s\n", prefix, instance, count, instanceAbsolutePosition));
}
}
}
/**
* Check whether the given type can be added to this component. A Stage allows
* only BodyComponents to be added.
@ -113,8 +88,12 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
*/
@Override
public boolean isCompatible(Class<? extends RocketComponent> type) {
if (type.equals(Stage.class)) {
return true;
} else {
return BodyComponent.class.isAssignableFrom(type);
}
}
@Override
public void cloneFlightConfiguration(String oldConfigId, String newConfigId) {
@ -129,35 +108,34 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
return copy;
}
@Override
public boolean getOutside() {
return this.outside;
return !isCenterline();
}
/**
* Detects if this Stage is attached directly to the Rocket (and is thus centerline)
* Or if this stage is a parallel (external) stage.
*
* @return whether this Stage is along the center line of the Rocket.
*/
@Override
public boolean isCenterline() {
return !this.outside;
if (this.parent instanceof Rocket) {
this.centerline = true;
} else {
this.centerline = false;
}
return this.centerline;
}
/**
* Stub.
* The actual value is set via 'isCenterline()'
*/
@Override
public void setOutside(final boolean _outside) {
if (this.outside == _outside) {
return;
}
this.outside = _outside;
if (this.outside) {
this.relativePosition = Position.BOTTOM;
if (null == this.stageRelativeTo) {
this.stageRelativeTo = this.updatePrevAxialStage();
}
} else {
this.relativePosition = Position.AFTER;
this.stageRelativeTo = this.updatePrevAxialStage();
this.count = 1;
}
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
@Override
@ -172,67 +150,81 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
@Override
public void setInstanceCount(final int _count) {
mutex.verify();
if (this.centerline) {
return;
}
this.count = _count;
this.angularSeparation = Math.PI * 2 / this.count;
if (this.outside) {
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
}
@Override
public double getAngularOffset() {
if (this.outside) {
return this.angularPosition_rad;
} else {
if (this.centerline) {
return 0.;
} else {
return this.angularPosition_rad;
}
}
@Override
public void setAngularOffset(final double angle_rad) {
this.angularPosition_rad = angle_rad;
if (this.outside) {
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
if (this.centerline) {
return;
}
this.angularPosition_rad = angle_rad;
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
@Override
public double getRadialOffset() {
if (this.outside) {
return this.radialPosition_m;
} else {
if (this.centerline) {
return 0.;
} else {
return this.radialPosition_m;
}
}
@Override
public void setRadialOffset(final double radius) {
this.radialPosition_m = radius;
// log.error(" set radial position for: " + this.getName() + " to: " + this.radialPosition_m + " ... in meters?");
if (this.outside) {
if (false == this.centerline) {
this.radialPosition_m = radius;
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
}
public void setRelativePositionMethod(final Position _newPosition) {
if (Position.AFTER != _newPosition) {
this.outside = true;
if (null == this.parent) {
throw new NullPointerException(" a Stage requires a parent before any positioning! ");
}
if (this.isCenterline()) {
// Centerline stages must be set via AFTER-- regardless of what was requested:
super.setRelativePosition(Position.AFTER);
} else if (this.parent instanceof Stage) {
if (Position.AFTER == _newPosition) {
log.warn("Stages cannot be relative to other stages via AFTER! Ignoring.");
super.setRelativePosition(Position.TOP);
} else {
super.setRelativePosition(_newPosition);
}
}
}
@Override
public double getPositionValue() {
mutex.verify();
if (null == this.stageRelativeTo) {
return super.asPositionValue(this.relativePosition, this.getParent());
} else {
return getAxialOffset();
}
/*
* @deprecated remove when the file is fixed....
*/
public void setRelativeToStage(final int _relToStage) {
// no-op
}
/**
@ -242,46 +234,43 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
* @return the stage number which this stage is positioned relative to
*/
public int getRelativeToStage() {
if (null == this.stageRelativeTo) {
if (null == this.parent) {
return -1;
} else if (this.parent instanceof Stage) {
return this.parent.parent.getChildPosition(this.parent);
} else if (this.isCenterline()) {
if (0 < this.stageNumber) {
return --this.stageNumber;
}
}
return -1;
}
return this.getRocket().getChildPosition(this.stageRelativeTo);
public static void resetStageCount() {
Stage.stageCount = 0;
}
/*
*
* @param _relTo the stage number which this stage is positioned relative to
*/
public Stage setRelativeToStage(final int _relTo) {
mutex.verify();
if ((_relTo < 0) || (_relTo >= this.getRocket().getStageCount())) {
log.error("attempt to position this stage relative to a non-existent stage number. Ignoring.");
this.stageRelativeTo = null;
} else if (_relTo == this.getRocket().getChildPosition(this)) {
// self-referential: also an error
this.stageRelativeTo = null;
} else if (this.isCenterline()) {
this.relativePosition = Position.AFTER;
updatePrevAxialStage();
} else {
this.stageRelativeTo = (Stage) this.getRocket().getChild(_relTo);
@Override
public int getStageNumber() {
return this.stageNumber;
}
return this.stageRelativeTo;
}
@Override
public double getAxialOffset() {
double returnValue;
if (null == this.stageRelativeTo) {
returnValue = super.asPositionValue(Position.TOP, this.getParent());
} else if (this.isCenterline()) {
returnValue = super.asPositionValue(Position.AFTER, this.stageRelativeTo);
if (this.isCenterline()) {
if (Position.AFTER == this.relativePosition) {
returnValue = super.getAxialOffset();
} else if (Position.TOP == this.relativePosition) {
this.relativePosition = Position.AFTER;
returnValue = super.getAxialOffset();
} else {
returnValue = super.asPositionValue(this.relativePosition, this.stageRelativeTo);
throw new BugException("found a Stage on centerline, but not positioned as AFTER. Please fix this! " + this.getName() + " is " + this.getRelativePosition().name());
}
} else {
returnValue = super.asPositionValue(this.relativePosition);
}
if (0.000001 > Math.abs(returnValue)) {
@ -294,12 +283,10 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
@Override
public void setAxialOffset(final double _pos) {
this.updateBounds();
super.setAxialOffset(this.relativePosition, _pos, this.stageRelativeTo);
super.setAxialOffset(this.relativePosition, _pos);
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// TOOD: unify with 'generate instanceOffsets()'
// what is the use of this again?
@Override
public Coordinate[] shiftCoordinates(Coordinate[] c) {
checkState();
@ -328,56 +315,74 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
return toReturn;
}
@Override
protected StringBuilder toDebugDetail() {
StringBuilder buf = super.toDebugDetail();
// if (-1 == this.getRelativeToStage()) {
// System.err.println(" >>refStageName: " + null + "\n");
// } else {
// Stage refStage = (Stage) this.parent;
// System.err.println(" >>refStageName: " + refStage.getName() + "\n");
// System.err.println(" ..refCenterX: " + refStage.position.x + "\n");
// System.err.println(" ..refLength: " + refStage.getLength() + "\n");
// }
return buf;
}
@Override
public void updateBounds() {
// currently only updates the length
this.length = 0;
Iterator<RocketComponent> childIterator = this.getChildren().iterator();
while (childIterator.hasNext()) {
RocketComponent curChild = childIterator.next();
if (curChild.isCenterline()) {
this.length += curChild.getLength();
}
}
}
/**
* @Warning this will return the previous axial stage REGARDLESS of whether 'this' is in the centerline stack or not.
* @return previous axial stage (defined as above, in the direction of launch)
*/
protected Stage updatePrevAxialStage() {
if (null != this.getParent()) {
Rocket rocket = this.getRocket();
int thisStageNumber = rocket.getChildPosition(this);
int curStageIndex = thisStageNumber - 1;
while (curStageIndex >= 0) {
Stage curStage = (Stage) rocket.getChild(curStageIndex);
if (curStage.isCenterline()) {
this.stageRelativeTo = curStage;
return this.stageRelativeTo;
}
curStageIndex--;
}
}
this.stageRelativeTo = null;
return null;
}
protected void updateCenter() {
if (null == this.stageRelativeTo) {
this.updatePrevAxialStage();
if (null == this.stageRelativeTo) {
// this stage is actually the topmost Stage, instead of just out-of-date
this.setAxialOffset(Position.ABSOLUTE, this.getLength() / 2, this.getRocket());
@Override
protected void update() {
if (null == this.parent) {
return;
}
this.updateBounds();
if (this.parent instanceof Rocket) {
int childNumber = this.parent.getChildPosition(this);
if (0 == childNumber) {
this.setAfter(null);
} else {
RocketComponent prevStage = this.parent.getChild(childNumber - 1);
this.setAfter(prevStage);
}
} else if (this.parent instanceof Stage) {
this.updateBounds();
super.update();
}
// general case:
double offset = super.asPositionValue(this.relativePosition, this.stageRelativeTo);
this.setAxialOffset(this.relativePosition, offset, this.stageRelativeTo);
this.updateChildSequence();
return;
}
protected void updateChildSequence() {
Iterator<RocketComponent> childIterator = this.getChildren().iterator();
RocketComponent prevComp = null;
while (childIterator.hasNext()) {
RocketComponent curChild = childIterator.next();
if (curChild.isCenterline()) {
curChild.previousComponent = prevComp;
prevComp = curChild;
} else {
curChild.previousComponent = null;
}
}
}
}

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.rocketcomponent;
//import junit.framework.TestCase;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import net.sf.openrocket.rocketcomponent.RocketComponent.Position;
import net.sf.openrocket.util.Coordinate;
@ -12,7 +13,7 @@ import org.junit.Test;
public class StageTest extends BaseTestCase {
// tolerance for compared double test results
protected final double EPSILON = 0.001;
protected final double EPSILON = 0.00001;
protected final Coordinate ZERO = new Coordinate(0., 0., 0.);
@ -23,8 +24,8 @@ public class StageTest extends BaseTestCase {
public Rocket createTestRocket() {
double tubeRadius = 1;
// setup
Rocket root = new Rocket();
root.setName("Rocket");
Rocket rocket = new Rocket();
rocket.setName("Rocket");
Stage sustainer = new Stage();
sustainer.setName("Sustainer stage");
@ -34,76 +35,48 @@ public class StageTest extends BaseTestCase {
RocketComponent sustainerBody = new BodyTube(3.0, tubeRadius, 0.01);
sustainerBody.setName("Sustainer Body ");
sustainer.addChild(sustainerBody);
root.addChild(sustainer);
rocket.addChild(sustainer);
Stage core = new Stage();
core.setName("Core stage");
BodyTube coreBody = new BodyTube(6.0, tubeRadius, 0.01);
coreBody.setName("Core Body ");
core.addChild(coreBody);
root.addChild(core);
return root;
rocket.addChild(core);
BodyTube coreUpperBody = new BodyTube(1.8, tubeRadius, 0.01);
coreUpperBody.setName("Core UpBody ");
core.addChild(coreUpperBody);
BodyTube coreLowerBody = new BodyTube(4.2, tubeRadius, 0.01);
coreLowerBody.setName("Core LoBody ");
core.addChild(coreLowerBody);
FinSet coreFins = new TrapezoidFinSet(4, 4, 2, 2, 4);
coreFins.setName("Core Fins");
coreLowerBody.addChild(coreFins);
return rocket;
}
public Stage createBooster() {
double tubeRadius = 0.8;
Stage booster = new Stage();
booster.setName("Booster Stage A");
booster.setName("Booster Stage");
booster.setOutside(true);
RocketComponent boosterNose = new NoseCone(Transition.Shape.CONICAL, 2.0, tubeRadius);
boosterNose.setName("Booster A Nosecone");
boosterNose.setName("Booster Nosecone");
booster.addChild(boosterNose);
RocketComponent boosterBody = new BodyTube(2.0, tubeRadius, 0.01);
boosterBody.setName("Booster A Body ");
boosterBody.setName("Booster Body ");
booster.addChild(boosterBody);
Transition boosterTail = new Transition();
boosterTail.setName("Booster A Tail");
boosterTail.setName("Booster Tail");
boosterTail.setForeRadius(1.0);
boosterTail.setAftRadius(0.5);
boosterTail.setLength(1.0);
booster.addChild(boosterTail);
booster.setInstanceCount(3);
booster.setRadialOffset(1.8);
return booster;
}
// // instantiate a rocket with realistic numbers, matching a file that exhibited errors
// public Rocket createDeltaIIRocket() {
//
// // setup
// Rocket root = new Rocket();
// root.setName("Rocket");
//
// Stage payloadFairing = new Stage();
// root.addChild(payloadFairing);
// payloadFairing.setName("Payload Fairing");
// NoseCone payloadNose = new NoseCone(Transition.Shape.POWER, 0.0535, 0.03);
// payloadNose.setShapeParameter(0.55);
// payloadNose.setName("Payload Nosecone");
// payloadNose.setAftRadius(0.3);
// payloadNose.setThickness(0.001);
// payloadFairing.addChild(payloadNose);
// BodyTube payloadBody = new BodyTube(0.0833, 0.03, 0.001);
// payloadBody.setName("Payload Body ");
// payloadFairing.addChild(payloadBody);
// Transition payloadTransition = new Transition();
// payloadTransition.setName("Payload Aft Transition");
// payloadTransition.setForeRadius(0.03);
// payloadTransition.setAftRadius(0.024);
// payloadTransition.setLength(0.04);
// payloadFairing.addChild(payloadTransition);
//
// Stage core = new Stage();
// core.setName("Delta Core stage");
// BodyTube coreBody = new BodyTube(0.0833, 0.3, 0.001);
// coreBody.setName("Delta Core Body ");
// core.addChild(coreBody);
// root.addChild(core);
//
// return root;
// }
/* From OpenRocket Technical Documentation
*
* 3.1.4 Coordinate systems
@ -116,41 +89,45 @@ public class StageTest extends BaseTestCase {
@Test
public void testSetRocketPositionFail() {
RocketComponent root = createTestRocket();
RocketComponent rocket = createTestRocket();
Coordinate expectedPosition;
Coordinate targetPosition;
Coordinate resultPosition;
// case 1: the Root Rocket should be stationary
// case 1: the rocket Rocket should be stationary
expectedPosition = ZERO;
targetPosition = new Coordinate(+4.0, 0.0, 0.0);
root.setAxialOffset(targetPosition.x);
resultPosition = root.getRelativePositionVector();
assertThat(" Moved the rocket root itself-- this should not be enabled.", expectedPosition.x, equalTo(resultPosition.x));
rocket.setAxialOffset(targetPosition.x);
resultPosition = rocket.getRelativePositionVector();
assertThat(" Moved the rocket rocket itself-- this should not be enabled.", expectedPosition.x, equalTo(resultPosition.x));
}
@Test
public void testAddTopStage() {
RocketComponent root = createTestRocket();
public void testAddSustainerStage() {
RocketComponent rocket = createTestRocket();
// Sustainer Stage
Stage sustainer = (Stage) root.getChild(0);
Stage sustainer = (Stage) rocket.getChild(0);
RocketComponent sustainerNose = sustainer.getChild(0);
RocketComponent sustainerBody = sustainer.getChild(1);
assertThat(" createTestRocket failed: is sustainer stage an ancestor of the sustainer stage? ", sustainer.isAncestor(sustainer), equalTo(false));
assertThat(" createTestRocket failed: is sustainer stage an ancestor of the sustainer nose? ", sustainer.isAncestor(sustainerNose), equalTo(true));
assertThat(" createTestRocket failed: is the root rocket an ancestor of the sustainer Nose? ", root.isAncestor(sustainerNose), equalTo(true));
assertThat(" createTestRocket failed: is the rocket rocket an ancestor of the sustainer Nose? ", rocket.isAncestor(sustainerNose), equalTo(true));
assertThat(" createTestRocket failed: is sustainer Body an ancestor of the sustainer Nose? ", sustainerBody.isAncestor(sustainerNose), equalTo(false));
int relToExpected = -1;
int relToStage = sustainer.getRelativeToStage();
assertThat(" createTestRocket failed: sustainer relative position: ", relToStage, equalTo(relToExpected));
double expectedSustainerLength = 5.0;
assertThat(" createTestRocket failed: Sustainer size: ", sustainer.getLength(), equalTo(expectedSustainerLength));
double expectedSustainerX = +2.5;
double sustainerX;
sustainerX = sustainer.getRelativePositionVector().x;
assertThat(" createTestRocket failed: Relative position: ", sustainerX, equalTo(expectedSustainerX));
assertThat(" createTestRocket failed: sustainer Relative position: ", sustainerX, equalTo(expectedSustainerX));
sustainerX = sustainer.getRelativePositionVector().x;
assertThat(" createTestRocket failed: Absolute position: ", sustainerX, equalTo(expectedSustainerX));
assertThat(" createTestRocket failed: sustainer Absolute position: ", sustainerX, equalTo(expectedSustainerX));
double expectedSustainerNoseX = -1.5;
double sustainerNosePosition = sustainerNose.getRelativePositionVector().x;
@ -170,44 +147,67 @@ public class StageTest extends BaseTestCase {
// WARNING: this test will not pass unless 'testAddTopStage' is passing as well -- that function tests the dependencies...
@Test
public void testAddMiddleStage() {
RocketComponent root = createTestRocket();
public void testAddCoreStage() {
// vvvv function under test vvvv ( which indirectly tests initialization code, and that the test setup creates the preconditions that we expect
RocketComponent rocket = createTestRocket();
// ^^^^ function under test ^^^^
// Core Stage
Stage core = (Stage) root.getChild(1);
Stage core = (Stage) rocket.getChild(1);
double expectedCoreLength = 6.0;
assertThat(" createTestRocket failed: Core size: ", core.getLength(), equalTo(expectedCoreLength));
double expectedCoreX = +8.0;
double coreX;
core.setRelativePosition(Position.AFTER);
int relToExpected = 0;
int relToStage = core.getRelativeToStage();
assertThat(" createTestRocket failed: corerelative position: ", relToStage, equalTo(relToExpected));
coreX = core.getRelativePositionVector().x;
assertThat(" createTestRocket failed: Relative position: ", coreX, equalTo(expectedCoreX));
assertThat(" createTestRocket failed: core Relative position: ", coreX, equalTo(expectedCoreX));
coreX = core.getAbsolutePositionVector().x;
assertThat(" createTestRocket failed: Absolute position: ", coreX, equalTo(expectedCoreX));
assertThat(" createTestRocket failed: core Absolute position: ", coreX, equalTo(expectedCoreX));
RocketComponent coreBody = core.getChild(0);
double expectedCoreBodyX = 0.0;
double coreBodyX = coreBody.getRelativePositionVector().x;
assertThat(" createTestRocket failed: core body rel X: ", coreBodyX, equalTo(expectedCoreBodyX));
expectedCoreBodyX = expectedCoreX;
coreBodyX = coreBody.getAbsolutePositionVector().x;
assertThat(" createTestRocket failed: core body abs X: ", coreBodyX, equalTo(expectedCoreBodyX));
RocketComponent coreUpBody = core.getChild(0);
double expectedX = -2.1;
double resultantX = coreUpBody.getRelativePositionVector().x;
assertThat(" createTestRocket failed: core body rel X: ", resultantX, equalTo(expectedX));
expectedX = 5.9;
resultantX = coreUpBody.getAbsolutePositionVector().x;
assertThat(" createTestRocket failed: core body abs X: ", resultantX, equalTo(expectedX));
RocketComponent coreLoBody = core.getChild(1);
expectedX = 0.9;
resultantX = coreLoBody.getRelativePositionVector().x;
assertEquals(" createTestRocket failed: core body rel X: ", expectedX, resultantX, EPSILON);
expectedX = 8.9;
resultantX = coreLoBody.getAbsolutePositionVector().x;
assertEquals(" createTestRocket failed: core body abs X: ", expectedX, resultantX, EPSILON);
RocketComponent coreFins = coreLoBody.getChild(0);
expectedX = 0.1;
resultantX = coreFins.getRelativePositionVector().x;
assertEquals(" createTestRocket failed: core Fins rel X: ", expectedX, resultantX, EPSILON);
expectedX = 9.0;
resultantX = coreFins.getAbsolutePositionVector().x;
assertEquals(" createTestRocket failed: core Fins abs X: ", expectedX, resultantX, EPSILON);
}
@Test
public void testSetStagePosition_topOfStack() {
// setup
RocketComponent root = createTestRocket();
Stage sustainer = (Stage) root.getChild(0);
RocketComponent rocket = createTestRocket();
Stage sustainer = (Stage) rocket.getChild(0);
Coordinate expectedPosition = new Coordinate(+2.5, 0., 0.); // i.e. half the tube length
Coordinate targetPosition = new Coordinate(+4.0, 0., 0.);
// without making the rocket 'external' and the Stage should be restricted to AFTER positioning.
sustainer.setOutside(false);
sustainer.setRelativePositionMethod(Position.ABSOLUTE);
assertThat("Setting a stage's position method to anything other than AFTER flags it off-center", sustainer.getOutside(), equalTo(true));
assertThat("Setting a centerline stage to anything other than AFTER is ignored.", sustainer.getOutside(), equalTo(false));
assertThat("Setting a centerline stage to anything other than AFTER is ignored.", sustainer.getRelativePosition(), equalTo(Position.AFTER));
// vv function under test
sustainer.setAxialOffset(targetPosition.x);
@ -215,69 +215,89 @@ public class StageTest extends BaseTestCase {
Coordinate resultantRelativePosition = sustainer.getRelativePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantRelativePosition.x, equalTo(expectedPosition.x));
// for all stages, the absolute position should equal the relative, because the direct parent is the root component (i.e. the Rocket)
// for all stages, the absolute position should equal the relative, because the direct parent is the rocket component (i.e. the Rocket)
Coordinate resultantAbsolutePosition = sustainer.getAbsolutePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedPosition.x));
}
@Test
public void testFindPrevAxialStage() {
RocketComponent root = createTestRocket();
Stage core = (Stage) root.getChild(1);
Stage booster = createBooster();
root.addChild(booster);
public void testBoosterInitialization() {
// setup
RocketComponent rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage boosterSet = createBooster();
core.addChild(boosterSet);
Stage booster2 = new Stage();
booster2.setOutside(true);
booster2.setName("Booster Set 2");
RocketComponent booster2Body = new BodyTube(2.0, 1.0, 0.01);
booster2Body.setName("Booster Body 2");
booster2.addChild(booster2Body);
root.addChild(booster2);
double targetOffset = 0;
boosterSet.setAxialOffset(Position.BOTTOM, targetOffset);
// vv function under test
boosterSet.setInstanceCount(2);
boosterSet.setRadialOffset(4.0);
boosterSet.setAngularOffset(Math.PI / 2);
// ^^ function under test
String treeDump = rocket.toDebugTree();
Stage booster3 = new Stage();
booster3.setOutside(true);
booster3.setName("Booster Set 3");
RocketComponent booster3Body = new BodyTube(4.0, 1.0, 0.01);
booster3Body.setName("Booster Body 3");
booster3.addChild(booster3Body);
root.addChild(booster3);
int expectedInstanceCount = 2;
int instanceCount = boosterSet.getInstanceCount();
assertThat(" 'setInstancecount(int)' failed: ", instanceCount, equalTo(expectedInstanceCount));
Stage tail = new Stage();
tail.setName("Tail");
RocketComponent tailBody = new BodyTube(4.0, 1.0, 0.01);
tailBody.setName("TailBody");
root.addChild(tail);
tail.addChild(tailBody);
double expectedAbsX = 8.5;
Coordinate resultantCenter = boosterSet.getAbsolutePositionVector();
assertEquals(treeDump + "\n>>'setAxialOffset()' failed: ", expectedAbsX, resultantCenter.x, EPSILON);
Stage prevAxialStage;
prevAxialStage = booster3.updatePrevAxialStage();
assertThat(" 'setAxialPosition(double)' failed. Absolute position: ", prevAxialStage, equalTo(core));
prevAxialStage = tail.updatePrevAxialStage();
assertThat(" 'setAxialPosition(double)' failed. Absolute position: ", prevAxialStage, equalTo(core));
double expectedRadialOffset = 4.0;
double radialOffset = boosterSet.getRadialOffset();
assertEquals(" 'setRadialOffset(double)' failed. offset: ", expectedRadialOffset, radialOffset, EPSILON);
double expectedAngularOffset = Math.PI / 2;
double angularOffset = boosterSet.getAngularOffset();
assertEquals(" 'setAngularOffset(double)' failed. offset: ", expectedAngularOffset, angularOffset, EPSILON);
}
// because even though this is an "outside" stage, it's relative to itself -- i.e. an error.
// also an error with a well-defined failure result (i.e. just failover to AFTER placement as the first stage of a rocket.
@Test
public void testSetStagePosition_inStack() {
public void testBoosterInstanceLocation_BOTTOM() {
// setup
RocketComponent root = createTestRocket();
Stage sustainer = (Stage) root.getChild(0);
Stage core = (Stage) root.getChild(1);
Coordinate expectedSustainerPosition = new Coordinate(+2.5, 0., 0.); // i.e. half the tube length
Coordinate expectedCorePosition = new Coordinate(+8.0, 0., 0.);
Coordinate targetPosition = new Coordinate(+17.0, 0., 0.);
RocketComponent rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage boosterSet = createBooster();
core.addChild(boosterSet);
sustainer.setAxialOffset(targetPosition.x);
Coordinate sustainerPosition = sustainer.getRelativePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", sustainerPosition.x, equalTo(expectedSustainerPosition.x));
double targetOffset = 0;
boosterSet.setAxialOffset(Position.BOTTOM, targetOffset);
int targetInstanceCount = 3;
double targetRadialOffset = 1.8;
// vv function under test
boosterSet.setInstanceCount(targetInstanceCount);
boosterSet.setRadialOffset(targetRadialOffset);
// ^^ function under test
String treeDump = rocket.toDebugTree();
core.setAxialOffset(targetPosition.x);
Coordinate resultantCorePosition = core.getRelativePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Absolute position: ", resultantCorePosition.x, equalTo(expectedCorePosition.x));
double expectedX = 8.5;
double angle = Math.PI * 2 / targetInstanceCount;
double radius = targetRadialOffset;
Coordinate componentAbsolutePosition = boosterSet.getAbsolutePositionVector();
Coordinate[] instanceCoords = new Coordinate[] { componentAbsolutePosition };
instanceCoords = boosterSet.shiftCoordinates(instanceCoords);
int inst = 0;
Coordinate expectedPosition0 = new Coordinate(expectedX, radius * Math.cos(angle * inst), radius * Math.sin(angle * inst));
Coordinate resultantPosition0 = instanceCoords[0];
assertEquals(treeDump + "\n>> Failed to generate Parallel Stage instances correctly: ", expectedPosition0, resultantPosition0);
inst = 1;
Coordinate expectedPosition1 = new Coordinate(expectedX, radius * Math.cos(angle * inst), radius * Math.sin(angle * inst));
Coordinate resultantPosition1 = instanceCoords[1];
assertEquals(treeDump + "\n>> Failed to generate Parallel Stage instances correctly: ", expectedPosition1, resultantPosition1);
inst = 2;
Coordinate expectedPosition2 = new Coordinate(expectedX, radius * Math.cos(angle * inst), radius * Math.sin(angle * inst));
Coordinate resultantPosition2 = instanceCoords[2];
assertEquals(treeDump + "\n>> Failed to generate Parallel Stage instances correctly: ", expectedPosition2, resultantPosition2);
}
@ -286,31 +306,28 @@ public class StageTest extends BaseTestCase {
@Test
public void testSetStagePosition_outsideABSOLUTE() {
// setup
RocketComponent root = createTestRocket();
Stage core = (Stage) root.getChild(1);
RocketComponent rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage booster = createBooster();
root.addChild(booster);
core.addChild(booster);
Coordinate targetPosition = new Coordinate(+17.0, 0., 0.);
double expectedX = targetPosition.x;
double targetX = +17.0;
double expectedX = targetX - core.getAbsolutePositionVector().x;
// when 'external' the stage should be freely movable
booster.setOutside(true);
booster.setRelativePositionMethod(Position.ABSOLUTE);
booster.setRelativeToStage(1);
// when subStages should be freely movable
// vv function under test
booster.setAxialOffset(targetPosition.x);
booster.setAxialOffset(Position.ABSOLUTE, targetX);
// ^^ function under test
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantRelativePosition.x, equalTo(expectedX));
double resultantPositionValue = booster.getPositionValue();
assertThat(" 'setAxialPosition(double)' failed. PositionValue: ", resultantPositionValue, equalTo(expectedX));
assertThat(" 'setAxialPosition(double)' failed. PositionValue: ", resultantPositionValue, equalTo(targetX));
double resultantAxialPosition = booster.getAxialOffset();
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantAxialPosition, equalTo(expectedX));
// for all stages, the absolute position should equal the relative, because the direct parent is the root component (i.e. the Rocket)
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantAxialPosition, equalTo(targetX));
// for all stages, the absolute position should equal the relative, because the direct parent is the rocket component (i.e. the Rocket)
Coordinate resultantAbsolutePosition = booster.getAbsolutePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedX));
assertThat(" 'setAxialPosition(double)' failed. Absolute position: ", resultantAbsolutePosition.x, equalTo(targetX));
}
// WARNING:
@ -319,17 +336,17 @@ public class StageTest extends BaseTestCase {
@Test
public void testSetStagePosition_outsideTopOfStack() {
// setup
RocketComponent root = createTestRocket();
Stage sustainer = (Stage) root.getChild(0);
RocketComponent rocket = createTestRocket();
Stage sustainer = (Stage) rocket.getChild(0);
Coordinate expectedPosition = new Coordinate(+2.5, 0., 0.);
Coordinate targetPosition = new Coordinate(+4.0, 0., 0.);
// when 'external' the stage should be freely movable
sustainer.setOutside(true);
sustainer.setRelativePositionMethod(Position.TOP);
sustainer.setRelativeToStage(0);
int expectedRelativeIndex = -1;
assertThat(" 'setRelativeToStage(int)' failed. Relative stage index:", sustainer.getRelativeToStage(), equalTo(expectedRelativeIndex));
int resultantRelativeIndex = sustainer.getRelativeToStage();
assertThat(" 'setRelativeToStage(int)' failed. Relative stage index:", expectedRelativeIndex, equalTo(resultantRelativeIndex));
// vv function under test
sustainer.setAxialOffset(targetPosition.x);
@ -344,31 +361,31 @@ public class StageTest extends BaseTestCase {
double expectedAxialPosition = 0;
double resultantAxialPosition = sustainer.getAxialOffset();
assertThat(" 'getAxialPosition()' failed. Relative position: ", resultantAxialPosition, equalTo(expectedAxialPosition));
// for all stages, the absolute position should equal the relative, because the direct parent is the root component (i.e. the Rocket)
// for all stages, the absolute position should equal the relative, because the direct parent is the rocket component (i.e. the Rocket)
Coordinate resultantAbsolutePosition = sustainer.getAbsolutePositionVector();
assertThat(" 'setAbsolutePositionVector()' failed. Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedPosition.x));
}
@Test
public void testSetStagePosition_outsideTOP() {
Rocket root = this.createTestRocket();
Rocket rocket = this.createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage booster = createBooster();
root.addChild(booster);
core.addChild(booster);
booster.setOutside(true);
booster.setRelativePositionMethod(Position.TOP);
booster.setRelativeToStage(1);
// vv function under test
double targetOffset = +2.0;
booster.setAxialOffset(targetOffset);
// vv function under test
booster.setAxialOffset(Position.TOP, targetOffset);
// ^^ function under test
double expectedX = +9.5;
double expectedAbsoluteX = +9.5;
double expectedRelativeX = 1.5;
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantRelativePosition.x, equalTo(expectedX));
// for all stages, the absolute position should equal the relative, because the direct parent is the root component (i.e. the Rocket)
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantRelativePosition.x, equalTo(expectedRelativeX));
// for all stages, the absolute position should equal the relative, because the direct parent is the rocket component (i.e. the Rocket)
Coordinate resultantAbsolutePosition = booster.getAbsolutePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedX));
assertThat(" 'setAxialPosition(double)' failed. Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedAbsoluteX));
double resultantAxialOffset = booster.getAxialOffset();
assertThat(" 'getAxialPosition()' failed. Relative position: ", resultantAxialOffset, equalTo(targetOffset));
@ -380,25 +397,24 @@ public class StageTest extends BaseTestCase {
@Test
public void testSetStagePosition_outsideMIDDLE() {
// setup
RocketComponent root = createTestRocket();
RocketComponent rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage booster = createBooster();
root.addChild(booster);
core.addChild(booster);
// when 'external' the stage should be freely movable
booster.setOutside(true);
booster.setRelativePositionMethod(Position.MIDDLE);
booster.setRelativeToStage(1);
// vv function under test
double targetOffset = +2.0;
booster.setAxialOffset(targetOffset);
booster.setAxialOffset(Position.MIDDLE, targetOffset);
// ^^ function under test
double expectedX = +10.0;
double expectedRelativeX = +2.0;
double expectedAbsoluteX = +10.0;
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantRelativePosition.x, equalTo(expectedX));
// for all stages, the absolute position should equal the relative, because the direct parent is the root component (i.e. the Rocket)
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantRelativePosition.x, equalTo(expectedRelativeX));
// for all stages, the absolute position should equal the relative, because the direct parent is the rocket component (i.e. the Rocket)
Coordinate resultantAbsolutePosition = booster.getAbsolutePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedX));
assertThat(" 'setAxialPosition(double)' failed. Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedAbsoluteX));
double resultantPositionValue = booster.getPositionValue();
@ -411,26 +427,23 @@ public class StageTest extends BaseTestCase {
@Test
public void testSetStagePosition_outsideBOTTOM() {
// setup
RocketComponent root = createTestRocket();
RocketComponent rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage booster = createBooster();
root.addChild(booster);
core.addChild(booster);
// when 'external' the stage should be freely movable
booster.setOutside(true);
booster.setRelativePositionMethod(Position.BOTTOM);
booster.setRelativeToStage(1);
// vv function under test
double targetOffset = +4.0;
booster.setAxialOffset(targetOffset);
booster.setAxialOffset(Position.BOTTOM, targetOffset);
// ^^ function under test
double expectedX = +12.5;
double expectedRelativeX = +4.5;
double expectedAbsoluteX = +12.5;
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantRelativePosition.x, equalTo(expectedX));
// for all stages, the absolute position should equal the relative, because the direct parent is the root component (i.e. the Rocket)
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantRelativePosition.x, equalTo(expectedRelativeX));
// for all stages, the absolute position should equal the relative, because the direct parent is the rocket component (i.e. the Rocket)
Coordinate resultantAbsolutePosition = booster.getAbsolutePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedX));
assertThat(" 'setAxialPosition(double)' failed. Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedAbsoluteX));
double resultantPositionValue = booster.getPositionValue();
assertThat(" 'setPositionValue()' failed. Relative position: ", resultantPositionValue, equalTo(targetOffset));
@ -442,186 +455,260 @@ public class StageTest extends BaseTestCase {
@Test
public void testAxial_setTOP_getABSOLUTE() {
// setup
RocketComponent root = createTestRocket();
Stage core = (Stage) root.getChild(1);
RocketComponent rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage booster = createBooster();
root.addChild(booster);
core.addChild(booster);
double targetOffset = +4.50;
booster.setOutside(true);
booster.setRelativePositionMethod(Position.TOP);
booster.setRelativeToStage(1);
booster.setAxialOffset(targetOffset);
booster.setAxialOffset(Position.TOP, targetOffset);
double expectedAxialOffset = +12.0;
double expectedAxialOffset = +4.0;
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantRelativePosition.x, equalTo(expectedAxialOffset));
Stage refStage = core;
// vv function under test
double resultantAxialPosition = booster.asPositionValue(Position.ABSOLUTE, refStage);
double resultantAxialPosition = booster.asPositionValue(Position.ABSOLUTE);
// ^^ function under test
assertThat(" 'setPositionValue()' failed. Relative position: ", resultantAxialPosition, equalTo(expectedAxialOffset));
double expectedAbsoluteX = +12.0;
assertThat(" 'setPositionValue()' failed. Relative position: ", resultantAxialPosition, equalTo(expectedAbsoluteX));
}
@Test
public void testAxial_setTOP_getAFTER() {
// setup
RocketComponent root = createTestRocket();
Stage core = (Stage) root.getChild(1);
RocketComponent rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage booster = createBooster();
root.addChild(booster);
core.addChild(booster);
double targetOffset = +4.50;
booster.setOutside(true);
booster.setRelativePositionMethod(Position.TOP);
booster.setRelativeToStage(1);
booster.setAxialOffset(targetOffset);
booster.setAxialOffset(Position.TOP, targetOffset);
Coordinate expectedPosition = new Coordinate(+12.0, 0., 0.);
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantRelativePosition.x, equalTo(expectedPosition.x));
double expectedRelativeX = +4.0;
double resultantX = booster.getRelativePositionVector().x;
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantX, equalTo(expectedRelativeX));
Stage refStage = core;
double resultantAxialPosition;
double expectedAxialPosition;
// vv function under test
resultantAxialPosition = booster.asPositionValue(Position.AFTER, refStage);
// because this component is not initalized to
resultantX = booster.asPositionValue(Position.AFTER);
// ^^ function under test
expectedAxialPosition = -1.5;
assertThat(" 'setPositionValue()' failed. Relative position: ", resultantAxialPosition, equalTo(expectedAxialPosition));
double expectedAfterX = 4.5;
assertEquals(" 'setPositionValue()' failed. Relative position: ", expectedAfterX, resultantX, EPSILON);
}
@Test
public void testAxial_setTOP_getMIDDLE() {
// setup
RocketComponent root = createTestRocket();
Stage core = (Stage) root.getChild(1);
RocketComponent rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage booster = createBooster();
root.addChild(booster);
core.addChild(booster);
double targetOffset = +4.50;
booster.setOutside(true);
booster.setRelativePositionMethod(Position.TOP);
booster.setRelativeToStage(1);
booster.setAxialOffset(targetOffset);
booster.setAxialOffset(Position.TOP, targetOffset);
Coordinate expectedPosition = new Coordinate(+12.0, 0., 0.);
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantRelativePosition.x, equalTo(expectedPosition.x));
double expectedRelativeX = +4.0;
double resultantX = booster.getRelativePositionVector().x;
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantX, equalTo(expectedRelativeX));
Stage refStage = core;
double resultantAxialPosition;
double expectedAxialPosition = +4.0;
// vv function under test
resultantAxialPosition = booster.asPositionValue(Position.MIDDLE, refStage);
resultantAxialPosition = booster.asPositionValue(Position.MIDDLE);
// ^^ function under test
assertThat(" 'setPositionValue()' failed. Relative position: ", resultantAxialPosition, equalTo(expectedAxialPosition));
assertEquals(" 'setPositionValue()' failed. Relative position: ", expectedAxialPosition, resultantAxialPosition, EPSILON);
}
@Test
public void testAxial_setTOP_getBOTTOM() {
// setup
RocketComponent root = createTestRocket();
Stage core = (Stage) root.getChild(1);
RocketComponent rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage booster = createBooster();
root.addChild(booster);
core.addChild(booster);
double targetOffset = +4.50;
booster.setOutside(true);
booster.setRelativePositionMethod(Position.TOP);
booster.setRelativeToStage(1);
booster.setAxialOffset(targetOffset);
booster.setAxialOffset(Position.TOP, targetOffset);
Coordinate expectedPosition = new Coordinate(+12.0, 0., 0.);
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantRelativePosition.x, equalTo(expectedPosition.x));
double expectedRelativeX = +4.0;
double resultantX = booster.getRelativePositionVector().x;
assertEquals(" 'setAxialPosition(double)' failed. Relative position: ", expectedRelativeX, resultantX, EPSILON);
Stage refStage = core;
double resultantAxialPosition;
double expectedAxialPosition;
// vv function under test
resultantAxialPosition = booster.asPositionValue(Position.BOTTOM, refStage);
double resultantAxialOffset = booster.asPositionValue(Position.BOTTOM);
// ^^ function under test
expectedAxialPosition = +3.5;
assertThat(" 'setPositionValue()' failed. Relative position: ", resultantAxialPosition, equalTo(expectedAxialPosition));
double expectedAxialOffset = +3.5;
assertEquals(" 'setPositionValue()' failed. Relative position: ", expectedAxialOffset, resultantAxialOffset, EPSILON);
}
@Test
public void testAxial_setBOTTOM_getTOP() {
// setup
RocketComponent root = createTestRocket();
Stage core = (Stage) root.getChild(1);
RocketComponent rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage booster = createBooster();
root.addChild(booster);
core.addChild(booster);
double targetOffset = +4.50;
booster.setOutside(true);
booster.setRelativePositionMethod(Position.BOTTOM);
booster.setRelativeToStage(1);
booster.setAxialOffset(targetOffset);
booster.setAxialOffset(Position.BOTTOM, targetOffset);
Coordinate expectedPosition = new Coordinate(+13.0, 0., 0.);
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
assertThat(" 'setAxialPosition(double)' failed. Relative position: ", resultantRelativePosition.x, equalTo(expectedPosition.x));
Stage refStage = core;
double resultantAxialPosition;
double expectedAxialPosition;
double expectedRelativeX = +5.0;
double resultantX = booster.getRelativePositionVector().x;
assertEquals(" 'setAxialPosition(double)' failed. Relative position: ", expectedRelativeX, resultantX, EPSILON);
// vv function under test
resultantAxialPosition = booster.asPositionValue(Position.TOP, refStage);
double resultantAxialOffset = booster.asPositionValue(Position.TOP);
// ^^ function under test
expectedAxialPosition = 5.5;
assertThat(" 'setPositionValue()' failed. Relative position: ", resultantAxialPosition, equalTo(expectedAxialPosition));
double expectedAxialOffset = 5.5;
assertEquals(" 'setPositionValue()' failed. Relative position: ", expectedAxialOffset, resultantAxialOffset, EPSILON);
}
@Test
public void testInitializationOrder() {
Rocket root = createTestRocket();
public void testOutsideStageRepositionTOPAfterAdd() {
final double boosterRadius = 0.8;
final double targetOffset = +2.50;
final Position targetMethod = Position.TOP;
Rocket rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage booster = new Stage();
booster.setName("Booster Stage");
core.addChild(booster);
booster.setAxialOffset(targetMethod, targetOffset);
// requirement: regardless of initialization order (which we cannot control)
// a booster should retain it's positioning method and offset while adding on children
double expectedRelativeX = -0.5;
double resultantOffset = booster.getRelativePositionVector().x;
assertEquals(" init order error: Booster: initial relative X: ", expectedRelativeX, resultantOffset, EPSILON);
double expectedAxialOffset = targetOffset;
resultantOffset = booster.getAxialOffset();
assertEquals(" init order error: Booster: initial axial offset: ", expectedAxialOffset, resultantOffset, EPSILON);
// Body Component 2
RocketComponent boosterBody = new BodyTube(4.0, boosterRadius, 0.01);
boosterBody.setName("Booster Body ");
booster.addChild(boosterBody);
expectedAxialOffset = targetOffset;
resultantOffset = booster.getAxialOffset();
assertEquals(" init order error: Booster: populated axial offset: ", expectedAxialOffset, resultantOffset, EPSILON);
expectedRelativeX = 1.5;
resultantOffset = booster.getRelativePositionVector().x;
assertEquals(" init order error: Booster: populated relative X: ", expectedRelativeX, resultantOffset, EPSILON);
expectedAxialOffset = targetOffset;
}
@Test
public void testOutsideStageRepositionBOTTOMAfterAdd() {
final double boosterRadius = 0.8;
final double targetOffset = +2.50;
final Position targetMethod = Position.BOTTOM;
Rocket rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage booster = new Stage();
booster.setName("Booster Stage");
core.addChild(booster);
booster.setAxialOffset(targetMethod, targetOffset);
// requirement: regardless of initialization order (which we cannot control)
// a booster should retain it's positioning method and offset while adding on children
double expectedRelativeX = 5.5;
double resultantOffset = booster.getRelativePositionVector().x;
assertEquals(" init order error: Booster: initial relative X: ", expectedRelativeX, resultantOffset, EPSILON);
double expectedAxialOffset = targetOffset;
resultantOffset = booster.getAxialOffset();
assertEquals(" init order error: Booster: initial axial offset: ", expectedAxialOffset, resultantOffset, EPSILON);
// Body Component 2
RocketComponent boosterBody = new BodyTube(4.0, boosterRadius, 0.01);
boosterBody.setName("Booster Body ");
booster.addChild(boosterBody);
expectedAxialOffset = targetOffset;
resultantOffset = booster.getAxialOffset();
assertEquals(" init order error: Booster: populated axial offset: ", expectedAxialOffset, resultantOffset, EPSILON);
expectedRelativeX = 3.5;
resultantOffset = booster.getRelativePositionVector().x;
assertEquals(" init order error: Booster: populated relative X: ", expectedRelativeX, resultantOffset, EPSILON);
expectedAxialOffset = targetOffset;
}
@Test
public void testStageInitializationMethodValueOrder() {
Rocket rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
Stage boosterA = createBooster();
root.addChild(boosterA);
boosterA.setName("Booster A Stage");
core.addChild(boosterA);
Stage boosterB = createBooster();
root.addChild(boosterB);
boosterB.setName("Booster B Stage");
core.addChild(boosterB);
double targetOffset = +4.50;
double expectedOffset = +4.0;
// requirement: regardless of initialization order (which we cannot control)
// two boosters with identical initialization commands should end up at the same place.
boosterA.setOutside(true);
boosterA.setRelativePositionMethod(Position.BOTTOM);
boosterA.setRelativeToStage(1);
boosterA.setAxialOffset(targetOffset);
boosterA.setAxialOffset(Position.TOP, targetOffset);
boosterB.dumpDetail();
boosterB.setRelativePositionMethod(Position.TOP);
System.err.println(" B: setMeth: " + boosterB.getRelativePositionVector().x);
boosterB.setRelativeToStage(1);
System.err.println(" B: setRelTo: " + boosterB.getRelativePositionVector().x);
boosterB.setAxialOffset(targetOffset);
System.err.println(" B: setOffs: " + boosterB.getRelativePositionVector().x);
boosterB.setRelativePositionMethod(Position.BOTTOM);
System.err.println(" B: setMeth: " + boosterB.getRelativePositionVector().x);
boosterB.setOutside(true);
System.err.println(" B: setOutside:" + boosterB.getRelativePositionVector().x);
root.dumpTree(true, "");
double offsetA = boosterA.getAxialOffset();
double offsetB = boosterB.getAxialOffset();
assertThat(" init order error: Booster A: resultant positions: ", offsetA, equalTo(targetOffset));
assertThat(" init order error: Booster B: resultant positions: ", offsetB, equalTo(targetOffset));
double resultantOffsetA = boosterA.getRelativePositionVector().x;
double resultantOffsetB = boosterB.getRelativePositionVector().x;
assertEquals(" init order error: Booster A: resultant positions: ", expectedOffset, resultantOffsetA, EPSILON);
assertEquals(" init order error: Booster B: resultant positions: ", expectedOffset, resultantOffsetB, EPSILON);
}
@Test
public void testStageNumbering() {
Rocket rocket = createTestRocket();
Stage sustainer = (Stage) rocket.getChild(0);
Stage core = (Stage) rocket.getChild(1);
Stage boosterA = createBooster();
boosterA.setName("Booster A Stage");
core.addChild(boosterA);
boosterA.setAxialOffset(Position.BOTTOM, 0.0);
Stage boosterB = createBooster();
boosterB.setName("Booster B Stage");
core.addChild(boosterB);
boosterB.setAxialOffset(Position.BOTTOM, 0);
int expectedStageNumber = 0;
int actualStageNumber = sustainer.getStageNumber();
assertEquals(" init order error: sustainer: resultant positions: ", expectedStageNumber, actualStageNumber);
expectedStageNumber = 1;
actualStageNumber = core.getStageNumber();
assertEquals(" init order error: core: resultant positions: ", expectedStageNumber, actualStageNumber);
expectedStageNumber = 2;
actualStageNumber = boosterA.getStageNumber();
assertEquals(" init order error: Booster A: resultant positions: ", expectedStageNumber, actualStageNumber);
expectedStageNumber = 3;
actualStageNumber = boosterB.getStageNumber();
assertEquals(" init order error: Booster B: resultant positions: ", expectedStageNumber, actualStageNumber);
}
}

View File

@ -1,130 +0,0 @@
package net.sf.openrocket.gui.adaptors;
import java.util.EventObject;
import java.util.Iterator;
import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;
import javax.swing.event.ListDataListener;
import org.jfree.util.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Stage;
import net.sf.openrocket.util.ArrayList;
import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.Reflection;
import net.sf.openrocket.util.StateChangeListener;
public class StageSelectModel extends AbstractListModel<Stage> implements ComboBoxModel<Stage>, StateChangeListener {
private static final long serialVersionUID = 1311302134934033684L;
private static final Logger log = LoggerFactory.getLogger(StageSelectModel.class);
// protected final String nullText;
protected Stage sourceStage = null;
protected ArrayList<Stage> displayValues = new ArrayList<Stage>();
protected Stage selectedStage = null;
//@SuppressWarnings("unchecked")
public StageSelectModel( final Stage _stage) {
this.sourceStage = _stage;
// this.nullText = nullText;
populateDisplayValues();
stateChanged(null); // Update current value
this.sourceStage.addChangeListener(this);
}
private void populateDisplayValues(){
Rocket rocket = this.sourceStage.getRocket();
this.displayValues.clear();
Iterator<RocketComponent> stageIter = rocket.getChildren().iterator();
while( stageIter.hasNext() ){
RocketComponent curComp = stageIter.next();
if( curComp instanceof Stage ){
Stage curStage = (Stage)curComp;
if( curStage.equals( this.sourceStage )){
continue;
}else{
displayValues.add( curStage );
}
}else{
throw new IllegalStateException("Rocket has a child which is something other than a Stage: "+curComp.getClass().getCanonicalName()+"(called: "+curComp.getName()+")");
}
}
}
@Override
public int getSize() {
return this.displayValues.size();
}
@Override
public Stage getElementAt(int index) {
return this.displayValues.get(index);
}
@Override
public void setSelectedItem(Object newItem) {
if (newItem == null) {
// Clear selection - huh?
return;
}
if (newItem instanceof String) {
log.error("setStage to string? huh? (unexpected value type");
return;
}
if( newItem instanceof Stage ){
Stage nextStage = (Stage) newItem;
if (nextStage.equals(this.selectedStage)){
return; // i.e. no change
}
this.selectedStage = nextStage;
this.sourceStage.setRelativeToStage(nextStage.getStageNumber());
return;
}
}
@Override
public Stage getSelectedItem() {
return this.selectedStage;
//return "StageSelectModel["+this.selectedIndex+": "+this.displayValues.get(this.selectedIndex).getName()+"]";
}
@Override
public void stateChanged(EventObject eo) {
if( null == this.sourceStage){
return;
}
Rocket rkt = sourceStage.getRocket();
int sourceRelToIndex = this.sourceStage.getRelativeToStage();
int selectedStageIndex = -1;
if( null != this.selectedStage ){
selectedStageIndex = this.selectedStage.getStageNumber();
}
if ( selectedStageIndex != sourceRelToIndex){
this.selectedStage = (Stage)rkt.getChild(sourceRelToIndex);
}
}
@Override
public String toString() {
return "StageSelectModel["+this.selectedStage.getName()+" ("+this.selectedStage.getStageNumber()+")]";
}
}

View File

@ -256,7 +256,7 @@ public abstract class FinSetConfig extends RocketComponentConfig {
if (!rings.isEmpty()) {
FinSet.TabRelativePosition temp = (FinSet.TabRelativePosition) em.getSelectedItem();
em.setSelectedItem(FinSet.TabRelativePosition.FRONT);
double len = computeFinTabLength(rings, component.asPositionValue(RocketComponent.Position.TOP, parent),
double len = computeFinTabLength(rings, component.asPositionValue(RocketComponent.Position.TOP),
component.getLength(), mts, parent);
mtl.setValue(len);
//Be nice to the user and set the tab relative position enum back the way they had it.
@ -305,8 +305,8 @@ public abstract class FinSetConfig extends RocketComponentConfig {
Collections.sort(rings, new Comparator<CenteringRing>() {
@Override
public int compare(CenteringRing centeringRing, CenteringRing centeringRing1) {
return (int) (1000d * (centeringRing.asPositionValue(RocketComponent.Position.TOP, relativeTo) -
centeringRing1.asPositionValue(RocketComponent.Position.TOP, relativeTo)));
return (int) (1000d * (centeringRing.asPositionValue(RocketComponent.Position.TOP) -
centeringRing1.asPositionValue(RocketComponent.Position.TOP)));
}
});
@ -315,7 +315,7 @@ public abstract class FinSetConfig extends RocketComponentConfig {
//Handle centering rings that overlap or are adjacent by synthetically merging them into one virtual ring.
if (!positionsFromTop.isEmpty() &&
positionsFromTop.get(positionsFromTop.size() - 1).bottomSidePositionFromTop() >=
centeringRing.asPositionValue(RocketComponent.Position.TOP, relativeTo)) {
centeringRing.asPositionValue(RocketComponent.Position.TOP)) {
SortableRing adjacent = positionsFromTop.get(positionsFromTop.size() - 1);
adjacent.merge(centeringRing, relativeTo);
} else {
@ -440,7 +440,7 @@ public abstract class FinSetConfig extends RocketComponentConfig {
*/
SortableRing(CenteringRing r, RocketComponent relativeTo) {
thickness = r.getLength();
positionFromTop = r.asPositionValue(RocketComponent.Position.TOP, relativeTo);
positionFromTop = r.asPositionValue(RocketComponent.Position.TOP);
}
/**
@ -449,7 +449,7 @@ public abstract class FinSetConfig extends RocketComponentConfig {
* @param adjacent the adjacent ring
*/
public void merge(CenteringRing adjacent, RocketComponent relativeTo) {
double v = adjacent.asPositionValue(RocketComponent.Position.TOP, relativeTo);
double v = adjacent.asPositionValue(RocketComponent.Position.TOP);
if (positionFromTop < v) {
thickness = (v + adjacent.getLength()) - positionFromTop;
} else {

View File

@ -1,11 +1,6 @@
package net.sf.openrocket.gui.configdialog;
import java.awt.Component;
import java.awt.Container;
import java.util.List;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
@ -13,9 +8,6 @@ import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.SpinnerEditor;
@ -23,8 +15,6 @@ import net.sf.openrocket.gui.adaptors.BooleanModel;
import net.sf.openrocket.gui.adaptors.DoubleModel;
import net.sf.openrocket.gui.adaptors.EnumModel;
import net.sf.openrocket.gui.adaptors.IntegerModel;
import net.sf.openrocket.gui.adaptors.StageSelectModel;
import net.sf.openrocket.gui.components.BasicSlider;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.components.UnitSelector;
import net.sf.openrocket.gui.components.StyledLabel.Style;
@ -35,7 +25,6 @@ import net.sf.openrocket.rocketcomponent.Stage;
import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.ChangeSource;
public class StageConfig extends RocketComponentConfig {
private static final Translator trans = Application.getTranslator();
@ -60,13 +49,6 @@ public class StageConfig extends RocketComponentConfig {
private JPanel parallelTab( final Stage stage ){
JPanel motherPanel = new JPanel( new MigLayout("fill"));
// this stage is positioned relative to what stage?
JLabel relativeStageLabel = new JLabel(trans.get("Stage.parallel.componentname"));
motherPanel.add( relativeStageLabel);
ComboBoxModel<Stage> relativeStageModel = new StageSelectModel( stage );
JComboBox<Stage> relToCombo = new JComboBox<Stage>( relativeStageModel );
motherPanel.add( relToCombo , "growx, wrap");
// enable parallel staging
motherPanel.add(new JSeparator(SwingConstants.HORIZONTAL), "spanx 3, growx, wrap");
BooleanModel parallelEnabledModel = new BooleanModel( component, "Outside");
@ -146,6 +128,8 @@ public class StageConfig extends RocketComponentConfig {
motherPanel.add(axialOffsetUnitSelector, "growx 1, wrap");
parallelEnabledModel.addEnableComponent( axialOffsetUnitSelector , true);
System.err.println(stage.getRocket().toDebugTree());
return motherPanel;
}

View File

@ -86,8 +86,8 @@ public class CenteringRingStrategy extends AbstractPrintStrategy<Void> {
* @return true if the two physically intersect, from which we infer that the centering ring supports the tube
*/
private boolean overlaps(CenteringRing one, InnerTube two) {
final double crTopPosition = one.asPositionValue(RocketComponent.Position.ABSOLUTE, one.getParent());
final double mmTopPosition = two.asPositionValue(RocketComponent.Position.ABSOLUTE, two.getParent());
final double crTopPosition = one.asPositionValue(RocketComponent.Position.ABSOLUTE);
final double mmTopPosition = two.asPositionValue(RocketComponent.Position.ABSOLUTE);
final double crBottomPosition = one.getLength() + crTopPosition;
final double mmBottomPosition = two.getLength() + mmTopPosition;

View File

@ -1,5 +1,6 @@
package net.sf.openrocket.gui.rocketfigure;
import net.sf.openrocket.rocketcomponent.Stage;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.Transformation;
@ -21,7 +22,6 @@ public class BodyTubeShapes extends RocketComponentShape {
Coordinate[] instanceOffsets = new Coordinate[]{ transformation.transform( componentAbsoluteLocation )};
instanceOffsets = component.shiftCoordinates(instanceOffsets);
// System.err.println(">> Starting component "+component.getName()+" at: "+(instanceOffsets[0].x - length/2));
Shape[] s = new Shape[instanceOffsets.length];
for (int i=0; i < instanceOffsets.length; i++) {
s[i] = new Rectangle2D.Double((instanceOffsets[i].x-length/2)*S, //x - the X coordinate of the upper-left corner of the newly constructed Rectangle2D

View File

@ -22,7 +22,7 @@ public class ShockCordShapes extends RocketComponentShape {
double radius = massObj.getRadius();
double arc = Math.min(length, 2*radius) * 0.7;
Shape[] s = new Shape[0];
Shape[] s = new Shape[1];
Coordinate start = componentAbsoluteLocation;
s[0] = new RoundRectangle2D.Double((start.x-radius)*S,(start.y-radius)*S,
length*S,2*radius*S,arc*S,arc*S);
@ -47,7 +47,7 @@ public class ShockCordShapes extends RocketComponentShape {
double or = tube.getRadius();
Shape[] s = new Shape[0];
Shape[] s = new Shape[1];
Coordinate start = componentAbsoluteLocation;
s[0] = new Ellipse2D.Double((start.z-or)*S,(start.y-or)*S,2*or*S,2*or*S);

View File

@ -22,7 +22,7 @@ public class StreamerShapes extends RocketComponentShape {
double radius = massObj.getRadius();
double arc = Math.min(length, 2*radius) * 0.7;
Shape[] s = new Shape[0];
Shape[] s = new Shape[1];
Coordinate center = componentAbsoluteLocation;
s[0] = new RoundRectangle2D.Double((center.x-radius)*S,(center.y-radius)*S,
length*S,2*radius*S,arc*S,arc*S);
@ -45,7 +45,7 @@ public class StreamerShapes extends RocketComponentShape {
net.sf.openrocket.rocketcomponent.MassObject tube = (net.sf.openrocket.rocketcomponent.MassObject)component;
double or = tube.getRadius();
Shape[] s = new Shape[0];
Shape[] s = new Shape[1];
Coordinate center = componentAbsoluteLocation;
s[0] = new Ellipse2D.Double((center.z-or)*S,(center.y-or)*S,2*or*S,2*or*S);

View File

@ -23,9 +23,11 @@ import net.sf.openrocket.gui.figureelements.FigureElement;
import net.sf.openrocket.gui.util.ColorConversion;
import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.OutsideComponent;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Stage;
@ -442,27 +444,50 @@ public class RocketFigure extends AbstractScaleFigure {
// Coordinate componentRelativeLocation = comp.getRelativePositionVector();
Coordinate componentAbsoluteLocation = parentOffset.add(comp.getRelativePositionVector());
//System.err.println(">> Drawing component "+comp.getName()+" at relloc: "+componentAbsoluteLocation);
if( ( comp instanceof Rocket)||( comp instanceof Stage )){
// these components don't have any shapes to generate / get
// No-Op
// generate shapes:
if( comp instanceof Rocket){
// no-op. no shapes
}else if( comp instanceof Stage ){
// no-op; no shapes here, either.
}else{
// if( comp instanceof FinSet ){
// System.err.println(">> Drawing component "+comp.getName()+" at absloc: "+componentAbsoluteLocation);
// System.err.println(" (parent was at: "+parentOffset);
// }
// get all shapes for this component, add to return list.
RocketComponentShape[] childShapes = getThisShape( viewType, comp, componentAbsoluteLocation, viewTransform);
for ( RocketComponentShape curShape : childShapes ){
allShapes.add( curShape );
}
}
// recurse to each child
// recurse differently, depending on if this node has instances or not....
if( comp.isCenterline() ){
// recurse to each child with just the center
for( RocketComponent child: comp.getChildren() ){
getShapeTree( allShapes, child, componentAbsoluteLocation);
}
}else{
// DEBUG -- for external stages....
System.err.println(">> Drawing pStage: "+comp.getName()+" at absloc: "+componentAbsoluteLocation);
Stage testStage = (Stage)comp;
// System.err.println(">> Starting component "+component.getName()+" at: "+(instanceOffsets[0]));
// recurse to each child with each instance of this component
OutsideComponent outer = (OutsideComponent)comp;
// int instanceCount = outer.getInstanceCount();
// get the offsets for m instances
Coordinate[] instanceOffsets = new Coordinate[]{ componentAbsoluteLocation };
instanceOffsets = comp.shiftCoordinates( instanceOffsets);
// recurse to each child with each offset
for( RocketComponent child: comp.getChildren() ){
for( Coordinate curInstanceCoordinate : instanceOffsets){
getShapeTree( allShapes, child, curInstanceCoordinate);
}
}
}
return;
}