Fixed numerous display bugs-- including stage placement, engine instancing.

This commit is contained in:
Daniel_M_Williams 2015-08-12 14:02:24 -04:00
parent 6f039a992b
commit 0fbdc33188
11 changed files with 260 additions and 137 deletions

View File

@ -311,7 +311,8 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial
@Override
public Collection<Coordinate> getComponentBounds() {
Collection<Coordinate> bounds = new ArrayList<Coordinate>(8);
Coordinate ref = this.getAbsolutePositionVector();
// not exact, but should *usually* give the right bounds
Coordinate ref = this.getLocation()[0];
double r = getOuterRadius();
addBound(bounds, ref.x, r);
addBound(bounds, ref.x + length, r);

View File

@ -130,6 +130,7 @@ public class Configuration implements Cloneable, ChangeSource, ComponentChangeLi
public int[] getActiveStages() {
// temporary hack fix
//int stageCount = Stage.getStageCount();
int stageCount = getRocket().getChildCount();
List<Integer> active = new ArrayList<Integer>();
int[] ret;

View File

@ -621,7 +621,7 @@ public abstract class FinSet extends ExternalComponent {
@Override
public Collection<Coordinate> getComponentBounds() {
List<Coordinate> bounds = new ArrayList<Coordinate>();
double refx = this.getAbsolutePositionVector().x;
double refx = this.getLocation()[0].x;
double r = getBodyRadius();
for (Coordinate point : getFinPoints()) {

View File

@ -196,7 +196,23 @@ public class Rocket extends RocketComponent {
return functionalModID;
}
public ArrayList<Stage> getStageList() {
ArrayList<Stage> toReturn = new ArrayList<Stage>();
toReturn = Rocket.getStages(toReturn, this);
return toReturn;
}
private static ArrayList<Stage> getStages(ArrayList<Stage> accumulator, final RocketComponent parent) {
for (RocketComponent curChild : parent.getChildren()) {
if (curChild instanceof Stage) {
Stage curStage = (Stage) curChild;
accumulator.add(curStage);
}
}
return accumulator; // technically redundant, btw.
}
public ReferenceType getReferenceType() {

View File

@ -100,7 +100,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
/**
* Positioning of this component relative to the parent component.
*/
protected Position relativePosition;
protected Position relativePosition = Position.AFTER;
/**
* Offset of the position of this component relative to the normal position given by
@ -913,7 +913,11 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
result = thisX - relativeLength;
break;
case ABSOLUTE:
result = this.getAbsolutePositionVector().x;
Coordinate[] insts = this.getLocation();
if (1 < insts.length) {
return Double.NaN;
}
result = insts[0].x;
break;
case TOP:
result = thisX;
@ -941,7 +945,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
return this.getAxialOffset();
}
public double getAxialOffset() {
mutex.verify();
return this.asPositionValue(this.relativePosition);
@ -1008,7 +1011,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
}
} else {
refLength = referenceComponent.getLength();
double refRelX = referenceComponent.getRelativePositionVector().x;
double refRelX = referenceComponent.getOffset().x;
newAxialPosition = refRelX + refLength;
}
@ -1065,16 +1068,37 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
this.setAxialOffset(this.relativePosition, this.offset);
}
public Coordinate getRelativePositionVector() {
public Coordinate getOffset() {
return this.position;
}
public Coordinate getAbsolutePositionVector() {
/**
* @deprecated kept around as example code. instead use
* @return
*/
private Coordinate getAbsoluteVector() {
if (null == this.parent) {
// == improperly initialized components OR the root Rocket instance
return new Coordinate();
return Coordinate.ZERO;
} else {
return this.parent.getAbsolutePositionVector().add(this.getRelativePositionVector());
return this.getAbsoluteVector().add(this.getOffset());
}
}
public Coordinate[] getLocation() {
if (null == this.parent) {
// == improperly initialized components OR the root Rocket instance
return new Coordinate[] { Coordinate.ZERO };
} else {
Coordinate[] parentPositions = this.parent.getLocation();
int instCount = parentPositions.length;
Coordinate[] thesePositions = new Coordinate[instCount];
for (int pi = 0; pi < instCount; pi++) {
thesePositions[pi] = parentPositions[pi].add(this.getOffset());
}
return thesePositions;
}
}
@ -1090,9 +1114,18 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
*/
public Coordinate[] toAbsolute(Coordinate c) {
checkState();
final String lockText = "toAbsolute";
mutex.lock(lockText);
Coordinate[] thesePositions = this.getLocation();
Coordinate absCoord = this.getAbsolutePositionVector().add(c);
return new Coordinate[] { absCoord };
final int instanceCount = this.getInstanceCount();
Coordinate[] toReturn = new Coordinate[instanceCount];
for (int coordIndex = 0; coordIndex < instanceCount; coordIndex++) {
toReturn[coordIndex] = thesePositions[coordIndex].add(c);
}
mutex.unlock(lockText);
return toReturn;
}
// public Coordinate[] toAbsolute(final Coordinate[] toMove) {
@ -1116,13 +1149,11 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
* <p>
* The current implementation does not support rotating components.
*
* @deprecated to test alternate interface...
* @param c Coordinate in the component's coordinate system.
* @param dest Destination component coordinate system.
* @return an array of coordinates describing <code>c</code> in coordinates
* relative to <code>dest</code>.
*/
@Deprecated
public final Coordinate[] toRelative(Coordinate c, RocketComponent dest) {
if (null == dest) {
throw new BugException("calling toRelative(c,null) is being refactored. ");
@ -1131,33 +1162,29 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
checkState();
mutex.lock("toRelative");
final Coordinate sourceLoc = this.getAbsolutePositionVector();
final Coordinate destLoc = dest.getAbsolutePositionVector();
Coordinate newCoord = c.add(sourceLoc).sub(destLoc);
Coordinate[] toReturn = new Coordinate[] { newCoord };
// not sure if this will give us an answer, or THE answer...
//final Coordinate sourceLoc = this.getLocation()[0];
final Coordinate[] destLocs = dest.getLocation();
Coordinate[] toReturn = new Coordinate[destLocs.length];
for (int coordIndex = 0; coordIndex < dest.getInstanceCount(); coordIndex++) {
toReturn[coordIndex] = this.getLocation()[0].add(c).sub(destLocs[coordIndex]);
}
mutex.unlock("toRelative");
return toReturn;
}
/*
* @deprecated ? is this used by anything?
*/
protected static final Coordinate[] rebase(final Coordinate toMove[], final Coordinate source, final Coordinate dest) {
if ((null == toMove) || (null == source) || (null == dest)) {
throw new NullPointerException("rebase with any null pointer is out-of-spec.");
}
final Coordinate delta = source.sub(dest);
Coordinate[] toReturn = new Coordinate[toMove.length];
Coordinate translation = source.sub(dest);
for (int coordIndex = 0; coordIndex < toMove.length; coordIndex++) {
toReturn[coordIndex] = toMove[coordIndex].add(translation);
toReturn[coordIndex] = toMove[coordIndex].add(delta);
}
return toReturn;
}
/**
* Iteratively sum the lengths of all subcomponents that have position
* Position.AFTER.
@ -2047,10 +2074,8 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
}
public void toDebugTreeNode(final StringBuilder buffer, final String prefix) {
buffer.append(String.format("%s %-24s %5.3f %24f %24f\n", prefix, this.getName(), this.getLength(),
this.getRelativePositionVector().x, this.getAbsolutePositionVector().x));
// buffer.append(String.format("%s %-24s %5.3f %24s %24s\n", prefix, this.getName(), this.getLength(),
// this.getRelativePositionVector(), this.getAbsolutePositionVector()));
buffer.append(String.format("%s %-24s %5.3f %24s %24s\n", prefix, this.getName(), this.getLength(),
this.getOffset(), this.getLocation()[0]));
}
public void dumpTreeHelper(StringBuilder buffer, final String prefix) {

View File

@ -61,17 +61,26 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
@Override
public Collection<Coordinate> getComponentBounds() {
Collection<Coordinate> bounds = new ArrayList<Coordinate>(8);
final double WAG_FACTOR = 1.05;
Coordinate center = this.getAbsolutePositionVector();
double startx = center.x - this.length / 2;
double endx = center.x + this.length / 2;
double r = this.getRadialOffset() * WAG_FACTOR;
final double WAG_FACTOR = 1.1;
double x_min = Double.MAX_VALUE;
double x_max = Double.MIN_VALUE;
double r_max = 0;
if (!this.isCenterline()) {
System.err.println(">> <Stage: " + this.getName() + ">.getComponentBounds(): r=" + r);
Coordinate[] instanceLocations = this.getLocation();
for (Coordinate currentInstanceLocation : instanceLocations) {
if (x_min > (currentInstanceLocation.x)) {
x_min = currentInstanceLocation.x;
}
if (x_max < (currentInstanceLocation.x + this.length)) {
x_max = currentInstanceLocation.x + this.length;
}
if (r_max < (this.getRadialOffset() * WAG_FACTOR)) {
r_max = this.getRadialOffset() * WAG_FACTOR;
}
}
addBound(bounds, startx, r);
addBound(bounds, endx, r);
addBound(bounds, x_min, r_max);
addBound(bounds, x_max, r_max);
return bounds;
}
@ -106,6 +115,27 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
return copy;
}
@Override
public Coordinate[] getLocation() {
if (null == this.parent) {
throw new BugException(" Attempted to get absolute position Vector of a Stage without a parent. ");
}
if (this.isCenterline()) {
return super.getLocation();
} else {
Coordinate[] parentInstances = this.parent.getLocation();
if (1 != parentInstances.length) {
throw new BugException(" OpenRocket does not (yet) support external stages attached to external stages. " +
"(assumed reason for getting multiple parent locations into an external stage.)");
}
Coordinate[] toReturn = this.shiftCoordinates(parentInstances);
return toReturn;
}
}
@Override
public boolean getOutside() {
@ -151,6 +181,10 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
if (this.centerline) {
return;
}
if (_count < 1) {
// there must be at least one instance....
return;
}
this.count = _count;
this.angularSeparation = Math.PI * 2 / this.count;
@ -209,13 +243,14 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
super.setRelativePosition(_newPosition);
}
}
fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE);
}
@Override
public double getPositionValue() {
mutex.verify();
return getAxialOffset();
return this.getAxialOffset();
}
/*
@ -294,11 +329,12 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
double radius = this.radialPosition_m;
double angle0 = this.angularPosition_rad;
double angleIncr = this.angularSeparation;
Coordinate center = this.position;
Coordinate[] toReturn = new Coordinate[this.count];
Coordinate thisOffset;
double thisAngle = angle0;
for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) {
thisOffset = new Coordinate(0, radius * Math.cos(thisAngle), radius * Math.sin(thisAngle));
thisOffset = center.add(0, radius * Math.cos(thisAngle), radius * Math.sin(thisAngle));
toReturn[instanceNumber] = thisOffset.add(c[0]);
thisAngle += angleIncr;
@ -326,26 +362,25 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
String thisLabel = this.getName() + " (" + this.getStageNumber() + ")";
buffer.append(String.format("%s %-24s %5.3f %24s %24s", prefix, thisLabel, this.getLength(),
this.getRelativePositionVector(), this.getAbsolutePositionVector()));
buffer.append(String.format("%s %-24s %5.3f", prefix, thisLabel, this.getLength()));
if (this.isCenterline()) {
buffer.append("\n");
buffer.append(String.format(" %24s %24s\n", this.getOffset(), this.getLocation()[0]));
} 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);
buffer.append(String.format(" %4.1f via: %s \n", this.getAxialOffset(), this.relativePosition.name()));
Coordinate[] relCoords = this.shiftCoordinates(new Coordinate[] { Coordinate.ZERO });
Coordinate[] absCoords = this.getLocation();
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));
for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) {
Coordinate instanceRelativePosition = relCoords[instanceNumber];
Coordinate instanceAbsolutePosition = absCoords[instanceNumber];
buffer.append(String.format("%s [instance %2d of %2d] %32s %32s\n", prefix, instanceNumber, count,
instanceRelativePosition, instanceAbsolutePosition));
}
}
}
@Override
public void updateBounds() {
// currently only updates the length

View File

@ -333,7 +333,7 @@ public class TubeFinSet extends ExternalComponent {
s = this.getParent();
while (s != null) {
if (s instanceof SymmetricComponent) {
double x = this.getRelativePositionVector().x;
double x = this.getOffset().x;
return ((SymmetricComponent) s).getRadius(x);
}
s = s.getParent();

View File

@ -98,7 +98,7 @@ public class StageTest extends BaseTestCase {
expectedPosition = ZERO;
targetPosition = new Coordinate(+4.0, 0.0, 0.0);
rocket.setAxialOffset(targetPosition.x);
resultPosition = rocket.getRelativePositionVector();
resultPosition = rocket.getOffset();
assertThat(" Moved the rocket rocket itself-- this should not be enabled.", expectedPosition.x, equalTo(resultPosition.x));
}
@ -126,23 +126,23 @@ public class StageTest extends BaseTestCase {
assertThat(" createTestRocket failed: Sustainer size: ", sustainer.getLength(), equalTo(expectedSustainerLength));
double expectedSustainerX = 0;
double sustainerX;
sustainerX = sustainer.getRelativePositionVector().x;
sustainerX = sustainer.getOffset().x;
assertThat(" createTestRocket failed:\n" + rocketTree + " sustainer Relative position: ", sustainerX, equalTo(expectedSustainerX));
sustainerX = sustainer.getAbsolutePositionVector().x;
sustainerX = sustainer.getLocation()[0].x;
assertThat(" createTestRocket failed:\n" + rocketTree + " sustainer Absolute position: ", sustainerX, equalTo(expectedSustainerX));
double expectedSustainerNoseX = 0;
double sustainerNosePosition = sustainerNose.getRelativePositionVector().x;
double sustainerNosePosition = sustainerNose.getOffset().x;
assertThat(" createTestRocket failed:\n" + rocketTree + " sustainer Nose X position: ", sustainerNosePosition, equalTo(expectedSustainerNoseX));
expectedSustainerNoseX = 0;
sustainerNosePosition = sustainerNose.getAbsolutePositionVector().x;
sustainerNosePosition = sustainerNose.getLocation()[0].x;
assertThat(" createTestRocket failed:\n" + rocketTree + " sustainer Nose X position: ", sustainerNosePosition, equalTo(expectedSustainerNoseX));
double expectedSustainerBodyX = 2;
double sustainerBodyX = sustainerBody.getRelativePositionVector().x;
double sustainerBodyX = sustainerBody.getOffset().x;
assertThat(" createTestRocket failed:\n" + rocketTree + " sustainer body rel X position: ", sustainerBodyX, equalTo(expectedSustainerBodyX));
expectedSustainerBodyX = 2;
sustainerBodyX = sustainerBody.getAbsolutePositionVector().x;
sustainerBodyX = sustainerBody.getLocation()[0].x;
assertThat(" createTestRocket failed:\n" + rocketTree + " sustainer body abs X position: ", sustainerBodyX, equalTo(expectedSustainerBodyX));
}
@ -166,37 +166,37 @@ public class StageTest extends BaseTestCase {
int relToStage = core.getRelativeToStage();
assertThat(" createTestRocket failed:\n" + rocketTree + " core relative position: ", relToStage, equalTo(relToExpected));
coreX = core.getRelativePositionVector().x;
coreX = core.getOffset().x;
assertThat(" createTestRocket failed:\n" + rocketTree + " core Relative position: ", coreX, equalTo(expectedCoreX));
coreX = core.getAbsolutePositionVector().x;
coreX = core.getLocation()[0].x;
assertThat(" createTestRocket failed:\n" + rocketTree + " core Absolute position: ", coreX, equalTo(expectedCoreX));
RocketComponent coreUpperBody = core.getChild(0);
double expectedX = 0;
double resultantX = coreUpperBody.getRelativePositionVector().x;
double resultantX = coreUpperBody.getOffset().x;
assertThat(" createTestRocket failed:\n" + rocketTree + " core body rel X: ", resultantX, equalTo(expectedX));
expectedX = expectedCoreX;
resultantX = coreUpperBody.getAbsolutePositionVector().x;
resultantX = coreUpperBody.getLocation()[0].x;
assertThat(" createTestRocket failed:\n" + rocketTree + " core body abs X: ", resultantX, equalTo(expectedX));
RocketComponent coreLowerBody = core.getChild(1);
expectedX = coreUpperBody.getLength();
resultantX = coreLowerBody.getRelativePositionVector().x;
resultantX = coreLowerBody.getOffset().x;
assertEquals(" createTestRocket failed:\n" + rocketTree + " core body rel X: ", expectedX, resultantX, EPSILON);
expectedX = expectedCoreX + coreUpperBody.getLength();
resultantX = coreLowerBody.getAbsolutePositionVector().x;
resultantX = coreLowerBody.getLocation()[0].x;
assertEquals(" createTestRocket failed:\n" + rocketTree + " core body abs X: ", expectedX, resultantX, EPSILON);
RocketComponent coreFins = coreLowerBody.getChild(0);
// default is offset=0, method=0
expectedX = 0.2;
resultantX = coreFins.getRelativePositionVector().x;
resultantX = coreFins.getOffset().x;
assertEquals(" createTestRocket failed:\n" + rocketTree + " core Fins rel X: ", expectedX, resultantX, EPSILON);
// 5 + 1.8 + 4.2 = 11
// 11 - 4 = 7;
expectedX = 7.0;
resultantX = coreFins.getAbsolutePositionVector().x;
resultantX = coreFins.getLocation()[0].x;
assertEquals(" createTestRocket failed:\n" + rocketTree + " core Fins abs X: ", expectedX, resultantX, EPSILON);
}
@ -220,10 +220,10 @@ public class StageTest extends BaseTestCase {
// ^^ function under test
String rocketTree = rocket.toDebugTree();
Coordinate resultantRelativePosition = sustainer.getRelativePositionVector();
Coordinate resultantRelativePosition = sustainer.getOffset();
assertThat(" 'setAxialPosition(double)' failed:\n" + rocketTree + " Relative position: ", resultantRelativePosition.x, equalTo(expectedPosition.x));
// 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();
Coordinate resultantAbsolutePosition = sustainer.getLocation()[0];
assertThat(" 'setAxialPosition(double)' failed:\n" + rocketTree + " Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedPosition.x));
}
@ -250,8 +250,8 @@ public class StageTest extends BaseTestCase {
assertThat(" 'setInstancecount(int)' failed: ", instanceCount, equalTo(expectedInstanceCount));
double expectedAbsX = 6.0;
Coordinate resultantCenter = boosterSet.getAbsolutePositionVector();
assertEquals(treeDump + "\n>>'setAxialOffset()' failed:\n" + treeDump + " absolute position", expectedAbsX, resultantCenter.x, EPSILON);
double resultantX = boosterSet.getLocation()[0].x;
assertEquals(">>'setAxialOffset()' failed:\n" + treeDump + " 1st Inst absolute position", expectedAbsX, resultantX, EPSILON);
double expectedRadialOffset = 4.0;
double radialOffset = boosterSet.getRadialOffset();
@ -286,24 +286,24 @@ public class StageTest extends BaseTestCase {
double angle = Math.PI * 2 / targetInstanceCount;
double radius = targetRadialOffset;
Coordinate componentAbsolutePosition = boosterSet.getAbsolutePositionVector();
Coordinate[] instanceCoords = new Coordinate[] { componentAbsolutePosition };
instanceCoords = boosterSet.shiftCoordinates(instanceCoords);
Coordinate[] instanceAbsoluteCoords = boosterSet.getLocation();
// Coordinate[] instanceRelativeCoords = new Coordinate[] { componentAbsolutePosition };
// instanceRelativeCoords = boosterSet.shiftCoordinates(instanceRelativeCoords);
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);
Coordinate resultantPosition0 = instanceAbsoluteCoords[inst];
assertThat(treeDump + "\n>> Failed to generate Parallel Stage instances correctly: ", resultantPosition0, equalTo(expectedPosition0));
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);
Coordinate resultantPosition1 = instanceAbsoluteCoords[inst];
assertThat(treeDump + "\n>> Failed to generate Parallel Stage instances correctly: ", resultantPosition1, equalTo(expectedPosition1));
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);
Coordinate resultantPosition2 = instanceAbsoluteCoords[inst];
assertThat(treeDump + "\n>> Failed to generate Parallel Stage instances correctly: ", resultantPosition2, equalTo(expectedPosition2));
}
@ -318,7 +318,7 @@ public class StageTest extends BaseTestCase {
core.addChild(booster);
double targetX = +17.0;
double expectedX = targetX - core.getAbsolutePositionVector().x;
double expectedX = targetX - core.getLocation()[0].x;
// when subStages should be freely movable
// vv function under test
@ -326,14 +326,14 @@ public class StageTest extends BaseTestCase {
// ^^ function under test
String treeDump = rocket.toDebugTree();
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
Coordinate resultantRelativePosition = booster.getOffset();
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " Relative position: ", resultantRelativePosition.x, equalTo(expectedX));
double resultantPositionValue = booster.getPositionValue();
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " PositionValue: ", resultantPositionValue, equalTo(targetX));
double resultantAxialPosition = booster.getAxialOffset();
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " 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();
Coordinate resultantAbsolutePosition = booster.getLocation()[0];
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " Absolute position: ", resultantAbsolutePosition.x, equalTo(targetX));
}
@ -359,7 +359,7 @@ public class StageTest extends BaseTestCase {
String treeDump = rocket.toDebugTree();
double expectedX = 0;
Coordinate resultantRelativePosition = sustainer.getRelativePositionVector();
Coordinate resultantRelativePosition = sustainer.getOffset();
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " Sustainer Relative position: ", resultantRelativePosition.x, equalTo(expectedX));
double expectedPositionValue = 0;
double resultantPositionValue = sustainer.getPositionValue();
@ -369,7 +369,7 @@ public class StageTest extends BaseTestCase {
double resultantAxialOffset = sustainer.getAxialOffset();
assertThat(" 'getAxialPosition()' failed: \n" + treeDump + " Relative position: ", resultantAxialOffset, equalTo(expectedAxialOffset));
// 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();
Coordinate resultantAbsolutePosition = sustainer.getLocation()[0];
assertThat(" 'setAbsolutePositionVector()' failed: \n" + treeDump + " Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedX));
}
@ -389,10 +389,10 @@ public class StageTest extends BaseTestCase {
double expectedRelativeX = 2;
double expectedAbsoluteX = 7;
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
Coordinate resultantRelativePosition = booster.getOffset();
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " 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();
Coordinate resultantAbsolutePosition = booster.getLocation()[0];
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedAbsoluteX));
double resultantAxialOffset = booster.getAxialOffset();
@ -419,10 +419,10 @@ public class StageTest extends BaseTestCase {
double expectedRelativeX = 2.5;
double expectedAbsoluteX = 7.5;
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
Coordinate resultantRelativePosition = booster.getOffset();
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " 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();
Coordinate resultantAbsolutePosition = booster.getLocation()[0];
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedAbsoluteX));
double resultantPositionValue = booster.getPositionValue();
@ -448,10 +448,10 @@ public class StageTest extends BaseTestCase {
double expectedRelativeX = 5;
double expectedAbsoluteX = +10;
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
Coordinate resultantRelativePosition = booster.getOffset();
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " 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();
Coordinate resultantAbsolutePosition = booster.getLocation()[0];
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " Absolute position: ", resultantAbsolutePosition.x, equalTo(expectedAbsoluteX));
double resultantPositionValue = booster.getPositionValue();
@ -474,7 +474,7 @@ public class StageTest extends BaseTestCase {
String treeDump = rocket.toDebugTree();
double expectedRelativePositionX = targetOffset;
Coordinate resultantRelativePosition = booster.getRelativePositionVector();
Coordinate resultantRelativePosition = booster.getOffset();
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " Relative position: ", resultantRelativePosition.x, equalTo(expectedRelativePositionX));
// vv function under test
@ -498,7 +498,7 @@ public class StageTest extends BaseTestCase {
String treeDump = rocket.toDebugTree();
double expectedRelativeX = targetOffset;
double resultantX = booster.getRelativePositionVector().x;
double resultantX = booster.getOffset().x;
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " Relative position: ", resultantX, equalTo(expectedRelativeX));
// vv function under test
@ -522,7 +522,7 @@ public class StageTest extends BaseTestCase {
String treeDump = rocket.toDebugTree();
double expectedRelativeX = targetOffset;
double resultantX = booster.getRelativePositionVector().x;
double resultantX = booster.getOffset().x;
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " Relative position: ", resultantX, equalTo(expectedRelativeX));
double resultantAxialPosition;
@ -548,7 +548,7 @@ public class StageTest extends BaseTestCase {
String treeDump = rocket.toDebugTree();
double expectedRelativeX = targetOffset;
double resultantX = booster.getRelativePositionVector().x;
double resultantX = booster.getOffset().x;
assertThat(" 'setAxialPosition(double)' failed: \n" + treeDump + " Relative position: ", resultantX, equalTo(expectedRelativeX));
// vv function under test
@ -572,7 +572,7 @@ public class StageTest extends BaseTestCase {
String treeDump = rocket.toDebugTree();
double expectedRelativeX = +5.5;
double resultantX = booster.getRelativePositionVector().x;
double resultantX = booster.getOffset().x;
assertEquals(" 'setAxialPosition(double)' failed: \n" + treeDump + " Relative position: ", expectedRelativeX, resultantX, EPSILON);
// vv function under test
@ -599,7 +599,7 @@ public class StageTest extends BaseTestCase {
// 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 = 2.5;
double resultantOffset = booster.getRelativePositionVector().x;
double resultantOffset = booster.getOffset().x;
assertEquals(" init order error: Booster: " + treeDumpBefore + " initial relative X: ", expectedRelativeX, resultantOffset, EPSILON);
double expectedAxialOffset = targetOffset;
resultantOffset = booster.getAxialOffset();
@ -613,7 +613,7 @@ public class StageTest extends BaseTestCase {
String treeDumpAfter = rocket.toDebugTree();
expectedRelativeX = 2.5; // no change
resultantOffset = booster.getRelativePositionVector().x;
resultantOffset = booster.getOffset().x;
assertEquals(" init order error: Booster: " + treeDumpBefore + " =======> " + treeDumpAfter + " populated relative X: ", expectedRelativeX, resultantOffset, EPSILON);
expectedAxialOffset = targetOffset; // again, no change
resultantOffset = booster.getAxialOffset();
@ -642,8 +642,8 @@ public class StageTest extends BaseTestCase {
boosterB.setAxialOffset(targetOffset);
String treeDump = rocket.toDebugTree();
double resultantOffsetA = boosterA.getRelativePositionVector().x;
double resultantOffsetB = boosterB.getRelativePositionVector().x;
double resultantOffsetA = boosterA.getOffset().x;
double resultantOffsetB = boosterB.getOffset().x;
assertEquals(" init order error: " + treeDump + " Booster A: resultant positions: ", expectedOffset, resultantOffsetA, EPSILON);
assertEquals(" init order error: " + treeDump + " Booster B: resultant positions: ", expectedOffset, resultantOffsetB, EPSILON);
@ -684,6 +684,44 @@ public class StageTest extends BaseTestCase {
}
@Test
public void testToAbsolute() {
Rocket rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
String treeDump = rocket.toDebugTree();
Coordinate input = new Coordinate(3, 0, 0);
Coordinate[] actual = core.toAbsolute(input);
double expectedX = 8;
assertEquals(treeDump + " coordinate transform through 'core.toAbsolute(c)' failed: ", expectedX, actual[0].x, EPSILON);
}
@Test
public void testToRelative() {
Rocket rocket = createTestRocket();
Stage core = (Stage) rocket.getChild(1);
RocketComponent ubody = core.getChild(0);
RocketComponent lbody = core.getChild(1);
String treeDump = rocket.toDebugTree();
Coordinate input = new Coordinate(1, 0, 0);
Coordinate actual = core.toAbsolute(input)[0];
double expectedX = 6;
assertEquals(treeDump + " coordinate transform through 'core.toAbsolute(c)' failed: ", expectedX, actual.x, EPSILON);
input = new Coordinate(1, 0, 0);
actual = ubody.toRelative(input, lbody)[0];
expectedX = -0.8;
assertEquals(treeDump + " coordinate transform through 'core.toAbsolute(c)' failed: ", expectedX, actual.x, EPSILON);
}
}

View File

@ -107,8 +107,7 @@ public class StageConfig extends RocketComponentConfig {
RocketComponent.Position.TOP,
RocketComponent.Position.MIDDLE,
RocketComponent.Position.BOTTOM,
RocketComponent.Position.ABSOLUTE,
RocketComponent.Position.AFTER
RocketComponent.Position.ABSOLUTE
});
JComboBox<?> positionMethodCombo = new JComboBox<RocketComponent.Position>( relativePositionMethodModel );
motherPanel.add(positionMethodCombo, "spanx 2, growx, wrap");

View File

@ -24,6 +24,9 @@ public class RocketComponentShape {
final public LineStyle lineStyle;
final public RocketComponent component;
//fillColor);
//borderColor);
protected RocketComponentShape(){
this.hasShape = false;
this.shape = null;

View File

@ -349,35 +349,41 @@ public class RocketFigure extends AbstractScaleFigure {
Motor motor = mount.getMotor(motorID);
double motorLength = motor.getLength();
double motorRadius = motor.getDiameter() / 2;
// Steps for instancing:
// 1) mountComponent has an instanced ancestor:
// 2) which may be an arbitrary number of levels up, so calling mount.parent.getInstances is not enough.
// 3) therefore <component>.getLocation() will return all the instances of this owning component
// 4) Then, for each instance of the component, draw each cluster.
RocketComponent mountComponent = ((RocketComponent) mount);
Coordinate mountPosition = mountComponent.getAbsolutePositionVector();
Coordinate[] mountLocations = mountComponent.getLocation();
//Coordinate curInstancePosition = mountLocations[0]; // placeholder
double mountLength = mountComponent.getLength();
Coordinate[] motorPositions;
Coordinate[] clusterTop = new Coordinate[]{mountPosition.add( mountLength - motorLength + mount.getMotorOverhang() , 0, 0)};
motorPositions = mountComponent.shiftCoordinates(clusterTop);
for (int i = 0; i < motorPositions.length; i++) {
motorPositions[i] = transformation.transform(motorPositions[i]);
}
for (Coordinate coord : motorPositions) {
Shape s;
if (currentViewType == RocketPanel.VIEW_TYPE.SideView) {
s = new Rectangle2D.Double(EXTRA_SCALE * coord.x,
EXTRA_SCALE * (coord.y - motorRadius), EXTRA_SCALE * motorLength,
EXTRA_SCALE * 2 * motorRadius);
} else {
s = new Ellipse2D.Double(EXTRA_SCALE * (coord.z - motorRadius),
EXTRA_SCALE * (coord.y - motorRadius), EXTRA_SCALE * 2 * motorRadius,
EXTRA_SCALE * 2 * motorRadius);
for ( Coordinate curInstanceLocation : mountLocations ){
Coordinate[] motorPositions;
Coordinate[] clusterCenterTop = new Coordinate[]{ curInstanceLocation.add( mountLength - motorLength + mount.getMotorOverhang(), 0, 0)};
motorPositions = mountComponent.shiftCoordinates(clusterCenterTop);
for (int i = 0; i < motorPositions.length; i++) {
motorPositions[i] = transformation.transform(motorPositions[i]);
}
for (Coordinate coord : motorPositions) {
Shape s;
if (currentViewType == RocketPanel.VIEW_TYPE.SideView) {
s = new Rectangle2D.Double(EXTRA_SCALE * coord.x,
EXTRA_SCALE * (coord.y - motorRadius), EXTRA_SCALE * motorLength,
EXTRA_SCALE * 2 * motorRadius);
} else {
s = new Ellipse2D.Double(EXTRA_SCALE * (coord.z - motorRadius),
EXTRA_SCALE * (coord.y - motorRadius), EXTRA_SCALE * 2 * motorRadius,
EXTRA_SCALE * 2 * motorRadius);
}
g2.setColor(fillColor);
g2.fill(s);
g2.setColor(borderColor);
g2.draw(s);
}
g2.setColor(fillColor);
g2.fill(s);
g2.setColor(borderColor);
g2.draw(s);
}
}
@ -432,14 +438,13 @@ public class RocketFigure extends AbstractScaleFigure {
private void getShapeTree(
ArrayList<RocketComponentShape> allShapes, // this is the output parameter
final RocketComponent comp,
final Coordinate parentOffset){
final Coordinate parentLocation){
RocketPanel.VIEW_TYPE viewType = this.currentViewType;
Transformation viewTransform = this.transformation;
// Coordinate componentRelativeLocation = comp.getRelativePositionVector();
Coordinate componentAbsoluteLocation = parentOffset.add(comp.getRelativePositionVector());
Coordinate componentAbsoluteLocation = parentLocation.add(comp.getOffset());
// generate shapes:
if( comp instanceof Rocket){
// no-op. no shapes
@ -461,9 +466,9 @@ public class RocketFigure extends AbstractScaleFigure {
}
}else{
// get the offsets for each component instance
Coordinate[] instanceOffsets = new Coordinate[]{ componentAbsoluteLocation };
Coordinate[] instanceOffsets = new Coordinate[]{ parentLocation };
instanceOffsets = comp.shiftCoordinates( instanceOffsets);
// recurse to each child with each instance of this component
for( RocketComponent child: comp.getChildren() ){
for( Coordinate curInstanceCoordinate : instanceOffsets){