bugfixing core RocketComponent placement code

This commit is contained in:
Daniel_M_Williams 2015-08-01 08:52:37 -04:00
parent c1d9ff5d41
commit 2ac17cd0d5
5 changed files with 90 additions and 211 deletions

View File

@ -2,7 +2,6 @@ package net.sf.openrocket.rocketcomponent;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.EventListener;
import java.util.EventObject;
import java.util.Iterator;
@ -29,7 +28,7 @@ public class Configuration implements Cloneable, ChangeSource, ComponentChangeLi
Iterable<RocketComponent>, Monitorable {
private Rocket rocket;
private BitSet stages = new BitSet();
private BitSet stagesActive = new BitSet();
private String flightConfigurationId = null;
@ -68,8 +67,8 @@ public class Configuration implements Cloneable, ChangeSource, ComponentChangeLi
public void setAllStages() {
stages.clear();
stages.set(0, rocket.getStageCount());
stagesActive.clear();
stagesActive.set(0, Stage.getStageCount());
fireChangeEvent();
}
@ -81,15 +80,15 @@ public class Configuration implements Cloneable, ChangeSource, ComponentChangeLi
* @param stage the stage number.
*/
public void setToStage(int stage) {
stages.clear();
stages.set(0, stage + 1, true);
stagesActive.clear();
stagesActive.set(0, stage + 1, true);
// stages.set(stage+1, rocket.getStageCount(), false);
fireChangeEvent();
}
public void setOnlyStage(int stage) {
stages.clear();
stages.set(stage, stage + 1, true);
stagesActive.clear();
stagesActive.set(stage, stage + 1, true);
fireChangeEvent();
}
@ -108,33 +107,33 @@ public class Configuration implements Cloneable, ChangeSource, ComponentChangeLi
* Check whether the stage specified by the index is active.
*/
public boolean isStageActive(int stage) {
if (stage >= rocket.getStageCount())
if (stage >= Stage.getStageCount())
return false;
return stages.get(stage);
return stagesActive.get(stage);
}
public int getStageCount() {
return rocket.getStageCount();
return Stage.getStageCount();
}
public int getActiveStageCount() {
int count = 0;
int s = rocket.getStageCount();
int s = Stage.getStageCount();
for (int i = 0; i < s; i++) {
if (stages.get(i))
if (stagesActive.get(i))
count++;
}
return count;
}
public int[] getActiveStages() {
int stageCount = rocket.getStageCount();
int stageCount = Stage.getStageCount();
List<Integer> active = new ArrayList<Integer>();
int[] ret;
for (int i = 0; i < stageCount; i++) {
if (stages.get(i)) {
if (stagesActive.get(i)) {
active.add(i);
}
}
@ -262,7 +261,7 @@ public class Configuration implements Cloneable, ChangeSource, ComponentChangeLi
/**
* Return the bounds of the current configuration. The bounds are cached.
*
* @return a <code>Collection</code> containing coordinates bouding the rocket.
* @return a <code>Collection</code> containing coordinates bounding the rocket.
*/
public Collection<Coordinate> getBounds() {
if (rocket.getModID() != boundsModID) {
@ -313,9 +312,30 @@ public class Configuration implements Cloneable, ChangeSource, ComponentChangeLi
*/
@Override
public Iterator<RocketComponent> iterator() {
return new ConfigurationIterator();
List<RocketComponent> accumulator = new ArrayList<RocketComponent>();
accumulator = this.getActiveComponents(accumulator, rocket.getChildren());
return accumulator.iterator();
}
private List<RocketComponent> getActiveComponents(List<RocketComponent> accumulator, final List<RocketComponent> toScan) {
for (RocketComponent rc : toScan) {
if (rc instanceof Stage) {
if (isStageActive(rc.getStageNumber())) {
// recurse to children
getActiveComponents(accumulator, rc.getChildren());
} else {
continue;
}
} else {
accumulator.add(rc);
}
}
return accumulator;
}
/**
* Return an iterator that iterates over all <code>MotorMount</code>s within the
@ -337,7 +357,7 @@ public class Configuration implements Cloneable, ChangeSource, ComponentChangeLi
try {
Configuration config = (Configuration) super.clone();
config.listenerList = new ArrayList<EventListener>();
config.stages = (BitSet) this.stages.clone();
config.stagesActive = (BitSet) this.stagesActive.clone();
config.cachedBounds = new ArrayList<Coordinate>();
config.boundsModID = -1;
config.refLengthModID = -1;
@ -354,68 +374,6 @@ public class Configuration implements Cloneable, ChangeSource, ComponentChangeLi
return modID + rocket.getModID();
}
/**
* A class that iterates over all currently active components.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
private class ConfigurationIterator implements Iterator<RocketComponent> {
Iterator<Iterator<RocketComponent>> iterators;
Iterator<RocketComponent> current = null;
public ConfigurationIterator() {
List<Iterator<RocketComponent>> list = new ArrayList<Iterator<RocketComponent>>();
for (RocketComponent stage : rocket.getChildren()) {
if (isComponentActive(stage)) {
list.add(stage.iterator(false));
}
}
// Get iterators and initialize current
iterators = list.iterator();
if (iterators.hasNext()) {
current = iterators.next();
} else {
List<RocketComponent> l = Collections.emptyList();
current = l.iterator();
}
}
@Override
public boolean hasNext() {
if (!current.hasNext())
getNextIterator();
return current.hasNext();
}
@Override
public RocketComponent next() {
if (!current.hasNext())
getNextIterator();
return current.next();
}
/**
* Get the next iterator that has items. If such an iterator does
* not exist, current is left to an empty iterator.
*/
private void getNextIterator() {
while ((!current.hasNext()) && iterators.hasNext()) {
current = iterators.next();
}
}
@Override
public void remove() {
throw new UnsupportedOperationException("remove unsupported");
}
}
private class MotorIterator implements Iterator<MotorMount> {
private final Iterator<RocketComponent> iterator;
private MotorMount next = null;

View File

@ -130,7 +130,7 @@ public class Rocket extends RocketComponent {
*/
public int getStageCount() {
checkState();
return this.getChildCount();
return Stage.getStageCount();
}

View File

@ -1068,10 +1068,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
}
protected void update() {
if (null == this.parent) {
return;
}
this.setAxialOffset(this.relativePosition, this.offset);
}
@ -1092,17 +1088,29 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
/**
* Returns coordinate c in absolute/global/rocket coordinates. Equivalent to toComponent(c,null).
* Input coordinate C is interpreted to be position relative to this component's *center*, just as
* this component's center is the root of the component coordinate frame.
*
* @param c Coordinate in the component's coordinate system.
* @return an array of coordinates describing <code>c</code> in global coordinates.
*/
public Coordinate[] toAbsolute(Coordinate c) {
// checkState();
// return toRelative(c, null);
checkState();
Coordinate absCoord = this.getAbsolutePositionVector().add(c);
return new Coordinate[] { absCoord };
}
// public Coordinate[] toAbsolute(final Coordinate[] toMove) {
// Coordinate[] toReturn = new Coordinate[toMove.length];
//
// Coordinate translation = this.getAbsolutePositionVector();
// for (int coordIndex = 0; coordIndex < toMove.length; coordIndex++) {
// toReturn[coordIndex] = translation.add(toMove[coordIndex]);
// }
// return toReturn;
// }
/**
* Return coordinate <code>c</code> described in the coordinate system of
* <code>dest</code>. If <code>dest</code> is <code>null</code> returns
@ -1122,126 +1130,39 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
*/
@Deprecated
public final Coordinate[] toRelative(Coordinate c, RocketComponent dest) {
checkState();
mutex.lock("toRelative");
if (null == dest) {
throw new BugException("calling toRelative(c,null) is being refactored. ");
}
try {
double absoluteX = Double.NaN;
double relativeX = 0;
double relativeY = 0;
double relativeZ = 0;
RocketComponent search = dest;
Coordinate[] array = new Coordinate[1];
array[0] = c;
RocketComponent component = this;
while ((component != search) && (component.parent != null)) {
array = component.shiftCoordinates(array);
switch (component.relativePosition) {
case TOP:
for (int i = 0; i < array.length; i++) {
array[i] = array[i].add(relativeX, relativeY, relativeZ);
}
break;
case MIDDLE:
relativeX = component.position.x;
for (int i = 0; i < array.length; i++) {
array[i] = array[i].add(relativeX + (component.parent.length - component.length) / 2,
relativeY, relativeZ);
}
break;
case BOTTOM:
relativeX = component.position.x;
for (int i = 0; i < array.length; i++) {
array[i] = array[i].add(relativeX + (component.parent.length - component.length),
relativeY, relativeZ);
}
break;
case AFTER:
relativeX = component.position.x;
// Add length of all previous brother-components with POSITION_RELATIVE_AFTER
int index = component.parent.children.indexOf(component);
assert (index >= 0);
for (index--; index >= 0; index--) {
RocketComponent comp = component.parent.children.get(index);
double componentLength = comp.getTotalLength();
for (int i = 0; i < array.length; i++) {
array[i] = array[i].add(componentLength, relativeY, relativeZ);
}
}
for (int i = 0; i < array.length; i++) {
array[i] = array[i].add(relativeX + component.parent.length, relativeY, relativeZ);
}
break;
case ABSOLUTE:
search = null; // Requires back-search if dest!=null
if (Double.isNaN(absoluteX)) {
// TODO: requires debugging if thsi component is an External Pods or stage
absoluteX = relativeX;
}
break;
default:
throw new BugException("Unknown relative positioning type of component" +
component + ": " + component.relativePosition);
}
component = component.parent; // parent != null
}
if (!Double.isNaN(absoluteX)) {
for (int i = 0; i < array.length; i++) {
// TODO: requires debugging if thsi component is an External Pods or stage
array[i] = array[i].setX(absoluteX + c.x);
}
}
// Check whether destination has been found or whether to backtrack
// TODO: LOW: Backtracking into clustered components uses only one component
if ((dest != null) && (component != dest)) {
Coordinate origin = dest.getAbsolutePositionVector();
for (int i = 0; i < array.length; i++) {
array[i] = array[i].sub(origin);
}
}
return array;
} finally {
mutex.unlock("toRelative");
}
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 };
mutex.unlock("toRelative");
return toReturn;
}
// public final Coordinate[] toRelative(Coordinate[] coords, RocketComponent dest) {
// Coordinate[] toReturn = new Coordinate[coords.length];
//
//
// // Coordinate[] array = new Coordinate[] { c };
// // // if( dest.isCluster() ){
// // // if( dest.multiplicity > 1){
// // array = dest.shiftCoordinates(array);
// // return this.toRelative(array, dest);
// // // }
//
// Coordinate destCenter = dest.getAbsolutePositionVector();
// Coordinate thisCenter = this.getAbsolutePositionVector();
// Coordinate relVector = destCenter.sub(thisCenter);
//
// for (int coord_index = 0; coord_index < coords.length; coord_index++) {
// toReturn[coord_index] = coords[coord_index].add(relVector);
// }
// 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.");
}
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);
}
return toReturn;
}
/**
* Iteratively sum the lengths of all subcomponents that have position
@ -1266,7 +1187,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
}
/////////// Total mass and CG calculation ////////////
/**

View File

@ -36,8 +36,10 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
Stage.stageCount++;
}
protected String toPositionString() {
return ">> " + this.getName() + " rel: " + this.getRelativePositionVector().x + " abs: " + this.getAbsolutePositionVector().x;
@Override
public boolean allowsChildren() {
return true;
}
@ -47,13 +49,12 @@ public class Stage extends ComponentAssembly implements FlightConfigurableCompon
return trans.get("Stage.Stage");
}
public FlightConfiguration<StageSeparationConfiguration> getStageSeparationConfiguration() {
return separationConfigurations;
public static int getStageCount() {
return Stage.stageCount;
}
@Override
public boolean allowsChildren() {
return true;
public FlightConfiguration<StageSeparationConfiguration> getStageSeparationConfiguration() {
return separationConfigurations;
}
// not strictly accurate, but this should provide an acceptable estimate for total vehicle size

View File

@ -59,7 +59,7 @@ public final class Coordinate implements Cloneable, Serializable {
//////// End debug section
public static final Coordinate ZERO = new Coordinate(0, 0, 0, 0);
public static final Coordinate NUL = new Coordinate(0, 0, 0, 0);
public static final Coordinate NaN = new Coordinate(Double.NaN, Double.NaN,
Double.NaN, Double.NaN);
@ -151,7 +151,7 @@ public final class Coordinate implements Cloneable, Serializable {
/**
* Subtract a Coordinate from this Coordinate. The weight of the resulting Coordinate
* is the same as of this Coordinate, the weight of the argument is ignored.
* is the same as of this Coordinate; i.e. the weight of the argument is ignored.
*
* @param other Coordinate to subtract from this.
* @return The result