bugfixing core RocketComponent placement code
This commit is contained in:
parent
c1d9ff5d41
commit
2ac17cd0d5
@ -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;
|
||||
|
@ -130,7 +130,7 @@ public class Rocket extends RocketComponent {
|
||||
*/
|
||||
public int getStageCount() {
|
||||
checkState();
|
||||
return this.getChildCount();
|
||||
return Stage.getStageCount();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 ////////////
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user