[refactor] RocketComponent positioning is now centralized in AxialMethod class

- also relaxed visibility for Component::setAxialMethod(...)
This commit is contained in:
Daniel_M_Williams 2018-09-16 11:54:48 -04:00
parent 7d813b4e55
commit b268d3aa59
25 changed files with 146 additions and 341 deletions

@ -325,7 +325,8 @@ class FinSetHandler extends AbstractElementHandler {
result.setBaseRotation(radialAngle); result.setBaseRotation(radialAngle);
result.setCrossSection(convertTipShapeCode(tipShapeCode)); result.setCrossSection(convertTipShapeCode(tipShapeCode));
result.setAxialMethod(axialMethod); result.setAxialMethod(axialMethod);
PositionDependentHandler.setLocation(result, axialMethod, location); result.setAxialOffset(location);
return result; return result;
} }

@ -15,7 +15,6 @@ import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.material.Material; import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.InnerTube; import net.sf.openrocket.rocketcomponent.InnerTube;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
/** /**
* A SAX handler for Rocksim inside tubes. * A SAX handler for Rocksim inside tubes.
@ -99,17 +98,6 @@ class InnerBodyTubeHandler extends PositionDependentHandler<InnerTube> {
return bodyTube; return bodyTube;
} }
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
@Override
public void setAxialMethod(AxialMethod position) {
bodyTube.setAxialMethod(position);
}
/** /**
* Get the required type of material for this component. * Get the required type of material for this component.
* *

@ -16,7 +16,6 @@ import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.material.Material; import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.LaunchLug; import net.sf.openrocket.rocketcomponent.LaunchLug;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
/** /**
* The SAX handler for Rocksim Launch Lugs. * The SAX handler for Rocksim Launch Lugs.
@ -91,17 +90,6 @@ class LaunchLugHandler extends PositionDependentHandler<LaunchLug> {
return lug; return lug;
} }
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param newMethod the OpenRocket position
*/
@Override
public void setAxialMethod(AxialMethod newMethod) {
lug.setAxialMethod(newMethod);
}
/** /**
* Get the required type of material for this component. * Get the required type of material for this component.
* *

@ -17,7 +17,6 @@ import net.sf.openrocket.rocketcomponent.MassComponent;
import net.sf.openrocket.rocketcomponent.MassObject; import net.sf.openrocket.rocketcomponent.MassObject;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.ShockCord; import net.sf.openrocket.rocketcomponent.ShockCord;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -184,17 +183,6 @@ class MassObjectHandler extends PositionDependentHandler<MassObject> {
return current; return current;
} }
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
@Override
public void setAxialMethod( AxialMethod position) {
current.setAxialMethod(position);
}
/** /**
* Get the required type of material for this component. Does not apply to MassComponents, but does apply to Shock * Get the required type of material for this component. Does not apply to MassComponents, but does apply to Shock
* Cords. * Cords.

@ -15,18 +15,18 @@ import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
/** /**
* An abstract base class that handles position dependencies for all lower level components that * An abstract base class that handles axialMethod dependencies for all lower level components that
* are position aware. * are axialMethod aware.
* *
* @param <C> the specific position dependent RocketComponent subtype for which the concrete handler can create * @param <C> the specific axialMethod dependent RocketComponent subtype for which the concrete handler can create
*/ */
public abstract class PositionDependentHandler<C extends RocketComponent> extends BaseHandler<C> { public abstract class PositionDependentHandler<C extends RocketComponent> extends BaseHandler<C> {
/** Temporary position value. */ /** Temporary axialMethod value. */
private Double positionValue = 0d; private Double positionValue = 0d;
/** Temporary position. */ /** Temporary axialMethod. */
private AxialMethod position = AxialMethod.TOP; private AxialMethod axialMethod = AxialMethod.TOP;
public PositionDependentHandler(DocumentLoadingContext context) { public PositionDependentHandler(DocumentLoadingContext context) {
super(context); super(context);
@ -43,15 +43,15 @@ public abstract class PositionDependentHandler<C extends RocketComponent> extend
positionValue = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH; positionValue = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH;
} }
if (RocksimCommonConstants.LOCATION_MODE.equals(element)) { if (RocksimCommonConstants.LOCATION_MODE.equals(element)) {
position = RocksimLocationMode.fromCode(Integer.parseInt( axialMethod = RocksimLocationMode.fromCode(Integer.parseInt(
content)).asOpenRocket(); content)).asOpenRocket();
} }
} }
/** /**
* This method sets the position information onto the component. Rocksim splits the location/position * This method sets the axialMethod information onto the component. Rocksim splits the location/axialMethod
* information into two disparate data elements. Both pieces of data are necessary to map into OpenRocket's * information into two disparate data elements. Both pieces of data are necessary to map into OpenRocket's
* position model. * axialMethod model.
* *
* @param element the element name * @param element the element name
* @param attributes the attributes * @param attributes the attributes
@ -63,31 +63,18 @@ public abstract class PositionDependentHandler<C extends RocketComponent> extend
public void endHandler(String element, HashMap<String, String> attributes, public void endHandler(String element, HashMap<String, String> attributes,
String content, WarningSet warnings) throws SAXException { String content, WarningSet warnings) throws SAXException {
super.endHandler(element, attributes, content, warnings); super.endHandler(element, attributes, content, warnings);
setAxialMethod(position); setLocation();
setLocation(getComponent(), position, positionValue);
} }
/** /**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not * Set the axialMethod of a component.
* public in all components.
*
* @param position the OpenRocket position
*/ */
protected abstract void setAxialMethod(AxialMethod position); protected void setLocation() {
getComponent().setAxialMethod(axialMethod);
/** if (axialMethod.equals(AxialMethod.BOTTOM)) {
* Set the position of a component. getComponent().setAxialOffset(-1d * positionValue);
* } else {
* @param component the component getComponent().setAxialOffset(positionValue);
* @param position the relative position
* @param location the actual position value
*/
public static void setLocation(RocketComponent component, AxialMethod position, double location) {
if (position.equals(AxialMethod.BOTTOM)) {
component.setAxialOffset(-1d * location);
}
else {
component.setAxialOffset(location);
} }
} }

@ -11,7 +11,6 @@ import net.sf.openrocket.file.rocksim.RocksimCommonConstants;
import net.sf.openrocket.file.rocksim.RocksimDensityType; import net.sf.openrocket.file.rocksim.RocksimDensityType;
import net.sf.openrocket.material.Material; import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.RecoveryDevice; import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -95,18 +94,7 @@ public abstract class RecoveryDeviceHandler<C extends RecoveryDevice> extends Po
} }
return result; return result;
} }
/**
* Set the relative position onto the component. This cannot be done directly because setRelativePosition is not
* public in all components.
*
* @param position the OpenRocket position
*/
@Override
public void setAxialMethod( AxialMethod position) {
getComponent().setAxialMethod(position);
}
/** /**
* Get the required type of material for this component. This is the OpenRocket type, which does NOT always * Get the required type of material for this component. This is the OpenRocket type, which does NOT always
* correspond to Rocksim. Some streamer material is defined as BULK in the Rocksim file. In those cases * correspond to Rocksim. Some streamer material is defined as BULK in the Rocksim file. In those cases

@ -19,7 +19,6 @@ import net.sf.openrocket.rocketcomponent.EngineBlock;
import net.sf.openrocket.rocketcomponent.RingComponent; import net.sf.openrocket.rocketcomponent.RingComponent;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.TubeCoupler; import net.sf.openrocket.rocketcomponent.TubeCoupler;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
/** /**
* A SAX handler for centering rings, tube couplers, and bulkheads. * A SAX handler for centering rings, tube couplers, and bulkheads.
@ -180,17 +179,6 @@ class RingHandler extends PositionDependentHandler<CenteringRing> {
result.setThickness(result.getThickness()); result.setThickness(result.getThickness());
} }
/**
* Set the relative position onto the component. This cannot be done directly because setAxialMethod is not
* public in all components.
*
* @param position the OpenRocket position
*/
@Override
public void setAxialMethod(AxialMethod position) {
ring.setAxialMethod(position);
}
@Override @Override
public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException { public void endHandler(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
super.endHandler(element, attributes, content, warnings); super.endHandler(element, attributes, content, warnings);

@ -9,7 +9,6 @@ import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.material.Material; import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.TubeFinSet; import net.sf.openrocket.rocketcomponent.TubeFinSet;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -34,25 +33,14 @@ public class TubeFinSetHandler extends PositionDependentHandler<TubeFinSet> {
* @throws IllegalArgumentException thrown if <code>c</code> is null * @throws IllegalArgumentException thrown if <code>c</code> is null
*/ */
public TubeFinSetHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) throws IllegalArgumentException { public TubeFinSetHandler(DocumentLoadingContext context, RocketComponent c, WarningSet warnings) throws IllegalArgumentException {
super(context); super(context);
if (c == null) { if (c == null) {
throw new IllegalArgumentException("The parent component of a tube fin may not be null."); throw new IllegalArgumentException("The parent component of a tube fin may not be null.");
} }
tubeFin = new TubeFinSet(); tubeFin = new TubeFinSet();
if (isCompatible(c, TubeFinSet.class, warnings)) { if (isCompatible(c, TubeFinSet.class, warnings)) {
c.addChild(tubeFin); c.addChild(tubeFin);
} }
}
/**
* Set the relative position onto the component.
*
* @param position the OpenRocket position
*/
@Override
protected void setAxialMethod(final AxialMethod position) {
tubeFin.setAxialMethod(position);
} }
/** /**

@ -32,7 +32,11 @@ public abstract class ComponentAssembly extends RocketComponent implements Axia
public ComponentAssembly() { public ComponentAssembly() {
super( AxialMethod.AFTER); super( AxialMethod.AFTER);
} }
public ComponentAssembly( final AxialMethod initialAxialMethod) {
super(initialAxialMethod);
}
@Override @Override
public boolean allowsChildren(){ public boolean allowsChildren(){
return true; return true;
@ -40,7 +44,7 @@ public abstract class ComponentAssembly extends RocketComponent implements Axia
@Override @Override
public double getAxialOffset() { public double getAxialOffset() {
return asPositionValue( this.axialMethod ); return getAxialOffset( this.axialMethod );
} }
/** /**

@ -476,7 +476,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
* Copy all available information attached to this, and attached copies to the * Copy all available information attached to this, and attached copies to the
* new configuration * new configuration
* *
* @param copyId attached the new configuration to this Id * @param newId attached the new configuration to this Id
* @return the new configuration * @return the new configuration
*/ */
@Override @Override

@ -21,7 +21,7 @@ public class LaunchLug extends ExternalComponent implements AnglePositionable, C
private double thickness; private double thickness;
private double radialDirection = 0; private double radialDirection = 0;
protected double radialDistance = 0; private double radialDistance = 0;
private int instanceCount = 1; private int instanceCount = 1;
private double instanceSeparation = 0; // front-front along the positive rocket axis. i.e. [1,0,0]; private double instanceSeparation = 0; // front-front along the positive rocket axis. i.e. [1,0,0];
@ -98,15 +98,7 @@ public class LaunchLug extends ExternalComponent implements AnglePositionable, C
public boolean isAfter() { public boolean isAfter() {
return false; return false;
} }
@Override
public void setAxialMethod( AxialMethod position) {
super.setAxialMethod(position);
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
@Override @Override
protected void loadFromPreset(ComponentPreset preset) { protected void loadFromPreset(ComponentPreset preset) {
if (preset.has(ComponentPreset.OUTER_DIAMETER)) { if (preset.has(ComponentPreset.OUTER_DIAMETER)) {

@ -157,7 +157,7 @@ public class PodSet extends ComponentAssembly implements RingInstanceable {
// remember the implicit (this instanceof Stage) // remember the implicit (this instanceof Stage)
throw new BugException("found a pod positioned via: AFTER, but is not on the centerline?!: " + this.getName() + " is " + this.getAxialMethod().name() ); throw new BugException("found a pod positioned via: AFTER, but is not on the centerline?!: " + this.getName() + " is " + this.getAxialMethod().name() );
} else { } else {
returnValue = super.asPositionValue(this.axialMethod); returnValue = super.getAxialOffset(this.axialMethod);
} }
if (0.000001 > Math.abs(returnValue)) { if (0.000001 > Math.abs(returnValue)) {

@ -11,8 +11,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import net.sf.openrocket.startup.Application; import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.ArrayList; import net.sf.openrocket.util.ArrayList;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.StateChangeListener; import net.sf.openrocket.util.StateChangeListener;
import net.sf.openrocket.util.UniqueID; import net.sf.openrocket.util.UniqueID;
@ -74,6 +76,7 @@ public class Rocket extends ComponentAssembly {
///////////// Constructor ///////////// ///////////// Constructor /////////////
public Rocket() { public Rocket() {
super(AxialMethod.ABSOLUTE);
modID = UniqueID.next(); modID = UniqueID.next();
massModID = modID; massModID = modID;
aeroModID = modID; aeroModID = modID;
@ -244,7 +247,18 @@ public class Rocket extends ComponentAssembly {
/*package-local*/ void forgetStage(final AxialStage oldStage) { /*package-local*/ void forgetStage(final AxialStage oldStage) {
this.stageMap.remove(oldStage.getStageNumber()); this.stageMap.remove(oldStage.getStageNumber());
} }
@Override
public void setAxialMethod(final AxialMethod newAxialMethod) {
this.axialMethod = AxialMethod.ABSOLUTE;
}
@Override
public void setAxialOffset( final double requestOffset ) {
this.axialOffset = 0.;
this.position = Coordinate.ZERO;
}
public ReferenceType getReferenceType() { public ReferenceType getReferenceType() {
checkState(); checkState();
return refType; return refType;
@ -707,9 +721,9 @@ public class Rocket extends ComponentAssembly {
* Return a flight configuration. If the supplied index is out of bounds, an exception is thrown. * Return a flight configuration. If the supplied index is out of bounds, an exception is thrown.
* If the default instance is allowed, the default will be at index 0. * If the default instance is allowed, the default will be at index 0.
* *
* @param includeDefault Whether to allow returning the default instance * @param allowDefault Whether to allow returning the default instance
* @param configIndex The flight configuration index number * @param configIndex The flight configuration index number
* @return a FlightConfiguration instance * @return FlightConfiguration instance
*/ */
public FlightConfiguration getFlightConfigurationByIndex( int configIndex, final boolean allowDefault ) { public FlightConfiguration getFlightConfigurationByIndex( int configIndex, final boolean allowDefault ) {
if( allowDefault ){ if( allowDefault ){

@ -910,7 +910,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
/** /**
* Get the positioning of the component relative to its parent component. * Get the positioning of the component relative to its parent component.
* This is one of the enums of {@link Position}. A setter method is not provided, * This is one of the enums of {@link AxialMethod}. A setter method is not provided,
* but can be provided by a subclass. * but can be provided by a subclass.
*/ */
public final AxialMethod getAxialMethod() { public final AxialMethod getAxialMethod() {
@ -929,7 +929,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
* *
* @param newAxialMethod the relative positioning. * @param newAxialMethod the relative positioning.
*/ */
protected void setAxialMethod(final AxialMethod newAxialMethod) { public void setAxialMethod(final AxialMethod newAxialMethod) {
if (newAxialMethod == this.axialMethod) { if (newAxialMethod == this.axialMethod) {
// no change. // no change.
return; return;
@ -938,44 +938,32 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
// this variable does not change the internal representation // 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. // the relativePosition (method) is just the lens through which external code may view this component's position.
this.axialMethod = newAxialMethod; this.axialMethod = newAxialMethod;
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
} }
/** /**
* Determine position relative to given position argument. Note: This is a side-effect free method. No state * Determine position relative to given position argument. Note: This is a side-effect free method. No state
* is modified. * is modified.
* *
* @param outOffsetMethod the relative position to be used as the basis for the computation * @param asMethod the relative positioning method to be used for the computation
* @param relativeTo the position is computed relative the the given component
* *
* @return double position of the component relative to the parent, with respect to <code>position</code> * @return double position of the component relative to the parent, with respect to <code>position</code>
*/ */
public double asPositionValue(AxialMethod asMethod) { public double getAxialOffset(AxialMethod asMethod) {
double parentLength = 0; double parentLength = 0;
if (null != this.parent) { if (null != this.parent) {
parentLength = this.parent.length; parentLength = this.parent.length;
} }
double result = Double.NaN; if(AxialMethod.ABSOLUTE == asMethod){
if( AxialMethod.AFTER == asMethod) { return this.getComponentLocations()[0].x;
result = this.position.x - parentLength;
}else if( AxialMethod.ABSOLUTE == asMethod) {
result = this.getComponentLocations()[0].x;
}else if( AxialMethod.TOP == asMethod) {
result = this.position.x;
}else if( AxialMethod.MIDDLE == asMethod) {
result = this.position.x + ( this.length - parentLength) / 2;
}else if( AxialMethod.BOTTOM == asMethod) {
result = this.position.x + ( this.length - parentLength);
}else { }else {
throw new BugException("Unknown position type: " + asMethod.name() ); return asMethod.getAsOffset(this.position.x, this.length, parentLength);
} }
return result;
} }
public double getAxialOffset() { public double getAxialOffset() {
mutex.verify(); return this.axialOffset;
return this.asPositionValue(this.axialMethod);
} }
public double getRadiusOffset() { public double getRadiusOffset() {
@ -1003,7 +991,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
return false; return false;
} }
protected void setAfter() { protected void setAfter() {
checkState(); checkState();
@ -1013,87 +1000,59 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
} }
// if first component in the stage. => position from the top of the parent // if first component in the stage. => position from the top of the parent
double newAxialPosition= 0;
final int thisIndex = this.parent.getChildPosition( this ); final int thisIndex = this.parent.getChildPosition( this );
if( 0 < thisIndex ) { if( 0 < thisIndex ) {
RocketComponent referenceComponent = parent.getChild( thisIndex - 1 ); RocketComponent referenceComponent = parent.getChild( thisIndex - 1 );
double refLength = referenceComponent.getLength(); double refLength = referenceComponent.getLength();
double refRelX = referenceComponent.getPosition().x; double refRelX = referenceComponent.getPosition().x;
newAxialPosition = refRelX + refLength; this.axialMethod = AxialMethod.AFTER;
this.axialOffset = 0.;
this.position = this.position.setX(refRelX + refLength);
} }
this.position = this.position.setX( newAxialPosition );
} }
/** /**
* Set the position value of the component. The exact meaning of the value * Set the position value of the component. The exact meaning of the value
* depends on the current relative positioning. * depends on the current relative positioning.
* <p> *
* Mince many components do not support setting the relative position. A component that does support * @param newOffset the position value of the component.
* it should override this with a public method that simply calls this
* supermethod AND fire a suitable ComponentChangeEvent.
*
* @param value the position value of the component.
*/ */
public void setAxialOffset(double _value) { public void setAxialOffset(double newOffset) {
this.setAxialOffset(this.axialMethod, _value); this.setAxialOffset(this.axialMethod, newOffset);
this.fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); this.fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
} }
final protected void setAxialOffset( final AxialMethod requestedMethod, final double requestedOffset) {
protected void setAxialOffset( final AxialMethod requestedMethod, double requestedOffset) {
checkState(); checkState();
AxialMethod newMethod = requestedMethod;
double newOffset = requestedOffset;
double newX = Double.NaN; double newX = Double.NaN;
if ( this.isAfter()){ if (null == this.parent) {
newMethod= AxialMethod.AFTER;
}
if( this instanceof Rocket ){
newMethod = AxialMethod.ABSOLUTE;
newOffset = 0.;
newX = 0.;
}else if(null == this.parent) {
// best-effort approximation. this should be corrected later on in the initialization process. // best-effort approximation. this should be corrected later on in the initialization process.
newX = newOffset; newX = requestedOffset;
}else { } else if (AxialMethod.ABSOLUTE == requestedMethod){
final double refLength = this.parent.getLength(); // in this case, this is simply the intended result
newX = requestedOffset - this.parent.getComponentLocations()[0].x;
if( AxialMethod.ABSOLUTE == newMethod) { } else if ( this.isAfter()){
newX = newOffset - this.parent.getComponentLocations()[0].x; this.setAfter();
}else if( AxialMethod.AFTER == newMethod) { return;
newOffset = 0; } else {
this.setAfter(); newX = requestedMethod.getAsPosition(requestedOffset, this.length, this.parent.getLength());
newX = this.position.x;
}else if( AxialMethod.TOP == newMethod) {
newX = newOffset;
}else if( AxialMethod.MIDDLE == newMethod) {
newX = (refLength - this.length) / 2 + newOffset;
}else if( AxialMethod.BOTTOM == newMethod) {
newX = (refLength - this.length) + newOffset;
}else{
throw new BugException("Unknown position type: " + this.axialMethod);
}
} }
// snap to zero if less than the threshold 'EPSILON' // snap to zero if less than the threshold 'EPSILON'
final double EPSILON = 0.000001; final double EPSILON = 0.000001;
if (EPSILON > Math.abs(newX)) { if (EPSILON > Math.abs(newX)) {
newX = 0.0; newX = 0.0;
} } else if (Double.isNaN(newX)){
if (Double.isNaN(newX)){
throw new BugException("setAxialOffset is broken -- attempted to update as NaN: " + this.toDebugDetail()); throw new BugException("setAxialOffset is broken -- attempted to update as NaN: " + this.toDebugDetail());
} }
this.axialMethod = newMethod; // store for later:
this.axialOffset = newOffset; this.axialMethod = requestedMethod;
this.axialOffset = requestedOffset;
this.position = this.position.setX( newX ); this.position = this.position.setX( newX );
} }
@ -1118,12 +1077,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
* For example, the absolute position of any given instance is the parent's position * For example, the absolute position of any given instance is the parent's position
* plus the instance position returned by this method * plus the instance position returned by this method
* <p> * <p>
* NOTE: this default implementation simply returns this.position
* NOTE: the length of this array returned always equals this.getInstanceCount() * NOTE: the length of this array returned always equals this.getInstanceCount()
* *
* @param c an array of coordinates to shift. * @return an generated (i.e. new) array of instance locations
* @return an array of shifted coordinates. The method may modify the contents
* of the passed array and return the array itself.
*/ */
// @Override Me ! // @Override Me !
public Coordinate[] getInstanceLocations(){ public Coordinate[] getInstanceLocations(){
@ -1142,13 +1098,14 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
/** /**
* Provides locations of all instances of component relative to this component's reference point * Provides locations of all instances of component relative to this component's reference point
* *
* <p> * <p>
* NOTE: the length of this array returned always equals this.getInstanceCount() * NOTE: the length of this array returned always equals this.getInstanceCount()
* @return * NOTE: default implementation just returns (0,0,0)
*
* @returns returns an array of coordinates, relative to its parent's position
*/ */
public Coordinate[] getInstanceOffsets(){ public Coordinate[] getInstanceOffsets(){
// According to the language specification, Java will initialized double values to 0.0
return new Coordinate[]{Coordinate.ZERO}; return new Coordinate[]{Coordinate.ZERO};
} }
@ -1159,13 +1116,15 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
return getComponentLocations(); return getComponentLocations();
} }
/** /**
* Provides locations of all instances of component *accounting for all parent instancing* * Provides locations of all instances of component *accounting for all parent instancing*
* *
* <p> * <p>
* NOTE: the length of this array MAY OR MAY NOT EQUAL this.getInstanceCount() * NOTE: the length of this array MAY OR MAY NOT EQUAL this.getInstanceCount()
* @return * --> RocketComponent::getInstanceCount() counts how many times this component replicates on its own
* --> vs. the total instance count due to parent assembly instancing
*
* @return Coordinates of all instance locations in the rocket, relative to the rocket's origin
*/ */
public Coordinate[] getComponentLocations() { public Coordinate[] getComponentLocations() {
if (null == this.parent) { if (null == this.parent) {
@ -1175,23 +1134,20 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
Coordinate[] parentPositions = this.parent.getComponentLocations(); Coordinate[] parentPositions = this.parent.getComponentLocations();
int parentCount = parentPositions.length; int parentCount = parentPositions.length;
// override <instance>.getInstanceOffsets() in the subclass you want to fix. // override <instance>.getInstanceLocations() in each subclass
Coordinate[] instanceOffsets = this.getInstanceLocations(); Coordinate[] instanceLocations = this.getInstanceLocations();
int instanceCount = instanceOffsets.length; int instanceCount = instanceLocations.length;
// usual case optimization // usual case optimization
if((1 == parentCount)&&(1 == instanceCount)){ if((1 == parentCount)&&(1 == instanceCount)){
return new Coordinate[]{parentPositions[0].add(instanceOffsets[0])}; return new Coordinate[]{parentPositions[0].add(instanceLocations[0])};
} }
int thisCount = instanceCount*parentCount; int thisCount = instanceCount*parentCount;
Coordinate[] thesePositions = new Coordinate[thisCount]; Coordinate[] thesePositions = new Coordinate[thisCount];
for (int pi = 0; pi < parentCount; pi++) { for (int pi = 0; pi < parentCount; pi++) {
for( int ii = 0; ii < instanceCount; ii++ ){ for( int ii = 0; ii < instanceCount; ii++ ){
// System.err.println(" #"+pi+", "+ii+" = "+(pi + parentCount*ii)); thesePositions[pi + parentCount*ii] = parentPositions[pi].add(instanceLocations[ii]);
// System.err.println(" "+parentPositions[pi]+" + "+instanceOffsets[ii]);
thesePositions[pi + parentCount*ii] = parentPositions[pi].add(instanceOffsets[ii]);
// System.err.println(" ="+thesePositions[pi+parentCount*ii]);
} }
} }
return thesePositions; return thesePositions;
@ -1228,17 +1184,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
mutex.unlock(lockText); mutex.unlock(lockText);
return toReturn; return toReturn;
} }
// 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 * Return coordinate <code>c</code> described in the coordinate system of
* <code>dest</code>. If <code>dest</code> is <code>null</code> returns * <code>dest</code>. If <code>dest</code> is <code>null</code> returns

@ -31,9 +31,9 @@ public enum AxialMethod implements DistanceMethod {
@Override @Override
public double getAsOffset(double position, double innerLength, double outerLength){ public double getAsOffset(double position, double innerLength, double outerLength){
return outerLength - position; return position - outerLength;
} }
}, },
// measure from the top of the target component to the top of the subject component // measure from the top of the target component to the top of the subject component
TOP (Application.getTranslator().get("RocketComponent.Position.Method.Axial.TOP")){ TOP (Application.getTranslator().get("RocketComponent.Position.Method.Axial.TOP")){
@ -60,7 +60,7 @@ public enum AxialMethod implements DistanceMethod {
@Override @Override
public double getAsPosition(double offset, double innerLength, double outerLength){ public double getAsPosition(double offset, double innerLength, double outerLength){
return (outerLength - innerLength) / 2 - offset; return offset + (outerLength - innerLength) / 2;
} }
@Override @Override
@ -76,7 +76,7 @@ public enum AxialMethod implements DistanceMethod {
@Override @Override
public double getAsPosition(double offset, double innerLength, double outerLength){ public double getAsPosition(double offset, double innerLength, double outerLength){
return outerLength - innerLength - offset; return offset + (outerLength - innerLength);
} }
@Override @Override

@ -9,7 +9,6 @@ import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.material.Material; import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.InnerTube; import net.sf.openrocket.rocketcomponent.InnerTube;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import org.junit.Assert; import org.junit.Assert;
@ -118,20 +117,6 @@ public class InnerBodyTubeHandlerTest extends RocksimTestBase {
handler.closeElement("Name", attributes, "Test Name", warnings); handler.closeElement("Name", attributes, "Test Name", warnings);
Assert.assertEquals("Test Name", component.getName()); Assert.assertEquals("Test Name", component.getName());
} }
/**
* Method: setRelativePosition(AxialMethod position)
*
* @throws Exception thrown if something goes awry
*/
@org.junit.Test
public void testSetRelativePosition() throws Exception {
BodyTube tube = new BodyTube();
InnerBodyTubeHandler handler = new InnerBodyTubeHandler(null, tube, new WarningSet());
InnerTube component = (InnerTube) getField(handler, "bodyTube");
handler.setAxialMethod(AxialMethod.ABSOLUTE);
Assert.assertEquals(AxialMethod.ABSOLUTE, component.getAxialMethod());
}
/** /**
* Method: getComponent() * Method: getComponent()

@ -10,7 +10,6 @@ import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.ExternalComponent; import net.sf.openrocket.rocketcomponent.ExternalComponent;
import net.sf.openrocket.rocketcomponent.LaunchLug; import net.sf.openrocket.rocketcomponent.LaunchLug;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import org.junit.Assert; import org.junit.Assert;
@ -109,20 +108,6 @@ public class LaunchLugHandlerTest extends RocksimTestBase {
handler.closeElement("Name", attributes, "Test Name", warnings); handler.closeElement("Name", attributes, "Test Name", warnings);
Assert.assertEquals("Test Name", component.getName()); Assert.assertEquals("Test Name", component.getName());
} }
/**
* Method: setRelativePosition(AxialMethod position)
*
* @throws Exception thrown if something goes awry
*/
@org.junit.Test
public void testSetRelativePosition() throws Exception {
BodyTube tube = new BodyTube();
LaunchLugHandler handler = new LaunchLugHandler(null, tube, new WarningSet());
LaunchLug component = (LaunchLug) getField(handler, "lug");
handler.setAxialMethod(AxialMethod.ABSOLUTE);
Assert.assertEquals(AxialMethod.ABSOLUTE, component.getAxialMethod());
}
/** /**
* Method: getComponent() * Method: getComponent()

@ -9,7 +9,6 @@ import net.sf.openrocket.file.simplesax.PlainTextHandler;
import net.sf.openrocket.material.Material; import net.sf.openrocket.material.Material;
import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.MassComponent; import net.sf.openrocket.rocketcomponent.MassComponent;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import org.junit.Assert; import org.junit.Assert;
@ -90,20 +89,6 @@ public class MassObjectHandlerTest extends RocksimTestBase {
warnings.clear(); warnings.clear();
} }
/**
* Method: setRelativePosition(AxialMethod position)
*
* @throws Exception thrown if something goes awry
*/
@org.junit.Test
public void testSetRelativePosition() throws Exception {
BodyTube tube = new BodyTube();
MassObjectHandler handler = new MassObjectHandler(null, tube, new WarningSet());
MassComponent component = (MassComponent) getField(handler, "mass");
handler.setAxialMethod(AxialMethod.ABSOLUTE);
Assert.assertEquals(AxialMethod.ABSOLUTE, component.getAxialMethod());
}
/** /**
* Method: getComponent() * Method: getComponent()

@ -113,7 +113,7 @@ public class ParachuteHandlerTest extends RocksimTestBase {
BodyTube tube = new BodyTube(); BodyTube tube = new BodyTube();
ParachuteHandler handler = new ParachuteHandler(null, tube, new WarningSet()); ParachuteHandler handler = new ParachuteHandler(null, tube, new WarningSet());
Parachute component = (Parachute) getField(handler, "chute"); Parachute component = (Parachute) getField(handler, "chute");
handler.setAxialMethod(AxialMethod.ABSOLUTE); handler.getComponent().setAxialMethod(AxialMethod.ABSOLUTE);
Assert.assertEquals(AxialMethod.ABSOLUTE, component.getAxialMethod()); Assert.assertEquals(AxialMethod.ABSOLUTE, component.getAxialMethod());
} }

@ -246,21 +246,6 @@ public class RingHandlerTest extends RocksimTestBase {
@SuppressWarnings("unused") @SuppressWarnings("unused")
CenteringRing component = (CenteringRing) getField(handler, "ring"); CenteringRing component = (CenteringRing) getField(handler, "ring");
} }
/**
* Method: setAxialMethod(AxialMethod position)
*
* @throws Exception thrown if something goes awry
*/
@org.junit.Test
public void testsetAxialMethod() throws Exception {
BodyTube tube = new BodyTube();
RingHandler handler = new RingHandler(null, tube, new WarningSet());
CenteringRing component = (CenteringRing) getField(handler, "ring");
handler.setAxialMethod(AxialMethod.ABSOLUTE);
Assert.assertEquals(AxialMethod.ABSOLUTE, component.getAxialMethod());
}
/** /**
* Method: getComponent() * Method: getComponent()

@ -109,7 +109,7 @@ public class StreamerHandlerTest extends RocksimTestBase {
BodyTube tube = new BodyTube(); BodyTube tube = new BodyTube();
StreamerHandler handler = new StreamerHandler(null, tube, new WarningSet()); StreamerHandler handler = new StreamerHandler(null, tube, new WarningSet());
Streamer component = (Streamer) getField(handler, "streamer"); Streamer component = (Streamer) getField(handler, "streamer");
handler.setAxialMethod(AxialMethod.ABSOLUTE); handler.getComponent().setAxialMethod(AxialMethod.ABSOLUTE);
Assert.assertEquals(AxialMethod.ABSOLUTE, component.getAxialMethod()); Assert.assertEquals(AxialMethod.ABSOLUTE, component.getAxialMethod());
} }

@ -2,8 +2,7 @@ package net.sf.openrocket.rocketcomponent;
//import junit.framework.TestCase; //import junit.framework.TestCase;
import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.*;
import static org.junit.Assert.assertThat;
import org.junit.Test; import org.junit.Test;
@ -18,20 +17,15 @@ public class ParallelStageTest extends BaseTestCase {
// tolerance for compared double test results // tolerance for compared double test results
protected final double EPSILON = 0.000001; protected final double EPSILON = 0.000001;
protected final Coordinate ZERO = new Coordinate(0., 0., 0.);
/* From OpenRocket Technical Documentation /* From OpenRocket Technical Documentation
* *
* 3.1.4 Coordinate systems * 3.1.4 Coordinate systems
* During calculation of the aerodynamic properties a coordinate system fixed to the rocket will be used. * During calculation of the aerodynamic properties a coordinate system fixed to the rocket will be used.
* The origin of the coordinates is at the nose cone tip with the positive x-axis directed along the rocket * The origin of the coordinates is at the nose cone tip with the positive x-axis directed along the rocket
@@ -41,70 +35,302 @@ public class BodyTubeTest extends TestCase { * when discussing the fins. During simulation, however, the y- and z-axes are fixed in relation to the rocket,
* when discussing the fins. During simulation, however, the y- and z-axes are fixed in relation to the rocket,
* and do not necessarily align with the plane of the pitching moments. * and do not necessarily align with the plane of the pitching moments.
*/ */
public ParallelStage createExtraBooster() { public ParallelStage createExtraBooster() {
double tubeRadius = 0.8; double tubeRadius = 0.8;
@ -60,7 +54,7 @@ public class ParallelStageTest extends BaseTestCase {
@Test @Test
public void testSetRocketPositionFail() { public void testSetRocketPositionFail() {
final Rocket rocket = TestRockets.makeFalcon9Heavy(); final Rocket rocket = TestRockets.makeFalcon9Heavy();
// case 1: the rocket Rocket should be stationary // case 1: the rocket Rocket should be stationary
rocket.setAxialOffset( +4.8 ); rocket.setAxialOffset( +4.8 );
@ -106,10 +100,10 @@ public class ParallelStageTest extends BaseTestCase {
// WARNING: this test will not pass unless 'testAddTopStage' is passing as well -- that function tests the dependencies... // WARNING: this test will not pass unless 'testAddTopStage' is passing as well -- that function tests the dependencies...
@Test @Test
public void testCreateCoreStage() { public void testCreateCoreStage() {
// vvvv function under test vvvv ( which indirectly tests initialization code, and that the test setup creates the preconditions that we expect // vvvv function under test vvvv
final Rocket rocket = TestRockets.makeFalcon9Heavy(); final Rocket rocket = TestRockets.makeFalcon9Heavy();
// ^^^^ function under test ^^^^ // ^^^^ function under test ^^^^
// Payload Stage // Payload Stage
AxialStage payloadStage = (AxialStage)rocket.getChild(0); AxialStage payloadStage = (AxialStage)rocket.getChild(0);
final double expectedPayloadLength = 0.564; final double expectedPayloadLength = 0.564;
@ -195,7 +189,7 @@ public class ParallelStageTest extends BaseTestCase {
assertThat(" 'setInstancecount(int)' failed: ", 2, equalTo(parallelBoosterSet.getInstanceCount())); assertThat(" 'setInstancecount(int)' failed: ", 2, equalTo(parallelBoosterSet.getInstanceCount()));
assertEquals( RadiusMethod.FREE.clampToZero(), false ); assertFalse( RadiusMethod.FREE.clampToZero());
assertEquals(" error while setting radius method: ", RadiusMethod.FREE, parallelBoosterSet.getRadiusMethod() ); assertEquals(" error while setting radius method: ", RadiusMethod.FREE, parallelBoosterSet.getRadiusMethod() );
assertEquals(" error while setting radius offset: ", 2.0, parallelBoosterSet.getRadiusOffset(), EPSILON); assertEquals(" error while setting radius offset: ", 2.0, parallelBoosterSet.getRadiusOffset(), EPSILON);
@ -220,7 +214,7 @@ public class ParallelStageTest extends BaseTestCase {
assertThat(" 'setInstancecount(int)' failed: ", 2, equalTo(parallelBoosterStage.getInstanceCount())); assertThat(" 'setInstancecount(int)' failed: ", 2, equalTo(parallelBoosterStage.getInstanceCount()));
assertEquals( RadiusMethod.SURFACE.clampToZero(), true ); assertTrue( RadiusMethod.SURFACE.clampToZero());
assertEquals(" error while setting radius method: ", RadiusMethod.SURFACE, parallelBoosterStage.getRadiusMethod() ); assertEquals(" error while setting radius method: ", RadiusMethod.SURFACE, parallelBoosterStage.getRadiusMethod() );
assertEquals(" error while setting radius offset: ", 0.0, parallelBoosterStage.getRadiusOffset(), EPSILON); assertEquals(" error while setting radius offset: ", 0.0, parallelBoosterStage.getRadiusOffset(), EPSILON);
@ -260,7 +254,7 @@ public class ParallelStageTest extends BaseTestCase {
parallelBoosterStage.setRadius( RadiusMethod.RELATIVE, targetRadiusOffset ); parallelBoosterStage.setRadius( RadiusMethod.RELATIVE, targetRadiusOffset );
// ^^ function under test // ^^ function under test
assertEquals( RadiusMethod.RELATIVE.clampToZero(), false ); assertFalse(RadiusMethod.RELATIVE.clampToZero());
assertEquals(" error while setting radius method: ", RadiusMethod.RELATIVE, parallelBoosterStage.getRadiusMethod() ); assertEquals(" error while setting radius method: ", RadiusMethod.RELATIVE, parallelBoosterStage.getRadiusMethod() );
assertEquals(" error while setting radius offset: ", targetRadiusOffset, parallelBoosterStage.getRadiusOffset() , EPSILON); assertEquals(" error while setting radius offset: ", targetRadiusOffset, parallelBoosterStage.getRadiusOffset() , EPSILON);
@ -332,16 +326,16 @@ public class ParallelStageTest extends BaseTestCase {
double targetAbsoluteX = 0.8; double targetAbsoluteX = 0.8;
double expectedRelativeX = 0.236; double expectedRelativeX = 0.236;
double expectedAbsoluteX = 0.8; double expectedAbsoluteX = 0.8;
// when subStages should be freely movable // when substages should be freely movable
// vv function under test // vv function under test
boosterStage.setAxialOffset(AxialMethod.ABSOLUTE, targetAbsoluteX); boosterStage.setAxialOffset(AxialMethod.ABSOLUTE, targetAbsoluteX);
// ^^ function under test // ^^ function under test
assertEquals("setAxialOffset( method, double) failed: ", AxialMethod.ABSOLUTE, boosterStage.getAxialMethod() ); assertEquals("setAxialOffset( method, double) failed: ", AxialMethod.ABSOLUTE, boosterStage.getAxialMethod() );
assertEquals("setAxialOffset( method, double) failed: ", targetAbsoluteX, boosterStage.getAxialOffset(), EPSILON ); assertEquals("setAxialOffset( method, double) failed: ", targetAbsoluteX, boosterStage.getAxialOffset(), EPSILON );
double actualRelativeX = boosterStage.asPositionValue(AxialMethod.TOP); double actualRelativeX = boosterStage.getAxialOffset(AxialMethod.TOP);
assertEquals(" 'setAxialPosition(double)' failed: Relative position: ", expectedRelativeX, actualRelativeX, EPSILON ); assertEquals(" 'setAxialPosition(double)' failed: Relative position: ", expectedRelativeX, actualRelativeX, EPSILON );
double actualAbsoluteX = boosterStage.getComponentLocations()[0].x; double actualAbsoluteX = boosterStage.getComponentLocations()[0].x;
@ -410,7 +404,7 @@ public class ParallelStageTest extends BaseTestCase {
final RocketComponent rocket = TestRockets.makeFalcon9Heavy(); final RocketComponent rocket = TestRockets.makeFalcon9Heavy();
final AxialStage coreStage = (AxialStage) rocket.getChild(1); final AxialStage coreStage = (AxialStage) rocket.getChild(1);
final ParallelStage boosterStage = (ParallelStage)coreStage.getChild(0).getChild(0); final ParallelStage boosterStage = (ParallelStage)coreStage.getChild(0).getChild(0);
// when 'external' the stage should be freely movable // when 'external' the stage should be freely movable
// vv function under test // vv function under test
double targetOffset = 0.2; double targetOffset = 0.2;
@ -418,11 +412,10 @@ public class ParallelStageTest extends BaseTestCase {
// ^^ function under test // ^^ function under test
Assert.assertEquals( targetOffset, boosterStage.getAxialOffset(), EPSILON ); Assert.assertEquals( targetOffset, boosterStage.getAxialOffset(), EPSILON );
Assert.assertEquals( 0.16, boosterStage.getPosition().x, EPSILON ); Assert.assertEquals( 0.16, boosterStage.getPosition().x, EPSILON );
Assert.assertEquals( 0.724, boosterStage.getComponentLocations()[0].x, EPSILON ); Assert.assertEquals( 0.724, boosterStage.getComponentLocations()[0].x, EPSILON );
} }
@Test @Test
@ -456,14 +449,14 @@ public class ParallelStageTest extends BaseTestCase {
// ^^ function under test // ^^ function under test
Assert.assertEquals( targetOffset, boosterStage.getAxialOffset(), EPSILON ); Assert.assertEquals( targetOffset, boosterStage.getAxialOffset(), EPSILON );
Assert.assertEquals( 0.2, boosterStage.getPosition().x, EPSILON ); Assert.assertEquals( targetOffset, boosterStage.getPosition().x, EPSILON );
final double expectedRelativePositionX = targetOffset; final double expectedRelativePositionX = 0.2;
final double resultantRelativePosition = boosterStage.getPosition().x; final double resultantRelativePosition = boosterStage.getPosition().x;
Assert.assertEquals(expectedRelativePositionX, resultantRelativePosition, EPSILON); Assert.assertEquals(expectedRelativePositionX, resultantRelativePosition, EPSILON);
// vv function under test // vv function under test
final double actualAbsoluteX = boosterStage.asPositionValue(AxialMethod.ABSOLUTE); final double actualAbsoluteX = boosterStage.getAxialOffset(AxialMethod.ABSOLUTE);
// ^^ function under test // ^^ function under test
Assert.assertEquals( 0.764, actualAbsoluteX, EPSILON ); Assert.assertEquals( 0.764, actualAbsoluteX, EPSILON );
@ -486,7 +479,7 @@ public class ParallelStageTest extends BaseTestCase {
// vv function under test // vv function under test
double actualPositionXAfter = boosterStage.asPositionValue(AxialMethod.AFTER); double actualPositionXAfter = boosterStage.getAxialOffset(AxialMethod.AFTER);
// ^^ function under test // ^^ function under test
Assert.assertEquals( -0.6, actualPositionXAfter, EPSILON ); Assert.assertEquals( -0.6, actualPositionXAfter, EPSILON );
@ -508,7 +501,7 @@ public class ParallelStageTest extends BaseTestCase {
Assert.assertEquals( 0.2, boosterStage.getPosition().x, EPSILON ); Assert.assertEquals( 0.2, boosterStage.getPosition().x, EPSILON );
// vv function under test // vv function under test
final double actualAxialPosition = boosterStage.asPositionValue(AxialMethod.MIDDLE); final double actualAxialPosition = boosterStage.getAxialOffset(AxialMethod.MIDDLE);
// ^^ function under test // ^^ function under test
Assert.assertEquals( 0.24, actualAxialPosition, EPSILON ); Assert.assertEquals( 0.24, actualAxialPosition, EPSILON );
@ -530,7 +523,7 @@ public class ParallelStageTest extends BaseTestCase {
Assert.assertEquals( 0.2, boosterStage.getPosition().x, EPSILON ); Assert.assertEquals( 0.2, boosterStage.getPosition().x, EPSILON );
// vv function under test // vv function under test
double actualAxialBottomOffset = boosterStage.asPositionValue(AxialMethod.BOTTOM); double actualAxialBottomOffset = boosterStage.getAxialOffset(AxialMethod.BOTTOM);
// ^^ function under test // ^^ function under test
Assert.assertEquals( 0.28, actualAxialBottomOffset, EPSILON ); Assert.assertEquals( 0.28, actualAxialBottomOffset, EPSILON );
@ -552,7 +545,7 @@ public class ParallelStageTest extends BaseTestCase {
Assert.assertEquals( 0.120, boosterStage.getPosition().x, EPSILON); Assert.assertEquals( 0.120, boosterStage.getPosition().x, EPSILON);
// vv function under test // vv function under test
double actualAxialTopOffset = boosterStage.asPositionValue(AxialMethod.TOP); double actualAxialTopOffset = boosterStage.getAxialOffset(AxialMethod.TOP);
// ^^ function under test // ^^ function under test
Assert.assertEquals( 0.12, actualAxialTopOffset, EPSILON); Assert.assertEquals( 0.12, actualAxialTopOffset, EPSILON);

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

@ -87,8 +87,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 * @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) { private boolean overlaps(CenteringRing one, InnerTube two) {
final double crTopPosition = one.asPositionValue( AxialMethod.ABSOLUTE); final double crTopPosition = one.getAxialOffset( AxialMethod.ABSOLUTE);
final double mmTopPosition = two.asPositionValue( AxialMethod.ABSOLUTE); final double mmTopPosition = two.getAxialOffset( AxialMethod.ABSOLUTE);
final double crBottomPosition = one.getLength() + crTopPosition; final double crBottomPosition = one.getLength() + crTopPosition;
final double mmBottomPosition = two.getLength() + mmTopPosition; final double mmBottomPosition = two.getLength() + mmTopPosition;

@ -159,7 +159,7 @@ public class FinPointFigure extends AbstractScaleFigure {
Transition body = (Transition) finset.getParent(); Transition body = (Transition) finset.getParent();
final float xResolution_m = 0.01f; // distance between draw points, in meters final float xResolution_m = 0.01f; // distance between draw points, in meters
final double xFinStart = finset.asPositionValue(AxialMethod.TOP); //<< in body frame final double xFinStart = finset.getAxialOffset(AxialMethod.TOP); //<< in body frame
// vv in fin-frame == draw-frame vv // vv in fin-frame == draw-frame vv
final double xOffset = -xFinStart; final double xOffset = -xFinStart;
@ -355,7 +355,7 @@ public class FinPointFigure extends AbstractScaleFigure {
// update to bound the parent body: // update to bound the parent body:
SymmetricComponent parent = (SymmetricComponent)this.finset.getParent(); SymmetricComponent parent = (SymmetricComponent)this.finset.getParent();
final double xFinFront = finset.asPositionValue(AxialMethod.TOP); final double xFinFront = finset.getAxialOffset(AxialMethod.TOP);
final double xParent = -xFinFront; final double xParent = -xFinFront;
final double yParent = -parent.getRadius(xParent); // from parent centerline to fin front. final double yParent = -parent.getRadius(xParent); // from parent centerline to fin front.
final double rParent = Math.max(parent.getForeRadius(), parent.getAftRadius()); final double rParent = Math.max(parent.getForeRadius(), parent.getAftRadius());