Merge branch 'parallel_staging' of https://github.com/teyrana/openrocket into parallel_staging

This commit is contained in:
Daniel_M_Williams 2015-11-21 15:19:59 -05:00
commit 0972ee389a
18 changed files with 373 additions and 169 deletions

View File

@ -894,6 +894,7 @@ StageConfig.tab.Separation.ttip = Stage separation options
StageConfig.separation.lbl.title = Select when this stage separates:
StageConfig.separation.lbl.plus = plus
StageConfig.separation.lbl.seconds = seconds
StageConfig.parallel.autoradius = Enable Automatic Positioning
StageConfig.parallel.radius = Radial Distance
StageConfig.parallel.angle = Angle
StageConfig.parallel.count = Number of Copies

View File

@ -19,7 +19,7 @@ import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.document.StorageOptions;
import net.sf.openrocket.file.RocketSaver;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BoosterSet;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.FlightConfigurableComponent;
@ -259,7 +259,7 @@ public class OpenRocketSaver extends RocketSaver {
/////////////////
// Search the rocket for any Boosters or Pods (version 1.8)
for (RocketComponent c : document.getRocket()) {
if ((c instanceof BoosterSet) || (c instanceof PodSet)) {
if ((c instanceof ParallelStage) || (c instanceof PodSet)) {
return FILE_VERSION_DIVISOR + 8;
}
}

View File

@ -9,7 +9,7 @@ import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyComponent;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.BoosterSet;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.Bulkhead;
import net.sf.openrocket.rocketcomponent.CenteringRing;
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
@ -90,7 +90,7 @@ class DocumentConfig {
// Other
constructors.put("stage", AxialStage.class.getConstructor(new Class<?>[0]));
constructors.put("boosterset", BoosterSet.class.getConstructor(new Class<?>[0]));
constructors.put("boosterset", ParallelStage.class.getConstructor(new Class<?>[0]));
constructors.put("podset", PodSet.class.getConstructor(new Class<?>[0]));
} catch (NoSuchMethodException e) {
@ -150,11 +150,11 @@ class DocumentConfig {
// BoosterSet
setters.put("BoosterSet:instancecount", new IntSetter(
Reflection.findMethod(BoosterSet.class, "setInstanceCount",int.class)));
Reflection.findMethod(ParallelStage.class, "setInstanceCount",int.class)));
setters.put("BoosterSet:radialoffset", new DoubleSetter(
Reflection.findMethod(BoosterSet.class, "setRadialOffset", double.class)));
Reflection.findMethod(ParallelStage.class, "setRadialOffset", double.class)));
setters.put("BoosterSet:angleoffset", new DoubleSetter(
Reflection.findMethod(BoosterSet.class, "setAngularOffset", double.class)));
Reflection.findMethod(ParallelStage.class, "setAngularOffset", double.class)));
// SymmetricComponent
setters.put("SymmetricComponent:thickness", new DoubleSetter(

View File

@ -4,7 +4,7 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.rocketcomponent.BoosterSet;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.InternalComponent;
import net.sf.openrocket.rocketcomponent.LaunchLug;
@ -46,8 +46,8 @@ class PositionSetter implements Setter {
} else if (c instanceof TubeFinSet) {
((TubeFinSet) c).setRelativePosition(type);
c.setAxialOffset(pos);
} else if (c instanceof BoosterSet) {
((BoosterSet) c).setRelativePositionMethod(type);
} else if (c instanceof ParallelStage) {
((ParallelStage) c).setRelativePositionMethod(type);
c.setAxialOffset(pos);
} else if (c instanceof PodSet) {
((PodSet) c).setRelativePositionMethod(type);

View File

@ -5,7 +5,7 @@ import java.util.List;
import java.util.Locale;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BoosterSet;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationID;
import net.sf.openrocket.rocketcomponent.Rocket;
@ -28,7 +28,7 @@ public class AxialStageSaver extends ComponentAssemblySaver {
list.add("</stage>");
}
} else {
if (c instanceof BoosterSet) {
if (c instanceof ParallelStage) {
list.add("<boosterset>");
instance.addParams(c, list);
list.add("</boosterset>");

View File

@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import net.sf.openrocket.rocketcomponent.BoosterSet;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
import net.sf.openrocket.rocketcomponent.Instanceable;
import net.sf.openrocket.rocketcomponent.PodSet;
@ -24,7 +24,7 @@ public class ComponentAssemblySaver extends RocketComponentSaver {
list.add("<podset>");
instance.addParams(c, list);
list.add("</podset>");
} else if (c instanceof BoosterSet) {
} else if (c instanceof ParallelStage) {
list.add("<boosterset>");
instance.addParams(c, list);
list.add("</boosterset>");

View File

@ -13,7 +13,7 @@ import net.sf.openrocket.motor.MotorInstanceConfiguration;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.ThrustCurveMotor;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BoosterSet;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.Instanceable;
@ -345,7 +345,7 @@ public class MassCalculator implements Monitorable {
MassData childrenData = MassData.ZERO_DATA;
// Combine data for subcomponents
for (RocketComponent child : component.getChildren()) {
if( child instanceof BoosterSet ){
if( child instanceof ParallelStage ){
// this stage will be tallied separately... skip.
continue;
}
@ -401,7 +401,7 @@ public class MassCalculator implements Monitorable {
// move to parent's reference point
resultantData = resultantData.move( component.getOffset() );
if( component instanceof BoosterSet ){
if( component instanceof ParallelStage ){
// hacky correction for the fact Booster Stages aren't direct subchildren to the rocket
resultantData = resultantData.move( component.getParent().getOffset() );
}

View File

@ -63,7 +63,7 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
*/
@Override
public boolean isCompatible(Class<? extends RocketComponent> type) {
if (BoosterSet.class.isAssignableFrom(type)) {
if (ParallelStage.class.isAssignableFrom(type)) {
return true;
} else if (PodSet.class.isAssignableFrom(type)) {
return true;

View File

@ -81,6 +81,22 @@ public abstract class ComponentAssembly extends RocketComponent {
return 0;
}
public double getOuterRadius(){
double outerRadius=0;
for( RocketComponent comp : children ){
double thisRadius=0;
if( comp instanceof BodyTube ){
thisRadius = ((BodyTube)comp).getOuterRadius();
}else if( comp instanceof Transition ){
Transition trans = (Transition)comp;
thisRadius = Math.max( trans.getForeRadius(), trans.getAftRadius());
}
outerRadius = Math.max( outerRadius, thisRadius);
}
return outerRadius;
}
/**
* Components have no aerodynamic effect, so return false.
*/
@ -113,7 +129,7 @@ public abstract class ComponentAssembly extends RocketComponent {
if (null == this.parent) {
throw new NullPointerException(" a Stage requires a parent before any positioning! ");
}
if ((this instanceof BoosterSet ) || ( this instanceof PodSet )){
if ((this instanceof ParallelStage ) || ( this instanceof PodSet )){
if (Position.AFTER == _newPosition) {
log.warn("Stages (or Pods) cannot be relative to other stages via AFTER! Ignoring.");
super.setRelativePosition(Position.TOP);

View File

@ -11,7 +11,7 @@ import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Coordinate;
public class BoosterSet extends AxialStage implements FlightConfigurableComponent, RingInstanceable {
public class ParallelStage extends AxialStage implements FlightConfigurableComponent, RingInstanceable {
private static final Translator trans = Application.getTranslator();
//private static final Logger log = LoggerFactory.getLogger(BoosterSet.class);
@ -20,15 +20,16 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen
protected double angularSeparation = Math.PI;
protected double angularPosition_rad = 0;
protected boolean autoRadialPosition = true;
protected double radialPosition_m = 0;
public BoosterSet() {
public ParallelStage() {
this.count = 2;
this.relativePosition = Position.BOTTOM;
this.angularSeparation = Math.PI * 2 / this.count;
}
public BoosterSet( final int _count ){
public ParallelStage( final int _count ){
this();
this.count = _count;
@ -88,7 +89,7 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen
@Override
protected RocketComponent copyWithOriginalID() {
BoosterSet copy = (BoosterSet) (super.copyWithOriginalID());
ParallelStage copy = (ParallelStage) (super.copyWithOriginalID());
return copy;
}
@ -192,6 +193,15 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen
return this.getAxialOffset();
}
public boolean getAutoRadialOffset(){
return this.autoRadialPosition;
}
public void setAutoRadialOffset( final boolean enabled ){
this.autoRadialPosition = enabled;
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
@Override
public void setRadialOffset(final double radius) {
mutex.verify();
@ -206,32 +216,6 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
// @Override
// protected Coordinate[] shiftCoordinates(Coordinate[] c) {
// checkState();
//
// if (1 < c.length) {
// throw new BugException("implementation of 'shiftCoordinates' assumes the coordinate array has len == 1; The length here is "+c.length+"! ");
// }
//
// double radius = this.radialPosition_m;
// double angle0 = this.angularPosition_rad;
// double angleIncr = this.angularSeparation;
// Coordinate center = c[0];
// Coordinate[] toReturn = new Coordinate[this.count];
// //Coordinate thisOffset;
// double thisAngle = angle0;
// for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) {
// toReturn[instanceNumber] = center.add(0, radius * Math.cos(thisAngle), radius * Math.sin(thisAngle));
//
// thisAngle += angleIncr;
// }
//
// return toReturn;
// }
//
@Override
public void toDebugTreeNode(final StringBuilder buffer, final String prefix) {
buffer.append(String.format("%s %-24s (stage: %d)", prefix, this.getName(), this.getStageNumber()));
@ -248,5 +232,20 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen
}
@Override
protected void update() {
super.update();
if( this.autoRadialPosition ){
AxialStage parentStage = (AxialStage)this.parent;
if( null == parentStage ){
this.radialPosition_m = this.getOuterRadius();
}else{
this.radialPosition_m = this.getOuterRadius() + parentStage.getOuterRadius();
}
}
}
}

View File

@ -21,7 +21,7 @@ import net.sf.openrocket.preset.InvalidComponentPresetException;
import net.sf.openrocket.preset.TypedPropertyMap;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.BoosterSet;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.Bulkhead;
import net.sf.openrocket.rocketcomponent.CenteringRing;
import net.sf.openrocket.rocketcomponent.ClusterConfiguration;
@ -829,7 +829,7 @@ public class TestRockets {
// ====== Booster Stage Set ======
// ====== ====== ====== ======
BoosterSet boosterStage = new BoosterSet();
ParallelStage boosterStage = new ParallelStage();
boosterStage.setName("Booster Stage");
coreStage.addChild( boosterStage);
boosterStage.setRelativePositionMethod(Position.BOTTOM);

View File

@ -8,7 +8,7 @@ import org.junit.Test;
import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
import net.sf.openrocket.motor.MotorInstance;
import net.sf.openrocket.rocketcomponent.BoosterSet;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationID;
import net.sf.openrocket.rocketcomponent.InnerTube;
@ -119,7 +119,7 @@ public class MassCalculatorTest extends BaseTestCase {
// ====== Booster Set Stage ======
// ====== ====== ======
BoosterSet boosters = (BoosterSet) rkt.getChild(1).getChild(1);
ParallelStage boosters = (ParallelStage) rkt.getChild(1).getChild(1);
{
expMass = 0.01530561538;
cc= boosters.getChild(0);
@ -232,7 +232,7 @@ public class MassCalculatorTest extends BaseTestCase {
// ====== Booster Set Stage ======
// ====== ====== ======
BoosterSet boosters = (BoosterSet) rkt.getChild(1).getChild(1);
ParallelStage boosters = (ParallelStage) rkt.getChild(1).getChild(1);
{
cc= boosters.getChild(0);
expInertia = 5.20107e-6;
@ -264,7 +264,7 @@ public class MassCalculatorTest extends BaseTestCase {
Rocket rocket = TestRockets.makeFalcon9Heavy();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
BoosterSet boosters = (BoosterSet) rocket.getChild(1).getChild(1);
ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
rocket.getDefaultConfiguration().setAllStages(false);
@ -293,7 +293,7 @@ public class MassCalculatorTest extends BaseTestCase {
Rocket rocket = TestRockets.makeFalcon9Heavy();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
BoosterSet boosters = (BoosterSet) rocket.getChild(1).getChild(1);
ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
rocket.getDefaultConfiguration().setAllStages(false);
rocket.getDefaultConfiguration().setOnlyStage( boostNum);
@ -339,7 +339,7 @@ public class MassCalculatorTest extends BaseTestCase {
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
FlightConfiguration defaultConfig = rocket.getDefaultConfiguration();
BoosterSet boosters = (BoosterSet) rocket.getChild(1).getChild(1);
ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
rocket.getDefaultConfiguration().setAllStages(false);
@ -365,7 +365,7 @@ public class MassCalculatorTest extends BaseTestCase {
FlightConfiguration defaultConfig = rocket.getDefaultConfiguration();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
BoosterSet boosters = (BoosterSet) rocket.getChild(1).getChild(1);
ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
rocket.getDefaultConfiguration().setAllStages(false);
@ -393,7 +393,7 @@ public class MassCalculatorTest extends BaseTestCase {
FlightConfiguration config = rocket.getDefaultConfiguration();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
BoosterSet boosters = (BoosterSet) rocket.getChild(1).getChild(1);
ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
config.setAllStages(false);
config.setOnlyStage( boostNum);
@ -444,7 +444,7 @@ public class MassCalculatorTest extends BaseTestCase {
FlightConfiguration config = rocket.getDefaultConfiguration();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
BoosterSet boosters = (BoosterSet) rocket.getChild(1).getChild(1);
ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
config.setAllStages(false);
config.setOnlyStage( boostNum);

View File

@ -23,7 +23,7 @@ public class BoosterSetTest extends BaseTestCase {
}
public Rocket createTestRocket() {
double tubeRadius = 1;
double tubeRadius = 1.2;
// setup
Rocket rocket = new Rocket();
rocket.setName("Rocket");
@ -53,28 +53,29 @@ public class BoosterSetTest extends BaseTestCase {
return rocket;
}
public BoosterSet createBooster() {
public ParallelStage createBooster() {
double tubeRadius = 0.8;
BoosterSet booster = new BoosterSet();
booster.setName("Booster Stage");
ParallelStage strapon = new ParallelStage();
strapon.setName("Booster Stage");
strapon.setAutoRadialOffset(true);
RocketComponent boosterNose = new NoseCone(Transition.Shape.CONICAL, 2.0, tubeRadius);
boosterNose.setName("Booster Nosecone");
booster.addChild(boosterNose);
strapon.addChild(boosterNose);
RocketComponent boosterBody = new BodyTube(2.0, tubeRadius, 0.01);
boosterBody.setName("Booster Body ");
booster.addChild(boosterBody);
strapon.addChild(boosterBody);
Transition boosterTail = new Transition();
boosterTail.setName("Booster Tail");
boosterTail.setForeRadius(1.0);
boosterTail.setAftRadius(0.5);
boosterTail.setLength(1.0);
booster.addChild(boosterTail);
strapon.addChild(boosterTail);
booster.setInstanceCount(3);
booster.setRadialOffset(1.8);
strapon.setInstanceCount(3);
strapon.setRadialOffset(1.8);
return booster;
return strapon;
}
/* From OpenRocket Technical Documentation
@ -104,7 +105,7 @@ public class BoosterSetTest extends BaseTestCase {
}
@Test
public void testAddSustainerStage() {
public void testCreateSustainer() {
RocketComponent rocket = createTestRocket();
// Sustainer Stage
@ -200,7 +201,7 @@ public class BoosterSetTest extends BaseTestCase {
assertEquals(" createTestRocket failed:\n" + rocketTree + " core Fins abs X: ", expectedX, resultantX, EPSILON);
}
@Test
public void testSetStagePosition_topOfStack() {
// setup
@ -233,15 +234,17 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet set0 = createBooster();
ParallelStage set0 = createBooster();
core.addChild(set0);
double targetOffset = 0;
set0.setAxialOffset(Position.BOTTOM, targetOffset);
// vv function under test
set0.setAutoRadialOffset(true);
set0.setInstanceCount(2);
set0.setRadialOffset(4.0);
set0.setAngularOffset(Math.PI / 2);
// ^^ function under test
String treeDump = rocket.toDebugTree();
@ -262,6 +265,49 @@ public class BoosterSetTest extends BaseTestCase {
assertEquals(" 'setAngularOffset(double)' failed:\n" + treeDump + " angular offset: ", expectedAngularOffset, angularOffset, EPSILON);
}
@Test
public void testAddStraponAuto() {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
ParallelStage strapons = createBooster();
core.addChild( strapons);
double targetXOffset = +1.0;
strapons.setAxialOffset(Position.BOTTOM, targetXOffset);
double targetRadialOffset = 0.01;
// vv function under test
strapons.setRadialOffset(targetRadialOffset);
strapons.setAutoRadialOffset(true);
// ^^ function under test
String treeDump = rocket.toDebugTree();
double expectedRadialOffset = core.getOuterRadius() + strapons.getOuterRadius();
double actualRadialOffset = strapons.getRadialOffset();
assertEquals(" 'setAutoRadialOffset()' failed:\n" + treeDump , expectedRadialOffset, actualRadialOffset, EPSILON);
// Coordinate[] instanceAbsoluteCoords = set0.getLocations();
// // 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 = instanceAbsoluteCoords[inst];
// assertEquals(" 'setAngularOffset(double)' failed:\n" + treeDump + " angular offset: ", resultantPosition0, equalTo(expectedPosition0));
//
// inst = 1;
// Coordinate expectedPosition1 = new Coordinate(expectedX, radius * Math.cos(angle * inst), radius * Math.sin(angle * inst));
// 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 = instanceAbsoluteCoords[inst];
// assertThat(treeDump + "\n>> Failed to generate Parallel Stage instances correctly: ", resultantPosition2, equalTo(expectedPosition2));
//
}
// because even though this is an "outside" stage, it's relative to itself -- i.e. an error.
// also an error with a well-defined failure result (i.e. just failover to AFTER placement as the first stage of a rocket.
@Test
@ -269,7 +315,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet set0 = createBooster();
ParallelStage set0 = createBooster();
core.addChild(set0);
double targetOffset = 0;
@ -314,7 +360,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet booster = createBooster();
ParallelStage booster = createBooster();
core.addChild(booster);
double targetX = +17.0;
@ -376,7 +422,7 @@ public class BoosterSetTest extends BaseTestCase {
public void testSetStagePosition_outsideTOP() {
Rocket rocket = this.createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet booster = createBooster();
ParallelStage booster = createBooster();
core.addChild(booster);
double targetOffset = +2.0;
@ -406,7 +452,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet booster = createBooster();
ParallelStage booster = createBooster();
core.addChild(booster);
// when 'external' the stage should be freely movable
@ -436,7 +482,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet booster = createBooster();
ParallelStage booster = createBooster();
core.addChild(booster);
// vv function under test
@ -465,7 +511,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet booster = createBooster();
ParallelStage booster = createBooster();
core.addChild(booster);
double targetOffset = +4.50;
@ -489,7 +535,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet booster = createBooster();
ParallelStage booster = createBooster();
core.addChild(booster);
double targetOffset = +4.50;
@ -513,7 +559,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet booster = createBooster();
ParallelStage booster = createBooster();
core.addChild(booster);
double targetOffset = +4.50;
@ -538,7 +584,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet booster = createBooster();
ParallelStage booster = createBooster();
core.addChild(booster);
@ -563,7 +609,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet booster = createBooster();
ParallelStage booster = createBooster();
core.addChild(booster);
double targetOffset = +4.50;
@ -587,7 +633,7 @@ public class BoosterSetTest extends BaseTestCase {
Rocket rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet booster = new BoosterSet();
ParallelStage booster = new ParallelStage();
booster.setName("Booster Stage");
core.addChild(booster);
final double targetOffset = +2.50;
@ -623,10 +669,10 @@ public class BoosterSetTest extends BaseTestCase {
public void testStageInitializationMethodValueOrder() {
Rocket rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet boosterA = createBooster();
ParallelStage boosterA = createBooster();
boosterA.setName("Booster A Stage");
core.addChild(boosterA);
BoosterSet boosterB = createBooster();
ParallelStage boosterB = createBooster();
boosterB.setName("Booster B Stage");
core.addChild(boosterB);
@ -653,11 +699,11 @@ public class BoosterSetTest extends BaseTestCase {
Rocket rocket = createTestRocket();
AxialStage sustainer = (AxialStage) rocket.getChild(0);
AxialStage core = (AxialStage) rocket.getChild(1);
BoosterSet boosterA = createBooster();
ParallelStage boosterA = createBooster();
boosterA.setName("Booster A Stage");
core.addChild(boosterA);
boosterA.setAxialOffset(Position.BOTTOM, 0.0);
BoosterSet boosterB = createBooster();
ParallelStage boosterB = createBooster();
boosterB.setName("Booster B Stage");
core.addChild(boosterB);
boosterB.setAxialOffset(Position.BOTTOM, 0);
@ -691,7 +737,7 @@ public class BoosterSetTest extends BaseTestCase {
actualStageCount = rocket.getDefaultConfiguration().getStageCount();
assertEquals(" Stage tracking error: removed booster A, but configuration not updated: " + treedump, expectedStageCount, actualStageCount);
BoosterSet boosterC = createBooster();
ParallelStage boosterC = createBooster();
boosterC.setName("Booster C Stage");
core.addChild(boosterC);
boosterC.setAxialOffset(Position.BOTTOM, 0);

View File

@ -27,82 +27,6 @@ public class ComponentAssemblyConfig extends RocketComponentConfig {
public ComponentAssemblyConfig(OpenRocketDocument document, RocketComponent component) {
super(document, component);
// For DEBUG purposes
if( component instanceof AxialStage ){
System.err.println(" Dumping AxialStage tree info for devel / debugging.");
System.err.println(component.toDebugTree());
}
// only stages which are actually off-centerline will get the dialog here:
if(( component instanceof ComponentAssembly )&&( 1 < component.getInstanceCount() )){
tabbedPane.insertTab( trans.get("RocketCompCfg.tab.Parallel"), null, parallelTab( (ComponentAssembly) component ), trans.get("RocketCompCfg.tab.ParallelComment"), 1);
}
}
private JPanel parallelTab( final ComponentAssembly assembly ){
JPanel motherPanel = new JPanel( new MigLayout("fill"));
// set radial distance
JLabel radiusLabel = new JLabel(trans.get("StageConfig.parallel.radius"));
motherPanel.add( radiusLabel , "align left");
DoubleModel radiusModel = new DoubleModel( assembly, "RadialOffset", UnitGroup.UNITS_LENGTH, 0);
//radiusModel.setCurrentUnit( UnitGroup.UNITS_LENGTH.getUnit("cm"));
JSpinner radiusSpinner = new JSpinner( radiusModel.getSpinnerModel());
radiusSpinner.setEditor(new SpinnerEditor(radiusSpinner ));
motherPanel.add(radiusSpinner , "growx 1, align right");
UnitSelector radiusUnitSelector = new UnitSelector(radiusModel);
motherPanel.add(radiusUnitSelector, "growx 1, wrap");
// set location angle around the primary stage
JLabel angleLabel = new JLabel(trans.get("StageConfig.parallel.angle"));
motherPanel.add( angleLabel, "align left");
DoubleModel angleModel = new DoubleModel( assembly, "AngularOffset", 1.0, UnitGroup.UNITS_ANGLE, 0.0, Math.PI*2);
angleModel.setCurrentUnit( UnitGroup.UNITS_ANGLE.getUnit("rad"));
JSpinner angleSpinner = new JSpinner(angleModel.getSpinnerModel());
angleSpinner.setEditor(new SpinnerEditor(angleSpinner));
motherPanel.add(angleSpinner, "growx 1");
UnitSelector angleUnitSelector = new UnitSelector(angleModel);
motherPanel.add( angleUnitSelector, "growx 1, wrap");
// set multiplicity
JLabel countLabel = new JLabel(trans.get("StageConfig.parallel.count"));
motherPanel.add( countLabel, "align left");
IntegerModel countModel = new IntegerModel( assembly, "InstanceCount", 2);
JSpinner countSpinner = new JSpinner(countModel.getSpinnerModel());
countSpinner.setEditor(new SpinnerEditor(countSpinner));
motherPanel.add(countSpinner, "growx 1, wrap");
// setPositions relative to parent component
JLabel positionLabel = new JLabel(trans.get("LaunchLugCfg.lbl.Posrelativeto"));
motherPanel.add( positionLabel);
// EnumModel(ChangeSource source, String valueName, Enum<T>[] values) {
ComboBoxModel<RocketComponent.Position> relativePositionMethodModel = new EnumModel<RocketComponent.Position>(component, "RelativePositionMethod",
new RocketComponent.Position[] {
RocketComponent.Position.TOP,
RocketComponent.Position.MIDDLE,
RocketComponent.Position.BOTTOM,
RocketComponent.Position.ABSOLUTE
});
JComboBox<?> positionMethodCombo = new JComboBox<RocketComponent.Position>( relativePositionMethodModel );
motherPanel.add(positionMethodCombo, "spanx 2, growx, wrap");
// relative offset labels
JLabel positionPlusLabel = new JLabel(trans.get("StageConfig.parallel.offset"));
motherPanel.add( positionPlusLabel );
DoubleModel axialOffsetModel = new DoubleModel( assembly, "AxialOffset", UnitGroup.UNITS_LENGTH);
axialOffsetModel.setCurrentUnit(UnitGroup.UNITS_LENGTH.getUnit("cm"));
JSpinner axPosSpin= new JSpinner( axialOffsetModel.getSpinnerModel());
axPosSpin.setEditor(new SpinnerEditor(axPosSpin));
motherPanel.add(axPosSpin, "growx");
UnitSelector axialOffsetUnitSelector = new UnitSelector(axialOffsetModel);
motherPanel.add(axialOffsetUnitSelector, "growx 1, wrap");
// For DEBUG purposes
//System.err.println(assembly.getRocket().toDebugTree());
return motherPanel;
}
}

View File

@ -0,0 +1,118 @@
package net.sf.openrocket.gui.configdialog;
import javax.swing.ComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.SpinnerEditor;
import net.sf.openrocket.gui.adaptors.BooleanModel;
import net.sf.openrocket.gui.adaptors.DoubleModel;
import net.sf.openrocket.gui.adaptors.EnumModel;
import net.sf.openrocket.gui.adaptors.IntegerModel;
import net.sf.openrocket.gui.components.UnitSelector;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.ChangeSource;
public class ParallelStageConfig extends RocketComponentConfig {
private static final long serialVersionUID = -944969957186522471L;
private static final Translator trans = Application.getTranslator();
public ParallelStageConfig(OpenRocketDocument document, RocketComponent component) {
super(document, component);
// For DEBUG purposes
if( component instanceof AxialStage ){
System.err.println(" Dumping AxialStage tree info for devel / debugging.");
System.err.println(component.toDebugTree());
}
// only stages which are actually off-centerline will get the dialog here:
tabbedPane.insertTab( trans.get("RocketCompCfg.tab.Parallel"), null, parallelTab( (ParallelStage)component ), trans.get("RocketCompCfg.tab.ParallelComment"), 1);
}
private JPanel parallelTab( final ParallelStage boosters ){
JPanel motherPanel = new JPanel( new MigLayout("fill"));
// auto radial distance
BooleanModel autoRadOffsModel = new BooleanModel( boosters, "AutoRadialOffset");
JCheckBox autoRadCheckBox = new JCheckBox( autoRadOffsModel );
autoRadCheckBox.setText( trans.get("StageConfig.parallel.autoradius"));
motherPanel.add( autoRadCheckBox, "align left, wrap");
// set radial distance
JLabel radiusLabel = new JLabel(trans.get("StageConfig.parallel.radius"));
motherPanel.add( radiusLabel , "align left");
autoRadOffsModel.addEnableComponent(radiusLabel, false);
DoubleModel radiusModel = new DoubleModel( boosters, "RadialOffset", UnitGroup.UNITS_LENGTH, 0);
//radiusModel.setCurrentUnit( UnitGroup.UNITS_LENGTH.getUnit("cm"));
JSpinner radiusSpinner = new JSpinner( radiusModel.getSpinnerModel());
radiusSpinner.setEditor(new SpinnerEditor(radiusSpinner ));
motherPanel.add(radiusSpinner , "growx 1, align right");
autoRadOffsModel.addEnableComponent(radiusSpinner, false);
UnitSelector radiusUnitSelector = new UnitSelector(radiusModel);
motherPanel.add(radiusUnitSelector, "growx 1, wrap");
autoRadOffsModel.addEnableComponent(radiusUnitSelector, false);
// set location angle around the primary stage
JLabel angleLabel = new JLabel(trans.get("StageConfig.parallel.angle"));
motherPanel.add( angleLabel, "align left");
DoubleModel angleModel = new DoubleModel( boosters, "AngularOffset", 1.0, UnitGroup.UNITS_ANGLE, 0.0, Math.PI*2);
angleModel.setCurrentUnit( UnitGroup.UNITS_ANGLE.getUnit("rad"));
JSpinner angleSpinner = new JSpinner(angleModel.getSpinnerModel());
angleSpinner.setEditor(new SpinnerEditor(angleSpinner));
motherPanel.add(angleSpinner, "growx 1");
UnitSelector angleUnitSelector = new UnitSelector(angleModel);
motherPanel.add( angleUnitSelector, "growx 1, wrap");
// set multiplicity
JLabel countLabel = new JLabel(trans.get("StageConfig.parallel.count"));
motherPanel.add( countLabel, "align left");
IntegerModel countModel = new IntegerModel( boosters, "InstanceCount", 2);
JSpinner countSpinner = new JSpinner(countModel.getSpinnerModel());
countSpinner.setEditor(new SpinnerEditor(countSpinner));
motherPanel.add(countSpinner, "growx 1, wrap");
// setPositions relative to parent component
JLabel positionLabel = new JLabel(trans.get("LaunchLugCfg.lbl.Posrelativeto"));
motherPanel.add( positionLabel);
// EnumModel(ChangeSource source, String valueName, Enum<T>[] values) {
ComboBoxModel<RocketComponent.Position> relativePositionMethodModel = new EnumModel<RocketComponent.Position>(component, "RelativePositionMethod",
new RocketComponent.Position[] {
RocketComponent.Position.TOP,
RocketComponent.Position.MIDDLE,
RocketComponent.Position.BOTTOM,
RocketComponent.Position.ABSOLUTE
});
JComboBox<?> positionMethodCombo = new JComboBox<RocketComponent.Position>( relativePositionMethodModel );
motherPanel.add(positionMethodCombo, "spanx 2, growx, wrap");
// relative offset labels
JLabel positionPlusLabel = new JLabel(trans.get("StageConfig.parallel.offset"));
motherPanel.add( positionPlusLabel );
DoubleModel axialOffsetModel = new DoubleModel( boosters, "AxialOffset", UnitGroup.UNITS_LENGTH);
axialOffsetModel.setCurrentUnit(UnitGroup.UNITS_LENGTH.getUnit("cm"));
JSpinner axPosSpin= new JSpinner( axialOffsetModel.getSpinnerModel());
axPosSpin.setEditor(new SpinnerEditor(axPosSpin));
motherPanel.add(axPosSpin, "growx");
UnitSelector axialOffsetUnitSelector = new UnitSelector(axialOffsetModel);
motherPanel.add(axialOffsetUnitSelector, "growx 1, wrap");
// For DEBUG purposes
//System.err.println(assembly.getRocket().toDebugTree());
return motherPanel;
}
}

View File

@ -0,0 +1,100 @@
package net.sf.openrocket.gui.configdialog;
import javax.swing.ComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.SpinnerEditor;
import net.sf.openrocket.gui.adaptors.DoubleModel;
import net.sf.openrocket.gui.adaptors.EnumModel;
import net.sf.openrocket.gui.adaptors.IntegerModel;
import net.sf.openrocket.gui.components.UnitSelector;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
public class PodSetConfig extends RocketComponentConfig {
private static final long serialVersionUID = -944969957186522471L;
private static final Translator trans = Application.getTranslator();
public PodSetConfig(OpenRocketDocument document, RocketComponent component) {
super(document, component);
// only stages which are actually off-centerline will get the dialog here:
tabbedPane.insertTab( trans.get("RocketCompCfg.tab.Parallel"), null, parallelTab( (ComponentAssembly) component ), trans.get("RocketCompCfg.tab.ParallelComment"), 1);
}
private JPanel parallelTab( final ComponentAssembly assembly ){
JPanel motherPanel = new JPanel( new MigLayout("fill"));
// set radial distance
JLabel radiusLabel = new JLabel(trans.get("StageConfig.parallel.radius"));
motherPanel.add( radiusLabel , "align left");
DoubleModel radiusModel = new DoubleModel( assembly, "RadialOffset", UnitGroup.UNITS_LENGTH, 0);
//radiusModel.setCurrentUnit( UnitGroup.UNITS_LENGTH.getUnit("cm"));
JSpinner radiusSpinner = new JSpinner( radiusModel.getSpinnerModel());
radiusSpinner.setEditor(new SpinnerEditor(radiusSpinner ));
motherPanel.add(radiusSpinner , "growx 1, align right");
UnitSelector radiusUnitSelector = new UnitSelector(radiusModel);
motherPanel.add(radiusUnitSelector, "growx 1, wrap");
// set location angle around the primary stage
JLabel angleLabel = new JLabel(trans.get("StageConfig.parallel.angle"));
motherPanel.add( angleLabel, "align left");
DoubleModel angleModel = new DoubleModel( assembly, "AngularOffset", 1.0, UnitGroup.UNITS_ANGLE, 0.0, Math.PI*2);
angleModel.setCurrentUnit( UnitGroup.UNITS_ANGLE.getUnit("rad"));
JSpinner angleSpinner = new JSpinner(angleModel.getSpinnerModel());
angleSpinner.setEditor(new SpinnerEditor(angleSpinner));
motherPanel.add(angleSpinner, "growx 1");
UnitSelector angleUnitSelector = new UnitSelector(angleModel);
motherPanel.add( angleUnitSelector, "growx 1, wrap");
// set multiplicity
JLabel countLabel = new JLabel(trans.get("StageConfig.parallel.count"));
motherPanel.add( countLabel, "align left");
IntegerModel countModel = new IntegerModel( assembly, "InstanceCount", 2);
JSpinner countSpinner = new JSpinner(countModel.getSpinnerModel());
countSpinner.setEditor(new SpinnerEditor(countSpinner));
motherPanel.add(countSpinner, "growx 1, wrap");
// setPositions relative to parent component
JLabel positionLabel = new JLabel(trans.get("LaunchLugCfg.lbl.Posrelativeto"));
motherPanel.add( positionLabel);
// EnumModel(ChangeSource source, String valueName, Enum<T>[] values) {
ComboBoxModel<RocketComponent.Position> relativePositionMethodModel = new EnumModel<RocketComponent.Position>(component, "RelativePositionMethod",
new RocketComponent.Position[] {
RocketComponent.Position.TOP,
RocketComponent.Position.MIDDLE,
RocketComponent.Position.BOTTOM,
RocketComponent.Position.ABSOLUTE
});
JComboBox<?> positionMethodCombo = new JComboBox<RocketComponent.Position>( relativePositionMethodModel );
motherPanel.add(positionMethodCombo, "spanx 2, growx, wrap");
// relative offset labels
JLabel positionPlusLabel = new JLabel(trans.get("StageConfig.parallel.offset"));
motherPanel.add( positionPlusLabel );
DoubleModel axialOffsetModel = new DoubleModel( assembly, "AxialOffset", UnitGroup.UNITS_LENGTH);
axialOffsetModel.setCurrentUnit(UnitGroup.UNITS_LENGTH.getUnit("cm"));
JSpinner axPosSpin= new JSpinner( axialOffsetModel.getSpinnerModel());
axPosSpin.setEditor(new SpinnerEditor(axPosSpin));
motherPanel.add(axPosSpin, "growx");
UnitSelector axialOffsetUnitSelector = new UnitSelector(axialOffsetModel);
motherPanel.add(axialOffsetUnitSelector, "growx 1, wrap");
// For DEBUG purposes
//System.err.println(assembly.getRocket().toDebugTree());
return motherPanel;
}
}

View File

@ -34,7 +34,7 @@ import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.Markers;
import net.sf.openrocket.rocketcomponent.BodyComponent;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.BoosterSet;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.Bulkhead;
import net.sf.openrocket.rocketcomponent.CenteringRing;
import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
@ -167,7 +167,7 @@ public class ComponentAddButtons extends JPanel implements Scrollable {
//// Component Assembly Components:
ComponentButton[] buttonsToAdd = {
new ComponentButton(AxialStage.class, trans.get("RocketActions.NewStageAct.Newstage")),
new ComponentButton(BoosterSet.class, trans.get("compaddbuttons.newBooster.lbl")),
new ComponentButton(ParallelStage.class, trans.get("compaddbuttons.newBooster.lbl")),
new ComponentButton(PodSet.class, trans.get("compaddbuttons.newPods.lbl"))};
addButtonGroup(row, buttonsToAdd);

View File

@ -12,7 +12,7 @@ import javax.swing.ImageIcon;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.BoosterSet;
import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.Bulkhead;
import net.sf.openrocket.rocketcomponent.CenteringRing;
import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
@ -86,7 +86,7 @@ public class ComponentIcons {
load("stage", trans.get("ComponentIcons.Stage"),
AxialStage.class);
load("boosters", trans.get("ComponentIcons.Boosters"),
BoosterSet.class);
ParallelStage.class);
load("pods", trans.get("ComponentIcons.Pods"),
PodSet.class);
// // Mass components